@live-change/task-frontend 0.8.27 → 0.8.29
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/front/src/Index.vue +49 -5
- package/package.json +38 -38
- package/server/app.config.js +3 -0
- package/server/services.list.js +5 -0
- package/server/testTasks.js +287 -0
- package/front/src/components/Clock.vue +0 -22
package/front/src/Index.vue
CHANGED
|
@@ -1,13 +1,57 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div>
|
|
3
|
-
<
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
<div class="flex flex-row w-full justify-content-evenly">
|
|
3
|
+
<div class="surface-card shadow-1 border-round px-3 py-1">
|
|
4
|
+
<h2>Built shelters</h2>
|
|
5
|
+
|
|
6
|
+
<div>
|
|
7
|
+
|
|
8
|
+
</div>
|
|
9
|
+
|
|
10
|
+
<command-form service="testTasks" action="buildShelter" reset-on-done v-slot="{ data, definition }">
|
|
11
|
+
<pre>{{ definition.properties }}</pre>
|
|
12
|
+
<pre>{{data}}</pre>
|
|
13
|
+
|
|
14
|
+
<div class="text text-xl">
|
|
15
|
+
Size:
|
|
16
|
+
</div>
|
|
17
|
+
<div class="pl-2">
|
|
18
|
+
<div class="flex flex-row align-items-center">
|
|
19
|
+
<label for="role" class="mr-2 w-5rem text-right">Width:</label>
|
|
20
|
+
<InputNumber v-model="data.size.width" mode="decimal"
|
|
21
|
+
showButtons :min="3" :max="9" />
|
|
22
|
+
</div>
|
|
23
|
+
<div class="flex flex-row align-items-center">
|
|
24
|
+
<label for="role" class="mr-2 w-5rem text-right">Height:</label>
|
|
25
|
+
<InputNumber v-model="data.size.height" mode="decimal" showButtons :min="3" :max="9" />
|
|
26
|
+
</div>
|
|
27
|
+
<div class="flex flex-row align-items-center">
|
|
28
|
+
<label for="role" class="mr-2 w-5rem text-right">Length:</label>
|
|
29
|
+
<InputNumber v-model="data.size.length" mode="decimal" showButtons :min="3" :max="9" />
|
|
30
|
+
</div>
|
|
31
|
+
|
|
32
|
+
<div class="flex flex-row align-items-center">
|
|
33
|
+
<label for="role" class="mr-2 w-5rem">Wood type:</label>
|
|
34
|
+
<Dropdown id="role" class="w-14rem" v-model="data.woodType" placeholder="Select a Wood type"
|
|
35
|
+
:options="definition.properties.woodType.options" />
|
|
36
|
+
</div>
|
|
37
|
+
|
|
38
|
+
<div class="text-right">
|
|
39
|
+
<Button type="submit" icon="pi pi-play" label="Build" class="mt-2" />
|
|
40
|
+
</div>
|
|
41
|
+
</div>
|
|
42
|
+
|
|
43
|
+
</command-form>
|
|
44
|
+
</div>
|
|
45
|
+
<div class="surface-card shadow-1 border-round px-3 py-1">
|
|
46
|
+
<h2>Tasks</h2>
|
|
47
|
+
|
|
48
|
+
</div>
|
|
6
49
|
</div>
|
|
7
50
|
</template>
|
|
8
51
|
|
|
9
52
|
<script setup>
|
|
10
|
-
|
|
53
|
+
|
|
54
|
+
|
|
11
55
|
|
|
12
56
|
</script>
|
|
13
57
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@live-change/task-frontend",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.29",
|
|
4
4
|
"scripts": {
|
|
5
5
|
"memDev": "node server/start.js memDev --enableSessions --initScript ./init.js --dbAccess",
|
|
6
6
|
"localDevInit": "rm tmp.db; node server/start.js localDev --enableSessions --initScript ./init.js",
|
|
@@ -35,41 +35,41 @@
|
|
|
35
35
|
"@codemirror/language": "6.10.1",
|
|
36
36
|
"@dotenvx/dotenvx": "0.27.0",
|
|
37
37
|
"@fortawesome/fontawesome-free": "^6.4.2",
|
|
38
|
-
"@live-change/access-control-frontend": "^0.8.
|
|
39
|
-
"@live-change/access-control-service": "^0.8.
|
|
40
|
-
"@live-change/backup-service": "^0.8.
|
|
41
|
-
"@live-change/blog-frontend": "^0.8.
|
|
42
|
-
"@live-change/blog-service": "^0.8.
|
|
43
|
-
"@live-change/cli": "^0.8.
|
|
44
|
-
"@live-change/content-frontend": "^0.8.
|
|
45
|
-
"@live-change/content-service": "^0.8.
|
|
46
|
-
"@live-change/dao": "^0.8.
|
|
47
|
-
"@live-change/dao-vue3": "^0.8.
|
|
48
|
-
"@live-change/dao-websocket": "^0.8.
|
|
49
|
-
"@live-change/db-client": "^0.8.
|
|
50
|
-
"@live-change/email-service": "^0.8.
|
|
51
|
-
"@live-change/framework": "^0.8.
|
|
52
|
-
"@live-change/frontend-auto-form": "^0.8.
|
|
53
|
-
"@live-change/frontend-base": "^0.8.
|
|
54
|
-
"@live-change/geoip-service": "^0.8.
|
|
55
|
-
"@live-change/image-frontend": "^0.8.
|
|
56
|
-
"@live-change/locale-settings-service": "^0.8.
|
|
57
|
-
"@live-change/password-authentication-service": "^0.8.
|
|
58
|
-
"@live-change/prosemirror-service": "^0.8.
|
|
59
|
-
"@live-change/secret-code-service": "^0.8.
|
|
60
|
-
"@live-change/secret-link-service": "^0.8.
|
|
61
|
-
"@live-change/session-service": "^0.8.
|
|
62
|
-
"@live-change/task-service": "^0.8.
|
|
63
|
-
"@live-change/upload-frontend": "^0.8.
|
|
64
|
-
"@live-change/url-frontend": "^0.8.
|
|
65
|
-
"@live-change/url-service": "^0.8.
|
|
66
|
-
"@live-change/user-frontend": "^0.8.
|
|
67
|
-
"@live-change/user-identification-service": "^0.8.
|
|
68
|
-
"@live-change/user-service": "^0.8.
|
|
69
|
-
"@live-change/vote-service": "^0.8.
|
|
70
|
-
"@live-change/vue3-components": "^0.8.
|
|
71
|
-
"@live-change/vue3-ssr": "^0.8.
|
|
72
|
-
"@live-change/wysiwyg-frontend": "^0.8.
|
|
38
|
+
"@live-change/access-control-frontend": "^0.8.29",
|
|
39
|
+
"@live-change/access-control-service": "^0.8.29",
|
|
40
|
+
"@live-change/backup-service": "^0.8.29",
|
|
41
|
+
"@live-change/blog-frontend": "^0.8.29",
|
|
42
|
+
"@live-change/blog-service": "^0.8.29",
|
|
43
|
+
"@live-change/cli": "^0.8.29",
|
|
44
|
+
"@live-change/content-frontend": "^0.8.29",
|
|
45
|
+
"@live-change/content-service": "^0.8.29",
|
|
46
|
+
"@live-change/dao": "^0.8.29",
|
|
47
|
+
"@live-change/dao-vue3": "^0.8.29",
|
|
48
|
+
"@live-change/dao-websocket": "^0.8.29",
|
|
49
|
+
"@live-change/db-client": "^0.8.29",
|
|
50
|
+
"@live-change/email-service": "^0.8.29",
|
|
51
|
+
"@live-change/framework": "^0.8.29",
|
|
52
|
+
"@live-change/frontend-auto-form": "^0.8.29",
|
|
53
|
+
"@live-change/frontend-base": "^0.8.29",
|
|
54
|
+
"@live-change/geoip-service": "^0.8.29",
|
|
55
|
+
"@live-change/image-frontend": "^0.8.29",
|
|
56
|
+
"@live-change/locale-settings-service": "^0.8.29",
|
|
57
|
+
"@live-change/password-authentication-service": "^0.8.29",
|
|
58
|
+
"@live-change/prosemirror-service": "^0.8.29",
|
|
59
|
+
"@live-change/secret-code-service": "^0.8.29",
|
|
60
|
+
"@live-change/secret-link-service": "^0.8.29",
|
|
61
|
+
"@live-change/session-service": "^0.8.29",
|
|
62
|
+
"@live-change/task-service": "^0.8.29",
|
|
63
|
+
"@live-change/upload-frontend": "^0.8.29",
|
|
64
|
+
"@live-change/url-frontend": "^0.8.29",
|
|
65
|
+
"@live-change/url-service": "^0.8.29",
|
|
66
|
+
"@live-change/user-frontend": "^0.8.29",
|
|
67
|
+
"@live-change/user-identification-service": "^0.8.29",
|
|
68
|
+
"@live-change/user-service": "^0.8.29",
|
|
69
|
+
"@live-change/vote-service": "^0.8.29",
|
|
70
|
+
"@live-change/vue3-components": "^0.8.29",
|
|
71
|
+
"@live-change/vue3-ssr": "^0.8.29",
|
|
72
|
+
"@live-change/wysiwyg-frontend": "^0.8.29",
|
|
73
73
|
"@vueuse/core": "^10.9.0",
|
|
74
74
|
"codeceptjs-assert": "^0.0.5",
|
|
75
75
|
"compression": "^1.7.4",
|
|
@@ -91,7 +91,7 @@
|
|
|
91
91
|
"vue3-scroll-border": "0.1.6"
|
|
92
92
|
},
|
|
93
93
|
"devDependencies": {
|
|
94
|
-
"@live-change/codeceptjs-helper": "^0.8.
|
|
94
|
+
"@live-change/codeceptjs-helper": "^0.8.29",
|
|
95
95
|
"codeceptjs": "^3.5.12",
|
|
96
96
|
"generate-password": "1.7.1",
|
|
97
97
|
"playwright": "^1.41.2",
|
|
@@ -102,5 +102,5 @@
|
|
|
102
102
|
"author": "Michał Łaszczewski <michal@laszczewski.pl>",
|
|
103
103
|
"license": "ISC",
|
|
104
104
|
"description": "",
|
|
105
|
-
"gitHead": "
|
|
105
|
+
"gitHead": "9bc23973964b33f2e837db9fbf8dfb51916752a8"
|
|
106
106
|
}
|
package/server/app.config.js
CHANGED
package/server/services.list.js
CHANGED
package/server/testTasks.js
CHANGED
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
import App from '@live-change/framework'
|
|
2
|
+
const app = App.app()
|
|
3
|
+
|
|
4
|
+
import relationsPlugin from '@live-change/relations-plugin'
|
|
5
|
+
import accessControlService from '@live-change/access-control-service'
|
|
6
|
+
|
|
7
|
+
const definition = app.createServiceDefinition({
|
|
8
|
+
name: "testTasks",
|
|
9
|
+
use: [ relationsPlugin, accessControlService ]
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
import { task } from '@live-change/task-service'
|
|
13
|
+
|
|
14
|
+
import PQueue from 'p-queue'
|
|
15
|
+
|
|
16
|
+
const workersCount = 2
|
|
17
|
+
const workDuration = 1000
|
|
18
|
+
const pauseDuration = 500
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms))
|
|
22
|
+
|
|
23
|
+
const workerQueue = new PQueue({ concurrency: workersCount })
|
|
24
|
+
|
|
25
|
+
const getWood = task({
|
|
26
|
+
name: 'getWood',
|
|
27
|
+
properties: {
|
|
28
|
+
woodType: {
|
|
29
|
+
type: String,
|
|
30
|
+
validation: ['nonEmpty']
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
returns: {
|
|
34
|
+
type: 'Wood',
|
|
35
|
+
properties: {
|
|
36
|
+
type: {
|
|
37
|
+
type: String
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
async execute({ woodType }, { service, task }, emit) {
|
|
42
|
+
await sleep(workDuration)
|
|
43
|
+
return {
|
|
44
|
+
type: 'Wood',
|
|
45
|
+
woodType
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
const cutWood = task({
|
|
51
|
+
name: 'cutWood',
|
|
52
|
+
properties: {
|
|
53
|
+
wood: {
|
|
54
|
+
type: 'Wood',
|
|
55
|
+
properties: {
|
|
56
|
+
woodType: {
|
|
57
|
+
type: String
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
returns: {
|
|
63
|
+
type: Array,
|
|
64
|
+
of: {
|
|
65
|
+
type: 'Plank',
|
|
66
|
+
properties: {
|
|
67
|
+
type: {
|
|
68
|
+
type: String
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
async execute({ wood }, { service, task }, emit) {
|
|
74
|
+
await sleep(workDuration)
|
|
75
|
+
return Array(4).fill(0).map(() => ({
|
|
76
|
+
type: 'Plank',
|
|
77
|
+
woodType: wood.woodType
|
|
78
|
+
}))
|
|
79
|
+
}
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
const makePlanks = task({
|
|
83
|
+
name: 'makePlanks',
|
|
84
|
+
properties: {
|
|
85
|
+
woodType: {
|
|
86
|
+
type: String,
|
|
87
|
+
validation: ['nonEmpty']
|
|
88
|
+
},
|
|
89
|
+
},
|
|
90
|
+
returns: {
|
|
91
|
+
type: Array,
|
|
92
|
+
of: {
|
|
93
|
+
type: 'Plank',
|
|
94
|
+
properties: {
|
|
95
|
+
type: {
|
|
96
|
+
type: String
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
async execute({ type }, { service, task }, emit) {
|
|
102
|
+
const wood = await workerQueue.add(task.run(getWood, { type }))
|
|
103
|
+
await sleep(pauseDuration)
|
|
104
|
+
const planks = await workerQueue.add(task.run(cutWood, { wood }))
|
|
105
|
+
await sleep(pauseDuration)
|
|
106
|
+
return planks
|
|
107
|
+
}
|
|
108
|
+
})
|
|
109
|
+
|
|
110
|
+
const buildShelter = task({
|
|
111
|
+
name: "buildShelter",
|
|
112
|
+
properties: {
|
|
113
|
+
size: {
|
|
114
|
+
type: Object,
|
|
115
|
+
properties: {
|
|
116
|
+
width: { type: Number },
|
|
117
|
+
height: { type: Number },
|
|
118
|
+
length: { type: Number }
|
|
119
|
+
},
|
|
120
|
+
validation: ['nonEmpty']
|
|
121
|
+
},
|
|
122
|
+
woodType: {
|
|
123
|
+
type: String,
|
|
124
|
+
options: ['acacia', 'oak', 'birch', 'spruce'],
|
|
125
|
+
validation: ['nonEmpty']
|
|
126
|
+
},
|
|
127
|
+
},
|
|
128
|
+
returns: {
|
|
129
|
+
type: 'Shelter',
|
|
130
|
+
properties: {
|
|
131
|
+
walls: {
|
|
132
|
+
type: Array,
|
|
133
|
+
of: {
|
|
134
|
+
type: 'Wall'
|
|
135
|
+
}
|
|
136
|
+
},
|
|
137
|
+
roof: {
|
|
138
|
+
type: 'Roof'
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
},
|
|
142
|
+
async execute({ size: { width, height, length }, woodType }, { service, task }, emit) {
|
|
143
|
+
//// Probably useless
|
|
144
|
+
// compute wall sizes
|
|
145
|
+
const wall1Size = width * height
|
|
146
|
+
const wall2Size = length * height
|
|
147
|
+
// compute roof size
|
|
148
|
+
const roofSize = width * length
|
|
149
|
+
// compute total plank blocks amount
|
|
150
|
+
const howManyPlanks = wall1Size * 2 + wall2Size * 2 + roof
|
|
151
|
+
|
|
152
|
+
let planksCounter = 0
|
|
153
|
+
task.progress(planksCounter, howManyPlanks)
|
|
154
|
+
// gather planks
|
|
155
|
+
const planks = await Promise.all( // do planks in parallel
|
|
156
|
+
Array(howManyPlanks / 4)
|
|
157
|
+
.fill(0)
|
|
158
|
+
.map(
|
|
159
|
+
() => workerQueue.add(async () => {
|
|
160
|
+
const planks = await task.run(makePlanks, { woodType })
|
|
161
|
+
planksCounter += 4
|
|
162
|
+
task.progress(planksCounter, howManyPlanks)
|
|
163
|
+
return planks
|
|
164
|
+
})
|
|
165
|
+
)
|
|
166
|
+
)
|
|
167
|
+
|
|
168
|
+
await sleep(pauseDuration)
|
|
169
|
+
|
|
170
|
+
let placedPlanks = 0
|
|
171
|
+
// build walls
|
|
172
|
+
const walls = await Promise.all( // do walls in parallel
|
|
173
|
+
[wall1, wall2, wall1, wall2].map(
|
|
174
|
+
async (wallSize) => {
|
|
175
|
+
const wall = await workerQueue.add(task.run(buildWall, { planks, wallSize }))
|
|
176
|
+
placedPlanks += wallSize
|
|
177
|
+
task.progress(planksCounter, howManyPlanks)
|
|
178
|
+
return wall
|
|
179
|
+
}
|
|
180
|
+
)
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
await sleep(pauseDuration)
|
|
184
|
+
|
|
185
|
+
// build roof
|
|
186
|
+
const roof = await workerQueue.add(
|
|
187
|
+
async () => {
|
|
188
|
+
const roof = await task.run(buildRoof, { planks })
|
|
189
|
+
placedPlanks += roofSize
|
|
190
|
+
return roof
|
|
191
|
+
}
|
|
192
|
+
)
|
|
193
|
+
|
|
194
|
+
await sleep(pauseDuration)
|
|
195
|
+
|
|
196
|
+
return {
|
|
197
|
+
type: 'Shelter',
|
|
198
|
+
walls,
|
|
199
|
+
roof
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
})
|
|
203
|
+
|
|
204
|
+
definition.action({
|
|
205
|
+
name: "buildShelter",
|
|
206
|
+
properties: {
|
|
207
|
+
size: {
|
|
208
|
+
type: Object,
|
|
209
|
+
properties: {
|
|
210
|
+
width: {
|
|
211
|
+
type: Number,
|
|
212
|
+
default: 4
|
|
213
|
+
},
|
|
214
|
+
height: {
|
|
215
|
+
type: Number,
|
|
216
|
+
default: 3
|
|
217
|
+
},
|
|
218
|
+
length: {
|
|
219
|
+
type: Number,
|
|
220
|
+
default: 4
|
|
221
|
+
}
|
|
222
|
+
},
|
|
223
|
+
validation: ['nonEmpty']
|
|
224
|
+
},
|
|
225
|
+
woodType: {
|
|
226
|
+
type: String,
|
|
227
|
+
validation: ['nonEmpty'],
|
|
228
|
+
options: ['acacia', 'oak', 'birch', 'spruce'],
|
|
229
|
+
default: 'oak'
|
|
230
|
+
},
|
|
231
|
+
place: {
|
|
232
|
+
type: String,
|
|
233
|
+
validation: ['nonEmpty'],
|
|
234
|
+
default: 'forest'
|
|
235
|
+
}
|
|
236
|
+
},
|
|
237
|
+
async execute({ size, woodType, place }, { service, client, command }, emit) {
|
|
238
|
+
await buildShelter.start({ size, woodType, place }, 'userAction', command.id)
|
|
239
|
+
|
|
240
|
+
}
|
|
241
|
+
})
|
|
242
|
+
|
|
243
|
+
const Shelter = definition.model({
|
|
244
|
+
name: "Shelter",
|
|
245
|
+
properties: {
|
|
246
|
+
size: {
|
|
247
|
+
type: Object,
|
|
248
|
+
properties: {
|
|
249
|
+
width: { type: Number },
|
|
250
|
+
height: { type: Number },
|
|
251
|
+
length: { type: Number }
|
|
252
|
+
},
|
|
253
|
+
validation: ['nonEmpty']
|
|
254
|
+
},
|
|
255
|
+
woodType: {
|
|
256
|
+
type: String,
|
|
257
|
+
options: ['acacia', 'oak', 'birch', 'spruce'],
|
|
258
|
+
validation: ['nonEmpty']
|
|
259
|
+
},
|
|
260
|
+
walls: {
|
|
261
|
+
type: Array,
|
|
262
|
+
of: {
|
|
263
|
+
type: 'Wall'
|
|
264
|
+
}
|
|
265
|
+
},
|
|
266
|
+
roof: {
|
|
267
|
+
type: 'Roof'
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
})
|
|
271
|
+
|
|
272
|
+
definition.trigger({
|
|
273
|
+
name: 'taskBuildShelterDone',
|
|
274
|
+
properties: {
|
|
275
|
+
shelter: {
|
|
276
|
+
type: 'Shelter'
|
|
277
|
+
}
|
|
278
|
+
},
|
|
279
|
+
async execute(props, { service, client }, emit) {
|
|
280
|
+
console.log("Task done", props)
|
|
281
|
+
const { result } = props
|
|
282
|
+
console.log("Shelter built", result)
|
|
283
|
+
}
|
|
284
|
+
})
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
export default definition
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
<template>
|
|
3
|
-
<div class="surface-card p-3 shadow-2 border-round">
|
|
4
|
-
{{ d(new Date(), 'long') }}
|
|
5
|
-
</div>
|
|
6
|
-
</template>
|
|
7
|
-
|
|
8
|
-
<script setup lang="ts">
|
|
9
|
-
import { defineProps, toRefs } from 'vue'
|
|
10
|
-
import { useI18n } from 'vue-i18n'
|
|
11
|
-
const { t, d, n } = useI18n()
|
|
12
|
-
|
|
13
|
-
const props = defineProps<{
|
|
14
|
-
time: number
|
|
15
|
-
}>()
|
|
16
|
-
|
|
17
|
-
const { time } = toRefs(props)
|
|
18
|
-
</script>
|
|
19
|
-
|
|
20
|
-
<style scoped>
|
|
21
|
-
|
|
22
|
-
</style>
|