@things-factory/worklist 6.0.32 → 6.0.33
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/client/pages/activity/activity-list-page.ts +78 -3
- package/client/pages/activity-template/activity-template-list-page.ts +2 -0
- package/client/pages/activity-thread/activity-thread-view-page.ts +293 -0
- package/client/pages/installable-activity/installable-activity-list-page.ts +2 -0
- package/client/pages/todo/done-list-page.ts +3 -3
- package/client/pages/todo/todo-list-page.ts +3 -4
- package/client/route.ts +4 -0
- package/dist-client/components/activity-search-keys-input.d.ts +17 -0
- package/dist-client/components/activity-search-keys-input.js +173 -0
- package/dist-client/components/activity-search-keys-input.js.map +1 -0
- package/dist-client/components/grist-editor-activity-search-key.d.ts +12 -0
- package/dist-client/components/grist-editor-activity-search-key.js +70 -0
- package/dist-client/components/grist-editor-activity-search-key.js.map +1 -0
- package/dist-client/components/popup-activity-search-keys-input.d.ts +17 -0
- package/dist-client/components/popup-activity-search-keys-input.js +177 -0
- package/dist-client/components/popup-activity-search-keys-input.js.map +1 -0
- package/dist-client/pages/activity/activity-list-page.d.ts +3 -1
- package/dist-client/pages/activity/activity-list-page.js +73 -3
- package/dist-client/pages/activity/activity-list-page.js.map +1 -1
- package/dist-client/pages/activity-template/activity-template-list-page.js +2 -0
- package/dist-client/pages/activity-template/activity-template-list-page.js.map +1 -1
- package/dist-client/pages/activity-thread/activity-thread-view-page.d.ts +43 -0
- package/dist-client/pages/activity-thread/activity-thread-view-page.js +268 -0
- package/dist-client/pages/activity-thread/activity-thread-view-page.js.map +1 -0
- package/dist-client/pages/installable-activity/installable-activity-list-page.js +2 -0
- package/dist-client/pages/installable-activity/installable-activity-list-page.js.map +1 -1
- package/dist-client/pages/todo/done-list-page.d.ts +1 -1
- package/dist-client/pages/todo/done-list-page.js +3 -3
- package/dist-client/pages/todo/done-list-page.js.map +1 -1
- package/dist-client/pages/todo/todo-list-page.js +3 -4
- package/dist-client/pages/todo/todo-list-page.js.map +1 -1
- package/dist-client/route.d.ts +1 -1
- package/dist-client/route.js +3 -0
- package/dist-client/route.js.map +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-client/types/domain.d.ts +16 -0
- package/dist-client/types/domain.js +3 -0
- package/dist-client/types/domain.js.map +1 -0
- package/dist-client/types/privilege.d.ts +16 -0
- package/dist-client/types/privilege.js +3 -0
- package/dist-client/types/privilege.js.map +1 -0
- package/dist-client/types/role.d.ts +19 -0
- package/dist-client/types/role.js +3 -0
- package/dist-client/types/role.js.map +1 -0
- package/dist-client/types/user.d.ts +18 -0
- package/dist-client/types/user.js +12 -0
- package/dist-client/types/user.js.map +1 -0
- package/dist-client/types.d.ts +25 -0
- package/dist-client/types.js +38 -0
- package/dist-client/types.js.map +1 -0
- package/dist-server/controllers/activity-installation/callback-registry.js +21 -0
- package/dist-server/controllers/activity-installation/callback-registry.js.map +1 -0
- package/dist-server/controllers/activity-installation-controller.js +17 -0
- package/dist-server/controllers/activity-installation-controller.js.map +1 -0
- package/dist-server/controllers/activity-instance/draft.js +1 -6
- package/dist-server/controllers/activity-instance/draft.js.map +1 -1
- package/dist-server/controllers/activity-instance/post.js +11 -7
- package/dist-server/controllers/activity-instance/post.js.map +1 -1
- package/dist-server/controllers/call-webhook.js +41 -0
- package/dist-server/controllers/call-webhook.js.map +1 -0
- package/dist-server/controllers/common.js +3 -0
- package/dist-server/controllers/common.js.map +1 -1
- package/dist-server/routes.js +30 -0
- package/dist-server/routes.js.map +1 -1
- package/dist-server/service/activity/activity-history.js +5 -0
- package/dist-server/service/activity/activity-history.js.map +1 -1
- package/dist-server/service/activity/activity-mutation.js +92 -0
- package/dist-server/service/activity/activity-mutation.js.map +1 -1
- package/dist-server/service/activity/activity-type.js +8 -0
- package/dist-server/service/activity/activity-type.js.map +1 -1
- package/dist-server/service/activity/activity.js +6 -3
- package/dist-server/service/activity/activity.js.map +1 -1
- package/dist-server/service/activity-approval/event-subscriber.js.map +1 -1
- package/dist-server/service/activity-key-set/activity-key-item-type.js +50 -0
- package/dist-server/service/activity-key-set/activity-key-item-type.js.map +1 -0
- package/dist-server/service/activity-key-set/activity-key-set-mutation.js +127 -0
- package/dist-server/service/activity-key-set/activity-key-set-mutation.js.map +1 -0
- package/dist-server/service/activity-key-set/activity-key-set-query.js +97 -0
- package/dist-server/service/activity-key-set/activity-key-set-query.js.map +1 -0
- package/dist-server/service/activity-key-set/activity-key-set-type.js +74 -0
- package/dist-server/service/activity-key-set/activity-key-set-type.js.map +1 -0
- package/dist-server/service/activity-key-set/activity-key-set.js +86 -0
- package/dist-server/service/activity-key-set/activity-key-set.js.map +1 -0
- package/dist-server/service/activity-key-set/index.js +9 -0
- package/dist-server/service/activity-key-set/index.js.map +1 -0
- package/dist-server/service/activity-template/activity-template-type.js +16 -0
- package/dist-server/service/activity-template/activity-template-type.js.map +1 -1
- package/dist-server/service/activity-template/activity-template.js +10 -0
- package/dist-server/service/activity-template/activity-template.js.map +1 -1
- package/dist-server/service/installable-activity/installable-activity.js +8 -0
- package/dist-server/service/installable-activity/installable-activity.js.map +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -2
- package/server/controllers/activity-instance/draft.ts +4 -4
- package/server/controllers/activity-instance/post.ts +13 -7
- package/server/controllers/common.ts +4 -0
- package/server/routes.ts +47 -0
- package/server/service/activity/activity-history.ts +4 -0
- package/server/service/activity/activity-mutation.ts +102 -0
- package/server/service/activity/activity-type.ts +6 -0
- package/server/service/activity/activity.ts +5 -3
- package/server/service/activity-approval/event-subscriber.ts +1 -1
- package/server/service/activity-template/activity-template-type.ts +12 -0
- package/server/service/activity-template/activity-template.ts +8 -0
- package/server/service/installable-activity/installable-activity.ts +6 -0
- package/things-factory.config.js +1 -0
- package/translations/en.json +2 -0
- package/translations/ko.json +2 -0
- package/translations/ms.json +2 -0
- package/translations/zh.json +2 -0
- package/client/pages/activity-thread/activity-thread-view.ts +0 -102
|
@@ -10,7 +10,7 @@ import moment from 'moment-timezone'
|
|
|
10
10
|
import { DataGrist, getEditor, getRenderer } from '@operato/data-grist'
|
|
11
11
|
import { client } from '@operato/graphql'
|
|
12
12
|
import { i18next, localize } from '@operato/i18n'
|
|
13
|
-
import { openPopup } from '@operato/layout'
|
|
13
|
+
import { notify, openPopup } from '@operato/layout'
|
|
14
14
|
import { PageView, store } from '@operato/shell'
|
|
15
15
|
import { CommonButtonStyles, CommonGristStyles, ScrollbarStyles } from '@operato/styles'
|
|
16
16
|
import { isMobileDevice } from '@operato/utils'
|
|
@@ -67,7 +67,7 @@ export class ActivityListPage extends connect(store)(localize(i18next)(PageView)
|
|
|
67
67
|
actions: [
|
|
68
68
|
{
|
|
69
69
|
title: i18next.t('button.save'),
|
|
70
|
-
action: this.
|
|
70
|
+
action: this.updateActivity.bind(this),
|
|
71
71
|
...CommonButtonStyles.save
|
|
72
72
|
}
|
|
73
73
|
]
|
|
@@ -120,6 +120,24 @@ export class ActivityListPage extends connect(store)(localize(i18next)(PageView)
|
|
|
120
120
|
columns: [
|
|
121
121
|
{ type: 'gutter', gutterName: 'sequence' },
|
|
122
122
|
{ type: 'gutter', gutterName: 'row-selector', multiple: true },
|
|
123
|
+
{
|
|
124
|
+
type: 'gutter',
|
|
125
|
+
gutterName: 'button',
|
|
126
|
+
icon: record => (!record || !record.name ? '' : record.scheduleId ? 'pause' : 'play_arrow'),
|
|
127
|
+
handlers: {
|
|
128
|
+
click: (columns, data, column, record, rowIndex) => {
|
|
129
|
+
if (!record || !record.name) {
|
|
130
|
+
/* TODO record가 새로 추가된 것이면 리턴하도록 한다. */
|
|
131
|
+
return
|
|
132
|
+
}
|
|
133
|
+
if (record.scheduleId) {
|
|
134
|
+
this.stopActivitySchedule(record)
|
|
135
|
+
} else {
|
|
136
|
+
this.startActivitySchedule(record)
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
},
|
|
123
141
|
{
|
|
124
142
|
type: 'gutter',
|
|
125
143
|
gutterName: 'button',
|
|
@@ -538,11 +556,14 @@ export class ActivityListPage extends connect(store)(localize(i18next)(PageView)
|
|
|
538
556
|
}
|
|
539
557
|
uiType
|
|
540
558
|
uiSource
|
|
559
|
+
viewType
|
|
560
|
+
viewSource
|
|
541
561
|
reportType
|
|
542
562
|
reportSource
|
|
543
563
|
startable
|
|
544
564
|
schedule
|
|
545
565
|
timezone
|
|
566
|
+
scheduleId
|
|
546
567
|
standardTime
|
|
547
568
|
leadTime
|
|
548
569
|
cycleTime
|
|
@@ -570,7 +591,7 @@ export class ActivityListPage extends connect(store)(localize(i18next)(PageView)
|
|
|
570
591
|
}
|
|
571
592
|
}
|
|
572
593
|
|
|
573
|
-
async
|
|
594
|
+
async updateActivity() {
|
|
574
595
|
let patches = this.grist?.dirtyRecords
|
|
575
596
|
if (patches && patches.length) {
|
|
576
597
|
patches = patches.map(patch => {
|
|
@@ -605,4 +626,58 @@ export class ActivityListPage extends connect(store)(localize(i18next)(PageView)
|
|
|
605
626
|
}
|
|
606
627
|
}
|
|
607
628
|
}
|
|
629
|
+
|
|
630
|
+
async startActivitySchedule(record) {
|
|
631
|
+
var response = await client.mutate({
|
|
632
|
+
mutation: gql`
|
|
633
|
+
mutation ($activityId: String!) {
|
|
634
|
+
startActivitySchedule(activityId: $activityId) {
|
|
635
|
+
scheduleId
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
`,
|
|
639
|
+
variables: {
|
|
640
|
+
activityId: record.id
|
|
641
|
+
}
|
|
642
|
+
})
|
|
643
|
+
|
|
644
|
+
const scheduleId = response.data.startActivitySchedule.scheduleId
|
|
645
|
+
record.scheduleId = scheduleId
|
|
646
|
+
|
|
647
|
+
notify({
|
|
648
|
+
level: 'info',
|
|
649
|
+
message: `${record.scheduleId ? 'success' : 'fail'} to start activity schedule : ${record.name}`
|
|
650
|
+
})
|
|
651
|
+
|
|
652
|
+
this.grist.fetch()
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
async stopActivitySchedule(record) {
|
|
656
|
+
var response = await client.mutate({
|
|
657
|
+
mutation: gql`
|
|
658
|
+
mutation ($activityId: String!) {
|
|
659
|
+
stopActivitySchedule(activityId: $activityId) {
|
|
660
|
+
scheduleId
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
`,
|
|
664
|
+
variables: {
|
|
665
|
+
activityId: record.id
|
|
666
|
+
}
|
|
667
|
+
})
|
|
668
|
+
|
|
669
|
+
if (!response.errors) {
|
|
670
|
+
notify({
|
|
671
|
+
level: 'info',
|
|
672
|
+
message: `success to stop activity schedule : ${record.name}`
|
|
673
|
+
})
|
|
674
|
+
} else {
|
|
675
|
+
notify({
|
|
676
|
+
level: 'error',
|
|
677
|
+
message: `${response.errors.map(error => error.message).join('\n')}`
|
|
678
|
+
})
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
this.grist.fetch()
|
|
682
|
+
}
|
|
608
683
|
}
|
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
import '@operato/property-editor/ox-properties-dynamic-view.js'
|
|
2
|
+
import '@operato/board/ox-board-viewer.js'
|
|
3
|
+
|
|
4
|
+
import gql from 'graphql-tag'
|
|
5
|
+
import { css, html } from 'lit'
|
|
6
|
+
import { unsafeHTML } from 'lit-html/directives/unsafe-html.js'
|
|
7
|
+
import { customElement, property, query, state } from 'lit/decorators.js'
|
|
8
|
+
import { keyed } from 'lit/directives/keyed.js'
|
|
9
|
+
import { connect } from 'pwa-helpers/connect-mixin.js'
|
|
10
|
+
|
|
11
|
+
import { client } from '@operato/graphql'
|
|
12
|
+
import { i18next, localize } from '@operato/i18n'
|
|
13
|
+
import { PageView, store } from '@operato/shell'
|
|
14
|
+
import { CommonGristStyles, ScrollbarStyles } from '@operato/styles'
|
|
15
|
+
import { provider } from '@things-factory/board-ui'
|
|
16
|
+
|
|
17
|
+
const ActivityThreadFetchResult = `\
|
|
18
|
+
{
|
|
19
|
+
id
|
|
20
|
+
state
|
|
21
|
+
dueAt
|
|
22
|
+
assignedAt
|
|
23
|
+
assignee {
|
|
24
|
+
id
|
|
25
|
+
name
|
|
26
|
+
}
|
|
27
|
+
output
|
|
28
|
+
round
|
|
29
|
+
activityInstance {
|
|
30
|
+
id
|
|
31
|
+
name
|
|
32
|
+
description
|
|
33
|
+
state
|
|
34
|
+
activity {
|
|
35
|
+
model {
|
|
36
|
+
name
|
|
37
|
+
description
|
|
38
|
+
active
|
|
39
|
+
tag
|
|
40
|
+
inout
|
|
41
|
+
type
|
|
42
|
+
unit
|
|
43
|
+
options
|
|
44
|
+
quantifier
|
|
45
|
+
spec
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
approvalLine {
|
|
49
|
+
type
|
|
50
|
+
value
|
|
51
|
+
approver {
|
|
52
|
+
id
|
|
53
|
+
name
|
|
54
|
+
description
|
|
55
|
+
controlNo
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
thumbnail
|
|
59
|
+
input
|
|
60
|
+
output
|
|
61
|
+
viewType
|
|
62
|
+
viewSource
|
|
63
|
+
dueAt
|
|
64
|
+
createdAt
|
|
65
|
+
}
|
|
66
|
+
}`
|
|
67
|
+
|
|
68
|
+
export const ActivityThreadStatus = {
|
|
69
|
+
Assigned: 'assigned',
|
|
70
|
+
Started: 'started',
|
|
71
|
+
Delegated: 'delegated',
|
|
72
|
+
Rejected: 'rejected',
|
|
73
|
+
Ended: 'ended',
|
|
74
|
+
Aborted: 'aborted'
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
@customElement('activity-thread-view-page')
|
|
78
|
+
export class ActivityThreadViewPage extends connect(store)(localize(i18next)(PageView)) {
|
|
79
|
+
static styles = [
|
|
80
|
+
ScrollbarStyles,
|
|
81
|
+
CommonGristStyles,
|
|
82
|
+
css`
|
|
83
|
+
:host {
|
|
84
|
+
display: flex;
|
|
85
|
+
flex-direction: column;
|
|
86
|
+
|
|
87
|
+
width: 100%;
|
|
88
|
+
padding: 5px;
|
|
89
|
+
overflow: auto;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
ox-board-viewer {
|
|
93
|
+
width: 100%;
|
|
94
|
+
height: 100%;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
#custom-content {
|
|
98
|
+
flex: 1;
|
|
99
|
+
}
|
|
100
|
+
`
|
|
101
|
+
]
|
|
102
|
+
|
|
103
|
+
@state() activityThread: any
|
|
104
|
+
@state() board: any
|
|
105
|
+
|
|
106
|
+
get context() {
|
|
107
|
+
return {
|
|
108
|
+
title: this.lifecycle?.params?.['title'] || i18next.t('title.activity'),
|
|
109
|
+
help: 'worklist/activity',
|
|
110
|
+
actions: [],
|
|
111
|
+
activityThread: this.activityThread
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
render() {
|
|
116
|
+
return html` ${this.activityContent()}`
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
activityContent() {
|
|
120
|
+
switch (this.activityThread?.activityInstance?.viewType) {
|
|
121
|
+
case 'template':
|
|
122
|
+
return this.templateContent()
|
|
123
|
+
case 'generated':
|
|
124
|
+
return this.generatedContent()
|
|
125
|
+
case 'board':
|
|
126
|
+
return this.boardContent()
|
|
127
|
+
case 'custom-element':
|
|
128
|
+
return this.customElementContent()
|
|
129
|
+
case 'page':
|
|
130
|
+
case 'external':
|
|
131
|
+
default:
|
|
132
|
+
return html``
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
templateContent() {
|
|
137
|
+
const { viewSource: template } = this.activityThread?.activityInstance
|
|
138
|
+
return unsafeHTML(template)
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
getInputSpec() {
|
|
142
|
+
const model = this.activityThread?.activityInstance?.activity?.model
|
|
143
|
+
|
|
144
|
+
return (model || [])
|
|
145
|
+
.filter(item => item.inout === 'in' || item.inout === 'inout')
|
|
146
|
+
.map(item => {
|
|
147
|
+
return {
|
|
148
|
+
...item,
|
|
149
|
+
label: item.name
|
|
150
|
+
}
|
|
151
|
+
})
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
getOutputSpec() {
|
|
155
|
+
const model = this.activityThread?.activityInstance?.activity?.model
|
|
156
|
+
|
|
157
|
+
return (model || [])
|
|
158
|
+
.filter(item => item.inout === 'inout' || item.inout === 'out')
|
|
159
|
+
.map(item => {
|
|
160
|
+
return {
|
|
161
|
+
...item,
|
|
162
|
+
label: item.name
|
|
163
|
+
}
|
|
164
|
+
})
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
generatedContent() {
|
|
168
|
+
var { output, activityInstance } = this.activityThread || {}
|
|
169
|
+
var { input } = activityInstance || {}
|
|
170
|
+
|
|
171
|
+
const inputSpec = this.getInputSpec()
|
|
172
|
+
const outputSpec = this.getOutputSpec()
|
|
173
|
+
|
|
174
|
+
if (!output) {
|
|
175
|
+
output = inputSpec
|
|
176
|
+
.filter(item => item.inout === 'inout')
|
|
177
|
+
.reduce((inout, item) => {
|
|
178
|
+
inout[item.name] = input[item.name]
|
|
179
|
+
return inout
|
|
180
|
+
}, {})
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
return keyed(
|
|
184
|
+
this.activityThread.id,
|
|
185
|
+
html`
|
|
186
|
+
<fieldset>
|
|
187
|
+
<legend>Input</legend>
|
|
188
|
+
<ox-properties-dynamic-view
|
|
189
|
+
data-name="input"
|
|
190
|
+
.props=${inputSpec}
|
|
191
|
+
.value=${input}
|
|
192
|
+
></ox-properties-dynamic-view>
|
|
193
|
+
</fieldset>
|
|
194
|
+
|
|
195
|
+
<fieldset>
|
|
196
|
+
<legend>Output</legend>
|
|
197
|
+
<ox-properties-dynamic-view
|
|
198
|
+
data-name="output"
|
|
199
|
+
.props=${outputSpec}
|
|
200
|
+
.value=${output}
|
|
201
|
+
@property-change=${e => (this.activityThread.output = e.currentTarget.value)}
|
|
202
|
+
></ox-properties-dynamic-view>
|
|
203
|
+
</fieldset>
|
|
204
|
+
`
|
|
205
|
+
)
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
boardContent() {
|
|
209
|
+
const { output, activityInstance } = this.activityThread
|
|
210
|
+
const { viewSource: boardId, input } = activityInstance || {}
|
|
211
|
+
|
|
212
|
+
if (!this.board || this.board.id !== boardId) {
|
|
213
|
+
this.board = {
|
|
214
|
+
id: boardId
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/*
|
|
219
|
+
ox-board-viewer에서 provider에 의해 공급되는 board가 각 id별로 instance를 하나씩 밖에 가지지 않으므로,
|
|
220
|
+
동일한 id의 보드를 다른 page에 뺏기는 경우가 있다.
|
|
221
|
+
따라서, Page가 active될 때마다 타임스탬프를 refresh key로 설정하였다.
|
|
222
|
+
*/
|
|
223
|
+
return keyed(
|
|
224
|
+
this.activityThread.id,
|
|
225
|
+
html`
|
|
226
|
+
<ox-board-viewer
|
|
227
|
+
style="background-color: white;"
|
|
228
|
+
.board=${this.board}
|
|
229
|
+
.provider=${provider}
|
|
230
|
+
.values=${{ ...input, ...output }}
|
|
231
|
+
hide-fullscreen
|
|
232
|
+
hide-navigation
|
|
233
|
+
></ox-board-viewer>
|
|
234
|
+
`
|
|
235
|
+
)
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
customElementContent() {
|
|
239
|
+
const { output, activityInstance } = this.activityThread
|
|
240
|
+
const { viewSource: tagName, input } = activityInstance || {}
|
|
241
|
+
|
|
242
|
+
const element = document.createElement(tagName)
|
|
243
|
+
element.id = 'custom-content'
|
|
244
|
+
element.input = input
|
|
245
|
+
element.output = output
|
|
246
|
+
element.addEventListener('change', (e: CustomEvent) => {
|
|
247
|
+
this.activityThread.output = e.detail
|
|
248
|
+
})
|
|
249
|
+
|
|
250
|
+
return element
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
@query('ox-board-viewer') oxBoardViewer: any
|
|
254
|
+
|
|
255
|
+
getOutputFromBoard() {
|
|
256
|
+
const outputSpec = this.getOutputSpec()
|
|
257
|
+
const data = this.oxBoardViewer.getSceneValues()
|
|
258
|
+
|
|
259
|
+
return outputSpec.reduce((output, spec) => {
|
|
260
|
+
output[spec.name] = data[spec.name]
|
|
261
|
+
return output
|
|
262
|
+
}, {})
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
updated(changes) {
|
|
266
|
+
if (changes.has('activityThread')) {
|
|
267
|
+
this.updateContext()
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
async pageUpdated(changes, lifecycle, changedBefore) {
|
|
272
|
+
if (this.active) {
|
|
273
|
+
this.fetchActivityThread(lifecycle.resourceId)
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
async fetchActivityThread(id) {
|
|
278
|
+
const response = await client.query({
|
|
279
|
+
query: gql`
|
|
280
|
+
query activityThread($id: String!) {
|
|
281
|
+
activityThread(id: $id) ${ActivityThreadFetchResult}
|
|
282
|
+
}
|
|
283
|
+
`,
|
|
284
|
+
variables: {
|
|
285
|
+
id
|
|
286
|
+
}
|
|
287
|
+
})
|
|
288
|
+
|
|
289
|
+
this.activityThread = response.data.activityThread
|
|
290
|
+
|
|
291
|
+
this.updateContext()
|
|
292
|
+
}
|
|
293
|
+
}
|
|
@@ -121,7 +121,7 @@ export class DoneListPage extends connect(store)(localize(i18next)(PageView)) {
|
|
|
121
121
|
handlers: {
|
|
122
122
|
click: (columns, data, column, record, rowIndex) => {
|
|
123
123
|
const { id } = record
|
|
124
|
-
this.
|
|
124
|
+
this.openActivityThreadViewPage(record)
|
|
125
125
|
}
|
|
126
126
|
}
|
|
127
127
|
},
|
|
@@ -338,7 +338,7 @@ export class DoneListPage extends connect(store)(localize(i18next)(PageView)) {
|
|
|
338
338
|
}
|
|
339
339
|
}
|
|
340
340
|
|
|
341
|
-
|
|
342
|
-
navigate(`activity-thread/${activityThread.id}?title=${activityThread.name}`)
|
|
341
|
+
openActivityThreadViewPage(activityThread) {
|
|
342
|
+
navigate(`activity-thread-view/${activityThread.id}?title=${activityThread.name}`)
|
|
343
343
|
}
|
|
344
344
|
}
|
|
@@ -185,13 +185,12 @@ export class TodoListPage extends connect(store)(localize(i18next)(PageView)) {
|
|
|
185
185
|
record: {
|
|
186
186
|
editable: false,
|
|
187
187
|
options: [
|
|
188
|
-
{ display: 'Draft', value: 'draft' },
|
|
189
|
-
{ display: 'Posted', value: 'posted' },
|
|
190
|
-
{ display: 'WaitingAssignment', value: 'waiting-assignment' },
|
|
191
188
|
{ display: 'Assigned', value: 'assigned' },
|
|
192
189
|
{ display: 'Started', value: 'started' },
|
|
193
|
-
{ display: '
|
|
190
|
+
{ display: 'Delegated', value: 'delegated' },
|
|
191
|
+
{ display: 'Submitted', value: 'submitted' },
|
|
194
192
|
{ display: 'Escalated', value: 'escalated' },
|
|
193
|
+
{ display: 'Rejected', value: 'rejected' },
|
|
195
194
|
{ display: 'Ended', value: 'ended' },
|
|
196
195
|
{ display: 'Aborted', value: 'aborted' }
|
|
197
196
|
]
|
package/client/route.ts
CHANGED
|
@@ -56,6 +56,10 @@ export default function route(page: string) {
|
|
|
56
56
|
import('./pages/activity-thread/activity-thread-page.js')
|
|
57
57
|
return page
|
|
58
58
|
|
|
59
|
+
case 'activity-thread-view':
|
|
60
|
+
import('./pages/activity-thread/activity-thread-view-page.js')
|
|
61
|
+
return page
|
|
62
|
+
|
|
59
63
|
case 'activity-approval':
|
|
60
64
|
import('./pages/activity-approval/activity-approval-page.js')
|
|
61
65
|
return page
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { LitElement } from 'lit';
|
|
2
|
+
import { FetchOption } from '@operato/data-grist';
|
|
3
|
+
import { ActivitySearchKeyItem } from '../types';
|
|
4
|
+
declare const ActivitySearchKeysInput_base: (new (...args: any[]) => LitElement) & typeof LitElement;
|
|
5
|
+
export declare class ActivitySearchKeysInput extends ActivitySearchKeysInput_base {
|
|
6
|
+
static styles: import("lit").CSSResult[];
|
|
7
|
+
value: ActivitySearchKeyItem[];
|
|
8
|
+
gristConfig: any;
|
|
9
|
+
private grist;
|
|
10
|
+
render(): import("lit-html").TemplateResult<1>;
|
|
11
|
+
fetchHandler({ filters, page, limit, sortings }: FetchOption): Promise<{
|
|
12
|
+
total: number;
|
|
13
|
+
records: ActivitySearchKeyItem[];
|
|
14
|
+
}>;
|
|
15
|
+
private updateSearchKeyItems;
|
|
16
|
+
}
|
|
17
|
+
export {};
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import { __decorate, __metadata } from "tslib";
|
|
2
|
+
import { css, html, LitElement } from 'lit';
|
|
3
|
+
import { customElement, property, query, state } from 'lit/decorators.js';
|
|
4
|
+
import { i18next, localize } from '@operato/i18n';
|
|
5
|
+
import { isMobileDevice } from '@operato/utils';
|
|
6
|
+
import { DataGrist } from '@operato/data-grist';
|
|
7
|
+
let ActivitySearchKeysInput = class ActivitySearchKeysInput extends localize(i18next)(LitElement) {
|
|
8
|
+
constructor() {
|
|
9
|
+
super(...arguments);
|
|
10
|
+
this.value = [];
|
|
11
|
+
this.gristConfig = {
|
|
12
|
+
list: { fields: ['name', 'description', 'active'] },
|
|
13
|
+
columns: [
|
|
14
|
+
{ type: 'gutter', gutterName: 'row-selector', multiple: true },
|
|
15
|
+
{
|
|
16
|
+
type: 'gutter',
|
|
17
|
+
gutterName: 'button',
|
|
18
|
+
icon: 'add',
|
|
19
|
+
handlers: {
|
|
20
|
+
click: 'record-copy'
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
type: 'gutter',
|
|
25
|
+
gutterName: 'button',
|
|
26
|
+
icon: 'delete',
|
|
27
|
+
handlers: {
|
|
28
|
+
click: 'record-delete'
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
{ type: 'gutter', gutterName: 'sequence' },
|
|
32
|
+
{
|
|
33
|
+
type: 'gutter',
|
|
34
|
+
gutterName: 'button',
|
|
35
|
+
icon: 'arrow_upward',
|
|
36
|
+
handlers: {
|
|
37
|
+
click: 'move-up'
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
type: 'gutter',
|
|
42
|
+
gutterName: 'button',
|
|
43
|
+
icon: 'arrow_downward',
|
|
44
|
+
handlers: {
|
|
45
|
+
click: 'move-down'
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
type: 'string',
|
|
50
|
+
name: 'name',
|
|
51
|
+
header: i18next.t('field.name'),
|
|
52
|
+
record: {
|
|
53
|
+
editable: true
|
|
54
|
+
},
|
|
55
|
+
width: 140
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
type: 'string',
|
|
59
|
+
name: 'description',
|
|
60
|
+
header: i18next.t('field.description'),
|
|
61
|
+
record: {
|
|
62
|
+
editable: true
|
|
63
|
+
},
|
|
64
|
+
width: 180
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
type: 'string',
|
|
68
|
+
name: 'inputKey',
|
|
69
|
+
header: i18next.t('field.input-key'),
|
|
70
|
+
record: {
|
|
71
|
+
editable: true
|
|
72
|
+
},
|
|
73
|
+
width: 180
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
type: 'string',
|
|
77
|
+
name: 'tKey',
|
|
78
|
+
header: i18next.t('field.t-key'),
|
|
79
|
+
record: {
|
|
80
|
+
editable: true
|
|
81
|
+
},
|
|
82
|
+
width: 180
|
|
83
|
+
}
|
|
84
|
+
],
|
|
85
|
+
rows: {
|
|
86
|
+
selectable: {
|
|
87
|
+
multiple: true
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
pagination: {
|
|
91
|
+
infinite: true
|
|
92
|
+
},
|
|
93
|
+
sorters: []
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
render() {
|
|
97
|
+
return html `
|
|
98
|
+
<ox-grist
|
|
99
|
+
.mode=${isMobileDevice() ? 'LIST' : 'GRID'}
|
|
100
|
+
.config=${this.gristConfig}
|
|
101
|
+
.fetchHandler=${this.fetchHandler.bind(this)}
|
|
102
|
+
></ox-grist>
|
|
103
|
+
<div class="button-container">
|
|
104
|
+
<mwc-button raised @click=${this.updateSearchKeyItems.bind(this)}>${i18next.t('button.save')}</mwc-button>
|
|
105
|
+
</div>
|
|
106
|
+
`;
|
|
107
|
+
}
|
|
108
|
+
async fetchHandler({ filters, page, limit, sortings = [] }) {
|
|
109
|
+
const records = this.value || [];
|
|
110
|
+
return {
|
|
111
|
+
total: records.length,
|
|
112
|
+
records
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
async updateSearchKeyItems() {
|
|
116
|
+
this.grist.commit();
|
|
117
|
+
this.value = this.grist.data.records.map(({ name, description, inputKey, tKey }) => {
|
|
118
|
+
return {
|
|
119
|
+
name,
|
|
120
|
+
description,
|
|
121
|
+
inputKey,
|
|
122
|
+
tKey
|
|
123
|
+
};
|
|
124
|
+
});
|
|
125
|
+
this.dispatchEvent(new CustomEvent('change', {
|
|
126
|
+
detail: this.value
|
|
127
|
+
}));
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
ActivitySearchKeysInput.styles = [
|
|
131
|
+
css `
|
|
132
|
+
:host {
|
|
133
|
+
display: flex;
|
|
134
|
+
flex-direction: column;
|
|
135
|
+
|
|
136
|
+
background-color: #fff;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
ox-grist {
|
|
140
|
+
flex: 1;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
.button-container {
|
|
144
|
+
display: flex;
|
|
145
|
+
margin-left: auto;
|
|
146
|
+
padding: var(--padding-default);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
[danger] {
|
|
150
|
+
--mdc-theme-primary: var(--mdc-danger-button-primary-color);
|
|
151
|
+
}
|
|
152
|
+
mwc-button {
|
|
153
|
+
margin-left: var(--margin-default);
|
|
154
|
+
}
|
|
155
|
+
`
|
|
156
|
+
];
|
|
157
|
+
__decorate([
|
|
158
|
+
property({ type: Array }),
|
|
159
|
+
__metadata("design:type", Array)
|
|
160
|
+
], ActivitySearchKeysInput.prototype, "value", void 0);
|
|
161
|
+
__decorate([
|
|
162
|
+
state(),
|
|
163
|
+
__metadata("design:type", Object)
|
|
164
|
+
], ActivitySearchKeysInput.prototype, "gristConfig", void 0);
|
|
165
|
+
__decorate([
|
|
166
|
+
query('ox-grist'),
|
|
167
|
+
__metadata("design:type", DataGrist)
|
|
168
|
+
], ActivitySearchKeysInput.prototype, "grist", void 0);
|
|
169
|
+
ActivitySearchKeysInput = __decorate([
|
|
170
|
+
customElement('activity-search-keys-input')
|
|
171
|
+
], ActivitySearchKeysInput);
|
|
172
|
+
export { ActivitySearchKeysInput };
|
|
173
|
+
//# sourceMappingURL=activity-search-keys-input.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"activity-search-keys-input.js","sourceRoot":"","sources":["../../client/components/activity-search-keys-input.ts"],"names":[],"mappings":"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","sourcesContent":["import { css, html, LitElement } from 'lit'\nimport { customElement, property, query, state } from 'lit/decorators.js'\n\nimport { i18next, localize } from '@operato/i18n'\nimport { isMobileDevice } from '@operato/utils'\nimport { getEditor, getRenderer, ColumnConfig, DataGrist, FetchOption, SortersControl } from '@operato/data-grist'\nimport { ActivitySearchKeyItem } from '../types'\n\n@customElement('activity-search-keys-input')\nexport class ActivitySearchKeysInput extends localize(i18next)(LitElement) {\n static styles = [\n css`\n :host {\n display: flex;\n flex-direction: column;\n\n background-color: #fff;\n }\n\n ox-grist {\n flex: 1;\n }\n\n .button-container {\n display: flex;\n margin-left: auto;\n padding: var(--padding-default);\n }\n\n [danger] {\n --mdc-theme-primary: var(--mdc-danger-button-primary-color);\n }\n mwc-button {\n margin-left: var(--margin-default);\n }\n `\n ]\n\n @property({ type: Array }) value: ActivitySearchKeyItem[] = []\n\n @state() gristConfig: any = {\n list: { fields: ['name', 'description', 'active'] },\n columns: [\n { type: 'gutter', gutterName: 'row-selector', multiple: true },\n {\n type: 'gutter',\n gutterName: 'button',\n icon: 'add',\n handlers: {\n click: 'record-copy'\n }\n },\n {\n type: 'gutter',\n gutterName: 'button',\n icon: 'delete',\n handlers: {\n click: 'record-delete'\n }\n },\n { type: 'gutter', gutterName: 'sequence' },\n {\n type: 'gutter',\n gutterName: 'button',\n icon: 'arrow_upward',\n handlers: {\n click: 'move-up'\n }\n },\n {\n type: 'gutter',\n gutterName: 'button',\n icon: 'arrow_downward',\n handlers: {\n click: 'move-down'\n }\n },\n {\n type: 'string',\n name: 'name',\n header: i18next.t('field.name'),\n record: {\n editable: true\n },\n width: 140\n },\n {\n type: 'string',\n name: 'description',\n header: i18next.t('field.description'),\n record: {\n editable: true\n },\n width: 180\n },\n {\n type: 'string',\n name: 'inputKey',\n header: i18next.t('field.input-key'),\n record: {\n editable: true\n },\n width: 180\n },\n {\n type: 'string',\n name: 'tKey',\n header: i18next.t('field.t-key'),\n record: {\n editable: true\n },\n width: 180\n }\n ],\n rows: {\n selectable: {\n multiple: true\n }\n },\n pagination: {\n infinite: true\n },\n sorters: []\n }\n\n @query('ox-grist') private grist!: DataGrist\n\n render() {\n return html`\n <ox-grist\n .mode=${isMobileDevice() ? 'LIST' : 'GRID'}\n .config=${this.gristConfig}\n .fetchHandler=${this.fetchHandler.bind(this)}\n ></ox-grist>\n <div class=\"button-container\">\n <mwc-button raised @click=${this.updateSearchKeyItems.bind(this)}>${i18next.t('button.save')}</mwc-button>\n </div>\n `\n }\n\n async fetchHandler({ filters, page, limit, sortings = [] }: FetchOption) {\n const records = this.value || []\n return {\n total: records.length,\n records\n }\n }\n\n private async updateSearchKeyItems() {\n this.grist.commit()\n\n this.value = this.grist.data.records.map(({ name, description, inputKey, tKey }) => {\n return {\n name,\n description,\n inputKey,\n tKey\n }\n })\n\n this.dispatchEvent(\n new CustomEvent('change', {\n detail: this.value\n })\n )\n }\n}\n"]}
|