@things-factory/organization 8.0.0-beta.0 → 8.0.0-beta.2

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.
Files changed (71) hide show
  1. package/package.json +6 -6
  2. package/client/bootstrap.ts +0 -32
  3. package/client/component/approval-line-brief.ts +0 -119
  4. package/client/component/approval-line-items-editor-popup.ts +0 -91
  5. package/client/component/approval-line-items-editor.ts +0 -325
  6. package/client/component/approval-line-selector.ts +0 -235
  7. package/client/component/approval-line-templates-manager.ts +0 -229
  8. package/client/component/approval-line-view.ts +0 -122
  9. package/client/component/assignees-editor-popup.ts +0 -79
  10. package/client/component/assignees-editor.ts +0 -217
  11. package/client/component/assignees-view.ts +0 -55
  12. package/client/component/department-selector.ts +0 -151
  13. package/client/component/department-view.ts +0 -107
  14. package/client/component/index.ts +0 -16
  15. package/client/component/recipients-editor-popup.ts +0 -79
  16. package/client/component/recipients-editor.ts +0 -212
  17. package/client/component/recipients-view.ts +0 -55
  18. package/client/filters-form/filter-department-object.ts +0 -11
  19. package/client/filters-form/ox-filter-department-object.ts +0 -136
  20. package/client/grist-editor/grist-editor-approval-line.ts +0 -70
  21. package/client/grist-editor/grist-editor-assignees.ts +0 -69
  22. package/client/grist-editor/grist-editor-department-object.ts +0 -78
  23. package/client/grist-editor/grist-editor-recipients.ts +0 -69
  24. package/client/grist-editor/grist-renderer-approval-line.ts +0 -13
  25. package/client/grist-editor/grist-renderer-assignees.ts +0 -13
  26. package/client/grist-editor/grist-renderer-department-object.ts +0 -13
  27. package/client/grist-editor/grist-renderer-recipients.ts +0 -13
  28. package/client/index.ts +0 -2
  29. package/client/pages/approval-line/common-approval-line-templates-page.ts +0 -382
  30. package/client/pages/approval-line/my-approval-line-templates-page.ts +0 -385
  31. package/client/pages/department/department-importer.ts +0 -87
  32. package/client/pages/department/department-list-page.ts +0 -450
  33. package/client/pages/department/department-tree-page.ts +0 -379
  34. package/client/pages/employee/employee-importer.ts +0 -87
  35. package/client/pages/employee/employee-list-page.ts +0 -772
  36. package/client/pages/employee/employees-by-department.ts +0 -519
  37. package/client/route.ts +0 -27
  38. package/client/tsconfig.json +0 -13
  39. package/client/types/approval-line.ts +0 -52
  40. package/client/types/contact.ts +0 -51
  41. package/client/types/department.ts +0 -29
  42. package/client/types/employee.ts +0 -50
  43. package/client/types/index.ts +0 -5
  44. package/client/types/org-member.ts +0 -27
  45. package/server/controllers/register-employee-as-system-user.ts +0 -136
  46. package/server/index.ts +0 -3
  47. package/server/migrations/1723861013111-seed-organization-codes.ts +0 -127
  48. package/server/migrations/index.ts +0 -9
  49. package/server/routes.ts +0 -26
  50. package/server/service/approval-line/approval-line-item.ts +0 -42
  51. package/server/service/approval-line/approval-line-mutation.ts +0 -394
  52. package/server/service/approval-line/approval-line-query.ts +0 -208
  53. package/server/service/approval-line/approval-line-type.ts +0 -63
  54. package/server/service/approval-line/approval-line.ts +0 -123
  55. package/server/service/approval-line/index.ts +0 -7
  56. package/server/service/department/department-history.ts +0 -141
  57. package/server/service/department/department-mutation.ts +0 -231
  58. package/server/service/department/department-query.ts +0 -131
  59. package/server/service/department/department-type.ts +0 -74
  60. package/server/service/department/department.ts +0 -116
  61. package/server/service/department/event-subscriber.ts +0 -17
  62. package/server/service/department/index.ts +0 -9
  63. package/server/service/employee/employee-history.ts +0 -189
  64. package/server/service/employee/employee-mutation.ts +0 -386
  65. package/server/service/employee/employee-query.ts +0 -172
  66. package/server/service/employee/employee-type.ts +0 -200
  67. package/server/service/employee/employee.ts +0 -193
  68. package/server/service/employee/event-subscriber.ts +0 -17
  69. package/server/service/employee/index.ts +0 -9
  70. package/server/service/index.ts +0 -39
  71. package/server/tsconfig.json +0 -10
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@things-factory/organization",
3
- "version": "8.0.0-beta.0",
3
+ "version": "8.0.0-beta.2",
4
4
  "main": "dist-server/index.js",
