[Pharo] Personal fitness tracker web app.
Brand new dialogs! :fire:
Changed files
- src/MyFitnessTracker/MFTConfirmDialog.class.st
- src/MyFitnessTracker/MFTDateDialog.class.st
- src/MyFitnessTracker/MFTDialog.class.st
- src/MyFitnessTracker/MFTExerciseDialog.class.st
- src/MyFitnessTracker/MFTExercisesDialog.class.st
- src/MyFitnessTracker/MFTPrimaryMuscleDialog.class.st
- src/MyFitnessTracker/MFTSecondaryMusclesDialog.class.st
- src/MyFitnessTracker/MFTStringDialog.class.st
- src/MyFitnessTracker/MFTWeightDialog.class.st
- src/MyFitnessTracker/MFTWorkoutDialog.class.st
src/MyFitnessTracker/MFTConfirmDialog.class.st
@@ -1,72 +1,43 @@
1
1
Class {
2
2
#name : #MFTConfirmDialog,
3
Removed:
#superclass : #SBSComponent,
4
Removed:
#instVars : [
5
Removed:
'action',
6
Removed:
'component'
7
Removed:
],
3
Added:
#superclass : #MFTDialog,
8
4
#category : #'MyFitnessTracker-Dialogs'
9
5
}
10
6
11
7
{ #category : #public }
12
Removed:
MFTConfirmDialog class >> delete: anObject [
8
Added:
MFTConfirmDialog class >> add: anObject [
13
9
14
10
^ self new
15
Removed:
action: #delete;
11
Added:
action: #add;
16
12
component: anObject;
17
13
yourself
18
14
]
19
15
20
Removed:
{ #category : #accessing }
21
Removed:
MFTConfirmDialog >> action [
16
Added:
{ #category : #public }
17
Added:
MFTConfirmDialog class >> delete: anObject [
22
18
23
Removed:
^ action
19
Added:
^ self new
20
Added:
action: #delete;
21
Added:
component: anObject;
22
Added:
yourself
24
23
]
25
24
26
Removed:
{ #category : #accessing }
27
Removed:
MFTConfirmDialog >> action: anObject [
25
Added:
{ #category : #'as yet unclassified' }
26
Added:
MFTConfirmDialog >> heading [
28
27
29
Removed:
action := anObject
28
Added:
^ 'You are about to ' , action , ' a ' , component class asString
29
Added:
, ':'
30
30
]
31
31
32
Removed:
{ #category : #accessing }
33
Removed:
MFTConfirmDialog >> component [
34
Removed:
35
Removed:
^ component
36
Removed:
]
37
Removed:
38
Removed:
{ #category : #accessing }
39
Removed:
MFTConfirmDialog >> component: anObject [
40
Removed:
41
Removed:
component := anObject
42
Removed:
]
43
Removed:
44
32
{ #category : #rendering }
45
33
MFTConfirmDialog >> renderContentOn: html [
46
34
47
Removed:
html container: [
48
Removed:
html heading:
49
Removed:
'You are about to ' , action , ' the following component:'.
50
Removed:
html heading
51
Removed:
level: 2;
52
Removed:
with: component class.
35
Added:
self renderDialogOn: html with: [
53
36
html render: component.
54
Removed:
html form: [
55
Removed:
html
56
Removed:
label: [
57
Removed:
html
58
Removed:
text: 'Are you sure?';
59
Removed:
space;
60
Removed:
strong: 'This action cannot be undone.' ];
61
Removed:
break.
62
Removed:
html buttonGroup: [
63
Removed:
html formButton
64
Removed:
beDanger;
65
Removed:
beSubmit;
66
Removed:
callback: [ self answer: true ];
67
Removed:
with: 'Confirm'.
68
Removed:
html formButton
69
Removed:
beSecondary;
70
Removed:
callback: [ self answer: false ];
71
Removed:
with: 'Cancel' ] ] ]
37
Added:
html label: [
38
Added:
html text: 'Are you sure?'.
39
Added:
action = #delete ifTrue: [
40
Added:
html
41
Added:
space;
42
Added:
strong: 'This action cannot be undone.' ] ] ]
72
43
]
src/MyFitnessTracker/MFTDateDialog.class.st
@@ -0,0 +1,47 @@
1
Added:
Class {
2
Added:
#name : #MFTDateDialog,
3
Added:
#superclass : #MFTDialog,
4
Added:
#instVars : [
5
Added:
'date'
6
Added:
],
7
Added:
#category : #'MyFitnessTracker-Dialogs'
8
Added:
}
9
Added:
10
Added:
{ #category : #accessing }
11
Added:
MFTDateDialog >> date [
12
Added:
13
Added:
^ date
14
Added:
]
15
Added:
16
Added:
{ #category : #accessing }
17
Added:
MFTDateDialog >> date: anObject [
18
Added:
19
Added:
date := anObject
20
Added:
]
21
Added:
22
Added:
{ #category : #initialization }
23
Added:
MFTDateDialog >> initialize [
24
Added:
25
Added:
super initialize.
26
Added:
date := Date today
27
Added:
]
28
Added:
29
Added:
{ #category : #rendering }
30
Added:
MFTDateDialog >> renderContentOn: html [
31
Added:
32
Added:
self renderDialogOn: html with: [
33
Added:
html dateInput5 formControl
34
Added:
value: date yyyymmdd;
35
Added:
callback: [ :value | date := Date fromString: value ] ]
36
Added:
]
37
Added:
38
Added:
{ #category : #rendering }
39
Added:
MFTDateDialog >> renderSubmitOn: html [
40
Added:
41
Added:
html buttonGroup: [
42
Added:
html formButton
43
Added:
beSubmit;
44
Added:
bePrimary;
45
Added:
callback: [ self answer: date ];
46
Added:
with: (completion ifNil: [ 'Submit' ] ifNotNil: [ 'Next' ]) ]
47
Added:
]
src/MyFitnessTracker/MFTDialog.class.st
@@ -2,59 +2,138 @@
2
2
#name : #MFTDialog,
3
3
#superclass : #SBSComponent,
4
4
#instVars : [
5
Removed:
'addOrEdit'
5
Added:
'heading',
6
Added:
'component',
7
Added:
'action',
8
Added:
'completion'
6
9
],
7
10
#category : #'MyFitnessTracker-Dialogs'
8
11
}
9
12
10
13
{ #category : #actions }
11
Removed:
MFTDialog class >> edit: aMFTWorkout [
14
Added:
MFTDialog class >> edit: anObject [
12
15
13
16
^ self new
14
Removed:
workout: aMFTWorkout;
15
Removed:
exercises: aMFTWorkout exercises;
16
Removed:
addOrEdit: #edit;
17
Added:
action: #edit;
18
Added:
component: anObject;
17
19
yourself
18
20
]
19
21
20
22
{ #category : #accessing }
21
Removed:
MFTDialog >> addOrEdit [
23
Added:
MFTDialog >> action [
22
24
23
Removed:
^ addOrEdit
25
Added:
^ action
24
26
]
25
27
26
28
{ #category : #accessing }
27
Removed:
MFTDialog >> addOrEdit: aRole [
29
Added:
MFTDialog >> action: anObject [
28
30
29
Removed:
addOrEdit := aRole
31
Added:
action := anObject
30
32
]
31
33
34
Added:
{ #category : #delegation }
35
Added:
MFTDialog >> answer [
36
Added:
37
Added:
self answer: component
38
Added:
]
39
Added:
40
Added:
{ #category : #accessing }
41
Added:
MFTDialog >> completion [
42
Added:
43
Added:
^ completion
44
Added:
]
45
Added:
46
Added:
{ #category : #accessing }
47
Added:
MFTDialog >> completion: anObject [
48
Added:
49
Added:
completion := anObject
50
Added:
]
51
Added:
52
Added:
{ #category : #accessing }
53
Added:
MFTDialog >> component [
54
Added:
55
Added:
^ component
56
Added:
]
57
Added:
58
Added:
{ #category : #accessing }
59
Added:
MFTDialog >> component: anObject [
60
Added:
61
Added:
component := anObject
62
Added:
]
63
Added:
64
Added:
{ #category : #'t - rotating' }
65
Added:
MFTDialog >> heading [
66
Added:
67
Added:
^ action capitalized , ' ' , (heading ifNil: [
68
Added:
('^MFT(.*)Dialog$' asRegex
69
Added:
search: self class name;
70
Added:
subexpression: 2) asCapitalizedPhrase ifNil: [
71
Added:
'Default Component' ] ])
72
Added:
]
73
Added:
74
Added:
{ #category : #accessing }
75
Added:
MFTDialog >> heading: aString [
76
Added:
77
Added:
heading := aString
78
Added:
]
79
Added:
32
80
{ #category : #initialization }
33
81
MFTDialog >> initialize [
34
82
35
83
super initialize.
36
Removed:
addOrEdit := #add
84
Added:
action := #add
37
85
]
38
86
39
87
{ #category : #rendering }
88
Added:
MFTDialog >> renderCompletionOn: html [
89
Added:
90
Added:
completion ifNotNil: [
91
Added:
html progress
92
Added:
class: 'my-3';
93
Added:
with: [
94
Added:
html progressBar
95
Added:
beStriped;
96
Added:
beAnimated;
97
Added:
successBackground;
98
Added:
valueNow: completion;
99
Added:
with: completion percent ] ]
100
Added:
]
101
Added:
102
Added:
{ #category : #rendering }
40
103
MFTDialog >> renderContentOn: html [
41
104
42
105
self renderDialogOn: html with: [
43
Removed:
html heading: 'Default ' , self class name.
44
Removed:
html form: [
45
Removed:
html formGroup: [
46
Removed:
html label: 'Don''t do anything'.
47
Removed:
html formButton
48
Removed:
beSecondary;
49
Removed:
formControl;
50
Removed:
callback: [ self answer: nil ];
51
Removed:
with: 'Cancel' ] ] ]
106
Added:
html text:
107
Added:
'By default, ' , self class name , ' doesn''t do anything.' ]
52
108
]
53
109
54
110
{ #category : #rendering }
55
111
MFTDialog >> renderDialogOn: html with: aBlock [
56
112
57
113
html container
58
Removed:
class: 'w-50';
59
Removed:
with: aBlock
114
Added:
style: 'max-width: 40rem';
115
Added:
with: [
116
Added:
html heading: self heading.
117
Added:
html form: [
118
Added:
aBlock value.
119
Added:
html horizontalRule.
120
Added:
self renderSubmitOn: html ].
121
Added:
self renderCompletionOn: html ]
122
Added:
]
123
Added:
124
Added:
{ #category : #rendering }
125
Added:
MFTDialog >> renderSubmitOn: html [
126
Added:
127
Added:
html buttonGroup: [
128
Added:
html formButton
129
Added:
beSubmit;
130
Added:
bePrimary;
131
Added:
beDangerIf: action = #delete;
132
Added:
callback: [ self answer: true ];
133
Added:
with: (completion ifNil: [ 'Submit' ] ifNotNil: [ 'Next' ]).
134
Added:
html formButton
135
Added:
beSubmit;
136
Added:
beSecondary;
137
Added:
callback: [ self answer: false ];
138
Added:
with: (completion ifNil: [ 'Cancel' ] ifNotNil: [ 'Skip' ]) ]
60
139
]
src/MyFitnessTracker/MFTExerciseDialog.class.st
@@ -1,11 +1,7 @@
1
1
Class {
2
2
#name : #MFTExerciseDialog,
3
Removed:
#superclass : #SBSComponent,
3
Added:
#superclass : #MFTDialog,
4
4
#instVars : [
5
Removed:
'selectedExercise',
6
Removed:
'currentFilter',
7
Removed:
'allExercises',
8
Removed:
'addOrEdit',
9
5
'exercise',
10
6
'sets'
11
7
],
@@ -16,55 +12,30 @@
16
12
MFTExerciseDialog class >> edit: aMFTExercise [
17
13
18
14
^ self new
19
Removed:
selectedExercise: aMFTExercise;
15
Added:
exercise: aMFTExercise;
20
16
sets: aMFTExercise sets;
21
Removed:
addOrEdit: #edit;
17
Added:
action: #edit;
22
18
yourself
23
19
]
24
20
25
21
{ #category : #accessing }
26
Removed:
MFTExerciseDialog >> addOrEdit [
27
Removed:
28
Removed:
^ addOrEdit
29
Removed:
]
30
Removed:
31
Removed:
{ #category : #accessing }
32
Removed:
MFTExerciseDialog >> addOrEdit: aRole [
33
Removed:
34
Removed:
addOrEdit := aRole
35
Removed:
]
36
Removed:
37
Removed:
{ #category : #accessing }
38
22
MFTExerciseDialog >> exercise [
39
23
40
24
^ exercise
41
25
]
42
26
43
27
{ #category : #accessing }
44
Removed:
MFTExerciseDialog >> exercise: aMFTExercise [
28
Added:
MFTExerciseDialog >> exercise: anObject [
45
29
46
Removed:
exercise := aMFTExercise
30
Added:
exercise := anObject
47
31
]
48
32
49
Removed:
{ #category : #rendering }
50
Removed:
MFTExerciseDialog >> filteredExercises [
51
Removed:
52
Removed:
^ currentFilter isEmpty
53
Removed:
ifTrue: [ allExercises ]
54
Removed:
ifFalse: [
55
Removed:
allExercises select: [ :each |
56
Removed:
each englishName asLowercase includesSubstring:
57
Removed:
currentFilter asLowercase ] ]
58
Removed:
]
59
Removed:
60
33
{ #category : #initialization }
61
34
MFTExerciseDialog >> initialize [
62
35
63
36
super initialize.
64
37
exercise := MFTExercise new.
65
Removed:
allExercises := MFTUtils allExercises.
66
Removed:
sets := OrderedCollection new.
67
Removed:
addOrEdit := #add
38
Added:
sets := OrderedCollection new
68
39
]
69
40
70
41
{ #category : #rendering }
@@ -85,43 +56,30 @@
85
56
{ #category : #rendering }
86
57
MFTExerciseDialog >> renderContentOn: html [
87
58
88
Removed:
html container: [
89
Removed:
html heading: addOrEdit capitalized , ' exercise'.
90
Removed:
html form: [
91
Removed:
self renderExerciseSelectOn: html.
92
Removed:
self renderSetsTableOn: html.
93
Removed:
self renderSubmitExerciseOn: html ] ]
59
Added:
self renderDialogOn: html with: [
60
Added:
self renderExerciseSelectOn: html.
61
Added:
self renderSetsTableOn: html ]
94
62
]
95
63
96
64
{ #category : #rendering }
97
65
MFTExerciseDialog >> renderExerciseSelectOn: html [
98
66
67
Added:
| allExercises selectedExercise |
68
Added:
allExercises := MFTUtils allExercises.
69
Added:
selectedExercise := allExercises
70
Added:
detect: [ :each |
71
Added:
each englishName = exercise englishName ]
72
Added:
ifNone: [ nil ].
99
73
html formGroup: [
100
74
html label: 'Exercise'.
101
Removed:
html formGroup: [ "html label: 'Filter exercises'.
102
Removed:
html textInput
103
Removed:
class: 'form-control';
104
Removed:
placeholder: 'Type to search...';
105
Removed:
callback: [ :value | currentFilter := value ];
106
Removed:
onKeyUp:
107
Removed:
(html jQuery this load html: [ :h |
108
Removed:
self renderFilteredExercisesOn: h ]) "
109
Removed:
html select formControl
110
Removed:
list: MFTUtils allExercises;
111
Removed:
selected: selectedExercise;
112
Removed:
labels: [ :each | each englishName ];
113
Removed:
callback: [ :value | selectedExercise := value ] ] ]
75
Added:
html select formControl
76
Added:
list: allExercises;
77
Added:
selected: selectedExercise;
78
Added:
callback: [ :value | exercise := value ];
79
Added:
labels: [ :each | each englishName ] ]
114
80
]
115
81
116
82
{ #category : #rendering }
117
Removed:
MFTExerciseDialog >> renderFilteredExercisesOn: html [
118
Removed:
119
Removed:
html unorderedList: [
120
Removed:
self filteredExercises do: [ :eachExercise |
121
Removed:
html listItem: eachExercise englishName ] ]
122
Removed:
]
123
Removed:
124
Removed:
{ #category : #rendering }
125
83
MFTExerciseDialog >> renderSetsRowsOn: html [
126
84
"TODO: something fishy is going on here. Why are reps and rpe instantiated as nil, but become the empty string after adding additional empty sets?"
127
85
@@ -130,23 +88,24 @@
130
88
html tableData: [
131
89
html buttonGroup: [
132
90
html outlineButton
133
Removed:
beSecondary;
91
Added:
beDanger;
134
92
beSmall;
135
93
callback: [ sets removeAt: i ];
136
94
with: 'Remove'.
137
95
html outlineButton
138
96
beSecondary;
139
97
beSmall;
140
Removed:
callback: [ sets add: set afterIndex: i ];
98
Added:
callback: [
99
Added:
sets add: (MFTSet reps: set reps rpe: set rpe) afterIndex: i ];
141
100
with: 'Duplicate' ] ].
142
101
html tableData: [
143
102
html numberInput
144
103
value: set reps;
145
Removed:
callback: [ :value | value ifNotNil: [ set reps: value ] ] ].
104
Added:
callback: [ :value | set reps: value ] ].
146
105
html tableData: [
147
106
html numberInput
148
107
value: set rpe;
149
Removed:
callback: [ :value | value ifNotNil: [ set rpe: value ] ] ] ] ]
108
Added:
callback: [ :value | set rpe: value ] ] ] ]
150
109
]
151
110
152
111
{ #category : #rendering }
@@ -162,26 +121,20 @@
162
121
self renderAddSetRowOn: html ] ]
163
122
]
164
123
165
Removed:
{ #category : #rendering }
166
Removed:
MFTExerciseDialog >> renderSubmitExerciseOn: html [
124
Added:
{ #category : #delegation }
125
Added:
MFTExerciseDialog >> renderSubmitOn: html [
167
126
168
Removed:
html formGroup: [ "html text: (sets collect: #reps).
169
Removed:
html break.
170
Removed:
html text: (sets collect: #rpe)."
171
Removed:
html buttonGroup: [
172
Removed:
html formButton
173
Removed:
bePrimary;
174
Removed:
beSubmit;
175
Removed:
callback: [
176
Removed:
sets removeAllSuchThat: [ :set |
177
Removed:
set reps isNil or: [ set reps = '' ] ].
178
Removed:
exercise := selectedExercise sets: sets.
179
Removed:
self answer: exercise ];
180
Removed:
with: 'Submit'.
181
Removed:
html formButton
182
Removed:
beSecondary;
183
Removed:
callback: [ self answer: nil ];
184
Removed:
with: 'Cancel' ] ]
127
Added:
html buttonGroup: [
128
Added:
html formButton
129
Added:
beSubmit;
130
Added:
bePrimary;
131
Added:
callback: [ self answer: (exercise sets: sets) ];
132
Added:
with: (completion ifNil: [ 'Submit' ] ifNotNil: [ 'Next' ]).
133
Added:
html formButton
134
Added:
beSubmit;
135
Added:
beSecondary;
136
Added:
callback: [ self answer: nil ];
137
Added:
with: (completion ifNil: [ 'Cancel' ] ifNotNil: [ 'Skip' ]) ]
185
138
]
186
139
187
140
{ #category : #rendering }
@@ -192,18 +145,6 @@
192
145
tableHeading;
193
146
tableHeading: 'Reps';
194
147
tableHeading: 'RPE' ]
195
Removed:
]
196
Removed:
197
Removed:
{ #category : #accessing }
198
Removed:
MFTExerciseDialog >> selectedExercise [
199
Removed:
200
Removed:
^ selectedExercise
201
Removed:
]
202
Removed:
203
Removed:
{ #category : #accessing }
204
Removed:
MFTExerciseDialog >> selectedExercise: aMFTExercise [
205
Removed:
206
Removed:
selectedExercise := aMFTExercise
207
148
]
208
149
209
150
{ #category : #accessing }
src/MyFitnessTracker/MFTExercisesDialog.class.st
@@ -0,0 +1,131 @@
1
Added:
Class {
2
Added:
#name : #MFTExercisesDialog,
3
Added:
#superclass : #MFTDialog,
4
Added:
#instVars : [
5
Added:
'exercises'
6
Added:
],
7
Added:
#category : #'MyFitnessTracker-Dialogs'
8
Added:
}
9
Added:
10
Added:
{ #category : #adding }
11
Added:
MFTExercisesDialog >> addExercise [
12
Added:
13
Added:
| exercise |
14
Added:
exercise := self call: MFTExerciseDialog new.
15
Added:
exercise ifNotNil: [ exercises add: exercise ]
16
Added:
]
17
Added:
18
Added:
{ #category : #accessing }
19
Added:
MFTExercisesDialog >> editExerciseAt: i [
20
Added:
21
Added:
| oldExercise newExercise |
22
Added:
oldExercise := exercises at: i.
23
Added:
newExercise := self call: (MFTExerciseDialog edit: oldExercise).
24
Added:
newExercise ifNotNil: [ exercises at: i put: newExercise ]
25
Added:
]
26
Added:
27
Added:
{ #category : #accessing }
28
Added:
MFTExercisesDialog >> exercises [
29
Added:
30
Added:
^ exercises
31
Added:
]
32
Added:
33
Added:
{ #category : #accessing }
34
Added:
MFTExercisesDialog >> exercises: aCollection [
35
Added:
36
Added:
exercises := aCollection
37
Added:
]
38
Added:
39
Added:
{ #category : #initialization }
40
Added:
MFTExercisesDialog >> initialize [
41
Added:
42
Added:
super initialize.
43
Added:
exercises := OrderedCollection new
44
Added:
]
45
Added:
46
Added:
{ #category : #rendering }
47
Added:
MFTExercisesDialog >> renderAddExerciseRowOn: html [
48
Added:
49
Added:
html tableRow: [
50
Added:
html tableData: [
51
Added:
html outlineButton
52
Added:
bePrimary;
53
Added:
beSmall;
54
Added:
callback: [ self addExercise ];
55
Added:
with: 'Add'.
56
Added:
html
57
Added:
tableData;
58
Added:
tableData.
59
Added:
((exercises collect: #sets) anySatisfy: #isNotEmpty) ifTrue: [
60
Added:
html tableData ] ] ]
61
Added:
]
62
Added:
63
Added:
{ #category : #rendering }
64
Added:
MFTExercisesDialog >> renderContentOn: html [
65
Added:
66
Added:
self renderDialogOn: html with: [
67
Added:
html table
68
Added:
class: 'table table-hover';
69
Added:
with: [
70
Added:
exercises ifNotEmpty: [
71
Added:
self renderTableHeaderOn: html.
72
Added:
self renderExercisesRowsOn: html ].
73
Added:
self renderAddExerciseRowOn: html ] ]
74
Added:
]
75
Added:
76
Added:
{ #category : #rendering }
77
Added:
MFTExercisesDialog >> renderExerciseActionsButtonGroupOn: html at: i [
78
Added:
79
Added:
html buttonGroup: [
80
Added:
html outlineButton
81
Added:
beSecondary;
82
Added:
beSmall;
83
Added:
callback: [ exercises removeAt: i ];
84
Added:
with: 'Delete'.
85
Added:
html outlineButton
86
Added:
beSecondary;
87
Added:
beSmall;
88
Added:
callback: [ self editExerciseAt: i ];
89
Added:
with: 'Edit' ]
90
Added:
]
91
Added:
92
Added:
{ #category : #rendering }
93
Added:
MFTExercisesDialog >> renderExercisesRowsOn: html [
94
Added:
95
Added:
exercises doWithIndex: [ :exercise :i |
96
Added:
html tableRow: [
97
Added:
html tableData: [
98
Added:
self renderExerciseActionsButtonGroupOn: html at: i ].
99
Added:
html tableData: exercise englishName.
100
Added:
html tableData: exercise primaryMuscle englishName.
101
Added:
((exercises collect: #sets) anySatisfy: #isNotEmpty) ifTrue: [
102
Added:
html tableData: exercise repsBySet asCommaString ] ] ]
103
Added:
]
104
Added:
105
Added:
{ #category : #rendering }
106
Added:
MFTExercisesDialog >> renderSubmitOn: html [
107
Added:
108
Added:
html buttonGroup: [
109
Added:
html formButton
110
Added:
beSubmit;
111
Added:
bePrimary;
112
Added:
callback: [ self answer: exercises ];
113
Added:
with: (completion ifNil: [ 'Submit' ] ifNotNil: [ 'Next' ]).
114
Added:
html formButton
115
Added:
beSubmit;
116
Added:
beSecondary;
117
Added:
callback: [ self answer: OrderedCollection new ];
118
Added:
with: (completion ifNil: [ 'Cancel' ] ifNotNil: [ 'Skip' ]) ]
119
Added:
]
120
Added:
121
Added:
{ #category : #rendering }
122
Added:
MFTExercisesDialog >> renderTableHeaderOn: html [
123
Added:
124
Added:
html tableHead: [
125
Added:
html
126
Added:
tableHeading;
127
Added:
tableHeading: 'Exercise';
128
Added:
tableHeading: 'Primary Muscle'.
129
Added:
((exercises collect: #sets) anySatisfy: #isNotEmpty) ifTrue: [
130
Added:
html tableHeading: 'Sets' ] ]
131
Added:
]
src/MyFitnessTracker/MFTPrimaryMuscleDialog.class.st
@@ -0,0 +1,62 @@
1
Added:
Class {
2
Added:
#name : #MFTPrimaryMuscleDialog,
3
Added:
#superclass : #MFTDialog,
4
Added:
#instVars : [
5
Added:
'primaryMuscle'
6
Added:
],
7
Added:
#category : #'MyFitnessTracker-Dialogs'
8
Added:
}
9
Added:
10
Added:
{ #category : #initialization }
11
Added:
MFTPrimaryMuscleDialog >> initialize [
12
Added:
13
Added:
super initialize.
14
Added:
primaryMuscle := MFTMuscle new
15
Added:
]
16
Added:
17
Added:
{ #category : #accessing }
18
Added:
MFTPrimaryMuscleDialog >> primaryMuscle [
19
Added:
20
Added:
^ primaryMuscle
21
Added:
]
22
Added:
23
Added:
{ #category : #accessing }
24
Added:
MFTPrimaryMuscleDialog >> primaryMuscle: anObject [
25
Added:
26
Added:
primaryMuscle := anObject
27
Added:
]
28
Added:
29
Added:
{ #category : #rendering }
30
Added:
MFTPrimaryMuscleDialog >> renderContentOn: html [
31
Added:
32
Added:
| allMuscles selectedMuscle |
33
Added:
allMuscles := MFTUtils allMuscleGroups.
34
Added:
selectedMuscle := allMuscles
35
Added:
detect: [ :each |
36
Added:
each englishName = primaryMuscle englishName ]
37
Added:
ifNone: [ nil ].
38
Added:
39
Added:
self renderDialogOn: html with: [
40
Added:
html formGroup: [
41
Added:
html select formControl
42
Added:
list: allMuscles;
43
Added:
selected: selectedMuscle;
44
Added:
labels: [ :muscleGroup | muscleGroup englishName ];
45
Added:
callback: [ :group | component := group ] ] ]
46
Added:
]
47
Added:
48
Added:
{ #category : #rendering }
49
Added:
MFTPrimaryMuscleDialog >> renderSubmitOn: html [
50
Added:
51
Added:
html buttonGroup: [
52
Added:
html formButton
53
Added:
beSubmit;
54
Added:
bePrimary;
55
Added:
callback: [ self answer: primaryMuscle ];
56
Added:
with: (completion ifNil: [ 'Submit' ] ifNotNil: [ 'Next' ]).
57
Added:
html formButton
58
Added:
beSubmit;
59
Added:
beSecondary;
60
Added:
callback: [ self answer: MFTMuscle new ];
61
Added:
with: (completion ifNil: [ 'Cancel' ] ifNotNil: [ 'Skip' ]) ]
62
Added:
]
src/MyFitnessTracker/MFTSecondaryMusclesDialog.class.st
@@ -0,0 +1,63 @@
1
Added:
Class {
2
Added:
#name : #MFTSecondaryMusclesDialog,
3
Added:
#superclass : #MFTDialog,
4
Added:
#instVars : [
5
Added:
'secondaryMuscles'
6
Added:
],
7
Added:
#category : #'MyFitnessTracker-Dialogs'
8
Added:
}
9
Added:
10
Added:
{ #category : #initialization }
11
Added:
MFTSecondaryMusclesDialog >> initialize [
12
Added:
13
Added:
super initialize.
14
Added:
secondaryMuscles := OrderedCollection with: MFTMuscle new
15
Added:
]
16
Added:
17
Added:
{ #category : #rendering }
18
Added:
MFTSecondaryMusclesDialog >> renderContentOn: html [
19
Added:
20
Added:
| allMuscles selectedMuscles |
21
Added:
allMuscles := MFTUtils allMuscleGroups.
22
Added:
"selectedMuscles := allMuscles
23
Added:
detect: [ :each |
24
Added:
each englishName
25
Added:
= (secondaryMuscles collect: #englishName) ]
26
Added:
ifNone: [ nil ]."
27
Added:
28
Added:
self renderDialogOn: html with: [
29
Added:
html multiSelect formControl
30
Added:
list: allMuscles;
31
Added:
"selected: selectedMuscles;"labels: [ :muscleGroup |
32
Added:
muscleGroup englishName ];
33
Added:
callback: [ :groups |
34
Added:
groups ifNotEmpty: [ secondaryMuscles := groups ] ] ]
35
Added:
]
36
Added:
37
Added:
{ #category : #rendering }
38
Added:
MFTSecondaryMusclesDialog >> renderSubmitOn: html [
39
Added:
40
Added:
html buttonGroup: [
41
Added:
html formButton
42
Added:
beSubmit;
43
Added:
bePrimary;
44
Added:
callback: [ self answer: secondaryMuscles ];
45
Added:
with: (completion ifNil: [ 'Submit' ] ifNotNil: [ 'Next' ]).
46
Added:
html formButton
47
Added:
beSubmit;
48
Added:
beSecondary;
49
Added:
callback: [ self answer: OrderedCollection new ];
50
Added:
with: (completion ifNil: [ 'Cancel' ] ifNotNil: [ 'Skip' ]) ]
51
Added:
]
52
Added:
53
Added:
{ #category : #accessing }
54
Added:
MFTSecondaryMusclesDialog >> secondaryMuscles [
55
Added:
56
Added:
^ secondaryMuscles
57
Added:
]
58
Added:
59
Added:
{ #category : #accessing }
60
Added:
MFTSecondaryMusclesDialog >> secondaryMuscles: anObject [
61
Added:
62
Added:
secondaryMuscles := anObject
63
Added:
]
src/MyFitnessTracker/MFTStringDialog.class.st
@@ -0,0 +1,55 @@
1
Added:
Class {
2
Added:
#name : #MFTStringDialog,
3
Added:
#superclass : #MFTDialog,
4
Added:
#instVars : [
5
Added:
'string'
6
Added:
],
7
Added:
#category : #'MyFitnessTracker-Dialogs'
8
Added:
}
9
Added:
10
Added:
{ #category : #actions }
11
Added:
MFTStringDialog class >> edit: aString [
12
Added:
13
Added:
^ self new
14
Added:
string: aString;
15
Added:
yourself
16
Added:
]
17
Added:
18
Added:
{ #category : #initialization }
19
Added:
MFTStringDialog >> initialize [
20
Added:
21
Added:
super initialize.
22
Added:
string := String new
23
Added:
]
24
Added:
25
Added:
{ #category : #rendering }
26
Added:
MFTStringDialog >> renderContentOn: html [
27
Added:
28
Added:
self renderDialogOn: html with: [
29
Added:
html textInput formControl
30
Added:
value: string;
31
Added:
callback: [ :value | string := value ] ]
32
Added:
]
33
Added:
34
Added:
{ #category : #rendering }
35
Added:
MFTStringDialog >> renderSubmitOn: html [
36
Added:
37
Added:
html buttonGroup: [
38
Added:
html formButton
39
Added:
beSubmit;
40
Added:
bePrimary;
41
Added:
callback: [ self answer: string ];
42
Added:
with: (completion ifNil: [ 'Submit' ] ifNotNil: [ 'Next' ]) ]
43
Added:
]
44
Added:
45
Added:
{ #category : #accessing }
46
Added:
MFTStringDialog >> string [
47
Added:
48
Added:
^ string
49
Added:
]
50
Added:
51
Added:
{ #category : #accessing }
52
Added:
MFTStringDialog >> string: anObject [
53
Added:
54
Added:
string := anObject
55
Added:
]
src/MyFitnessTracker/MFTWeightDialog.class.st
@@ -7,64 +7,54 @@
7
7
#category : #'MyFitnessTracker-Dialogs'
8
8
}
9
9
10
Added:
{ #category : #actions }
11
Added:
MFTWeightDialog class >> edit: aMFTWeight [
12
Added:
13
Added:
^ self new
14
Added:
action: #edit;
15
Added:
weight: aMFTWeight;
16
Added:
yourself
17
Added:
]
18
Added:
10
19
{ #category : #initialization }
11
20
MFTWeightDialog >> initialize [
12
21
13
22
super initialize.
14
Removed:
weight := MFTWeight new.
15
Removed:
addOrEdit := #add
23
Added:
weight := MFTWeight new
16
24
]
17
25
18
26
{ #category : #rendering }
19
27
MFTWeightDialog >> renderContentOn: html [
20
28
21
29
self renderDialogOn: html with: [
22
Removed:
html heading: self addOrEdit asCapitalizedPhrase , ' weight'.
23
Removed:
html form with: [
24
Removed:
self renderDateInputOn: html.
25
Removed:
self renderWeightInputOn: html.
26
Removed:
self renderSubmitWeightOn: html ] ]
30
Added:
html formGroup: [
31
Added:
html label: 'Date'.
32
Added:
html dateInput5 formControl
33
Added:
value: weight date yyyymmdd;
34
Added:
callback: [ :value | weight date: (Date fromString: value) ] ].
35
Added:
html formGroup: [
36
Added:
html label: 'Weight'.
37
Added:
html numberInput formControl
38
Added:
placeholder: weight value;
39
Added:
callback: [ :value | weight value: value ] ] ]
27
40
]
28
41
29
42
{ #category : #rendering }
30
Removed:
MFTWeightDialog >> renderDateInputOn: html [
43
Added:
MFTWeightDialog >> renderSubmitOn: html [
31
44
32
Removed:
html formGroup: [
33
Removed:
html label: 'Date'.
34
Removed:
html dateInput5 formControl
35
Removed:
value: weight date yyyymmdd;
36
Removed:
callback: [ :date | weight date: (Date fromString: date) ] ]
45
Added:
html buttonGroup: [
46
Added:
html formButton
47
Added:
beSubmit;
48
Added:
bePrimary;
49
Added:
callback: [ self answer: weight ];
50
Added:
with: (completion ifNil: [ 'Submit' ] ifNotNil: [ 'Next' ]).
51
Added:
html formButton
52
Added:
beSubmit;
53
Added:
beSecondary;
54
Added:
callback: [ self answer: nil ];
55
Added:
with: (completion ifNil: [ 'Cancel' ] ifNotNil: [ 'Skip' ]) ]
37
56
]
38
57
39
Removed:
{ #category : #rendering }
40
Removed:
MFTWeightDialog >> renderSubmitWeightOn: html [
41
Removed:
42
Removed:
html buttonGroup
43
Removed:
class: 'mt-3';
44
Removed:
with: [
45
Removed:
html formButton
46
Removed:
bePrimary;
47
Removed:
beSubmit;
48
Removed:
callback: [ self answer: weight ];
49
Removed:
with: 'Submit'.
50
Removed:
html formButton
51
Removed:
beSecondary;
52
Removed:
callback: [ self answer: nil ];
53
Removed:
with: 'Cancel' ]
54
Removed:
]
55
Removed:
56
Removed:
{ #category : #rendering }
57
Removed:
MFTWeightDialog >> renderWeightInputOn: html [
58
Removed:
59
Removed:
html formGroup: [
60
Removed:
html label: 'Weight'.
61
Removed:
html textInput
62
Removed:
formControl;
63
Removed:
placeholder: weight value;
64
Removed:
callback: [ :value | weight value: value ];
65
Removed:
with: weight value ]
66
Removed:
]
67
Removed:
68
58
{ #category : #accessing }
69
59
MFTWeightDialog >> weight [
70
60
@@ -72,7 +62,7 @@
72
62
]
73
63
74
64
{ #category : #accessing }
75
Removed:
MFTWeightDialog >> weight: anObject [
65
Added:
MFTWeightDialog >> weight: aMFTWeight [
76
66
77
Removed:
weight := anObject
67
Added:
weight := aMFTWeight
78
68
]
src/MyFitnessTracker/MFTWorkoutDialog.class.st
@@ -1,196 +0,0 @@
1
Removed:
Class {
2
Removed:
#name : #MFTWorkoutDialog,
3
Removed:
#superclass : #MFTDialog,
4
Removed:
#instVars : [
5
Removed:
'workout',
6
Removed:
'exercises'
7
Removed:
],
8
Removed:
#category : #'MyFitnessTracker-Dialogs'
9
Removed:
}
10
Removed:
11
Removed:
{ #category : #adding }
12
Removed:
MFTWorkoutDialog >> addExercise [
13
Removed:
14
Removed:
| exercise |
15
Removed:
exercise := self call: MFTExerciseDialog new.
16
Removed:
exercise ifNotNil: [ exercises add: exercise ]
17
Removed:
]
18
Removed:
19
Removed:
{ #category : #'as yet unclassified' }
20
Removed:
MFTWorkoutDialog >> editExerciseAt: i [
21
Removed:
22
Removed:
| oldExercise newExercise |
23
Removed:
oldExercise := exercises at: i.
24
Removed:
newExercise := self call: (MFTExerciseDialog edit: oldExercise).
25
Removed:
newExercise ifNotNil: [ exercises at: i put: newExercise ]
26
Removed:
]
27
Removed:
28
Removed:
{ #category : #accessing }
29
Removed:
MFTWorkoutDialog >> exercises [
30
Removed:
31
Removed:
^ exercises
32
Removed:
]
33
Removed:
34
Removed:
{ #category : #accessing }
35
Removed:
MFTWorkoutDialog >> exercises: anObject [
36
Removed:
37
Removed:
exercises := anObject
38
Removed:
]
39
Removed:
40
Removed:
{ #category : #initialization }
41
Removed:
MFTWorkoutDialog >> initialize [
42
Removed:
43
Removed:
super initialize.
44
Removed:
workout := MFTWorkout new.
45
Removed:
exercises := OrderedCollection new.
46
Removed:
addOrEdit := #add
47
Removed:
]
48
Removed:
49
Removed:
{ #category : #rendering }
50
Removed:
MFTWorkoutDialog >> renderAddExerciseButtonOn: html [
51
Removed:
52
Removed:
html outlineButton
53
Removed:
bePrimary;
54
Removed:
beSmall;
55
Removed:
callback: [ self addExercise ];
56
Removed:
with: 'Add'
57
Removed:
]
58
Removed:
59
Removed:
{ #category : #rendering }
60
Removed:
MFTWorkoutDialog >> renderAddExerciseRowOn: html [
61
Removed:
62
Removed:
html tableRow: [
63
Removed:
html tableData: [ self renderAddExerciseButtonOn: html ].
64
Removed:
1 to: 3 do: [ :each | html tableData ] ]
65
Removed:
]
66
Removed:
67
Removed:
{ #category : #rendering }
68
Removed:
MFTWorkoutDialog >> renderContentOn: html [
69
Removed:
70
Removed:
self renderDialogOn: html with: [
71
Removed:
html heading: self addOrEdit asCapitalizedPhrase , ' workout'.
72
Removed:
html form: [
73
Removed:
self renderDateInputOn: html.
74
Removed:
self renderExercisesTableOn: html.
75
Removed:
self renderPrimaryMuscleSelectOn: html.
76
Removed:
"TODO: use the workout guessPrimaryMuscle."
77
Removed:
self renderSecondaryMusclesSelectOn: html.
78
Removed:
self renderSubmitWorkoutOn: html ] ]
79
Removed:
]
80
Removed:
81
Removed:
{ #category : #rendering }
82
Removed:
MFTWorkoutDialog >> renderDateInputOn: html [
83
Removed:
84
Removed:
html formGroup: [
85
Removed:
html label: 'Date'.
86
Removed:
html dateInput5 formControl
87
Removed:
value: workout date yyyymmdd;
88
Removed:
callback: [ :date | workout date: (Date fromString: date) ] ]
89
Removed:
]
90
Removed:
91
Removed:
{ #category : #rendering }
92
Removed:
MFTWorkoutDialog >> renderExerciseActionsButtonGroupOn: html at: i [
93
Removed:
94
Removed:
html buttonGroup: [
95
Removed:
html outlineButton
96
Removed:
beSecondary;
97
Removed:
beSmall;
98
Removed:
callback: [ exercises removeAt: i ];
99
Removed:
with: 'Delete'.
100
Removed:
html outlineButton
101
Removed:
beSecondary;
102
Removed:
beSmall;
103
Removed:
callback: [ self editExerciseAt: i ];
104
Removed:
with: 'Edit' ]
105
Removed:
]
106
Removed:
107
Removed:
{ #category : #rendering }
108
Removed:
MFTWorkoutDialog >> renderExercisesRowsOn: html [
109
Removed:
110
Removed:
exercises doWithIndex: [ :exercise :i |
111
Removed:
html tableRow: [
112
Removed:
html tableData: [
113
Removed:
self renderExerciseActionsButtonGroupOn: html at: i ].
114
Removed:
html tableData: exercise englishName.
115
Removed:
html tableData: exercise primaryMuscle englishName.
116
Removed:
html tableData: exercise repsBySet asCommaString ] ]
117
Removed:
]
118
Removed:
119
Removed:
{ #category : #rendering }
120
Removed:
MFTWorkoutDialog >> renderExercisesTableOn: html [
121
Removed:
122
Removed:
html formGroup: [
123
Removed:
html label: 'Exercises'.
124
Removed:
html table
125
Removed:
class: 'table table-hover';
126
Removed:
with: [
127
Removed:
exercises isNotEmpty ifTrue: [ self renderTableHeaderOn: html ].
128
Removed:
self renderExercisesRowsOn: html.
129
Removed:
self renderAddExerciseRowOn: html ] ]
130
Removed:
]
131
Removed:
132
Removed:
{ #category : #rendering }
133
Removed:
MFTWorkoutDialog >> renderPrimaryMuscleSelectOn: html [
134
Removed:
"TODO: use the workout guessPrimaryMuscle."
135
Removed:
136
Removed:
html formGroup: [
137
Removed:
html label: 'Primary muscle'.
138
Removed:
html select formControl
139
Removed:
list: MFTUtils allMuscleGroups;
140
Removed:
selected: workout primaryMuscle;
141
Removed:
labels: [ :muscleGroup | muscleGroup englishName ];
142
Removed:
callback: [ :group | workout primaryMuscle: group ] ]
143
Removed:
]
144
Removed:
145
Removed:
{ #category : #rendering }
146
Removed:
MFTWorkoutDialog >> renderSecondaryMusclesSelectOn: html [
147
Removed:
148
Removed:
html formGroup: [
149
Removed:
html label: 'Secondary muscles'.
150
Removed:
html multiSelect formControl
151
Removed:
list: MFTUtils allMuscleGroups;
152
Removed:
selected: workout secondaryMuscles;
153
Removed:
labels: [ :muscleGroup | muscleGroup englishName ];
154
Removed:
callback: [ :groups | workout secondaryMuscles: groups ] ]
155
Removed:
]
156
Removed:
157
Removed:
{ #category : #rendering }
158
Removed:
MFTWorkoutDialog >> renderSubmitWorkoutOn: html [
159
Removed:
160
Removed:
html buttonGroup
161
Removed:
class: 'mt-3';
162
Removed:
with: [
163
Removed:
html formButton
164
Removed:
bePrimary;
165
Removed:
beSubmit;
166
Removed:
callback: [ self answer: (workout exercises: exercises) ];
167
Removed:
with: 'Submit'.
168
Removed:
html formButton
169
Removed:
beSecondary;
170
Removed:
callback: [ self answer: nil ];
171
Removed:
with: 'Cancel' ]
172
Removed:
]
173
Removed:
174
Removed:
{ #category : #rendering }
175
Removed:
MFTWorkoutDialog >> renderTableHeaderOn: html [
176
Removed:
177
Removed:
html tableHead: [
178
Removed:
html
179
Removed:
tableHeading;
180
Removed:
tableHeading: 'Name';
181
Removed:
tableHeading: 'Muscles'.
182
Removed:
((exercises collect: #sets) anySatisfy: #isNotEmpty) ifTrue: [
183
Removed:
html tableHeading: 'Sets' ] ]
184
Removed:
]
185
Removed:
186
Removed:
{ #category : #accessing }
187
Removed:
MFTWorkoutDialog >> workout [
188
Removed:
189
Removed:
^ workout
190
Removed:
]
191
Removed:
192
Removed:
{ #category : #accessing }
193
Removed:
MFTWorkoutDialog >> workout: aMFTWorkout [
194
Removed:
195
Removed:
workout := aMFTWorkout
196
Removed:
]