[Pharo] Personal fitness tracker web app.
Might break everything!
Changed files
- src/MyFitnessTracker/MFTDatabase.class.st
- src/MyFitnessTracker/MFTGlorpSession.class.st
- src/MyFitnessTracker/MFTLoginAndRegisterComponent.class.st
- src/MyFitnessTracker/MFTMainNavbarComponent.class.st
- src/MyFitnessTracker/MFTMainTabsComponent.class.st
- src/MyFitnessTracker/MFTMuscle.class.st
- src/MyFitnessTracker/MFTProfile.class.st
- src/MyFitnessTracker/MFTProfileTab.class.st
- src/MyFitnessTracker/MFTRootComponent.class.st
- src/MyFitnessTracker/MFTScreenComponent.class.st
- src/MyFitnessTracker/MFTSession.class.st
- src/MyFitnessTracker/MFTUser.class.st
- src/MyFitnessTracker/MFTUtils.class.st
- src/MyFitnessTracker/MFTWorkout.class.st
- src/MyFitnessTracker/MFTWorkoutsListTab.class.st
src/MyFitnessTracker/MFTDatabase.class.st
@@ -0,0 +1,52 @@
1
Added:
Class {
2
Added:
#name : #MFTDatabase,
3
Added:
#superclass : #Object,
4
Added:
#instVars : [
5
Added:
'connection'
6
Added:
],
7
Added:
#classInstVars : [
8
Added:
'connection'
9
Added:
],
10
Added:
#category : #'MyFitnessTracker-Model'
11
Added:
}
12
Added:
13
Added:
{ #category : #'as yet unclassified' }
14
Added:
MFTDatabase class >> checkCredentialsForUsername: aUsername password: aPassword [
15
Added:
16
Added:
| statement |
17
Added:
connection execute: 'CREATE TABLE IF NOT EXISTS user(
18
Added:
id INTEGER PRIMARY KEY AUTOINCREMENT,
19
Added:
username TEXT NOT NULL,
20
Added:
password TEXT NOT NULL,
21
Added:
);'
22
Added:
]
23
Added:
24
Added:
{ #category : #'instance creation' }
25
Added:
MFTDatabase class >> newConnectionToSQLite3 [
26
Added:
27
Added:
connection := SQLite3Connection on:
28
Added:
(Smalltalk imageDirectory / 'mft.db') fullName.
29
Added:
connection open
30
Added:
"TODO: MFTRoot is responsible for opening the connection?"
31
Added:
"^ self new
32
Added:
connection: connection;
33
Added:
yourself"
34
Added:
]
35
Added:
36
Added:
{ #category : #accessing }
37
Added:
MFTDatabase >> connection [
38
Added:
39
Added:
^ connection
40
Added:
]
41
Added:
42
Added:
{ #category : #accessing }
43
Added:
MFTDatabase >> connection: anObject [
44
Added:
45
Added:
connection := anObject
46
Added:
]
47
Added:
48
Added:
{ #category : #initialization }
49
Added:
MFTDatabase >> initialize [
50
Added:
51
Added:
super initialize
52
Added:
]
src/MyFitnessTracker/MFTGlorpSession.class.st
@@ -0,0 +1,5 @@
1
Added:
Class {
2
Added:
#name : #MFTGlorpSession,
3
Added:
#superclass : #GlorpSession,
4
Added:
#category : #'MyFitnessTracker-Model'
5
Added:
}
src/MyFitnessTracker/MFTLoginAndRegisterComponent.class.st
@@ -0,0 +1,173 @@
1
Added:
Class {
2
Added:
#name : #MFTLoginAndRegisterComponent,
3
Added:
#superclass : #SBSComponent,
4
Added:
#instVars : [
5
Added:
'user'
6
Added:
],
7
Added:
#category : #'MyFitnessTracker-Components'
8
Added:
}
9
Added:
10
Added:
{ #category : #initialization }
11
Added:
MFTLoginAndRegisterComponent >> initialize [
12
Added:
13
Added:
super initialize.
14
Added:
user := MFTUser new
15
Added:
]
16
Added:
17
Added:
{ #category : #rendering }
18
Added:
MFTLoginAndRegisterComponent >> renderContentOn: html [
19
Added:
"MFTUser isLoggedIn"
20
Added:
21
Added:
false
22
Added:
ifFalse: [ self renderLoginAndRegisterModalsOn: html ]
23
Added:
ifTrue: [ self renderLogoutButtonOn: html ]
24
Added:
]
25
Added:
26
Added:
{ #category : #rendering }
27
Added:
MFTLoginAndRegisterComponent >> renderLoginAndRegisterModalsOn: html [
28
Added:
"Logging in and registering display modal components; they are not in a form."
29
Added:
30
Added:
html buttonGroup: [
31
Added:
html formButton
32
Added:
beSecondary;
33
Added:
beSmall;
34
Added:
dataToggle: 'modal';
35
Added:
dataTarget: '#loginModal';
36
Added:
with: 'Login'.
37
Added:
html formButton
38
Added:
bePrimary;
39
Added:
beSmall;
40
Added:
dataToggle: 'modal';
41
Added:
dataTarget: '#registerModal';
42
Added:
with: 'Register' ].
43
Added:
self renderLoginModalOn: html.
44
Added:
self renderRegisterModalOn: html
45
Added:
]
46
Added:
47
Added:
{ #category : #rendering }
48
Added:
MFTLoginAndRegisterComponent >> renderLoginModalBodyOn: html [
49
Added:
50
Added:
html modalBody with: [
51
Added:
html text: 'Welcome!'.
52
Added:
html formGroup: [
53
Added:
html label: 'Username'.
54
Added:
html textInput formControl callback: [ :value |
55
Added:
user username: value ] ].
56
Added:
html formGroup: [
57
Added:
html label: 'Password'.
58
Added:
html passwordInput formControl callback: [ :value |
59
Added:
user passwordHash: value ] ] ]
60
Added:
]
61
Added:
62
Added:
{ #category : #rendering }
63
Added:
MFTLoginAndRegisterComponent >> renderLoginModalFooterOn: html [
64
Added:
65
Added:
html modalFooter: [
66
Added:
html formButton
67
Added:
beSecondary;
68
Added:
dataDismiss: 'modal';
69
Added:
with: 'Cancel'.
70
Added:
html formButton
71
Added:
bePrimary;
72
Added:
callback: [ MFTUser tryLoginUser: user ];
73
Added:
with: 'Login' ]
74
Added:
]
75
Added:
76
Added:
{ #category : #rendering }
77
Added:
MFTLoginAndRegisterComponent >> renderLoginModalHeaderOn: html [
78
Added:
79
Added:
html modalHeader: [
80
Added:
html modalTitle
81
Added:
level5;
82
Added:
with: 'Login'.
83
Added:
html modalCloseButton ]
84
Added:
]
85
Added:
86
Added:
{ #category : #rendering }
87
Added:
MFTLoginAndRegisterComponent >> renderLoginModalOn: html [
88
Added:
89
Added:
html modal
90
Added:
id: 'loginModal';
91
Added:
fade;
92
Added:
with: [
93
Added:
html modalDialog
94
Added:
beCentered;
95
Added:
with: [
96
Added:
html modalContent: [
97
Added:
html form: [
98
Added:
self renderLoginModalHeaderOn: html.
99
Added:
self renderLoginModalBodyOn: html.
100
Added:
self renderLoginModalFooterOn: html ] ] ] ]
101
Added:
]
102
Added:
103
Added:
{ #category : #rendering }
104
Added:
MFTLoginAndRegisterComponent >> renderLogoutButtonOn: html [
105
Added:
"Logging out is an action; the button is in a form."
106
Added:
107
Added:
html form: [
108
Added:
html formButton
109
Added:
beSecondary;
110
Added:
beSmall;
111
Added:
callback: [ MFTUser logout ];
112
Added:
with: 'Logout' ]
113
Added:
]
114
Added:
115
Added:
{ #category : #rendering }
116
Added:
MFTLoginAndRegisterComponent >> renderRegisterModalBodyOn: html [
117
Added:
118
Added:
html modalBody with: [
119
Added:
html text: 'Welcome!'.
120
Added:
html formGroup: [
121
Added:
html label: 'Username'.
122
Added:
html textInput formControl callback: [ :value |
123
Added:
user username: value ] ].
124
Added:
html formGroup: [
125
Added:
html label: 'Password'.
126
Added:
html passwordInput formControl callback: [ :value |
127
Added:
user passwordHash: (SHA256 new hashMessage: value) asString ] ].
128
Added:
html formGroup: [
129
Added:
html label: 'Date of Birth'.
130
Added:
html dateInput5 formControl callback: [ :date |
131
Added:
user dateOfBirth: (Date fromString: date) ] ] ]
132
Added:
]
133
Added:
134
Added:
{ #category : #rendering }
135
Added:
MFTLoginAndRegisterComponent >> renderRegisterModalFooterOn: html [
136
Added:
137
Added:
html modalFooter: [
138
Added:
html formButton
139
Added:
beSecondary;
140
Added:
dataDismiss: 'modal';
141
Added:
with: 'Cancel'.
142
Added:
html formButton
143
Added:
bePrimary;
144
Added:
callback: [ MFTUser tryLoginUser: user ];
145
Added:
with: 'Register' ]
146
Added:
]
147
Added:
148
Added:
{ #category : #rendering }
149
Added:
MFTLoginAndRegisterComponent >> renderRegisterModalHeaderOn: html [
150
Added:
151
Added:
html modalHeader: [
152
Added:
html modalTitle
153
Added:
level5;
154
Added:
with: 'Register'.
155
Added:
html modalCloseButton ]
156
Added:
]
157
Added:
158
Added:
{ #category : #rendering }
159
Added:
MFTLoginAndRegisterComponent >> renderRegisterModalOn: html [
160
Added:
161
Added:
html modal
162
Added:
id: 'registerModal';
163
Added:
fade;
164
Added:
with: [
165
Added:
html modalDialog
166
Added:
beCentered;
167
Added:
with: [
168
Added:
html modalContent: [
169
Added:
html form: [
170
Added:
self renderRegisterModalHeaderOn: html.
171
Added:
self renderRegisterModalBodyOn: html.
172
Added:
self renderRegisterModalFooterOn: html ] ] ] ]
173
Added:
]
src/MyFitnessTracker/MFTMainNavbarComponent.class.st
@@ -0,0 +1,91 @@
1
Added:
Class {
2
Added:
#name : #MFTMainNavbarComponent,
3
Added:
#superclass : #SBSComponent,
4
Added:
#instVars : [
5
Added:
'mainTabs',
6
Added:
'activeTab'
7
Added:
],
8
Added:
#category : #'MyFitnessTracker-Components'
9
Added:
}
10
Added:
11
Added:
{ #category : #hooks }
12
Added:
MFTMainNavbarComponent >> children [
13
Added:
14
Added:
^ mainTabs
15
Added:
]
16
Added:
17
Added:
{ #category : #initialization }
18
Added:
MFTMainNavbarComponent >> initialize [
19
Added:
20
Added:
super initialize.
21
Added:
mainTabs := {
22
Added:
MFTWorkoutsListTab placeholder.
23
Added:
MFTWeightsListTab new.
24
Added:
MFTLearnTab new.
25
Added:
MFTProfileTab new }.
26
Added:
activeTab := mainTabs first
27
Added:
]
28
Added:
29
Added:
{ #category : #rendering }
30
Added:
MFTMainNavbarComponent >> renderContentOn: html [
31
Added:
32
Added:
| bar |
33
Added:
bar := html navigationBar.
34
Added:
bar
35
Added:
beLight;
36
Added:
expandLarge.
37
Added:
bar background beLight.
38
Added:
bar
39
Added:
class: 'p-3 mb-3';
40
Added:
with: [ self renderNavigationBarItemsOn: html ].
41
Added:
html render: activeTab
42
Added:
]
43
Added:
44
Added:
{ #category : #rendering }
45
Added:
MFTMainNavbarComponent >> renderLoginOn: html [
46
Added:
47
Added:
^ MFTLoginAndRegisterComponent new renderContentOn: html
48
Added:
]
49
Added:
50
Added:
{ #category : #rendering }
51
Added:
MFTMainNavbarComponent >> renderNavigationBarItemsOn: html [
52
Added:
53
Added:
html navigationBarBrand: 'MyFitnessTracker'.
54
Added:
"The toggler that is only visible when reducing the width of screen"
55
Added:
html navigationBarToggler
56
Added:
beButtonType;
57
Added:
collapse;
58
Added:
dataTarget: '#navbarCollapsed';
59
Added:
with: [ html navigationBarTogglerIcon ].
60
Added:
html navigationBarCollapse collapse
61
Added:
id: 'navbarCollapsed';
62
Added:
with: [
63
Added:
html navigationBarNavigation: [
64
Added:
mainTabs do: [ :tab | self renderTab: tab on: html ].
65
Added:
html navigationItem dropdown with: [
66
Added:
html navigationLink
67
Added:
dropdownToggle;
68
Added:
dataToggle: 'dropdown';
69
Added:
with: 'Learn'.
70
Added:
html dropdownMenu
71
Added:
attributeAt: 'aria-labelledby' put: 'navbarDropdown';
72
Added:
with: [
73
Added:
html dropdownItem: 'Exercises'.
74
Added:
html dropdownItem: 'Muscles'
75
Added:
"html dropdownDivider.
76
Added:
html dropdownItem: 'Something else here'" ] ] ].
77
Added:
html div
78
Added:
class: 'ms-auto';
79
Added:
with: [ html render: MFTLoginAndRegisterComponent new ] ]
80
Added:
]
81
Added:
82
Added:
{ #category : #rendering }
83
Added:
MFTMainNavbarComponent >> renderTab: tab on: html [
84
Added:
85
Added:
html navigationItem
86
Added:
beActiveIf: [ activeTab = tab ];
87
Added:
with: [
88
Added:
html navigationLink
89
Added:
callback: [ activeTab := tab ];
90
Added:
with: tab title ]
91
Added:
]
src/MyFitnessTracker/MFTMainTabsComponent.class.st
@@ -1,78 +0,0 @@
1
Removed:
Class {
2
Removed:
#name : #MFTMainTabsComponent,
3
Removed:
#superclass : #SBSComponent,
4
Removed:
#instVars : [
5
Removed:
'mainTabs',
6
Removed:
'activeTab'
7
Removed:
],
8
Removed:
#category : #'MyFitnessTracker-Components'
9
Removed:
}
10
Removed:
11
Removed:
{ #category : #hooks }
12
Removed:
MFTMainTabsComponent >> children [
13
Removed:
14
Removed:
^ mainTabs
15
Removed:
]
16
Removed:
17
Removed:
{ #category : #initialization }
18
Removed:
MFTMainTabsComponent >> initialize [
19
Removed:
20
Removed:
super initialize.
21
Removed:
mainTabs := {
22
Removed:
MFTWorkoutsListTab placeholder.
23
Removed:
MFTWeightsListTab new.
24
Removed:
MFTLearnTab new.
25
Removed:
MFTProfileTab new }.
26
Removed:
activeTab := mainTabs first
27
Removed:
]
28
Removed:
29
Removed:
{ #category : #rendering }
30
Removed:
MFTMainTabsComponent >> renderContentOn: html [
31
Removed:
32
Removed:
| bar id |
33
Removed:
bar := html navigationBar.
34
Removed:
id := '#navbarCollapsed'.
35
Removed:
bar
36
Removed:
beLight;
37
Removed:
expandLarge.
38
Removed:
bar background beLight.
39
Removed:
bar with: [
40
Removed:
html navigationBarBrand: 'MyFitnessTracker'.
41
Removed:
"The toggler that is only visible when reducing the width of screen"
42
Removed:
html navigationBarToggler
43
Removed:
beButtonType;
44
Removed:
collapse;
45
Removed:
dataTarget: id;
46
Removed:
with: [ html navigationBarTogglerIcon ].
47
Removed:
html navigationBarCollapse collapse
48
Removed:
id: 'navbarCollapsed';
49
Removed:
with: [
50
Removed:
html navigationBarNavigation: [
51
Removed:
mainTabs do: [ :tab | self renderTab: tab on: html ].
52
Removed:
html navigationItem dropdown with: [
53
Removed:
html navigationLink
54
Removed:
dropdownToggle;
55
Removed:
dataToggle: 'dropdown';
56
Removed:
with: 'Learn'.
57
Removed:
58
Removed:
html dropdownMenu
59
Removed:
attributeAt: 'aria-labelledby' put: 'navbarDropdown';
60
Removed:
with: [
61
Removed:
html dropdownItem: 'Exercises'.
62
Removed:
html dropdownItem: 'Muscles'
63
Removed:
"html dropdownDivider.
64
Removed:
html dropdownItem: 'Something else here'" ] ] ] ] ].
65
Removed:
html break.
66
Removed:
html render: activeTab
67
Removed:
]
68
Removed:
69
Removed:
{ #category : #rendering }
70
Removed:
MFTMainTabsComponent >> renderTab: tab on: html [
71
Removed:
72
Removed:
html navigationItem
73
Removed:
beActiveIf: [ tab = activeTab ];
74
Removed:
with: [
75
Removed:
html navigationLink
76
Removed:
callback: [ activeTab := tab ];
77
Removed:
with: tab title ]
78
Removed:
]
src/MyFitnessTracker/MFTMuscle.class.st
@@ -58,7 +58,7 @@
58
58
MFTMuscle class >> erectorSpinae [
59
59
60
60
^ self newWithLatinName
61
Removed:
englishName: 'Erector Spinae';
61
Added:
englishName: 'erectors';
62
62
description:
63
63
'This group of muscles runs along the spine and is responsible for extending the vertebral column and maintaining an upright posture.';
64
64
yourself
@@ -177,8 +177,7 @@
177
177
178
178
| muscleNameFromSender |
179
179
muscleNameFromSender := (thisContext sender selector splitCamelCase
180
Removed:
collect: [ :word | word asLowercase ])
181
Removed:
joinUsing: ' '.
180
Added:
collect: #asLowercase) joinUsing: ' '.
182
181
^ self new
183
182
latinName: muscleNameFromSender;
184
183
yourself
src/MyFitnessTracker/MFTProfile.class.st
@@ -1,20 +0,0 @@
1
Removed:
Class {
2
Removed:
#name : #MFTProfile,
3
Removed:
#superclass : #Object,
4
Removed:
#instVars : [
5
Removed:
'reps'
6
Removed:
],
7
Removed:
#category : #MyFitnessTracker
8
Removed:
}
9
Removed:
10
Removed:
{ #category : #accessing }
11
Removed:
MFTProfile class >> reps [
12
Removed:
13
Removed:
^ 8
14
Removed:
]
15
Removed:
16
Removed:
{ #category : #'as yet unclassified' }
17
Removed:
MFTProfile class >> rpe [
18
Removed:
19
Removed:
^ 8
20
Removed:
]
src/MyFitnessTracker/MFTProfileTab.class.st
@@ -14,5 +14,5 @@
14
14
{ #category : #rendering }
15
15
MFTProfileTab >> renderContentOn: html [
16
16
17
Removed:
html text: 'Welcome!'
17
Added:
html container: [ html text: 'Welcome!' ]
18
18
]
src/MyFitnessTracker/MFTRootComponent.class.st
@@ -2,26 +2,27 @@
2
2
#name : #MFTRootComponent,
3
3
#superclass : #SBSRootComponent,
4
4
#instVars : [
5
Removed:
'main'
5
Added:
'main',
6
Added:
'connection'
6
7
],
7
8
#category : #'MyFitnessTracker-Components'
8
9
}
9
10
10
11
{ #category : #initialization }
11
12
MFTRootComponent class >> canBeRoot [
13
Added:
12
14
^ true
13
15
]
14
16
15
17
{ #category : #'class initialization' }
16
18
MFTRootComponent class >> initialize [
17
Removed:
"self initialize"
18
19
19
20
| app |
20
21
app := WAAdmin register: self asApplicationAt: 'MyFitnessTracker'.
21
22
app
22
Removed:
addLibrary: JQDeploymentLibrary;
23
Removed:
addLibrary: JQUiDeploymentLibrary;
24
Removed:
addLibrary: SBSDeploymentLibrary.
23
Added:
addLibrary: JQGoogleLibrary;
24
Added:
addLibrary: JQUiGoogleLibrary;
25
Added:
addLibrary: SBSCDNDeploymentLibrary.
25
26
^ app
26
27
]
27
28
@@ -35,7 +36,8 @@
35
36
MFTRootComponent >> initialize [
36
37
37
38
super initialize.
38
Removed:
main := MFTScreenComponent new
39
Added:
main := MFTScreenComponent new.
40
Added:
"connection := MFTDatabase newConnectionToSQLite3"
39
41
]
40
42
41
43
{ #category : #initialization }
@@ -55,6 +57,18 @@
55
57
56
58
super updateRoot: anHtmlRoot.
57
59
anHtmlRoot beHtml5.
58
Removed:
anHtmlRoot title: 'My Fitness Tracker'.
59
Removed:
anHtmlRoot script url: '/files/SBSDeploymentLibrary/js/bootstrap.bundle.min.js'
60
Added:
anHtmlRoot meta
61
Added:
name: 'viewport';
62
Added:
content: 'width=device-width, initial-scale=1'.
63
Added:
anHtmlRoot title: 'My Fitness Tracker ' , self version.
64
Added:
anHtmlRoot script url:
65
Added:
'/files/SBSDeploymentLibrary/js/bootstrap.bundle.min.js'
66
Added:
]
67
Added:
68
Added:
{ #category : #versions }
69
Added:
MFTRootComponent >> version [
70
Added:
71
Added:
| version |
72
Added:
version := MFTUtils version.
73
Added:
^ version ifNil: [ '[DEVELOP]' ] ifNotNil: [ #v , version asString ]
60
74
]
src/MyFitnessTracker/MFTScreenComponent.class.st
@@ -22,7 +22,7 @@
22
22
23
23
super initialize.
24
24
header := MFTHeaderComponent new.
25
Removed:
mainTabs := MFTMainTabsComponent new
25
Added:
mainTabs := MFTMainNavbarComponent new
26
26
]
27
27
28
28
{ #category : #rendering }
src/MyFitnessTracker/MFTSession.class.st
@@ -0,0 +1,8 @@
1
Added:
Class {
2
Added:
#name : #MFTSession,
3
Added:
#superclass : #WASession,
4
Added:
#instVars : [
5
Added:
'user'
6
Added:
],
7
Added:
#category : #'MyFitnessTracker-Session'
8
Added:
}
src/MyFitnessTracker/MFTUser.class.st
@@ -0,0 +1,90 @@
1
Added:
Class {
2
Added:
#name : #MFTUser,
3
Added:
#superclass : #Object,
4
Added:
#instVars : [
5
Added:
'username',
6
Added:
'passwordHash',
7
Added:
'realName',
8
Added:
'dateOfBirth'
9
Added:
],
10
Added:
#classInstVars : [
11
Added:
'isRegistered'
12
Added:
],
13
Added:
#category : #'MyFitnessTracker-Model'
14
Added:
}
15
Added:
16
Added:
{ #category : #testing }
17
Added:
MFTUser class >> isLoggedIn [
18
Added:
19
Added:
^ true
20
Added:
]
21
Added:
22
Added:
{ #category : #login }
23
Added:
MFTUser class >> logout [
24
Added:
25
Added:
^ true
26
Added:
]
27
Added:
28
Added:
{ #category : #'as yet unclassified' }
29
Added:
MFTUser class >> tryLoginUser: username [
30
Added:
31
Added:
self isLoggedIn
32
Added:
]
33
Added:
34
Added:
{ #category : #accessing }
35
Added:
MFTUser >> dateOfBirth [
36
Added:
37
Added:
^ dateOfBirth
38
Added:
]
39
Added:
40
Added:
{ #category : #accessing }
41
Added:
MFTUser >> dateOfBirth: anObject [
42
Added:
43
Added:
dateOfBirth := anObject
44
Added:
]
45
Added:
46
Added:
{ #category : #initialization }
47
Added:
MFTUser >> initialize [
48
Added:
49
Added:
super initialize.
50
Added:
username := String new.
51
Added:
passwordHash := String new.
52
Added:
realName := String new.
53
Added:
dateOfBirth := Date new
54
Added:
]
55
Added:
56
Added:
{ #category : #accessing }
57
Added:
MFTUser >> passwordHash [
58
Added:
59
Added:
^ passwordHash
60
Added:
]
61
Added:
62
Added:
{ #category : #accessing }
63
Added:
MFTUser >> passwordHash: anObject [
64
Added:
65
Added:
passwordHash := anObject
66
Added:
]
67
Added:
68
Added:
{ #category : #accessing }
69
Added:
MFTUser >> realName [
70
Added:
71
Added:
^ realName
72
Added:
]
73
Added:
74
Added:
{ #category : #accessing }
75
Added:
MFTUser >> realName: anObject [
76
Added:
77
Added:
realName := anObject
78
Added:
]
79
Added:
80
Added:
{ #category : #accessing }
81
Added:
MFTUser >> username [
82
Added:
83
Added:
^ username
84
Added:
]
85
Added:
86
Added:
{ #category : #accessing }
87
Added:
MFTUser >> username: anObject [
88
Added:
89
Added:
username := anObject
90
Added:
]
src/MyFitnessTracker/MFTUtils.class.st
@@ -1,7 +1,10 @@
1
1
Class {
2
2
#name : #MFTUtils,
3
3
#superclass : #Object,
4
Removed:
#category : #MyFitnessTracker
4
Added:
#classInstVars : [
5
Added:
'version'
6
Added:
],
7
Added:
#category : #'MyFitnessTracker-Utils'
5
8
}
6
9
7
10
{ #category : #'instance creation' }
@@ -41,7 +44,7 @@
41
44
42
45
{ #category : #'image manipulation' }
43
46
MFTUtils class >> configureImage [
44
Removed:
"I load the latest Seaside and Bootstrap repositories, I then initialize the MFT application."
47
Added:
"I load the latest MFT dependencies, and then initialize the MFT application."
45
48
46
49
Metacello new
47
50
baseline: 'Seaside3';
@@ -53,5 +56,44 @@
53
56
repository: 'github://astares/Seaside-Bootstrap5:master/src';
54
57
load.
55
58
59
Added:
Metacello new
60
Added:
baseline: 'SQLite3';
61
Added:
repository: 'github://pharo-rdbms/Pharo-SQLite3/src';
62
Added:
load.
63
Added:
64
Added:
Metacello new
65
Added:
baseline: 'Glorp';
66
Added:
repository: 'github://pharo-rdbms/glorp';
67
Added:
load.
68
Added:
56
69
MFTRootComponent initialize
70
Added:
]
71
Added:
72
Added:
{ #category : #utilities }
73
Added:
MFTUtils class >> createDeploymentImage: aVersion [
74
Added:
"TODO: simplify this whole process. Rsync already does a terrific job at compressing the image upon deployment."
75
Added:
76
Added:
| stdout |
77
Added:
version := aVersion.
78
Added:
stdout := NonInteractiveTranscript stdout.
79
Added:
stdout crShow: 'Setting the image in server mode.'.
80
Added:
WorldState serverMode: true.
81
Added:
stdout crShow: 'Disabling development tools.'.
82
Added:
WAAdmin disableDevelopmentTools.
83
Added:
stdout crShow: 'Clearing default dispatcher, caches, and sessions.'.
84
Added:
"WAAdmin clearAll."
85
Added:
stdout crShow:
86
Added:
'Setting the default Seaside dispatcher to ''MyFitnessTracker''.'.
87
Added:
WAAdmin defaultDispatcher defaultName: 'MyFitnessTracker'.
88
Added:
stdout crShow: 'Cleaning up image for release.'.
89
Added:
"ImageCleaner cleanUpForRelease."
90
Added:
stdout crShow: 'Saving and exiting from image.'.
91
Added:
stdout close.
92
Added:
SmalltalkImage current snapshot: true andQuit: true
93
Added:
]
94
Added:
95
Added:
{ #category : #versions }
96
Added:
MFTUtils class >> version [
97
Added:
98
Added:
^ version
57
99
]
src/MyFitnessTracker/MFTWorkout.class.st
@@ -7,7 +7,7 @@
7
7
'primaryMuscle',
8
8
'secondaryMuscles'
9
9
],
10
Removed:
#category : #'MyFitnessTracker-Components'
10
Added:
#category : #'MyFitnessTracker-Model'
11
11
}
12
12
13
13
{ #category : #accessing }
@@ -156,6 +156,30 @@
156
156
html
157
157
tableHeading: 'Exercise';
158
158
tableHeading: 'Reps' ]
159
Added:
]
160
Added:
161
Added:
{ #category : #'as yet unclassified' }
162
Added:
MFTWorkout >> saveToDatabase [
163
Added:
"Save data to the SQLite3 database"
164
Added:
165
Added:
| connection statement |
166
Added:
connection := SQLite3Connection on:
167
Added:
(Smalltalk imageDirectory / 'mft.db') fullName.
168
Added:
connection open.
169
Added:
connection execute: 'CREATE TABLE IF NOT EXISTS workout(
170
Added:
id INTEGER PRIMARY KEY AUTOINCREMENT,
171
Added:
date TEXT NOT NULL,
172
Added:
exercises JSON,
173
Added:
primaryMuscle TEXT,
174
Added:
secondaryMuscles TEXT
175
Added:
);'.
176
Added:
"Insert data into the database"
177
Added:
statement := 'INSERT INTO workout (date, exercises, primaryMuscle, secondaryMuscles) VALUES (?, ?, ?, ?)'.
178
Added:
connection execute: statement with: {
179
Added:
date.
180
Added:
exercises.
181
Added:
primaryMuscle latinName.
182
Added:
secondaryMuscles }
159
183
]
160
184
161
185
{ #category : #accessing }
src/MyFitnessTracker/MFTWorkoutsListTab.class.st
@@ -82,7 +82,9 @@
82
82
83
83
| newWorkout |
84
84
newWorkout := self call: MFTWorkoutDialog new.
85
Removed:
newWorkout ifNotNil: [ workouts addFirst: newWorkout ]
85
Added:
newWorkout ifNotNil: [
86
Added:
workouts addFirst: newWorkout.
87
Added:
MFTUser ifRegistered: [ MFTDatabase saveWorkout: newWorkout ] ]
86
88
]
87
89
88
90
{ #category : #hooks }
@@ -146,7 +148,6 @@
146
148
workouts ifEmpty: [
147
149
html jumbotron: [ html heading: self randomWittyCTA ] ].
148
150
self renderActionsButtonGroup: html.
149
Removed:
html break.
150
151
self renderWorkoutsAsAccordionOn: html ]
151
152
]
152
153
@@ -170,6 +171,7 @@
170
171
171
172
html accordion
172
173
id: 'accordion';
174
Added:
class: 'mt-3';
173
175
with: [
174
176
workouts doWithIndex: [ :workout :i |
175
177
html accordionItem: [