Add workout logbook viewer.

Commit
b2f126e1a4bc02537173e46908d1dc7841bcc980
Author
Marius Peter <dev@marius-peter.com>
Author date
Committer
Marius Peter <dev@marius-peter.com>
Committer date
Changed files
src/MyFitnessTracker-Web/MFTHomePage.class.st
index 20f39405..a914debe 100644..100644
@@ -3,8 +3,9 @@
3 3 #superclass : 'MFTPage',
4 4 #instVars : [
5 5 'statusComponent',
6 Added: 'homePageActionsComponent',
6 7 'nextWorkoutComponent',
7 Removed: 'homePageActionsComponent'
8 Added: 'previousWorkoutLogsComponent'
8 9 ],
9 10 #category : 'MyFitnessTracker-Web-Components',
10 11 #package : 'MyFitnessTracker-Web',
@@ -23,11 +24,14 @@
23 24 { #category : 'initialization' }
24 25 MFTHomePage >> initialize [
25 26
27 Added: | trainee |
28 Added: trainee := self session user trainee.
29 Added:
26 30 super initialize.
27 31 statusComponent := MFTStatusComponent new.
28 32 homePageActionsComponent := MFTMainActionsComponent new
29 33 onLogWorkout: [
30 Removed: | trainee workoutLog |
34 Added: | workoutLog |
31 35 trainee := self session user trainee.
32 36 workoutLog := self call:
33 37 (MFTWorkoutLogEditorPage
@@ -38,7 +42,10 @@
38 42 trainee logWorkout: workoutLog ] ];
39 43 yourself.
40 44 nextWorkoutComponent := MFTWorkoutPrescriptionViewerComponent new
41 Removed: heading: 'Next workout'
45 Added: heading: 'Next workout'.
46 Added: previousWorkoutLogsComponent := MFTLogBookViewerComponent new
47 Added: logBook: trainee logBook;
48 Added: heading: 'Previous workouts'
42 49 ]
43 50
44 51 { #category : 'rendering' }
@@ -56,7 +63,8 @@
56 63 html
57 64 render: statusComponent;
58 65 render: homePageActionsComponent;
59 Removed: render: nextWorkoutComponent ]
66 Added: render: nextWorkoutComponent;
67 Added: render: previousWorkoutLogsComponent ]
60 68 ]
61 69
62 70 { #category : 'accessing' }
src/MyFitnessTracker-Web/MFTLogBookViewerComponent.class.st
index 00000000..dc3b93ba 000000..100644
@@ -0,0 +1,55 @@
1 Added: Class {
2 Added: #name : 'MFTLogBookViewerComponent',
3 Added: #superclass : 'WAComponent',
4 Added: #instVars : [
5 Added: 'logBook',
6 Added: 'logBookItemComponents',
7 Added: 'heading'
8 Added: ],
9 Added: #category : 'MyFitnessTracker-Web-Components',
10 Added: #package : 'MyFitnessTracker-Web',
11 Added: #tag : 'Components'
12 Added: }
13 Added:
14 Added: { #category : 'accessing' }
15 Added: MFTLogBookViewerComponent class >> forLogBook: aMFTWorkoutLogBook [
16 Added:
17 Added: ^ self new logBook: aMFTWorkoutLogBook
18 Added: ]
19 Added:
20 Added: { #category : 'rendering' }
21 Added: MFTLogBookViewerComponent >> children [
22 Added:
23 Added: ^ logBookItemComponents
24 Added: ]
25 Added:
26 Added: { #category : 'rendering' }
27 Added: MFTLogBookViewerComponent >> heading: aString [
28 Added:
29 Added: heading := aString
30 Added: ]
31 Added:
32 Added: { #category : 'rendering' }
33 Added: MFTLogBookViewerComponent >> initialize [
34 Added:
35 Added: super initialize
36 Added: ]
37 Added:
38 Added: { #category : 'accessing' }
39 Added: MFTLogBookViewerComponent >> logBook: aMFTWorkoutLogBook [
40 Added:
41 Added: logBook := aMFTWorkoutLogBook.
42 Added: ]
43 Added:
44 Added: { #category : 'rendering' }
45 Added: MFTLogBookViewerComponent >> renderContentOn: html [
46 Added:
47 Added: logBookItemComponents := logBook workoutLogs collect: [ :each |
48 Added: MFTWorkoutLogViewerComponent
49 Added: forWorkoutLog: each ].
50 Added:
51 Added: html heading
52 Added: level: 2;
53 Added: with: heading.
54 Added: logBookItemComponents do: [ :each | html render: each ]
55 Added: ]
src/MyFitnessTracker-Web/MFTSetGroupLogEditorComponent.class.st
index 9f10068f..9d0e58f0 100644..100644
@@ -28,7 +28,7 @@
28 28 with: 'Save' ]
29 29 ]
30 30
31 Removed: { #category : 'rendering' }
31 Added: { #category : 'as yet unclassified' }
32 32 MFTSetGroupLogEditorComponent >> renderSetLogEditorOn: html setLog: setLog [
33 33
34 34 html heading
src/MyFitnessTracker-Web/MFTSetGroupLogViewerComponent.class.st
index f3caf2e3..6673faa2 100644..100644
@@ -2,7 +2,8 @@
2 2 #name : 'MFTSetGroupLogViewerComponent',
3 3 #superclass : 'WAComponent',
4 4 #instVars : [
5 Removed: 'setGroupLog'
5 Added: 'setGroupLog',
6 Added: 'isEditable'
6 7 ],
7 8 #category : 'MyFitnessTracker-Web-Components',
8 9 #package : 'MyFitnessTracker-Web',
@@ -18,6 +19,25 @@
18 19 ]
19 20
20 21 { #category : 'rendering' }
22 Added: MFTSetGroupLogViewerComponent >> beEditable [
23 Added:
24 Added: isEditable := true
25 Added: ]
26 Added:
27 Added: { #category : 'rendering' }
28 Added: MFTSetGroupLogViewerComponent >> initialize [
29 Added:
30 Added: super initialize.
31 Added: isEditable := false
32 Added: ]
33 Added:
34 Added: { #category : 'rendering' }
35 Added: MFTSetGroupLogViewerComponent >> isEditable [
36 Added:
37 Added: isEditable
38 Added: ]
39 Added:
40 Added: { #category : 'rendering' }
21 41 MFTSetGroupLogViewerComponent >> renderContentOn: html [
22 42
23 43 | completelyLogged buttonLabel |
@@ -30,14 +50,15 @@
30 50 completelyLogged
31 51 ifTrue: [ self renderSetGroupLogDataOn: html ]
32 52 ifFalse: [ self renderSetGroupLogExercisesOn: html ].
33 Removed: html anchor
34 Removed: callback: [
35 Removed: | editedLog |
36 Removed: editedLog := self call:
37 Removed: (MFTSetGroupLogEditorComponent forSetGroupLog:
38 Removed: setGroupLog).
39 Removed: editedLog ifNotNil: [ setGroupLog := editedLog ] ];
40 Removed: with: buttonLabel ]
53 Added: isEditable ifTrue: [
54 Added: html anchor
55 Added: callback: [
56 Added: | editedLog |
57 Added: editedLog := self call:
58 Added: (MFTSetGroupLogEditorComponent forSetGroupLog:
59 Added: setGroupLog).
60 Added: editedLog ifNotNil: [ setGroupLog := editedLog ] ];
61 Added: with: buttonLabel ] ]
41 62 ]
42 63
43 64 { #category : 'rendering' }
src/MyFitnessTracker-Web/MFTStatusComponent.class.st
index 0ba7010f..2c4daa96 100644..100644
@@ -14,6 +14,10 @@
14 14
15 15 html section: [
16 16 html definitionList: [
17 Added: trainee logBook durationSinceLastWorkout ifNotNil: [
18 Added: html definitionTerm: 'Hours since last workout'.
19 Added: html definitionData:
20 Added: trainee logBook durationSinceLastWorkout asHours rounded asString ].
17 21 html definitionTerm: 'Recovery status'.
18 22 html definitionData: (trainee isRecovered
19 23 ifTrue: [ 'Ready to train again' ]
src/MyFitnessTracker-Web/MFTWorkoutLogEditorComponent.class.st
index 00000000..fd069536 000000..100644
@@ -0,0 +1,130 @@
1 Added: Class {
2 Added: #name : 'MFTWorkoutLogEditorComponent',
3 Added: #superclass : 'WAComponent',
4 Added: #instVars : [
5 Added: 'workoutLog',
6 Added: 'setGroupLogComponents',
7 Added: 'onSaveWorkout',
8 Added: 'onDiscardWorkout'
9 Added: ],
10 Added: #category : 'MyFitnessTracker-Web-Components',
11 Added: #package : 'MyFitnessTracker-Web',
12 Added: #tag : 'Components'
13 Added: }
14 Added:
15 Added: { #category : 'as yet unclassified' }
16 Added: MFTWorkoutLogEditorComponent class >> forWorkoutLog: aMFTWorkoutLog [
17 Added:
18 Added: ^ self new
19 Added: workoutLog: aMFTWorkoutLog;
20 Added: yourself
21 Added: ]
22 Added:
23 Added: { #category : 'as yet unclassified' }
24 Added: MFTWorkoutLogEditorComponent >> children [
25 Added:
26 Added: ^ setGroupLogComponents
27 Added: ]
28 Added:
29 Added: { #category : 'as yet unclassified' }
30 Added: MFTWorkoutLogEditorComponent >> initialize [
31 Added:
32 Added: super initialize.
33 Added: setGroupLogComponents := OrderedCollection new
34 Added: ]
35 Added:
36 Added: { #category : 'as yet unclassified' }
37 Added: MFTWorkoutLogEditorComponent >> onDiscardWorkout: aBlock [
38 Added:
39 Added: onDiscardWorkout := aBlock
40 Added: ]
41 Added:
42 Added: { #category : 'as yet unclassified' }
43 Added: MFTWorkoutLogEditorComponent >> onSaveWorkout: aBlock [
44 Added:
45 Added: onSaveWorkout := aBlock
46 Added: ]
47 Added:
48 Added: { #category : 'rendering' }
49 Added: MFTWorkoutLogEditorComponent >> renderContentOn: html [
50 Added:
51 Added: html heading
52 Added: level: 1;
53 Added: with: 'Log Workout'.
54 Added: html heading
55 Added: level: 2;
56 Added: with: workoutLog prescription canonicalName.
57 Added: html form: [
58 Added: self renderWorkoutLogMetadataOn: html.
59 Added: setGroupLogComponents do: [ :each | html render: each ].
60 Added: self renderFormActionsOn: html ]
61 Added: ]
62 Added:
63 Added: { #category : 'as yet unclassified' }
64 Added: MFTWorkoutLogEditorComponent >> renderFormActionsOn: html [
65 Added:
66 Added: html submitButton
67 Added: callback: [ onSaveWorkout value ];
68 Added: with: 'Save workout'.
69 Added:
70 Added: html submitButton
71 Added: callback: [ onDiscardWorkout value ];
72 Added: with: 'Discard workout'
73 Added: ]
74 Added:
75 Added: { #category : 'as yet unclassified' }
76 Added: MFTWorkoutLogEditorComponent >> renderWorkoutLogMetadataOn: html [
77 Added:
78 Added: html fieldSet with: [
79 Added: html div
80 Added: class: 'mft-form-items-container';
81 Added: with: [
82 Added: html label
83 Added: for: 'start-date';
84 Added: with: 'Start'.
85 Added: html span: [
86 Added: html dateInput5
87 Added: id: 'start-date';
88 Added: value: Date today yyyymmdd;
89 Added: callback: [ :value |
90 Added: workoutLog startDate:
91 Added: (Date readFrom: value pattern: 'yyyy-mm-dd') ].
92 Added: html timeInput5
93 Added: id: 'start-time';
94 Added: value: workoutLog start asTime print24;
95 Added: callback: [ :value |
96 Added: workoutLog startTime: (Time fromString: value) ] ] ].
97 Added: html div
98 Added: class: 'mft-form-items-container';
99 Added: with: [
100 Added: html label
101 Added: for: 'finish-date';
102 Added: with: 'Finish'.
103 Added: html span: [
104 Added: html dateInput5
105 Added: id: 'finish-date';
106 Added: value: Date today yyyymmdd;
107 Added: callback: [ :value |
108 Added: workoutLog finishDate:
109 Added: (Date readFrom: value pattern: 'yyyy-mm-dd') ].
110 Added: html timeInput5
111 Added: id: 'finish-time';
112 Added: callback: [ :value |
113 Added: value ifNotEmpty: [
114 Added: workoutLog finishTime: (Time fromString: value) ] ] ] ] ]
115 Added: ]
116 Added:
117 Added: { #category : 'accessing' }
118 Added: MFTWorkoutLogEditorComponent >> title [
119 Added:
120 Added: ^ 'Log workout'
121 Added: ]
122 Added:
123 Added: { #category : 'accessing' }
124 Added: MFTWorkoutLogEditorComponent >> workoutLog: aMFTWorkoutLog [
125 Added:
126 Added: workoutLog := aMFTWorkoutLog.
127 Added: setGroupLogComponents := workoutLog setGroups collect: [ :setGroupLog |
128 Added: (MFTSetGroupLogViewerComponent
129 Added: forSetGroupLog: setGroupLog) beEditable ]
130 Added: ]
src/MyFitnessTracker-Web/MFTWorkoutLogEditorPage.class.st
index e2a06d34..fce0bec0 100644..100644
@@ -2,8 +2,8 @@
2 2 #name : 'MFTWorkoutLogEditorPage',
3 3 #superclass : 'MFTPage',
4 4 #instVars : [
5 Removed: 'workoutLog',
6 Removed: 'setGroupLogComponents'
5 Added: 'workoutLogEditorComponent',
6 Added: 'workoutLog'
7 7 ],
8 8 #category : 'MyFitnessTracker-Web-Components',
9 9 #package : 'MyFitnessTracker-Web',
@@ -15,6 +15,8 @@
15 15
16 16 ^ self new
17 17 workoutLog: aMFTWorkoutLog;
18 Added: workoutLogEditorComponent:
19 Added: (MFTWorkoutLogEditorComponent forWorkoutLog: aMFTWorkoutLog);
18 20 yourself
19 21 ]
20 22
@@ -32,86 +34,17 @@
32 34 { #category : 'as yet unclassified' }
33 35 MFTWorkoutLogEditorPage >> children [
34 36
35 Removed: ^ setGroupLogComponents
37 Added: ^ { workoutLogEditorComponent }
36 38 ]
37 39
38 Removed: { #category : 'initialization' }
39 Removed: MFTWorkoutLogEditorPage >> initialize [
40 Removed:
41 Removed: super initialize.
42 Removed: setGroupLogComponents := OrderedCollection new
43 Removed: ]
44 Removed:
45 40 { #category : 'rendering' }
46 41 MFTWorkoutLogEditorPage >> renderContentOn: html [
47 42
48 Removed: self renderPageOn: html with: [
49 Removed: html heading
50 Removed: level: 1;
51 Removed: with: 'Log Workout'.
52 Removed: html heading
53 Removed: level: 2;
54 Removed: with: workoutLog prescription canonicalName.
55 Removed: html form: [
56 Removed: self renderWorkoutLogMetadataOn: html.
57 Removed: setGroupLogComponents do: [ :each | html render: each ].
58 Removed: self renderFormActionsOn: html ] ]
43 Added: self
44 Added: renderPageOn: html
45 Added: with: [ html render: workoutLogEditorComponent ]
59 46 ]
60 47
61 Removed: { #category : 'rendering' }
62 Removed: MFTWorkoutLogEditorPage >> renderFormActionsOn: html [
63 Removed:
64 Removed: html submitButton
65 Removed: callback: [ self answer: workoutLog ];
66 Removed: with: 'Save workout'.
67 Removed:
68 Removed: html submitButton
69 Removed: callback: [ self answer: nil ];
70 Removed: with: 'Discard workout'
71 Removed: ]
72 Removed:
73 Removed: { #category : 'rendering' }
74 Removed: MFTWorkoutLogEditorPage >> renderWorkoutLogMetadataOn: html [
75 Removed:
76 Removed: ^ html fieldSet with: [
77 Removed: html div
78 Removed: class: 'mft-form-items-container';
79 Removed: with: [
80 Removed: html label
81 Removed: for: 'start-date';
82 Removed: with: 'Start'.
83 Removed: html span: [
84 Removed: html dateInput5
85 Removed: id: 'start-date';
86 Removed: value: Date today yyyymmdd;
87 Removed: callback: [ :value |
88 Removed: workoutLog startDate:
89 Removed: (Date readFrom: value pattern: 'yyyy-mm-dd') ].
90 Removed: html timeInput5
91 Removed: id: 'start-time';
92 Removed: value: workoutLog start asTime print24;
93 Removed: callback: [ :value |
94 Removed: workoutLog startTime: (Time fromString: value) ] ] ].
95 Removed: html div
96 Removed: class: 'mft-form-items-container';
97 Removed: with: [
98 Removed: html label
99 Removed: for: 'finish-date';
100 Removed: with: 'Finish'.
101 Removed: html span: [
102 Removed: html dateInput5
103 Removed: id: 'finish-date';
104 Removed: value: Date today yyyymmdd;
105 Removed: callback: [ :value |
106 Removed: workoutLog finishDate:
107 Removed: (Date readFrom: value pattern: 'yyyy-mm-dd') ].
108 Removed: html timeInput5
109 Removed: id: 'finish-time';
110 Removed: callback: [ :value |
111 Removed: value ifNotEmpty: [
112 Removed: workoutLog finishTime: (Time fromString: value) ] ] ] ] ]
113 Removed: ]
114 Removed:
115 48 { #category : 'accessing' }
116 49 MFTWorkoutLogEditorPage >> title [
117 50
@@ -121,8 +54,14 @@
121 54 { #category : 'accessing' }
122 55 MFTWorkoutLogEditorPage >> workoutLog: aMFTWorkoutLog [
123 56
124 Removed: workoutLog := aMFTWorkoutLog.
125 Removed: setGroupLogComponents := workoutLog setGroups collect: [ :setGroupLog |
126 Removed: MFTSetGroupLogViewerComponent forSetGroupLog:
127 Removed: setGroupLog ]
57 Added: workoutLog := aMFTWorkoutLog
58 Added: ]
59 Added:
60 Added: { #category : 'as yet unclassified' }
61 Added: MFTWorkoutLogEditorPage >> workoutLogEditorComponent: aMFTWorkoutLogEditorComponent [
62 Added:
63 Added: workoutLogEditorComponent := aMFTWorkoutLogEditorComponent
64 Added: onSaveWorkout: [
65 Added: self answer: workoutLog ];
66 Added: onDiscardWorkout: [ self answer: nil ]
128 67 ]
src/MyFitnessTracker-Web/MFTWorkoutLogViewerComponent.class.st
index 00000000..3768a117 000000..100644
@@ -0,0 +1,89 @@
1 Added: Class {
2 Added: #name : 'MFTWorkoutLogViewerComponent',
3 Added: #superclass : 'WAComponent',
4 Added: #instVars : [
5 Added: 'heading',
6 Added: 'workoutLog',
7 Added: 'beEditable',
8 Added: 'setGroupLogComponents',
9 Added: 'onEdit'
10 Added: ],
11 Added: #category : 'MyFitnessTracker-Web-Components',
12 Added: #package : 'MyFitnessTracker-Web',
13 Added: #tag : 'Components'
14 Added: }
15 Added:
16 Added: { #category : 'as yet unclassified' }
17 Added: MFTWorkoutLogViewerComponent class >> forWorkoutLog: aMFTWorkoutLog [
18 Added:
19 Added: ^ self new
20 Added: workoutLog: aMFTWorkoutLog;
21 Added: yourself
22 Added: ]
23 Added:
24 Added: { #category : 'accessing' }
25 Added: MFTWorkoutLogViewerComponent >> heading: aString [
26 Added:
27 Added: heading := aString
28 Added: ]
29 Added:
30 Added: { #category : 'initialization' }
31 Added: MFTWorkoutLogViewerComponent >> initialize [
32 Added:
33 Added: super initialize.
34 Added: beEditable := false.
35 Added: setGroupLogComponents := OrderedCollection new
36 Added: ]
37 Added:
38 Added: { #category : 'rendering' }
39 Added: MFTWorkoutLogViewerComponent >> onEdit: aBlock [
40 Added:
41 Added: onEdit := aBlock
42 Added: ]
43 Added:
44 Added: { #category : 'rendering' }
45 Added: MFTWorkoutLogViewerComponent >> renderContentOn: html [
46 Added:
47 Added: html section: [
48 Added: html heading
49 Added: level: 2;
50 Added: with: heading.
51 Added: html heading
52 Added: level: 3;
53 Added: with: workoutLog prescription canonicalName.
54 Added: self renderWorkoutLogMetadataOn: html.
55 Added: setGroupLogComponents do: [ :each | html render: each ].
56 Added: self renderFormActionsOn: html ]
57 Added: ]
58 Added:
59 Added: { #category : 'rendering' }
60 Added: MFTWorkoutLogViewerComponent >> renderFormActionsOn: html [
61 Added:
62 Added: ^ html form: [
63 Added: html submitButton
64 Added: callback: [ onEdit ];
65 Added: with: 'Edit' ]
66 Added: ]
67 Added:
68 Added: { #category : 'rendering' }
69 Added: MFTWorkoutLogViewerComponent >> renderWorkoutLogMetadataOn: html [
70 Added:
71 Added: html definitionList: [
72 Added: html
73 Added: definitionTerm: 'Start time';
74 Added: definitionData: workoutLog start asEmailString;
75 Added: definitionTerm: 'Duration';
76 Added: definitionData:
77 Added: workoutLog duration asMinutes rounded asString , ' minutes';
78 Added: definitionTerm: 'Intensity factor';
79 Added: definitionData: workoutLog intensityFactor asString , '%' ]
80 Added: ]
81 Added:
82 Added: { #category : 'accessing' }
83 Added: MFTWorkoutLogViewerComponent >> workoutLog: aMFTWorkoutLog [
84 Added:
85 Added: workoutLog := aMFTWorkoutLog.
86 Added: setGroupLogComponents := workoutLog setGroups collect: [ :setGroupLog |
87 Added: MFTSetGroupLogViewerComponent
88 Added: forSetGroupLog: setGroupLog ]
89 Added: ]
src/MyFitnessTracker-Web/MFTWorkoutPrescriptionViewerComponent.class.st
index eae39dae..e234332e 100644..100644
@@ -32,7 +32,7 @@
32 32 ((setGroup sets collect: #exercise) joinUsing: ', ') ] ] ]
33 33 ]
34 34
35 Removed: { #category : 'accessing' }
35 Added: { #category : 'as yet unclassified' }
36 36 MFTWorkoutPrescriptionViewerComponent >> workoutPrescription: aMFTWorkoutPrescription [
37 37
38 38 workoutPrescription := aMFTWorkoutPrescription