5
5
  "browser": "dist-client/index.js",
6
6
  "things-factory": true,
@@ -33,10 +33,10 @@
33
33
  "@operato/graphql": "^8.0.0-beta",
34
34
  "@operato/p13n": "^8.0.0-beta",
35
35
  "@operato/shell": "^8.0.0-beta",
36
- "@things-factory/auth-base": "^8.0.0-beta.0",
37
- "@things-factory/code-ui": "^8.0.0-beta.0",
38
- "@things-factory/contact": "^8.0.0-beta.0",
39
- "@things-factory/shell": "^8.0.0-beta.0"
36
+ "@things-factory/auth-base": "^8.0.0-beta.2",
37
+ "@things-factory/code-ui": "^8.0.0-beta.2",
38
+ "@things-factory/contact": "^8.0.0-beta.2",
39
+ "@things-factory/shell": "^8.0.0-beta.2"
40
40
  },
41
- "gitHead": "add6fb8224b2cb19cbea47bed6a5ecb0424c9a28"
41
+ "gitHead": "f03431a09435511b2595515658f9cb8f78ba4ebb"
42
42
  }
@@ -1,32 +0,0 @@
1
- import { registerEditor, registerRenderer, registerFilterRenderer } from '@operato/data-grist'
2
-
3
- import { FilterResourceCode } from '@operato/app/filters-form/filter-resource-code.js'
4
- import { FilterResourceObject } from '@operato/app/filters-form/filter-resource-object.js'
5
- import { FilterDepartmentObject } from './filters-form/filter-department-object.js'
6
-
7
- import { GristRendererDepartmentObject } from './grist-editor/grist-renderer-department-object'
8
- import { GristEditorDepartmentObject } from './grist-editor/grist-editor-department-object'
9
- import { GristEditorAssignees } from './grist-editor/grist-editor-assignees'
10
- import { GristRendererAssignees } from './grist-editor/grist-renderer-assignees'
11
- import { GristEditorRecipients } from './grist-editor/grist-editor-recipients'
12
- import { GristRendererRecipients } from './grist-editor/grist-renderer-recipients'
13
- import { GristEditorApprovalLine } from './grist-editor/grist-editor-approval-line'
14
- import { GristRendererApprovalLine } from './grist-editor/grist-renderer-approval-line'
15
-
16
- export default function bootstrap() {
17
- /* register grist renderer/editor for id */
18
- registerEditor('department-object', GristEditorDepartmentObject)
19
- registerEditor('approval-line', GristEditorApprovalLine)
20
- registerEditor('assignees', GristEditorAssignees)
21
- registerEditor('recipients', GristEditorRecipients)
22
-
23
- registerRenderer('department-object', GristRendererDepartmentObject)
24
- registerRenderer('approval-line', GristRendererApprovalLine)
25
- registerRenderer('assignees', GristRendererAssignees)
26
- registerRenderer('recipients', GristRendererRecipients)
27
-
28
- registerFilterRenderer('code', [FilterResourceCode])
29
- registerFilterRenderer('object', [FilterResourceObject])
30
- registerFilterRenderer('resource-object', [FilterResourceObject])
31
- registerFilterRenderer('department-object', [FilterDepartmentObject])
32
- }
@@ -1,119 +0,0 @@
1
- import { css, html, LitElement, TemplateResult } from 'lit'
2
- import { customElement, property, query } from 'lit/decorators.js'
3
-
4
- import { i18next, localize } from '@operato/i18n'
5
- import { ApprovalLineItem } from '../types/approval-line'
6
- import { OrgMemberTargetType } from '../types/org-member'
7
-
8
- @customElement('approval-line-brief')
9
- export class ApprovalLineBrief extends localize(i18next)(LitElement) {
10
- static styles = [
11
- css`
12
- :host {
13
- display: block;
14
- }
15
-
16
- ol {
17
- list-style: none;
18
- margin: 0;
19
- padding: 0;
20
- display: flex;
21
- }
22
-
23
- li {
24
- position: relative;
25
- width: 85px;
26
- text-align: center;
27
- color: rgba(255, 255, 255, 0.7);
28
- }
29
-
30
- li div {
31
- text-align: center;
32
- white-space: nowrap;
33
- overflow: hidden;
34
- text-overflow: ellipsis;
35
- }
36
-
37
- span:before {
38
- content: '';
39
- height: 2px;
40
- width: 70px;
41
- display: block;
42
- position: absolute;
43
- margin-left: -70px;
44
- margin-top: 6px;
45
- background-color: rgba(0, 0, 0, 0.4);
46
- }
47
-
48
- span {
49
- display: block;
50
- width: 15px;
51
- height: 15px;
52
- margin: auto;
53
- background-color: rgba(0, 0, 0, 0.4);
54
- border-radius: 50%;
55
- color: var(--md-sys-color-on-primary);
56
- line-height: 1.2;
57
- }
58
-
59
- [past] span {
60
- background-color: var(--md-sys-color-surface);
61
- color: var(--md-sys-color-on-surface);
62
- }
63
-
64
- [current] span {
65
- background-color: #84d600;
66
- color: var(--md-sys-color-on-primary);
67
- }
68
-
69
- [current] {
70
- font-weight: bold;
71
- color: var(--md-sys-color-on-primary);
72
- }
73
-
74
- [past] span:before,
75
- [current] span:before {
76
- background-color: rgba(255, 255, 255, 0.9);
77
- }
78
-
79
- li:first-child span:before {
80
- display: none;
81
- }
82
- `
83
- ]
84
-
85
- @property({ type: Array }) model: ApprovalLineItem[] = []
86
- @property({ type: Number }) current: number = -1
87
-
88
- render() {
89
- const items = this.model || []
90
- const current = this.current
91
-
92
- return html`
93
- <ol>
94
- ${this.model
95
- ? html` <li approver ?current=${this.current <= 0} ?past=${this.current > 0}><span>1</span>ME</li> `
96
- : html``}
97
- ${items.map((item, order) => this.renderItem(item, order + 1))}
98
- </ol>
99
- `
100
- }
101
-
102
- renderItem(item: ApprovalLineItem, order: number): TemplateResult {
103
- const { type, approver } = item
104
- const { name } = approver || {
105
- name: [OrgMemberTargetType.Myself, OrgMemberTargetType.MySupervisor, OrgMemberTargetType.MyDepartment].includes(
106
- type!
107
- )
108
- ? i18next.t(`label.${type}`)
109
- : ''
110
- }
111
-
112
- return html`
113
- <li approver ?current=${this.current == order} ?past=${this.current > order} title=${name || ''}>
114
- <span>${order + 1}</span>
115
- <div>${name}</div>
116
- </li>
117
- `
118
- }
119
- }
@@ -1,91 +0,0 @@
1
- import '@material/web/icon/icon.js'
2
- import { css, html, LitElement } from 'lit'
3
- import { customElement, property, query, state } from 'lit/decorators.js'
4
-
5
- import { i18next, localize } from '@operato/i18n'
6
- import { CommonHeaderStyles } from '@operato/styles'
7
- import { closePopup } from '@operato/popup'
8
- import { OxPrompt } from '@operato/popup/ox-prompt.js'
9
-
10
- import { ApprovalLineItemsEditor } from './approval-line-items-editor'
11
- import { ApprovalLineItem } from '../types/approval-line'
12
-
13
- /**
14
- * 결재선의 각 결재자 리스트를 편집한다.
15
- */
16
- @customElement('approval-line-items-editor-popup')
17
- export class ApprovalLineItemsEditorPopup extends localize(i18next)(LitElement) {
18
- static styles = [
19
- CommonHeaderStyles,
20
- css`
21
- :host {
22
- display: flex;
23
- flex-direction: column;
24
-
25
- background-color: var(--md-sys-color-surface);
26
- }
27
-
28
- approval-line-items-editor {
29
- flex: 1;
30
- }
31
- `
32
- ]
33
-
34
- @property({ type: Array }) value?: ApprovalLineItem[]
35
-
36
- @property({ type: Object }) confirmCallback?: (value?: ApprovalLineItem[] | null) => void
37
- @query('approval-line-items-editor') editor!: ApprovalLineItemsEditor
38
-
39
- /* this.value는 (원인불명으로) 값이 Reset되므로, 변화값을 유지하도록 별도로 changedValue를 사용함 */
40
- private changedValue?: ApprovalLineItem[] = this.value
41
-
42
- render() {
43
- return html`
44
- <approval-line-items-editor
45
- .value=${this.value}
46
- @change=${(e: CustomEvent) => {
47
- this.changedValue = [...e.detail]
48
- }}
49
- ></approval-line-items-editor>
50
-
51
- <div class="footer">
52
- <button @click=${this.onEmpty.bind(this)}>
53
- <md-icon>check_box_outline_blank</md-icon>${i18next.t('button.empty')}
54
- </button>
55
-
56
- <div filler></div>
57
-
58
- <button @click=${this.onCancel.bind(this)}><md-icon>cancel</md-icon>${i18next.t('button.cancel')}</button>
59
- <button @click=${this.onConfirm.bind(this)} done><md-icon>done</md-icon>${i18next.t('button.confirm')}</button>
60
- </div>
61
- `
62
- }
63
-
64
- firstUpdated() {
65
- this.changedValue = this.value
66
- }
67
-
68
- async onEmpty() {
69
- const reaction = await OxPrompt.open({
70
- title: i18next.t('text.are_you_sure'),
71
- text: i18next.t('prompt.sure to empty approval line ?'),
72
- confirmButton: { text: i18next.t('button.confirm') },
73
- cancelButton: { text: i18next.t('button.cancel') }
74
- })
75
-
76
- if (reaction) {
77
- this.confirmCallback && this.confirmCallback(null)
78
- closePopup(this)
79
- }
80
- }
81
-
82
- onCancel() {
83
- closePopup(this)
84
- }
85
-
86
- onConfirm() {
87
- this.confirmCallback && this.confirmCallback(this.changedValue)
88
-
89
- closePopup(this)
90
- }
91
- }
@@ -1,325 +0,0 @@
1
- import './approval-line-view'
2
- import './approval-line-selector'
3
-
4
- import { css, html, LitElement } from 'lit'
5
- import { customElement, property, query, state } from 'lit/decorators.js'
6
-
7
- import { i18next, localize } from '@operato/i18n'
8
- import { DataGrist, FetchOption, getEditor, getRenderer } from '@operato/data-grist'
9
- import { isMobileDevice } from '@operato/utils'
10
- import { ButtonContainerStyles, CommonHeaderStyles } from '@operato/styles'
11
- import { openPopup, PopupHandle } from '@operato/layout'
12
-
13
- import { ApprovalLineView } from './approval-line-view'
14
- import { ApprovalLine, ApprovalLineItem } from '../types/approval-line'
15
-
16
- /**
17
- * 결재선의 각 결재자 리스트를 편집한다.
18
- */
19
- @customElement('approval-line-items-editor')
20
- export class ApprovalLineItemsEditor extends localize(i18next)(LitElement) {
21
- static styles = [
22
- CommonHeaderStyles,
23
- ButtonContainerStyles,
24
- css`
25
- :host {
26
- display: flex;
27
- flex-direction: column;
28
-
29
- background-color: var(--md-sys-color-surface);
30
- }
31
-
32
- approval-line-view {
33
- min-height: 100px;
34
- }
35
-
36
- ox-grist {
37
- flex: 1;
38
- }
39
-
40
- .header {
41
- grid-template-areas: 'filters actions';
42
- }
43
- `
44
- ]
45
-
46
- @property({ type: Array }) value?: ApprovalLineItem[]
47
-
48
- @state() gristConfig?: any
49
-
50
- @query('ox-grist') grist?: DataGrist
51
- @query('approval-line-view') view?: ApprovalLineView
52
-
53
- private popup?: PopupHandle
54
-
55
- render() {
56
- return html`
57
- <approval-line-view .model=${this.value}></approval-line-view>
58
- <ox-grist
59
- .mode=${isMobileDevice() ? 'CARD' : 'GRID'}
60
- .config=${this.gristConfig}
61
- .fetchHandler=${this.fetchHandler.bind(this)}
62
- @record-change=${e => {
63
- this.value = ((this.grist as any)?._data.records || [])
64
- .map(v => {
65
- return { type: v.type, approver: v.approver }
66
- })
67
- .filter(v => v.type)
68
-
69
- this.dispatchEvent(
70
- new CustomEvent('change', {
71
- bubbles: true,
72
- composed: true,
73
- detail: this.value
74
- })
75
- )
76
- }}
77
- >
78
- <div slot="headroom" class="header">
79
- <div class="actions">
80
- <button @click=${this.openSelector.bind(this)}>
81
- <md-icon>content_copy</md-icon>${i18next.t('button.copy from')}
82
- </button>
83
-
84
- <button danger @click=${() => this.deleteDataItems()}>
85
- <md-icon>delete</md-icon>${i18next.t('button.delete')}
86
- </button>
87
- </div>
88
- </div>
89
- </ox-grist>
90
- `
91
- }
92
-
93
- async firstUpdated() {
94
- this.gristConfig = {
95
- list: {
96
- fields: ['type', 'approver']
97
- },
98
- columns: [
99
- { type: 'gutter', gutterName: 'row-selector', multiple: true },
100
- { type: 'gutter', gutterName: 'sequence' },
101
- {
102
- type: 'gutter',
103
- gutterName: 'button',
104
- icon: 'arrow_upward',
105
- handlers: {
106
- click: 'move-up'
107
- }
108
- },
109
- {
110
- type: 'gutter',
111
- gutterName: 'button',
112
- icon: 'arrow_downward',
113
- handlers: {
114
- click: 'move-down'
115
- }
116
- },
117
- {
118
- type: 'select',
119
- name: 'type',
120
- header: i18next.t('field.type'),
121
- record: {
122
- editable: true,
123
- options: ['', 'Employee', 'Department', 'Role', 'MyDepartment', 'MySupervisor', 'Myself']
124
- },
125
- width: 140
126
- },
127
- {
128
- type: 'resource-object',
129
- name: 'approver',
130
- header: i18next.t('field.approver'),
131
- record: {
132
- editable: true,
133
- editor: function (value, column, record, rowIndex, field) {
134
- var options = {}
135
- switch (record.type) {
136
- case 'Employee':
137
- options = {
138
- title: i18next.t('title.employee list'),
139
- pagination: { pages: [50, 100, 200] },
140
- basicArgs: { filters: [{ name: 'active', operator: 'eq', value: 'true' }] },
141
- queryName: 'employees',
142
- columns: [
143
- { name: 'id', hidden: true },
144
- {
145
- name: 'controlNo',
146
- width: 120,
147
- header: { renderer: () => i18next.t('field.control-no') },
148
- filter: 'search',
149
- sortable: true
150
- },
151
- {
152
- name: 'name',
153
- width: 120,
154
- header: { renderer: () => i18next.t('field.name') },
155
- filter: 'search',
156
- sortable: true
157
- },
158
- {
159
- name: 'alias',
160
- width: 150,
161
- header: { renderer: () => i18next.t('label.alias') },
162
- filter: 'search',
163
- sortable: true
164
- },
165
- {
166
- type: 'code',
167
- name: 'type',
168
- width: 110,
169
- header: { renderer: () => i18next.t('label.type') },
170
- record: {
171
- editable: false,
172
- codeName: 'EMPLOYEE_TYPE'
173
- }
174
- },
175
- {
176
- type: 'code',
177
- name: 'jobPosition',
178
- width: 110,
179
- header: { renderer: () => i18next.t('label.job-position') },
180
- record: {
181
- editable: false,
182
- codeName: 'JOB_POSITION'
183
- }
184
- },
185
- {
186
- type: 'code',
187
- name: 'jobResponsibility',
188
- width: 200,
189
- header: { renderer: () => i18next.t('label.job-responsibility') },
190
- record: {
191
- editable: false,
192
- codeName: 'JOB_RESPONSIBILITY'
193
- }
194
- },
195
- {
196
- type: 'date',
197
- name: 'hiredOn',
198
- header: { renderer: () => i18next.t('field.hired-on') },
199
- width: 100
200
- }
201
- ],
202
- list: { fields: ['controlNo', 'name', 'alias', 'hiredOn'] },
203
- valueField: 'id',
204
- nameField: 'name',
205
- descriptionField: 'controlNo'
206
- }
207
- break
208
- case 'Department':
209
- options = {
210
- title: i18next.t('title.department list'),
211
- queryName: 'departments',
212
- columns: [
213
- { name: 'id', hidden: true },
214
- {
215
- name: 'controlNo',
216
- header: { renderer: () => i18next.t('field.control-no') },
217
- filter: 'search'
218
- },
219
- { name: 'name', header: { renderer: () => i18next.t('field.name') }, filter: 'search' }
220
- ],
221
- list: { fields: ['name', 'control-no'] },
222
- valueField: 'id',
223
- nameField: 'name',
224
- descriptionField: 'controlNo'
225
- }
226
- break
227
- case 'Role':
228
- options = {
229
- title: i18next.t('title.lookup role'),
230
- queryName: 'roles'
231
- }
232
- break
233
- default:
234
- return null
235
- }
236
-
237
- var dynamicRecord = { ...column.record, options }
238
-
239
- return getEditor(column.type)(value, { ...column, record: dynamicRecord }, record, rowIndex, field)
240
- },
241
- renderer: function (value, column, record, rowIndex, field) {
242
- var options = {}
243
- switch (record.type) {
244
- case 'Employee':
245
- options = {
246
- valueField: 'id',
247
- nameField: 'name',
248
- descriptionField: 'controlNo'
249
- }
250
- break
251
- case 'Department':
252
- case 'Role':
253
- default:
254
- break
255
- }
256
-
257
- var dynamicRecord = { ...column.record, options }
258
-
259
- return getRenderer(column.type)(value, { ...column, record: dynamicRecord }, record, rowIndex, field)
260
- }
261
- },
262
- width: 180
263
- }
264
- ],
265
- rows: {
266
- selectable: {
267
- multiple: true
268
- }
269
- },
270
- pagination: {
271
- infinite: true
272
- },
273
- sorters: []
274
- }
275
- }
276
-
277
- fetchHandler({ filters, page, limit, sortings = [] }: FetchOption) {
278
- const value = [...(this.value || [])]
279
- this.value = value
280
-
281
- return {
282
- total: value.length,
283
- records: value
284
- }
285
- }
286
-
287
- async deleteDataItems() {
288
- this.grist?.deleteSelectedRecords(false)
289
- }
290
-
291
- openSelector() {
292
- if (this.popup) {
293
- delete this.popup
294
- }
295
-
296
- const confirmCallback = async (selected?: ApprovalLine) => {
297
- this.value = [...(selected?.model || [])]
298
-
299
- this.grist!.fetch()
300
-
301
- this.dispatchEvent(
302
- new CustomEvent('change', {
303
- bubbles: true,
304
- composed: true,
305
- detail: this.value
306
- })
307
- )
308
- }
309
-
310
- this.popup = openPopup(
311
- html` <approval-line-selector .confirmCallback=${confirmCallback.bind(this)}></approval-line-selector> `,
312
- {
313
- backdrop: true,
314
- size: 'large',
315
- search: {
316
- placeholder: i18next.t('title.approval-line template list'),
317
- handler: (instance: any, value: any) => {
318
- /* instance: template instance */
319
- instance.searchText(value)
320
- }
321
- }
322
- }
323
- )
324
- }
325
- }