MFTCard and MFTGraph are now subclasses of MFTWidget.

Commit
08cdafbf1b51fa56245f6164724edd202a7fd806
Author
Marius Peter <marius.peter@tutanota.com>
Author date
Committer
Marius Peter <marius.peter@tutanota.com>
Committer date
Changed files
src/MyFitnessTracker/MFTCard.class.st
index 22373968..427646c2 100644..100644
@@ -1,22 +1,10 @@
1 1 Class {
2 2 #name : #MFTCard,
3 Removed: #superclass : #SBSComponent,
4 Removed: #instVars : [
5 Removed: 'title',
6 Removed: 'type'
7 Removed: ],
3 Added: #superclass : #MFTWidget,
8 4 #category : #'MyFitnessTracker-Components'
9 5 }
10 6
11 7 { #category : #'accessing - structure variables' }
12 Removed: MFTCard class >> type: aType [
13 Removed:
14 Removed: ^ self new
15 Removed: type: aType;
16 Removed: yourself
17 Removed: ]
18 Removed:
19 Removed: { #category : #'accessing - structure variables' }
20 8 MFTCard class >> type: aType title: aString [
21 9
22 10 ^ self new
@@ -25,64 +13,42 @@
25 13 yourself
26 14 ]
27 15
28 Removed: { #category : #accessing }
29 Removed: MFTCard >> defaultTitle [
30 Removed:
31 Removed: ^ 'Default Card'
32 Removed: ]
33 Removed:
34 Removed: { #category : #initialization }
35 Removed: MFTCard >> initialize [
36 Removed:
37 Removed: super initialize.
38 Removed: title := self defaultTitle.
39 Removed: type := #default
40 Removed: ]
41 Removed:
42 16 { #category : #rendering }
43 Removed: MFTCard >> renderCardOn: html type: aType [
44 Removed:
45 Removed: html card
46 Removed: marginTopAndBottom: 3;
47 Removed: with: [
48 Removed: html cardHeader: self title.
49 Removed: self
50 Removed: perform: ('render' , aType asCamelCase , 'CardOn:') asSymbol
51 Removed: with: html ]
52 Removed: ]
53 Removed:
54 Removed: { #category : #rendering }
55 17 MFTCard >> renderContentOn: html [
56 18
57 Removed: self renderCardOn: html type: type
19 Added: self
20 Added: perform: ('render' , type asCamelCase , 'CardOn:') asSymbol
21 Added: with: html
58 22 ]
59 23
60 24 { #category : #rendering }
61 25 MFTCard >> renderDefaultCardOn: html [
62 26
63 Removed: html cardBody: [
64 Removed: html paragraph: 'I am the default MFTCard representation.' ]
27 Added: html cardBody: [ html paragraph: self defaultDescription ]
65 28 ]
66 29
67 30 { #category : #rendering }
68 31 MFTCard >> renderMainPublicCardOn: html [
69 32
70 Removed: html jumbotron
71 Removed: class: 'p-3 bg-light';
33 Added: html card
34 Added: marginTopAndBottom: 3;
72 35 with: [
73 Removed: html displayHeading
74 Removed: level: 1;
75 Removed: with: 'Welcome to My Fitness Tracker!'.
76 Removed: html big textMuted with: 'Free Software never looked so fit.'.
77 Removed: html form: [
78 Removed: html formButton
79 Removed: bePrimary;
80 Removed: beLarge;
81 Removed: class: 'mt-3';
82 Removed: callback: [
83 Removed: self session pageManager activePage:
84 Removed: (self session pageManager mainPages at: 2) ];
85 Removed: with: 'Log a workout' ] ]
36 Added: html jumbotron
37 Added: class: 'p-3 bg-light';
38 Added: with: [
39 Added: html displayHeading
40 Added: level: 1;
41 Added: with: 'Welcome to My Fitness Tracker!'.
42 Added: html big textMuted with: 'Free Software never looked so fit.'.
43 Added: html form: [
44 Added: html formButton
45 Added: bePrimary;
46 Added: beLarge;
47 Added: class: 'mt-3';
48 Added: callback: [
49 Added: self session pageManager activePage:
50 Added: (self session pageManager mainPages at: 2) ];
51 Added: with: 'Log a workout' ] ] ]
86 52 ]
87 53
88 54 { #category : #rendering }
@@ -98,171 +64,78 @@
98 64 'at'.
99 65 lastLoginDate asTimeUTC asString.
100 66 'UTC' } joinUsing: ' '.
101 Removed: html card: [
102 Removed: html jumbotron
103 Removed: class: 'p-3 bg-light';
104 Removed: with: [
105 Removed: html displayHeading
106 Removed: level: 1;
107 Removed: with: [
108 Removed: html
109 Removed: text: 'Welcome, ';
110 Removed: code: self session user username;
111 Removed: text: '!' ].
112 Removed: html big textMuted with: subtitle ] ]
67 Added:
68 Added:
69 Added: html card
70 Added: marginTopAndBottom: 3;
71 Added: with: [
72 Added: html jumbotron
73 Added: class: 'p-3 bg-light';
74 Added: with: [
75 Added: html displayHeading
76 Added: level: 1;
77 Added: with: [
78 Added: html
79 Added: text: 'Welcome, ';
80 Added: code: self session user username;
81 Added: text: '!' ].
82 Added: html big textMuted with: subtitle ] ]
113 83 ]
114 84
115 85 { #category : #rendering }
116 86 MFTCard >> renderPromisesCardOn: html [
117 87
118 Removed: html cardBody: [
119 Removed: html unorderedList: [
120 Removed: html listItem:
121 Removed: 'Every single feature shall always be free of charge.'.
122 Removed: html listItem:
123 Removed: 'No user data shall ever be sold, under any circumstances.'.
124 Removed: html listItem: 'No user data shall ever be tracked.' ] ]
88 Added: html card: [
89 Added: html cardHeader: self title.
90 Added: html cardBody: [
91 Added: html unorderedList: [
92 Added: html listItem:
93 Added: 'Every single feature shall always be free of charge.'.
94 Added: html listItem:
95 Added: 'No personal user data shall ever be sold, under any circumstances.'.
96 Added: html listItem:
97 Added: 'No external advertisements shall ever be displayed.' ] ] ]
125 98 ]
126 99
127 100 { #category : #rendering }
128 101 MFTCard >> renderWeightsCardOn: html [
129 102
130 Removed: html cardBody: [
131 Removed: html paragraph: 'Great job logging your weight '
132 Removed: , self session user weights size asString , ' times!'.
133 Removed: html form
134 Removed: class: 'my-3';
135 Removed: with: [
136 Removed: html formButton
137 Removed: bePrimary;
138 Removed: beSmall;
139 Removed: callback: [
140 Removed: self session pageManager activePage:
141 Removed: (self session pageManager mainPages at: 3) ];
142 Removed: with: 'Log a weight' ].
143 Removed: self renderWeightsGraphOn: html ]
103 Added: html card: [
104 Added: html cardHeader: self title.
105 Added: html cardBody: [
106 Added: html paragraph: 'Great job logging your weight '
107 Added: , self session user weights size asString , ' times!'.
108 Added: html form
109 Added: class: 'my-3';
110 Added: with: [
111 Added: html formButton
112 Added: bePrimary;
113 Added: beSmall;
114 Added: callback: [
115 Added: self session pageManager activePage:
116 Added: (self session pageManager mainPages at: 3) ];
117 Added: with: 'Log a weight' ].
118 Added: html render: (MFTGraph type: #weightVersusTime) ] ]
144 119 ]
145 120
146 121 { #category : #rendering }
147 Removed: MFTCard >> renderWeightsGraphOn: html [
148 Removed:
149 Removed: | labels data |
150 Removed: labels := self session user weights collect: [ :weight |
151 Removed: weight date yyyymmdd ].
152 Removed: data := self session user weights collect: #value.
153 Removed: html canvas
154 Removed: id: 'weightChart';
155 Removed: width: 4;
156 Removed: height: 1.
157 Removed: html script url: 'https://cdn.jsdelivr.net/npm/chart.js'.
158 Removed: html script:
159 Removed: 'var ctx = document.getElementById("weightChart").getContext("2d");
160 Removed: var weightChart = new Chart(ctx, {
161 Removed: type: "line",
162 Removed: data: {
163 Removed: labels: ' , labels asJavascript , ',
164 Removed: datasets: [{
165 Removed: label: "weight",
166 Removed: data: ' , data asJavascript , ',
167 Removed: backgroundColor: "rgba(255, 99, 132, 0.2)",
168 Removed: borderColor: "rgba(255, 99, 132, 1)",
169 Removed: borderWidth: 1
170 Removed: }]
171 Removed: },
172 Removed: options: {
173 Removed: scales: {
174 Removed: yAxes: [{
175 Removed: ticks: {
176 Removed: beginAtZero: true
177 Removed: }
178 Removed: }]
179 Removed: }
180 Removed: }
181 Removed: });'
182 Removed: ]
183 Removed:
184 Removed: { #category : #rendering }
185 122 MFTCard >> renderWorkoutsCardOn: html [
186 123
187 Removed: html cardBody: [
188 Removed: html paragraph:
189 Removed: 'Great job logging ' , self session user workouts size asString
190 Removed: , ' workouts!'.
191 Removed: html form
192 Removed: class: 'my-3';
193 Removed: with: [
194 Removed: html formButton
195 Removed: bePrimary;
196 Removed: beSmall;
197 Removed: callback: [
198 Removed: self session pageManager activePage:
199 Removed: (self session pageManager mainPages at: 2) ];
200 Removed: with: 'Log a workout' ].
201 Removed: self renderWorkoutsGraphOn: html ]
202 Removed: ]
203 Removed:
204 Removed: { #category : #rendering }
205 Removed: MFTCard >> renderWorkoutsGraphOn: html [
206 Removed:
207 Removed: | exercises labels data repTally |
208 Removed: exercises := self session user workouts flatCollect: #exercises.
209 Removed: repTally := Dictionary new.
210 Removed: exercises do: [ :exercise |
211 Removed: repTally at: exercise englishName ifAbsentPut: [ 0 ].
212 Removed: repTally
213 Removed: at: exercise englishName
214 Removed: put: (repTally at: exercise englishName) + exercise repsBySet sum ].
215 Removed: labels := repTally keys.
216 Removed: data := repTally values.
217 Removed: html div
218 Removed: style: 'max-width: 24rem';
219 Removed: with: [
220 Removed: html canvas
221 Removed: id: 'workoutChart';
222 Removed: width: 4;
223 Removed: height: 1.
224 Removed: html script url: 'https://cdn.jsdelivr.net/npm/chart.js'.
225 Removed: html script:
226 Removed: 'var ctx = document.getElementById("workoutChart").getContext("2d");
227 Removed: var workoutChart = new Chart(ctx, {
228 Removed: type: "doughnut",
229 Removed: data: {
230 Removed: labels: ' , labels asJavascript , ',
231 Removed: datasets: [{
232 Removed: data: ' , data asJavascript , '
233 Removed: }]
234 Removed: },
235 Removed: options: {
236 Removed: title: {
237 Removed: display: true,
238 Removed: text: "Reps by exercise"
239 Removed: }
240 Removed: }
241 Removed: });' ]
242 Removed: ]
243 Removed:
244 Removed: { #category : #accessing }
245 Removed: MFTCard >> title [
246 Removed:
247 Removed: ^ title = self defaultTitle
248 Removed: ifTrue: [ ^ type asCapitalizedPhrase ]
249 Removed: ifFalse: [ ^ title ]
250 Removed: ]
251 Removed:
252 Removed: { #category : #accessing }
253 Removed: MFTCard >> title: aString [
254 Removed:
255 Removed: title := aString
256 Removed: ]
257 Removed:
258 Removed: { #category : #accessing }
259 Removed: MFTCard >> type [
260 Removed:
261 Removed: ^ type
262 Removed: ]
263 Removed:
264 Removed: { #category : #accessing }
265 Removed: MFTCard >> type: anObject [
266 Removed:
267 Removed: type := anObject
124 Added: html card: [
125 Added: html cardHeader: self title.
126 Added: html cardBody: [
127 Added: html paragraph:
128 Added: 'Great job logging ' , self session user workouts size asString
129 Added: , ' workouts!'.
130 Added: html form
131 Added: class: 'my-3';
132 Added: with: [
133 Added: html formButton
134 Added: bePrimary;
135 Added: beSmall;
136 Added: callback: [
137 Added: self session pageManager activePage:
138 Added: (self session pageManager mainPages at: 2) ];
139 Added: with: 'Log a workout' ].
140 Added: html render: (MFTGraph type: #repsVersusExercises) ] ]
268 141 ]
src/MyFitnessTracker/MFTGraph.class.st
index 00000000..23992fb5 000000..100644
@@ -0,0 +1,105 @@
1 Added: Class {
2 Added: #name : #MFTGraph,
3 Added: #superclass : #MFTWidget,
4 Added: #category : #'MyFitnessTracker-Components'
5 Added: }
6 Added:
7 Added: { #category : #rendering }
8 Added: MFTGraph >> renderContentOn: html [
9 Added:
10 Added: html div: [
11 Added: self
12 Added: perform: ('render' , type asCamelCase , 'GraphOn:') asSymbol
13 Added: with: html ]
14 Added: ]
15 Added:
16 Added: { #category : #rendering }
17 Added: MFTGraph >> renderDefaultGraphOn: html [
18 Added:
19 Added: | labels data |
20 Added: labels := #( Monday Tuesday Wednesday Thursday Friday ).
21 Added: data := #( 5 1 6 2 7 ).
22 Added: html heading level5 with: self defaultDescription.
23 Added: html canvas id: 'defaultGraph'.
24 Added: html script:
25 Added: 'var ctx = document.getElementById("defaultGraph").getContext("2d");
26 Added: var defaultChart = new Chart(ctx, {
27 Added: type: "line",
28 Added: data: {
29 Added: labels: ' , labels asJavascript , ',
30 Added: datasets: [{
31 Added: label: "default data",
32 Added: data: ' , data asJavascript , ',
33 Added: borderWidth: 1
34 Added: }]
35 Added: }
36 Added: });'
37 Added: ]
38 Added:
39 Added: { #category : #rendering }
40 Added: MFTGraph >> renderRepsVersusExercisesGraphOn: html [
41 Added:
42 Added: | exercises labels data repTally |
43 Added: exercises := self session user workouts flatCollect: #exercises.
44 Added: repTally := Dictionary new.
45 Added: exercises do: [ :exercise |
46 Added: repTally at: exercise englishName ifAbsentPut: [ 0 ].
47 Added: repTally
48 Added: at: exercise englishName
49 Added: put: (repTally at: exercise englishName) + exercise repsBySet sum ].
50 Added: labels := repTally keys.
51 Added: data := repTally values.
52 Added:
53 Added: html canvas id: 'workoutChart'.
54 Added: html script:
55 Added: 'var ctx = document.getElementById("workoutChart").getContext("2d");
56 Added: var workoutChart = new Chart(ctx, {
57 Added: type: "doughnut",
58 Added: data: {
59 Added: labels: ' , labels asJavascript , ',
60 Added: datasets: [{
61 Added: data: ' , data asJavascript , '
62 Added: }]
63 Added: },
64 Added: options: {
65 Added: title: {
66 Added: display: true,
67 Added: text: "Reps by exercise"
68 Added: }
69 Added: }
70 Added: });'
71 Added: ]
72 Added:
73 Added: { #category : #rendering }
74 Added: MFTGraph >> renderWeightVersusTimeGraphOn: html [
75 Added:
76 Added: | labels data |
77 Added: labels := self session user weights collect: [ :weight |
78 Added: weight date yyyymmdd ].
79 Added: data := self session user weights collect: #value.
80 Added: html canvas id: 'weightChart'.
81 Added: html script:
82 Added: 'var ctx = document.getElementById("weightChart").getContext("2d");
83 Added: var weightChart = new Chart(ctx, {
84 Added: type: "line",
85 Added: data: {
86 Added: labels: ' , labels asJavascript , ',
87 Added: datasets: [{
88 Added: label: "weight",
89 Added: data: ' , data asJavascript , ',
90 Added: backgroundColor: "rgba(255, 99, 132, 0.2)",
91 Added: borderColor: "rgba(255, 99, 132, 1)",
92 Added: borderWidth: 1
93 Added: }]
94 Added: },
95 Added: options: {
96 Added: scales: {
97 Added: yAxes: [{
98 Added: ticks: {
99 Added: beginAtZero: true
100 Added: }
101 Added: }]
102 Added: }
103 Added: }
104 Added: });'
105 Added: ]
src/MyFitnessTracker/MFTHeaderComponent.class.st
index 00000000..dd3c2110 000000..100644
@@ -0,0 +1,109 @@
1 Added: Class {
2 Added: #name : #MFTHeaderComponent,
3 Added: #superclass : #SBSComponent,
4 Added: #instVars : [
5 Added: 'email',
6 Added: 'localPart',
7 Added: 'domain'
8 Added: ],
9 Added: #category : #'MyFitnessTracker-Components'
10 Added: }
11 Added:
12 Added: { #category : #adding }
13 Added: MFTHeaderComponent >> addUserEmail [
14 Added:
15 Added: | emailToCheck emailPattern |
16 Added: emailToCheck := self call: MFTEmailSignupDialog new.
17 Added: emailPattern := '^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]{3,}\.[a-zA-Z]{2,}$'
18 Added: asRegex.
19 Added: (emailToCheck isNil or: [ (emailPattern matches: emailToCheck) not ])
20 Added: ifTrue: [ ^ nil ].
21 Added: email := emailToCheck.
22 Added: MFTSQLite3Database storeProspectEmail: email
23 Added: ]
24 Added:
25 Added: { #category : #rendering }
26 Added: MFTHeaderComponent >> renderContentOn: html [
27 Added:
28 Added: email
29 Added: ifNil: [
30 Added: html alert
31 Added: beWarning;
32 Added: beDismissible;
33 Added: marginBottom: 0;
34 Added: with: [
35 Added: html closeButton dataDismiss: 'alert'.
36 Added: html alertHeading: 'This app is still in beta.'.
37 Added: html paragraph: [
38 Added: html
39 Added: text:
40 Added: 'My Fitness Tracker is still under heavy development, with improvements being made daily.';
41 Added: space;
42 Added: text: 'I can''t wait to share the finished product with you!' ].
43 Added: html form with: [
44 Added: html label
45 Added: style: 'margin-right: 1em';
46 Added: with: [ html strong: 'Want to know when version 1.0 is out?' ].
47 Added: html formButton
48 Added: beInfo;
49 Added: callback: [ self addUserEmail ];
50 Added: with: 'E-mail me!' ] ] ]
51 Added: ifNotNil: [
52 Added: html alert
53 Added: beSuccess;
54 Added: beDismissible;
55 Added: marginBottom: 0;
56 Added: with: [
57 Added: html closeButton dataDismiss: 'alert'.
58 Added: html text: email , ' will be notified when v1 is released!' ] ]
59 Added: ]
60 Added:
61 Added: { #category : #rendering }
62 Added: MFTHeaderComponent >> renderEmailInputModalButtonOn: html [
63 Added:
64 Added: ^ html formButton
65 Added: bePrimary;
66 Added: beSmall;
67 Added: dataToggle: 'modal';
68 Added: dataTarget: '#emailInputModal';
69 Added: with: 'E-mail me!'
70 Added: ]
71 Added:
72 Added: { #category : #rendering }
73 Added: MFTHeaderComponent >> renderEmailInputModalOn: html [
74 Added:
75 Added: html modal
76 Added: id: 'emailInputModal';
77 Added: fade;
78 Added: with: [
79 Added: html modalDialog
80 Added: beCentered;
81 Added: with: [
82 Added: html modalContent: [
83 Added: html form: [
84 Added: html modalHeader: [
85 Added: html modalTitle
86 Added: level5;
87 Added: with:
88 Added: 'You''ll be the first to know when My Fitness Tracker is ready to use.'.
89 Added: html modalCloseButton ].
90 Added:
91 Added: html modalBody: [
92 Added: html inputGroup: [
93 Added: html formTextInput
94 Added: callback: [ :value | localPart := value ];
95 Added: placeholder: 'my-user'.
96 Added: html inputGroupAppend: [ html inputGroupText: '@' ].
97 Added: html formTextInput
98 Added: callback: [ :value | domain := value ];
99 Added: placeholder: 'example.com' ] ].
100 Added:
101 Added: html modalFooter: [
102 Added: html paragraph:
103 Added: 'You will receive a single e-mail when the app is ready to use. Your e-mail address shall not be used in any other way.'.
104 Added: html formButton
105 Added: bePrimary;
106 Added: beSubmit;
107 Added: callback: [ email := localPart , '@' , domain ];
108 Added: with: 'Confirm' ] ] ] ] ]
109 Added: ]
src/MyFitnessTracker/MFTPageManager.class.st
index 4802804a..cb10f17f 100644..100644
@@ -99,5 +99,5 @@
99 99 { #category : #'as yet unclassified' }
100 100 MFTPageManager >> registerProspectHeader [
101 101
102 Removed: ^ MFTRegisterProspectHaederComponent new
102 Added: ^ MFTHeaderComponent new
103 103 ]
src/MyFitnessTracker/MFTPublicLandingPage.class.st
index 094858b1..c4fbbddf 100644..100644
@@ -16,8 +16,12 @@
16 16
17 17 html container: [
18 18 html render: (MFTCard type: #mainPublic).
19 Removed: html render: (MFTCard type: #workouts).
20 Removed: html render: (MFTCard type: #weights).
21 Removed: html render:
22 Removed: (MFTCard type: #promises title: 'My promises to all users') ]
19 Added: html div
20 Added: style:
21 Added: 'display: flex; flex-wrap: wrap; justify-content: space-evenly; gap: 1em';
22 Added: with: [
23 Added: html render: (MFTCard type: #workouts title: 'Workouts').
24 Added: html render: (MFTCard type: #weights title: 'Weights').
25 Added: html render:
26 Added: (MFTCard type: #promises title: 'My promises to all users') ] ]
23 27 ]
src/MyFitnessTracker/MFTRegisterProspectHaederComponent.class.st
index c97e0a69..00000000 100644..000000
@@ -1,109 +0,0 @@
1 Removed: Class {
2 Removed: #name : #MFTRegisterProspectHaederComponent,
3 Removed: #superclass : #SBSComponent,
4 Removed: #instVars : [
5 Removed: 'email',
6 Removed: 'localPart',
7 Removed: 'domain'
8 Removed: ],
9 Removed: #category : #'MyFitnessTracker-Components'
10 Removed: }
11 Removed:
12 Removed: { #category : #adding }
13 Removed: MFTRegisterProspectHaederComponent >> addUserEmail [
14 Removed:
15 Removed: | emailToCheck emailPattern |
16 Removed: emailToCheck := self call: MFTEmailSignupDialog new.
17 Removed: emailPattern := '^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]{3,}\.[a-zA-Z]{2,}$'
18 Removed: asRegex.
19 Removed: (emailToCheck isNil or: [ (emailPattern matches: emailToCheck) not ])
20 Removed: ifTrue: [ ^ nil ].
21 Removed: email := emailToCheck.
22 Removed: MFTSQLite3Database storeProspectEmail: email
23 Removed: ]
24 Removed:
25 Removed: { #category : #rendering }
26 Removed: MFTRegisterProspectHaederComponent >> renderContentOn: html [
27 Removed:
28 Removed: email
29 Removed: ifNil: [
30 Removed: html alert
31 Removed: beWarning;
32 Removed: beDismissible;
33 Removed: marginBottom: 0;
34 Removed: with: [
35 Removed: html closeButton dataDismiss: 'alert'.
36 Removed: html alertHeading: 'This app is still in beta.'.
37 Removed: html paragraph: [
38 Removed: html
39 Removed: text:
40 Removed: 'My Fitness Tracker is still under heavy development, with improvements being made daily.';
41 Removed: space;
42 Removed: text: 'I can''t wait to share the finished product with you!' ].
43 Removed: html form with: [
44 Removed: html label
45 Removed: style: 'margin-right: 1em';
46 Removed: with: [ html strong: 'Want to know when version 1.0 is out?' ].
47 Removed: html formButton
48 Removed: beInfo;
49 Removed: callback: [ self addUserEmail ];
50 Removed: with: 'E-mail me!' ] ] ]
51 Removed: ifNotNil: [
52 Removed: html alert
53 Removed: beSuccess;
54 Removed: beDismissible;
55 Removed: marginBottom: 0;
56 Removed: with: [
57 Removed: html closeButton dataDismiss: 'alert'.
58 Removed: html text: email , ' will be notified when v1 is released!' ] ]
59 Removed: ]
60 Removed:
61 Removed: { #category : #rendering }
62 Removed: MFTRegisterProspectHaederComponent >> renderEmailInputModalButtonOn: html [
63 Removed:
64 Removed: ^ html formButton
65 Removed: bePrimary;
66 Removed: beSmall;
67 Removed: dataToggle: 'modal';
68 Removed: dataTarget: '#emailInputModal';
69 Removed: with: 'E-mail me!'
70 Removed: ]
71 Removed:
72 Removed: { #category : #rendering }
73 Removed: MFTRegisterProspectHaederComponent >> renderEmailInputModalOn: html [
74 Removed:
75 Removed: html modal
76 Removed: id: 'emailInputModal';
77 Removed: fade;
78 Removed: with: [
79 Removed: html modalDialog
80 Removed: beCentered;
81 Removed: with: [
82 Removed: html modalContent: [
83 Removed: html form: [
84 Removed: html modalHeader: [
85 Removed: html modalTitle
86 Removed: level5;
87 Removed: with:
88 Removed: 'You''ll be the first to know when My Fitness Tracker is ready to use.'.
89 Removed: html modalCloseButton ].
90 Removed:
91 Removed: html modalBody: [
92 Removed: html inputGroup: [
93 Removed: html formTextInput
94 Removed: callback: [ :value | localPart := value ];
95 Removed: placeholder: 'my-user'.
96 Removed: html inputGroupAppend: [ html inputGroupText: '@' ].
97 Removed: html formTextInput
98 Removed: callback: [ :value | domain := value ];
99 Removed: placeholder: 'example.com' ] ].
100 Removed:
101 Removed: html modalFooter: [
102 Removed: html paragraph:
103 Removed: 'You will receive a single e-mail when the app is ready to use. Your e-mail address shall not be used in any other way.'.
104 Removed: html formButton
105 Removed: bePrimary;
106 Removed: beSubmit;
107 Removed: callback: [ email := localPart , '@' , domain ];
108 Removed: with: 'Confirm' ] ] ] ] ]
109 Removed: ]
src/MyFitnessTracker/MFTRootComponent.class.st
index 773d2e39..4a5baa9c 100644..100644
@@ -7,7 +7,7 @@
7 7 #category : #'MyFitnessTracker-Components'
8 8 }
9 9
10 Removed: { #category : #initialization }
10 Added: { #category : #testing }
11 11 MFTRootComponent class >> canBeRoot [
12 12
13 13 ^ true
@@ -73,6 +73,7 @@
73 73 { #category : #rendering }
74 74 MFTRootComponent >> renderContentOn: html [
75 75
76 Added: html script url: 'https://cdn.jsdelivr.net/npm/chart.js'.
76 77 html render: main.
77 78 self addBootstrapJSScriptTo: html
78 79 ]
src/MyFitnessTracker/MFTWeightsListPage.class.st
index b42e94fb..314522b7 100644..100644
@@ -72,7 +72,11 @@
72 72 html formButton
73 73 bePrimary;
74 74 callback: [ self addWeight ];
75 Removed: with: 'Add weight' ] ]
75 Added: with: 'Add weight'.
76 Added: html formButton
77 Added: beSecondary;
78 Added: callback: [ self ];
79 Added: with: 'View progress' ] ]
76 80 ]
77 81
78 82 { #category : #rendering }
src/MyFitnessTracker/MFTWidget.class.st
index 00000000..7148628b 000000..100644
@@ -0,0 +1,91 @@
1 Added: Class {
2 Added: #name : #MFTWidget,
3 Added: #superclass : #SBSComponent,
4 Added: #instVars : [
5 Added: 'title',
6 Added: 'type'
7 Added: ],
8 Added: #category : #'MyFitnessTracker-Components'
9 Added: }
10 Added:
11 Added: { #category : #accessing }
12 Added: MFTWidget class >> default [
13 Added:
14 Added: ^ self new
15 Added: title: 'Default ' , self name;
16 Added: yourself
17 Added: ]
18 Added:
19 Added: { #category : #'accessing - structure variables' }
20 Added: MFTWidget class >> type: aType [
21 Added:
22 Added: ^ self new
23 Added: type: aType;
24 Added: yourself
25 Added: ]
26 Added:
27 Added: { #category : #'accessing - structure variables' }
28 Added: MFTWidget class >> type: aType title: aString [
29 Added:
30 Added: ^ self new
31 Added: type: aType;
32 Added: title: aString;
33 Added: yourself
34 Added: ]
35 Added:
36 Added: { #category : #accessing }
37 Added: MFTWidget >> defaultDescription [
38 Added:
39 Added: ^ {
40 Added: 'I am a'.
41 Added: self class name.
42 Added: 'of type'.
43 Added: (type , '.') } joinUsing: ' '
44 Added: ]
45 Added:
46 Added: { #category : #initialization }
47 Added: MFTWidget >> initialize [
48 Added:
49 Added: super initialize.
50 Added: title := String new.
51 Added: type := #default
52 Added: ]
53 Added:
54 Added: { #category : #rendering }
55 Added: MFTWidget >> renderContentOn: html [
56 Added:
57 Added: html div: [
58 Added: title ifNotEmpty: [
59 Added: html heading
60 Added: level5;
61 Added: with: self title ].
62 Added: html paragraph: ({
63 Added: 'I am a'.
64 Added: self class name.
65 Added: 'of type'.
66 Added: (type , '.') } joinUsing: ' ') ]
67 Added: ]
68 Added:
69 Added: { #category : #accessing }
70 Added: MFTWidget >> title [
71 Added:
72 Added: ^ title ifEmpty: [ type asCapitalizedPhrase ]
73 Added: ]
74 Added:
75 Added: { #category : #accessing }
76 Added: MFTWidget >> title: aString [
77 Added:
78 Added: title := aString
79 Added: ]
80 Added:
81 Added: { #category : #accessing }
82 Added: MFTWidget >> type [
83 Added:
84 Added: ^ type
85 Added: ]
86 Added:
87 Added: { #category : #accessing }
88 Added: MFTWidget >> type: aTypeSymbol [
89 Added:
90 Added: type := aTypeSymbol
91 Added: ]
src/MyFitnessTracker/MFTWorkoutsListPage.class.st
index 105b4e64..0b170819 100644..100644
@@ -188,10 +188,10 @@
188 188 html
189 189 text:
190 190 workout date yyyymmdd , ' ('
191 Removed: , workout date dayOfWeekName asString , ') ';
191 Added: , workout date dayOfWeekName asString , ')';
192 192 space.
193 193 workout primaryMuscle englishName ifNotEmpty: [
194 Removed: html strong: workout primaryMuscle englishName asString ] ] ].
194 Added: html strong: workout primaryMuscle englishName ] ] ].
195 195 html accordionCollapse
196 196 id: 'collapse' , i asString;
197 197 class: 'collapse';