@things-factory/worklist-client 8.0.0-beta.8 → 8.0.0

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 (44) hide show
  1. package/client/bootstrap.ts +1 -0
  2. package/client/index.ts +0 -0
  3. package/client/pages/work-center/work-center-importer.ts +87 -0
  4. package/client/pages/work-center/work-center-list-page.ts +323 -0
  5. package/client/pages/work-center/work-center-page.ts +95 -0
  6. package/client/route.ts +7 -0
  7. package/client/tsconfig.json +13 -0
  8. package/dist-client/tsconfig.tsbuildinfo +1 -1
  9. package/dist-server/tsconfig.tsbuildinfo +1 -1
  10. package/package.json +7 -7
  11. package/server/controllers/activity-registry.ts +17 -0
  12. package/server/controllers/graphql-client.ts +67 -0
  13. package/server/controllers/index.ts +4 -0
  14. package/server/controllers/webhooks/decorators.ts +18 -0
  15. package/server/controllers/webhooks/index.ts +30 -0
  16. package/server/controllers/work-center/connect-work-center.ts +15 -0
  17. package/server/controllers/work-center/get-work-center.ts +9 -0
  18. package/server/controllers/work-center/index.ts +2 -0
  19. package/server/controllers/worklist-api/assign-activity-thread.ts +3 -0
  20. package/server/controllers/worklist-api/draft-activity-instance.ts +3 -0
  21. package/server/controllers/worklist-api/get-activity-list.ts +3 -0
  22. package/server/controllers/worklist-api/get-activity.ts +3 -0
  23. package/server/controllers/worklist-api/get-todo-list.ts +4 -0
  24. package/server/controllers/worklist-api/index.ts +8 -0
  25. package/server/controllers/worklist-api/register-activity.ts +3 -0
  26. package/server/controllers/worklist-api/unregister-activity.ts +3 -0
  27. package/server/controllers/worklist-api/update-activity.ts +3 -0
  28. package/server/index.ts +3 -0
  29. package/server/routes.ts +46 -0
  30. package/server/service/activity/activity-model-type.ts +106 -0
  31. package/server/service/activity/activity-mutation.ts +85 -0
  32. package/server/service/activity/activity-query.ts +64 -0
  33. package/server/service/activity/activity-type.ts +134 -0
  34. package/server/service/activity/activity.ts +133 -0
  35. package/server/service/activity/index.ts +6 -0
  36. package/server/service/index.ts +36 -0
  37. package/server/service/work-center/event-subscriber.ts +17 -0
  38. package/server/service/work-center/index.ts +9 -0
  39. package/server/service/work-center/work-center-history.ts +120 -0
  40. package/server/service/work-center/work-center-mutation.ts +198 -0
  41. package/server/service/work-center/work-center-query.ts +65 -0
  42. package/server/service/work-center/work-center-type.ts +61 -0
  43. package/server/service/work-center/work-center.ts +75 -0
  44. package/server/tsconfig.json +10 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@things-factory/worklist-client",
3
- "version": "8.0.0-beta.8",
3
+ "version": "8.0.0",
4
4
  "main": "dist-server/index.js",
5
5
  "browser": "dist-client/index.js",
6
6
  "things-factory": true,
@@ -27,11 +27,11 @@
27
27
  "migration:create": "node ../../node_modules/typeorm/cli.js migration:create ./server/migrations/migration"
28
28
  },
29
29
  "dependencies": {
30
- "@operato/graphql": "^8.0.0-beta",
31
- "@operato/shell": "^8.0.0-beta",
32
- "@things-factory/auth-base": "^8.0.0-beta.8",
33
- "@things-factory/oauth2-client": "^8.0.0-beta.8",
34
- "@things-factory/shell": "^8.0.0-beta.5"
30
+ "@operato/graphql": "^8.0.0",
31
+ "@operato/shell": "^8.0.0",
32
+ "@things-factory/auth-base": "^8.0.0",
33
+ "@things-factory/oauth2-client": "^8.0.0",
34
+ "@things-factory/shell": "^8.0.0"
35
35
  },
36
- "gitHead": "bf5206511b2d84dfb95edc3dae7f54f6cbb9bcca"
36
+ "gitHead": "07ef27d272dd9a067a9648ac7013748510556a18"
37
37
  }
@@ -0,0 +1,17 @@
1
+ import { Activity } from '../service/activity/activity'
2
+
3
+ export class ActivityRegistry {
4
+ static registry = new Map<string, Activity>()
5
+
6
+ static set(id: string, activity: Activity) {
7
+ ActivityRegistry.registry.set(id, activity)
8
+ }
9
+
10
+ static get(id: string) {
11
+ return ActivityRegistry.get(id)
12
+ }
13
+
14
+ static list(): Activity[] {
15
+ return ActivityRegistry.list()
16
+ }
17
+ }
@@ -0,0 +1,67 @@
1
+ import 'cross-fetch/polyfill'
2
+
3
+ import { ApolloClient, ApolloLink, from, HttpLink, InMemoryCache } from '@apollo/client/core'
4
+ import { onError } from '@apollo/client/link/error'
5
+ import { Oauth2Client } from '@things-factory/oauth2-client'
6
+ import { getRepository } from '@things-factory/shell'
7
+ import { config, logger } from '@things-factory/env'
8
+
9
+ const defaultOptions: any = {
10
+ watchQuery: {
11
+ fetchPolicy: 'no-cache',
12
+ errorPolicy: 'ignore'
13
+ },
14
+ query: {
15
+ fetchPolicy: 'no-cache', //'network-only'
16
+ errorPolicy: 'all'
17
+ },
18
+ mutate: {
19
+ errorPolicy: 'all'
20
+ }
21
+ }
22
+
23
+ const cache = new InMemoryCache({
24
+ addTypename: false
25
+ })
26
+
27
+ const uri = config.get('worklist/endpoint', 'https://gangsters.hatiolab.com/graphql')
28
+
29
+ export async function connect() {
30
+ var ERROR_HANDLER: any = ({ graphQLErrors, networkError }) => {
31
+ if (graphQLErrors)
32
+ graphQLErrors.map(({ message, locations, path }) => {
33
+ logger.error(`[GraphQL error] Message: ${message}, Location: ${locations}, Path: ${path}`)
34
+ })
35
+
36
+ if (networkError) {
37
+ logger.error(`[Network error - ${networkError.statusCode}] ${networkError}`)
38
+ }
39
+ }
40
+
41
+ const oauth2Client: Oauth2Client = await getRepository(Oauth2Client).findOneBy({ name: 'WORKLIST' })
42
+
43
+ const authMiddleware = new ApolloLink((operation, forward) => {
44
+ // add the authorization to the headers
45
+ operation.setContext(({ headers = {} }) => ({
46
+ headers: {
47
+ ...headers,
48
+ ...oauth2Client.getAuthHeaders()
49
+ }
50
+ }))
51
+
52
+ return forward(operation)
53
+ })
54
+
55
+ return new ApolloClient({
56
+ defaultOptions,
57
+ cache,
58
+ link: from([
59
+ authMiddleware,
60
+ onError(ERROR_HANDLER),
61
+ new HttpLink({
62
+ uri,
63
+ credentials: 'include'
64
+ })
65
+ ])
66
+ })
67
+ }
@@ -0,0 +1,4 @@
1
+ export * from './work-center'
2
+ export * from './worklist-api'
3
+ export * from './webhooks'
4
+ export * from './activity-registry'
@@ -0,0 +1,18 @@
1
+ import { WorkCenter } from '../../service/work-center/work-center'
2
+
3
+ export const webhook = (target: Object, property: string, descriptor: TypedPropertyDescriptor<any>): any => {
4
+ const method = descriptor.value
5
+
6
+ descriptor.value = async function (request) {
7
+ const WorklistWebhook = this
8
+
9
+ var m = WorklistWebhook.handlers[method.name]
10
+ if (!m) {
11
+ throw Error(`Worklist Webhook doesn't have the handler ${method.name}`)
12
+ }
13
+
14
+ return await m.apply(this, [request])
15
+ }
16
+
17
+ return descriptor
18
+ }
@@ -0,0 +1,30 @@
1
+ import { getRepository } from '@things-factory/shell'
2
+
3
+ import { WorkCenter } from '../../service/work-center/work-center'
4
+ import { webhook } from './decorators'
5
+
6
+ export class WorklistWebhook {
7
+ static handlers = {}
8
+
9
+ static registerHandlers(handlers) {
10
+ WorklistWebhook.handlers = handlers
11
+ }
12
+
13
+ static async getWorkCenter(id: string) {
14
+ return await getRepository(WorkCenter).findOne({
15
+ where: { workCenterId: id }
16
+ })
17
+ }
18
+
19
+ @webhook
20
+ static echo(center, req): any {}
21
+
22
+ @webhook
23
+ static onActivityApprovalUpdated(center, req): any {}
24
+
25
+ @webhook
26
+ static onActivityThreadUpdated(center, req): any {}
27
+
28
+ @webhook
29
+ static onActivityInstanceUpdated(center, req): any {}
30
+ }
@@ -0,0 +1,15 @@
1
+ import { Domain, getRepository } from '@things-factory/shell'
2
+ import { Oauth2Client } from '@things-factory/oauth2-client'
3
+
4
+ export async function connectWorkCenter(domain: Domain) {
5
+ const client = await getRepository(Oauth2Client).findOneBy({
6
+ domain: { id: domain.id },
7
+ authUrl: 'https://gangsters.hatiolab.com/oauth/authorize'
8
+ })
9
+
10
+ if (client) {
11
+ return client
12
+ }
13
+
14
+ // TODO else..
15
+ }
@@ -0,0 +1,9 @@
1
+ import { Domain, getRepository } from '@things-factory/shell'
2
+ import { Oauth2Client } from '@things-factory/oauth2-client'
3
+
4
+ export async function getWorkCenter(domain: Domain): Promise<Oauth2Client> {
5
+ return await getRepository(Oauth2Client).findOneBy({
6
+ domain: { id: domain.id },
7
+ authUrl: 'https://gangsters.hatiolab.com/oauth/authorize'
8
+ })
9
+ }
@@ -0,0 +1,2 @@
1
+ export * from './connect-work-center'
2
+ export * from './get-work-center'
@@ -0,0 +1,3 @@
1
+ import { WorkCenter } from 'service'
2
+
3
+ export async function assignActivityThread(center: WorkCenter, activityThread: any) {}
@@ -0,0 +1,3 @@
1
+ import { WorkCenter } from 'service'
2
+
3
+ export async function draftActivityInstance(center: WorkCenter, activityInstance: any) {}
@@ -0,0 +1,3 @@
1
+ import { WorkCenter } from 'service'
2
+
3
+ export async function getActivityList(center: WorkCenter) {}
@@ -0,0 +1,3 @@
1
+ import { WorkCenter } from 'service'
2
+
3
+ export async function getActivity(center: WorkCenter, options: any) {}
@@ -0,0 +1,4 @@
1
+ import { User } from '@things-factory/auth-base'
2
+ import { WorkCenter } from 'service'
3
+
4
+ export async function getToDoList(center: WorkCenter, user: User) {}
@@ -0,0 +1,8 @@
1
+ export * from './assign-activity-thread'
2
+ export * from './draft-activity-instance'
3
+ export * from './get-activity-list'
4
+ export * from './get-activity'
5
+ export * from './get-todo-list'
6
+ export * from './register-activity'
7
+ export * from './unregister-activity'
8
+ export * from './update-activity'
@@ -0,0 +1,3 @@
1
+ import { WorkCenter } from 'service'
2
+
3
+ export async function registerActivity(center: WorkCenter, activity: any) {}
@@ -0,0 +1,3 @@
1
+ import { WorkCenter } from 'service'
2
+
3
+ export async function unregisterActivity(center: WorkCenter, activity: any) {}
@@ -0,0 +1,3 @@
1
+ import { WorkCenter } from 'service'
2
+
3
+ export async function updateActivity(center: WorkCenter, activity: any) {}
@@ -0,0 +1,3 @@
1
+ export * from './controllers'
2
+
3
+ import './routes'
@@ -0,0 +1,46 @@
1
+ import { WorklistWebhook } from './controllers/webhooks'
2
+
3
+ process.on('bootstrap-module-global-public-route' as any, (app, globalPublicRouter) => {
4
+ globalPublicRouter.post('/worklist-client', async (context, next) => {
5
+ var { req } = context
6
+ var { tag, domain, data } = req
7
+
8
+ const center = WorklistWebhook.getWorkCenter(domain.id)
9
+
10
+ switch (tag) {
11
+ case 'activity-approval':
12
+ WorklistWebhook.onActivityApprovalUpdated(center, data)
13
+ break
14
+ case 'activity-thread':
15
+ WorklistWebhook.onActivityThreadUpdated(center, data)
16
+ break
17
+ case 'activity-instance':
18
+ WorklistWebhook.onActivityInstanceUpdated(center, data)
19
+ break
20
+ default:
21
+ WorklistWebhook.echo(center, data)
22
+ }
23
+
24
+ context.type = 'text/plain'
25
+ context.status = 200
26
+ context.body = 'OK'
27
+ })
28
+ })
29
+
30
+ process.on('bootstrap-module-global-private-route' as any, (app, globalPrivateRouter) => {
31
+ /*
32
+ * can add global private routes to application (auth required, tenancy not required)
33
+ */
34
+ })
35
+
36
+ process.on('bootstrap-module-domain-public-route' as any, (app, domainPublicRouter) => {
37
+ /*
38
+ * can add domain public routes to application (auth not required, tenancy required)
39
+ */
40
+ })
41
+
42
+ process.on('bootstrap-module-domain-private-route' as any, (app, domainPrivateRouter) => {
43
+ /*
44
+ * can add domain private routes to application (auth required, tenancy required)
45
+ */
46
+ })
@@ -0,0 +1,106 @@
1
+ import { Field, InputType, Int, ObjectType, registerEnumType } from 'type-graphql'
2
+
3
+ import { ScalarObject } from '@things-factory/shell'
4
+
5
+ export enum ActivityModelItemInoutType {
6
+ in = 'in',
7
+ out = 'out',
8
+ inout = 'inout'
9
+ }
10
+
11
+ registerEnumType(ActivityModelItemInoutType, {
12
+ name: 'ActivityModelItemInoutType',
13
+ description: 'inout enumeration of a activity-model-item'
14
+ })
15
+
16
+ export enum ActivityModelItemType {
17
+ number = 'number',
18
+ text = 'text',
19
+ textarea = 'textarea',
20
+ boolean = 'boolean',
21
+ select = 'select',
22
+ file = 'file'
23
+ }
24
+
25
+ registerEnumType(ActivityModelItemType, {
26
+ name: 'ActivityModelItemType',
27
+ description: 'data type enumeration of a activity-model-item'
28
+ })
29
+
30
+ @ObjectType({ description: 'Entity for ActivityModelItem' })
31
+ export class ActivityModelItem {
32
+ @Field()
33
+ name: string
34
+
35
+ @Field({ nullable: true })
36
+ description?: string
37
+
38
+ @Field({ nullable: true })
39
+ tag?: string
40
+
41
+ @Field({ nullable: true })
42
+ active?: boolean
43
+
44
+ @Field({ nullable: true })
45
+ hidden?: boolean
46
+
47
+ @Field({ nullable: true })
48
+ mandatory?: boolean
49
+
50
+ @Field(type => ActivityModelItemInoutType, { nullable: true })
51
+ inout?: ActivityModelItemInoutType
52
+
53
+ @Field({ nullable: true })
54
+ type?: ActivityModelItemType
55
+
56
+ @Field(type => ScalarObject, { nullable: true })
57
+ options?: { [option: string]: any }
58
+
59
+ @Field({ nullable: true })
60
+ unit?: string
61
+
62
+ @Field(type => [Int], { nullable: true })
63
+ quantifier: number[]
64
+
65
+ @Field(type => ScalarObject, { nullable: true })
66
+ spec?: { [key: string]: any }
67
+ }
68
+
69
+ @InputType()
70
+ export class ActivityModelItemPatch {
71
+ @Field({ nullable: true })
72
+ name?: string
73
+
74
+ @Field({ nullable: true })
75
+ description?: string
76
+
77
+ @Field({ nullable: true })
78
+ tag?: string
79
+
80
+ @Field(type => ActivityModelItemInoutType, { nullable: true })
81
+ inout?: ActivityModelItemInoutType
82
+
83
+ @Field(type => ActivityModelItemType, { nullable: true })
84
+ type?: ActivityModelItemType
85
+
86
+ @Field(type => ScalarObject, { nullable: true })
87
+ options?: { [option: string]: any }
88
+
89
+ @Field({ nullable: true })
90
+ unit?: string
91
+
92
+ @Field(type => [Int], { nullable: true })
93
+ quantifier: number[]
94
+
95
+ @Field({ nullable: true })
96
+ active?: boolean
97
+
98
+ @Field({ nullable: true })
99
+ mandatory?: boolean
100
+
101
+ @Field({ nullable: true })
102
+ hidden?: boolean
103
+
104
+ @Field(type => ScalarObject, { nullable: true })
105
+ spec?: { [key: string]: any }
106
+ }
@@ -0,0 +1,85 @@
1
+ import { Arg, Ctx, Directive, Mutation, Resolver } from 'type-graphql'
2
+
3
+ import { Activity } from './activity'
4
+ import { ActivityPatch, NewActivity } from './activity-type'
5
+
6
+ @Resolver(Activity)
7
+ export class ActivityMutation {
8
+ @Directive('@transaction')
9
+ @Mutation(returns => Activity, { description: 'To create new Activity' })
10
+ async createActivity(@Arg('activity') activity: NewActivity, @Ctx() context: ResolverContext): Promise<Activity> {
11
+ const { domain, user, tx } = context.state
12
+
13
+ // WorkCenter를 찾는다.
14
+ // WorkCenter에 graphql createActivity를 호출한다.
15
+ return
16
+ }
17
+
18
+ @Directive('@transaction')
19
+ @Mutation(returns => Activity, { description: 'To modify Activity information' })
20
+ async updateActivity(
21
+ @Arg('id') id: string,
22
+ @Arg('patch') patch: ActivityPatch,
23
+ @Ctx() context: ResolverContext
24
+ ): Promise<Activity> {
25
+ const { domain, user, tx } = context.state
26
+
27
+ // workcenter의 토큰을 가져온다.
28
+ // remote graphql의 activity query를 호출한다.
29
+
30
+ return
31
+ }
32
+
33
+ @Directive('@transaction')
34
+ @Mutation(returns => [Activity], { description: "To modify multiple Activities' information" })
35
+ async updateMultipleActivity(
36
+ @Arg('patches', type => [ActivityPatch]) patches: ActivityPatch[],
37
+ @Ctx() context: ResolverContext
38
+ ): Promise<Activity[]> {
39
+ const { domain, user, tx } = context.state
40
+
41
+ // workcenter의 토큰을 가져온다.
42
+ // remote graphql의 activity query를 호출한다.
43
+
44
+ return
45
+ }
46
+
47
+ @Directive('@transaction')
48
+ @Mutation(returns => Boolean, { description: 'To delete Activity' })
49
+ async deleteActivity(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<boolean> {
50
+ const { domain, tx } = context.state
51
+
52
+ // workcenter의 토큰을 가져온다.
53
+ // remote graphql의 activity query를 호출한다.
54
+
55
+ return
56
+ }
57
+
58
+ @Directive('@transaction')
59
+ @Mutation(returns => Boolean, { description: 'To delete multiple Activities' })
60
+ async deleteActivities(
61
+ @Arg('ids', type => [String]) ids: string[],
62
+ @Ctx() context: ResolverContext
63
+ ): Promise<boolean> {
64
+ const { domain, tx } = context.state
65
+
66
+ // workcenter의 토큰을 가져온다.
67
+ // remote graphql의 activity query를 호출한다.
68
+
69
+ return
70
+ }
71
+
72
+ @Directive('@transaction')
73
+ @Mutation(returns => Boolean, { description: 'To import multiple Activities' })
74
+ async importActivities(
75
+ @Arg('activities', type => [ActivityPatch]) activities: ActivityPatch[],
76
+ @Ctx() context: ResolverContext
77
+ ): Promise<boolean> {
78
+ const { domain, tx } = context.state
79
+
80
+ // workcenter의 토큰을 가져온다.
81
+ // remote graphql의 activity query를 호출한다.
82
+
83
+ return
84
+ }
85
+ }
@@ -0,0 +1,64 @@
1
+ import { Arg, Args, Ctx, Query, Resolver } from 'type-graphql'
2
+
3
+ import { getRepository, ListParam } from '@things-factory/shell'
4
+
5
+ import { Activity } from './activity'
6
+ import { ActivityList } from './activity-type'
7
+ import { ActivityRegistry } from '../../controllers/activity-registry'
8
+ import { WorkCenter } from '../work-center/work-center'
9
+
10
+ @Resolver(Activity)
11
+ export class ActivityQuery {
12
+ @Query(returns => Activity!, { nullable: true, description: 'To fetch a Activity' })
13
+ async registeredActivity(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<Activity> {
14
+ const { domain } = context.state
15
+
16
+ return ActivityRegistry.get(id)
17
+ }
18
+
19
+ @Query(returns => ActivityList, { description: 'To fetch multiple Activities' })
20
+ async registeredActivities(
21
+ @Args(type => ListParam) params: ListParam,
22
+ @Ctx() context: ResolverContext
23
+ ): Promise<ActivityList> {
24
+ const { domain } = context.state
25
+
26
+ const activities = ActivityRegistry.list()
27
+
28
+ return { items: activities, total: activities.length }
29
+ }
30
+
31
+ @Query(returns => Activity!, { nullable: true, description: 'To fetch a Activity' })
32
+ async activity(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<Activity> {
33
+ const { domain } = context.state
34
+
35
+ const workCenter = await getRepository(WorkCenter).findOne({
36
+ where: { domain: { id: domain.id }, id }
37
+ })
38
+
39
+ // workcenter의 토큰을 가져온다.
40
+ // remote graphql의 activity query를 호출한다.
41
+
42
+ return
43
+ }
44
+
45
+ @Query(returns => Activity!, { nullable: true, description: 'To fetch a Activity by name' })
46
+ async activityByName(@Arg('name') name: string, @Ctx() context: ResolverContext): Promise<Activity> {
47
+ const { domain } = context.state
48
+
49
+ // workcenter의 토큰을 가져온다.
50
+ // remote graphql의 activity query를 호출한다.
51
+
52
+ return
53
+ }
54
+
55
+ @Query(returns => ActivityList, { description: 'To fetch multiple Activities' })
56
+ async activities(@Args(type => ListParam) params: ListParam, @Ctx() context: ResolverContext): Promise<ActivityList> {
57
+ const { domain } = context.state
58
+
59
+ // workcenter의 토큰을 가져온다.
60
+ // remote graphql의 activity query를 호출한다.
61
+
62
+ return
63
+ }
64
+ }