@things-factory/worklist 10.1.168 → 10.1.170

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 (66) hide show
  1. package/dist-client/components/decision-content.d.ts +35 -0
  2. package/dist-client/components/decision-content.js +322 -0
  3. package/dist-client/components/decision-content.js.map +1 -0
  4. package/dist-client/components/decision-slots.d.ts +8 -0
  5. package/dist-client/components/decision-slots.js +17 -0
  6. package/dist-client/components/decision-slots.js.map +1 -1
  7. package/dist-client/components/work-box-groups.d.ts +25 -0
  8. package/dist-client/components/work-box-groups.js +98 -0
  9. package/dist-client/components/work-box-groups.js.map +1 -0
  10. package/dist-client/my-work-menus.d.ts +1 -6
  11. package/dist-client/my-work-menus.js +0 -1
  12. package/dist-client/my-work-menus.js.map +1 -1
  13. package/dist-client/pages/activity-approval/activity-approval-page.d.ts +2 -52
  14. package/dist-client/pages/activity-approval/activity-approval-page.js +8 -298
  15. package/dist-client/pages/activity-approval/activity-approval-page.js.map +1 -1
  16. package/dist-client/pages/activity-instance/activity-instance-view.d.ts +19 -2
  17. package/dist-client/pages/activity-instance/activity-instance-view.js +47 -23
  18. package/dist-client/pages/activity-instance/activity-instance-view.js.map +1 -1
  19. package/dist-client/pages/activity-thread/activity-thread-page.d.ts +6 -2
  20. package/dist-client/pages/activity-thread/activity-thread-page.js +31 -16
  21. package/dist-client/pages/activity-thread/activity-thread-page.js.map +1 -1
  22. package/dist-client/pages/activity-thread/activity-thread-view-page.js +2 -2
  23. package/dist-client/pages/activity-thread/activity-thread-view-page.js.map +1 -1
  24. package/dist-client/pages/activity-thread/thread-sections.d.ts +34 -0
  25. package/dist-client/pages/activity-thread/thread-sections.js +36 -0
  26. package/dist-client/pages/activity-thread/thread-sections.js.map +1 -0
  27. package/dist-client/pages/todo/approval-pending-list-page.d.ts +1 -0
  28. package/dist-client/pages/todo/approval-pending-list-page.js +10 -77
  29. package/dist-client/pages/todo/approval-pending-list-page.js.map +1 -1
  30. package/dist-client/pages/todo/draft-list-page.d.ts +20 -0
  31. package/dist-client/pages/todo/draft-list-page.js +102 -5
  32. package/dist-client/pages/todo/draft-list-page.js.map +1 -1
  33. package/dist-client/pages/todo/todo-list-page.d.ts +19 -0
  34. package/dist-client/pages/todo/todo-list-page.js +147 -23
  35. package/dist-client/pages/todo/todo-list-page.js.map +1 -1
  36. package/dist-client/pages/todo/work-box.d.ts +36 -0
  37. package/dist-client/pages/todo/work-box.js +44 -0
  38. package/dist-client/pages/todo/work-box.js.map +1 -0
  39. package/dist-client/route.d.ts +1 -1
  40. package/dist-client/route.js +0 -3
  41. package/dist-client/route.js.map +1 -1
  42. package/dist-client/tsconfig.tsbuildinfo +1 -1
  43. package/dist-client/types/activity.d.ts +2 -0
  44. package/dist-client/types/activity.js.map +1 -1
  45. package/dist-server/service/activity-summary/open-work.d.ts +0 -1
  46. package/dist-server/service/activity-summary/open-work.js +3 -15
  47. package/dist-server/service/activity-summary/open-work.js.map +1 -1
  48. package/dist-server/service/activity-thread/activity-thread-query.d.ts +3 -0
  49. package/dist-server/service/activity-thread/activity-thread-query.js +24 -5
  50. package/dist-server/service/activity-thread/activity-thread-query.js.map +1 -1
  51. package/dist-server/service/activity-thread/my-open-threads.d.ts +23 -4
  52. package/dist-server/service/activity-thread/my-open-threads.js +38 -7
  53. package/dist-server/service/activity-thread/my-open-threads.js.map +1 -1
  54. package/dist-server/tsconfig.tsbuildinfo +1 -1
  55. package/package.json +5 -5
  56. package/tests/open-doors.test.ts +3 -2
  57. package/things-factory.config.js +0 -1
  58. package/translations/en.json +10 -2
  59. package/translations/es.json +10 -2
  60. package/translations/ja.json +10 -2
  61. package/translations/ko.json +10 -2
  62. package/translations/ms.json +10 -2
  63. package/translations/zh.json +10 -2
  64. package/dist-client/pages/todo/done-list-page.d.ts +0 -38
  65. package/dist-client/pages/todo/done-list-page.js +0 -382
  66. package/dist-client/pages/todo/done-list-page.js.map +0 -1
@@ -2,6 +2,7 @@ import { Domain, User, Role } from '@operato/shell';
2
2
  import { ApprovalLineItem, AssigneeItem } from '@things-factory/organization/dist-client';
3
3
  import { ActivityModelItem } from './activity-model-type.js';
4
4
  import { ActivitySearchKeyItem } from './activity-search-key-item-type.js';
5
+ import type { DecisionKeyDeclaration } from '../components/decision-slots.js';
5
6
  export declare enum ActivityStatus {
6
7
  Draft = "draft",
7
8
  Released = "released",
@@ -40,6 +41,7 @@ export declare class Activity {
40
41
  activityType?: ActivityType;
41
42
  state?: ActivityStatus;
42
43
  searchKeys?: ActivitySearchKeyItem[];
44
+ decisionKeys?: DecisionKeyDeclaration[];
43
45
  model?: ActivityModelItem[];
44
46
  priority?: number;
45
47
  startingType?: ActivityStartingType;
@@ -1 +1 @@
1
- {"version":3,"file":"activity.js","sourceRoot":"","sources":["../../client/types/activity.ts"],"names":[],"mappings":"AAMA,MAAM,CAAN,IAAY,cAIX;AAJD,WAAY,cAAc;IACxB,iCAAe,CAAA;IACf,uCAAqB,CAAA;IACrB,2CAAyB,CAAA;AAC3B,CAAC,EAJW,cAAc,KAAd,cAAc,QAIzB;AAED,MAAM,CAAN,IAAY,YAWX;AAXD,WAAY,YAAY;IACtB,6BAAa,CAAA;IACb,mCAAmB,CAAA;IACnB,6BAAa,CAAA;IACb,mCAAmB,CAAA;IACnB,6BAAa,CAAA;IACb,iCAAiB,CAAA;IACjB,8CAA8B,CAAA;IAC9B,iCAAiB,CAAA;IACjB,0CAA0B,CAAA;IAC1B,6BAAa,CAAA;AACf,CAAC,EAXW,YAAY,KAAZ,YAAY,QAWvB;AAED,MAAM,CAAN,IAAY,cAOX;AAPD,WAAY,cAAc;IACxB,yCAAuB,CAAA;IACvB,uCAAqB,CAAA;IACrB,iCAAe,CAAA;IACf,kDAAgC,CAAA;IAChC,+BAAa,CAAA;IACb,uCAAqB,CAAA;AACvB,CAAC,EAPW,cAAc,KAAd,cAAc,QAOzB;AAED,MAAM,CAAN,IAAY,oBAGX;AAHD,WAAY,oBAAoB;IAC9B,qCAAa,CAAA;IACb,uCAAe,CAAA;AACjB,CAAC,EAHW,oBAAoB,KAApB,oBAAoB,QAG/B;AAED,MAAM,OAAO,QAAQ;IAArB;QAGE,YAAO,GAAY,CAAC,CAAA;QAgBpB,aAAQ,GAAY,CAAC,CAAA;IA2CvB,CAAC;CAAA","sourcesContent":["import { Domain, User, Role } from '@operato/shell'\nimport { ApprovalLineItem, AssigneeItem } from '@things-factory/organization/dist-client'\n\nimport { ActivityModelItem } from './activity-model-type.js'\nimport { ActivitySearchKeyItem } from './activity-search-key-item-type.js'\n\nexport enum ActivityStatus {\n Draft = 'draft',\n Released = 'released',\n Deprecated = 'deprecated'\n}\n\nexport enum ActivityType {\n Task = 'task',\n Service = 'service',\n Send = 'send',\n Receive = 'receive',\n User = 'user',\n Manual = 'manual',\n BusinessRule = 'business-rule',\n Script = 'script',\n Subprocess = 'sub-process',\n Call = 'call'\n}\n\nexport enum ActivityUIType {\n Generated = 'generated',\n Template = 'template',\n Board = 'board',\n CustomElement = 'custom-element',\n Page = 'page',\n External = 'external'\n}\n\nexport enum ActivityStartingType {\n post = 'post',\n issue = 'issue'\n}\n\nexport class Activity {\n id?: string\n\n version?: number = 1\n\n domain?: Domain\n\n name?: string\n\n description?: string\n\n activityType?: ActivityType\n\n state?: ActivityStatus\n\n searchKeys?: ActivitySearchKeyItem[]\n\n model?: ActivityModelItem[]\n\n priority?: number = 1\n\n startingType?: ActivityStartingType\n\n schedule?: string\n\n timzeone?: string\n\n standardTime?: number\n\n issuerRole?: Role\n\n assigneeRole?: Role\n\n supervisoryRole?: Role\n\n assignees?: AssigneeItem[]\n\n approvalLine?: ApprovalLineItem[]\n\n uiType?: ActivityUIType\n\n uiSource?: string\n\n viewType?: ActivityUIType\n\n viewSource?: string\n\n reportType?: ActivityUIType\n\n reportSource?: string\n\n createdAt?: Date\n\n updatedAt?: Date\n\n client?: User\n\n creator?: User\n\n updater?: User\n\n thumbnail?: string\n}\n"]}
1
+ {"version":3,"file":"activity.js","sourceRoot":"","sources":["../../client/types/activity.ts"],"names":[],"mappings":"AAOA,MAAM,CAAN,IAAY,cAIX;AAJD,WAAY,cAAc;IACxB,iCAAe,CAAA;IACf,uCAAqB,CAAA;IACrB,2CAAyB,CAAA;AAC3B,CAAC,EAJW,cAAc,KAAd,cAAc,QAIzB;AAED,MAAM,CAAN,IAAY,YAWX;AAXD,WAAY,YAAY;IACtB,6BAAa,CAAA;IACb,mCAAmB,CAAA;IACnB,6BAAa,CAAA;IACb,mCAAmB,CAAA;IACnB,6BAAa,CAAA;IACb,iCAAiB,CAAA;IACjB,8CAA8B,CAAA;IAC9B,iCAAiB,CAAA;IACjB,0CAA0B,CAAA;IAC1B,6BAAa,CAAA;AACf,CAAC,EAXW,YAAY,KAAZ,YAAY,QAWvB;AAED,MAAM,CAAN,IAAY,cAOX;AAPD,WAAY,cAAc;IACxB,yCAAuB,CAAA;IACvB,uCAAqB,CAAA;IACrB,iCAAe,CAAA;IACf,kDAAgC,CAAA;IAChC,+BAAa,CAAA;IACb,uCAAqB,CAAA;AACvB,CAAC,EAPW,cAAc,KAAd,cAAc,QAOzB;AAED,MAAM,CAAN,IAAY,oBAGX;AAHD,WAAY,oBAAoB;IAC9B,qCAAa,CAAA;IACb,uCAAe,CAAA;AACjB,CAAC,EAHW,oBAAoB,KAApB,oBAAoB,QAG/B;AAED,MAAM,OAAO,QAAQ;IAArB;QAGE,YAAO,GAAY,CAAC,CAAA;QAkBpB,aAAQ,GAAY,CAAC,CAAA;IA2CvB,CAAC;CAAA","sourcesContent":["import { Domain, User, Role } from '@operato/shell'\nimport { ApprovalLineItem, AssigneeItem } from '@things-factory/organization/dist-client'\n\nimport { ActivityModelItem } from './activity-model-type.js'\nimport { ActivitySearchKeyItem } from './activity-search-key-item-type.js'\nimport type { DecisionKeyDeclaration } from '../components/decision-slots.js'\n\nexport enum ActivityStatus {\n Draft = 'draft',\n Released = 'released',\n Deprecated = 'deprecated'\n}\n\nexport enum ActivityType {\n Task = 'task',\n Service = 'service',\n Send = 'send',\n Receive = 'receive',\n User = 'user',\n Manual = 'manual',\n BusinessRule = 'business-rule',\n Script = 'script',\n Subprocess = 'sub-process',\n Call = 'call'\n}\n\nexport enum ActivityUIType {\n Generated = 'generated',\n Template = 'template',\n Board = 'board',\n CustomElement = 'custom-element',\n Page = 'page',\n External = 'external'\n}\n\nexport enum ActivityStartingType {\n post = 'post',\n issue = 'issue'\n}\n\nexport class Activity {\n id?: string\n\n version?: number = 1\n\n domain?: Domain\n\n name?: string\n\n description?: string\n\n activityType?: ActivityType\n\n state?: ActivityStatus\n\n searchKeys?: ActivitySearchKeyItem[]\n\n decisionKeys?: DecisionKeyDeclaration[]\n\n model?: ActivityModelItem[]\n\n priority?: number = 1\n\n startingType?: ActivityStartingType\n\n schedule?: string\n\n timzeone?: string\n\n standardTime?: number\n\n issuerRole?: Role\n\n assigneeRole?: Role\n\n supervisoryRole?: Role\n\n assignees?: AssigneeItem[]\n\n approvalLine?: ApprovalLineItem[]\n\n uiType?: ActivityUIType\n\n uiSource?: string\n\n viewType?: ActivityUIType\n\n viewSource?: string\n\n reportType?: ActivityUIType\n\n reportSource?: string\n\n createdAt?: Date\n\n updatedAt?: Date\n\n client?: User\n\n creator?: User\n\n updater?: User\n\n thumbnail?: string\n}\n"]}
@@ -1,5 +1,4 @@
1
1
  import { Domain } from '@things-factory/shell';
2
2
  /** Threads assigned to the person and not finished, plus unassigned ones their role may pick up. */
3
3
  export declare function toDosOf(domain: Domain, userId: string): Promise<number>;
4
- /** Approvals waiting on the person - through the inbox's own clause. */
5
4
  export declare function pendingApprovalsOf(domain: Domain, userId: string): Promise<number>;
@@ -2,12 +2,12 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.toDosOf = toDosOf;
4
4
  exports.pendingApprovalsOf = pendingApprovalsOf;
5
- const typeorm_1 = require("typeorm");
6
5
  const auth_base_1 = require("@things-factory/auth-base");
7
6
  const shell_1 = require("@things-factory/shell");
8
7
  const activity_thread_js_1 = require("../activity-thread/activity-thread.js");
9
8
  const activity_approval_js_1 = require("../activity-approval/activity-approval.js");
10
9
  const my_pending_approvals_js_1 = require("../activity-approval/my-pending-approvals.js");
10
+ const my_open_threads_js_1 = require("../activity-thread/my-open-threads.js");
11
11
  /**
12
12
  * What a person has on their plate in one domain - the same questions the rail's badges ask.
13
13
  *
@@ -24,7 +24,7 @@ async function rolesIn(domain, userId) {
24
24
  /** Threads assigned to the person and not finished, plus unassigned ones their role may pick up. */
25
25
  async function toDosOf(domain, userId) {
26
26
  const roles = await rolesIn(domain, userId);
27
- const excludedStatuses = [activity_thread_js_1.ActivityThreadStatus.Unassigned, activity_thread_js_1.ActivityThreadStatus.Ended, activity_thread_js_1.ActivityThreadStatus.Aborted];
27
+ /* The list's own clause - the badge counts what 할 일 shows, not a copy of its rule. */
28
28
  return await (0, shell_1.getQueryBuilderFromListParams)({
29
29
  repository: (0, shell_1.getRepository)(activity_thread_js_1.ActivityThread),
30
30
  params: {},
@@ -32,21 +32,9 @@ async function toDosOf(domain, userId) {
32
32
  alias: 'at'
33
33
  })
34
34
  .innerJoinAndSelect('at.activityInstance', 'ai')
35
- .andWhere(new typeorm_1.Brackets(qb => {
36
- qb.where('at.state NOT IN (:...excludedStatuses)', { excludedStatuses }).andWhere('at.assignee = :userId', {
37
- userId
38
- });
39
- if (roles.length > 0) {
40
- qb.orWhere(new typeorm_1.Brackets(subQb => {
41
- subQb
42
- .where('ai.assigneeRole IN (:...roles)', { roles })
43
- .andWhere(`at.state = '${activity_thread_js_1.ActivityThreadStatus.Unassigned}'`);
44
- }));
45
- }
46
- }))
35
+ .andWhere((0, my_open_threads_js_1.myOpenThreadsWhere)({ userId, roles }))
47
36
  .getCount();
48
37
  }
49
- /** Approvals waiting on the person - through the inbox's own clause. */
50
38
  async function pendingApprovalsOf(domain, userId) {
51
39
  const roles = await rolesIn(domain, userId);
52
40
  return await (0, shell_1.getQueryBuilderFromListParams)({
@@ -1 +1 @@
1
- {"version":3,"file":"open-work.js","sourceRoot":"","sources":["../../../server/service/activity-summary/open-work.ts"],"names":[],"mappings":";;AAyBA,0BA6BC;AAGD,gDAaC;AAtED,qCAAkC;AAElC,yDAAgD;AAChD,iDAA4F;AAE5F,8EAA4F;AAC5F,oFAA4E;AAC5E,0FAAsF;AAEtF;;;;;;;GAOG;AAEH,iHAAiH;AACjH,KAAK,UAAU,OAAO,CAAC,MAAc,EAAE,MAAc;IACnD,MAAM,IAAI,GAAG,MAAM,IAAA,qBAAa,EAAC,gBAAI,CAAC,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,SAAS,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;IAC/F,OAAO,CAAC,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,KAAK,MAAM,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;AAC7F,CAAC;AAED,oGAAoG;AAC7F,KAAK,UAAU,OAAO,CAAC,MAAc,EAAE,MAAc;IAC1D,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC3C,MAAM,gBAAgB,GAAG,CAAC,yCAAoB,CAAC,UAAU,EAAE,yCAAoB,CAAC,KAAK,EAAE,yCAAoB,CAAC,OAAO,CAAC,CAAA;IAEpH,OAAO,MAAM,IAAA,qCAA6B,EAAC;QACzC,UAAU,EAAE,IAAA,qBAAa,EAAC,mCAAc,CAAC;QACzC,MAAM,EAAE,EAAE;QACV,MAAM;QACN,KAAK,EAAE,IAAI;KACZ,CAAC;SACC,kBAAkB,CAAC,qBAAqB,EAAE,IAAI,CAAC;SAC/C,QAAQ,CACP,IAAI,kBAAQ,CAAC,EAAE,CAAC,EAAE;QAChB,EAAE,CAAC,KAAK,CAAC,wCAAwC,EAAE,EAAE,gBAAgB,EAAE,CAAC,CAAC,QAAQ,CAAC,uBAAuB,EAAE;YACzG,MAAM;SACP,CAAC,CAAA;QAEF,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACrB,EAAE,CAAC,OAAO,CACR,IAAI,kBAAQ,CAAC,KAAK,CAAC,EAAE;gBACnB,KAAK;qBACF,KAAK,CAAC,gCAAgC,EAAE,EAAE,KAAK,EAAE,CAAC;qBAClD,QAAQ,CAAC,eAAe,yCAAoB,CAAC,UAAU,GAAG,CAAC,CAAA;YAChE,CAAC,CAAC,CACH,CAAA;QACH,CAAC;IACH,CAAC,CAAC,CACH;SACA,QAAQ,EAAE,CAAA;AACf,CAAC;AAED,wEAAwE;AACjE,KAAK,UAAU,kBAAkB,CAAC,MAAc,EAAE,MAAc;IACrE,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAE3C,OAAO,MAAM,IAAA,qCAA6B,EAAC;QACzC,UAAU,EAAE,IAAA,qBAAa,EAAC,uCAAgB,CAAC;QAC3C,MAAM,EAAE,EAAE;QACV,MAAM;QACN,KAAK,EAAE,IAAI;KACZ,CAAC;SACC,QAAQ,CAAC,mBAAmB,EAAE,IAAI,CAAC;SACnC,QAAQ,CAAC,qBAAqB,EAAE,IAAI,CAAC;SACrC,QAAQ,CAAC,IAAA,iDAAuB,EAAC,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;SACpD,QAAQ,EAAE,CAAA;AACf,CAAC","sourcesContent":["import { Brackets } from 'typeorm'\n\nimport { User } from '@things-factory/auth-base'\nimport { Domain, getQueryBuilderFromListParams, getRepository } from '@things-factory/shell'\n\nimport { ActivityThread, ActivityThreadStatus } from '../activity-thread/activity-thread.js'\nimport { ActivityApproval } from '../activity-approval/activity-approval.js'\nimport { myPendingApprovalsWhere } from '../activity-approval/my-pending-approvals.js'\n\n/**\n * What a person has on their plate in one domain - the same questions the rail's badges ask.\n *\n * The badges asked them only of whoever is signed in, with the rule written inline. The person 360\n * asks them of someone else (ADR-0067, the person 360 ruling), so the rule lives here once and both\n * readers call it - a second copy would drift the way the approval count once did\n * (`activity-summary-query.ts` records how).\n */\n\n/** The roles a person holds in this domain - an approval or a thread held by role reaches them through these. */\nasync function rolesIn(domain: Domain, userId: string): Promise<string[]> {\n const user = await getRepository(User).findOne({ where: { id: userId }, relations: ['roles'] })\n return (user?.roles || []).filter(role => role.domainId === domain.id).map(role => role.id)\n}\n\n/** Threads assigned to the person and not finished, plus unassigned ones their role may pick up. */\nexport async function toDosOf(domain: Domain, userId: string): Promise<number> {\n const roles = await rolesIn(domain, userId)\n const excludedStatuses = [ActivityThreadStatus.Unassigned, ActivityThreadStatus.Ended, ActivityThreadStatus.Aborted]\n\n return await getQueryBuilderFromListParams({\n repository: getRepository(ActivityThread),\n params: {},\n domain,\n alias: 'at'\n })\n .innerJoinAndSelect('at.activityInstance', 'ai')\n .andWhere(\n new Brackets(qb => {\n qb.where('at.state NOT IN (:...excludedStatuses)', { excludedStatuses }).andWhere('at.assignee = :userId', {\n userId\n })\n\n if (roles.length > 0) {\n qb.orWhere(\n new Brackets(subQb => {\n subQb\n .where('ai.assigneeRole IN (:...roles)', { roles })\n .andWhere(`at.state = '${ActivityThreadStatus.Unassigned}'`)\n })\n )\n }\n })\n )\n .getCount()\n}\n\n/** Approvals waiting on the person - through the inbox's own clause. */\nexport async function pendingApprovalsOf(domain: Domain, userId: string): Promise<number> {\n const roles = await rolesIn(domain, userId)\n\n return await getQueryBuilderFromListParams({\n repository: getRepository(ActivityApproval),\n params: {},\n domain,\n alias: 'ap'\n })\n .leftJoin('ap.activityThread', 'at')\n .leftJoin('at.activityInstance', 'ai')\n .andWhere(myPendingApprovalsWhere({ userId, roles }))\n .getCount()\n}\n"]}
1
+ {"version":3,"file":"open-work.js","sourceRoot":"","sources":["../../../server/service/activity-summary/open-work.ts"],"names":[],"mappings":";;AAwBA,0BAaC;AAED,gDAaC;AApDD,yDAAgD;AAChD,iDAA4F;AAE5F,8EAAsE;AACtE,oFAA4E;AAC5E,0FAAsF;AACtF,8EAA0E;AAE1E;;;;;;;GAOG;AAEH,iHAAiH;AACjH,KAAK,UAAU,OAAO,CAAC,MAAc,EAAE,MAAc;IACnD,MAAM,IAAI,GAAG,MAAM,IAAA,qBAAa,EAAC,gBAAI,CAAC,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,SAAS,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;IAC/F,OAAO,CAAC,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,KAAK,MAAM,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;AAC7F,CAAC;AAED,oGAAoG;AAC7F,KAAK,UAAU,OAAO,CAAC,MAAc,EAAE,MAAc;IAC1D,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAE3C,sFAAsF;IACtF,OAAO,MAAM,IAAA,qCAA6B,EAAC;QACzC,UAAU,EAAE,IAAA,qBAAa,EAAC,mCAAc,CAAC;QACzC,MAAM,EAAE,EAAE;QACV,MAAM;QACN,KAAK,EAAE,IAAI;KACZ,CAAC;SACC,kBAAkB,CAAC,qBAAqB,EAAE,IAAI,CAAC;SAC/C,QAAQ,CAAC,IAAA,uCAAkB,EAAC,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;SAC/C,QAAQ,EAAE,CAAA;AACf,CAAC;AAEM,KAAK,UAAU,kBAAkB,CAAC,MAAc,EAAE,MAAc;IACrE,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAE3C,OAAO,MAAM,IAAA,qCAA6B,EAAC;QACzC,UAAU,EAAE,IAAA,qBAAa,EAAC,uCAAgB,CAAC;QAC3C,MAAM,EAAE,EAAE;QACV,MAAM;QACN,KAAK,EAAE,IAAI;KACZ,CAAC;SACC,QAAQ,CAAC,mBAAmB,EAAE,IAAI,CAAC;SACnC,QAAQ,CAAC,qBAAqB,EAAE,IAAI,CAAC;SACrC,QAAQ,CAAC,IAAA,iDAAuB,EAAC,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;SACpD,QAAQ,EAAE,CAAA;AACf,CAAC","sourcesContent":["import { User } from '@things-factory/auth-base'\nimport { Domain, getQueryBuilderFromListParams, getRepository } from '@things-factory/shell'\n\nimport { ActivityThread } from '../activity-thread/activity-thread.js'\nimport { ActivityApproval } from '../activity-approval/activity-approval.js'\nimport { myPendingApprovalsWhere } from '../activity-approval/my-pending-approvals.js'\nimport { myOpenThreadsWhere } from '../activity-thread/my-open-threads.js'\n\n/**\n * What a person has on their plate in one domain - the same questions the rail's badges ask.\n *\n * The badges asked them only of whoever is signed in, with the rule written inline. The person 360\n * asks them of someone else (ADR-0067, the person 360 ruling), so the rule lives here once and both\n * readers call it - a second copy would drift the way the approval count once did\n * (`activity-summary-query.ts` records how).\n */\n\n/** The roles a person holds in this domain - an approval or a thread held by role reaches them through these. */\nasync function rolesIn(domain: Domain, userId: string): Promise<string[]> {\n const user = await getRepository(User).findOne({ where: { id: userId }, relations: ['roles'] })\n return (user?.roles || []).filter(role => role.domainId === domain.id).map(role => role.id)\n}\n\n/** Threads assigned to the person and not finished, plus unassigned ones their role may pick up. */\nexport async function toDosOf(domain: Domain, userId: string): Promise<number> {\n const roles = await rolesIn(domain, userId)\n\n /* The list's own clause - the badge counts what 할 일 shows, not a copy of its rule. */\n return await getQueryBuilderFromListParams({\n repository: getRepository(ActivityThread),\n params: {},\n domain,\n alias: 'at'\n })\n .innerJoinAndSelect('at.activityInstance', 'ai')\n .andWhere(myOpenThreadsWhere({ userId, roles }))\n .getCount()\n}\n\nexport async function pendingApprovalsOf(domain: Domain, userId: string): Promise<number> {\n const roles = await rolesIn(domain, userId)\n\n return await getQueryBuilderFromListParams({\n repository: getRepository(ActivityApproval),\n params: {},\n domain,\n alias: 'ap'\n })\n .leftJoin('ap.activityThread', 'at')\n .leftJoin('at.activityInstance', 'ai')\n .andWhere(myPendingApprovalsWhere({ userId, roles }))\n .getCount()\n}\n"]}
@@ -9,7 +9,10 @@ export declare class ActivityThreadQuery {
9
9
  activityThread(id: string, context: ResolverContext): Promise<ActivityThread>;
10
10
  activityThreads(params: ListParam, context: ResolverContext): Promise<ActivityThreadList>;
11
11
  todoList(params: ListParam, context: ResolverContext): Promise<ActivityThreadList>;
12
+ submittedList(params: ListParam, context: ResolverContext): Promise<ActivityThreadList>;
12
13
  doneList(params: ListParam, context: ResolverContext): Promise<ActivityThreadList>;
14
+ /** 할 일의 「제출한 것」·「완료」 — 내가 올린 것은 상신함이 따라간다(myThreadsOfOthersWhere). */
15
+ private myThreadsOfOthers;
13
16
  assignee(activityThread: ActivityThread): Promise<User>;
14
17
  activityInstance(activityThread: ActivityThread): Promise<ActivityInstance>;
15
18
  activityApprovals(activityThread: ActivityThread, context: ResolverContext): Promise<ActivityApproval[]>;
@@ -103,9 +103,16 @@ let ActivityThreadQuery = class ActivityThreadQuery {
103
103
  const [items, total] = await queryBuilder.getManyAndCount();
104
104
  return { items, total };
105
105
  }
106
+ async submittedList(params, context) {
107
+ const { domain, user } = context.state;
108
+ return await this.myThreadsOfOthers(params, domain, user.id, my_open_threads_js_1.WAITING_ON_OTHERS);
109
+ }
106
110
  async doneList(params, context) {
107
- var { domain, user } = context.state;
108
- const status = [activity_thread_js_1.ActivityThreadStatus.Ended, activity_thread_js_1.ActivityThreadStatus.Aborted];
111
+ const { domain, user } = context.state;
112
+ return await this.myThreadsOfOthers(params, domain, user.id, my_open_threads_js_1.FINISHED);
113
+ }
114
+ /** 할 일의 「제출한 것」·「완료」 — 내가 올린 것은 상신함이 따라간다(myThreadsOfOthersWhere). */
115
+ async myThreadsOfOthers(params, domain, userId, states) {
109
116
  const [items, total] = await (0, shell_1.getQueryBuilderFromListParams)({
110
117
  repository: (0, shell_1.getRepository)(activity_thread_js_1.ActivityThread),
111
118
  params,
@@ -118,8 +125,8 @@ let ActivityThreadQuery = class ActivityThreadQuery {
118
125
  priority: { columnName: 'priority', relationColumn: 'activityInstance' }
119
126
  }
120
127
  })
121
- .andWhere('at.state IN (:...status)', { status })
122
- .andWhere('at.assignee = :user', { user: user.id })
128
+ .innerJoinAndSelect('at.activityInstance', 'ai')
129
+ .andWhere((0, my_open_threads_js_1.myThreadsOfOthersWhere)({ userId, states }))
123
130
  .getManyAndCount();
124
131
  return { items, total };
125
132
  }
@@ -186,7 +193,19 @@ tslib_1.__decorate([
186
193
  tslib_1.__metadata("design:returntype", Promise)
187
194
  ], ActivityThreadQuery.prototype, "todoList", null);
188
195
  tslib_1.__decorate([
189
- (0, type_graphql_1.Query)(returns => activity_thread_type_js_1.ActivityThreadList, { description: 'To fetch the tasks(ActivityThreads) which has done by me' }),
196
+ (0, type_graphql_1.Query)(returns => activity_thread_type_js_1.ActivityThreadList, {
197
+ description: 'To fetch the tasks(ActivityThreads) I submitted that wait on an approval - of work someone else put up'
198
+ }),
199
+ tslib_1.__param(0, (0, type_graphql_1.Args)(type => shell_1.ListParam)),
200
+ tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
201
+ tslib_1.__metadata("design:type", Function),
202
+ tslib_1.__metadata("design:paramtypes", [shell_1.ListParam, Object]),
203
+ tslib_1.__metadata("design:returntype", Promise)
204
+ ], ActivityThreadQuery.prototype, "submittedList", null);
205
+ tslib_1.__decorate([
206
+ (0, type_graphql_1.Query)(returns => activity_thread_type_js_1.ActivityThreadList, {
207
+ description: 'To fetch the tasks(ActivityThreads) I finished - of work someone else put up'
208
+ }),
190
209
  tslib_1.__param(0, (0, type_graphql_1.Args)(type => shell_1.ListParam)),
191
210
  tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
192
211
  tslib_1.__metadata("design:type", Function),
@@ -1 +1 @@
1
- {"version":3,"file":"activity-thread-query.js","sourceRoot":"","sources":["../../../server/service/activity-thread/activity-thread-query.ts"],"names":[],"mappings":"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","sourcesContent":["import { Brackets } from 'typeorm'\nimport { Arg, Args, Ctx, Directive, FieldResolver, Query, Resolver, Root } from 'type-graphql'\n\nimport { User } from '@things-factory/auth-base'\nimport { Domain, getQueryBuilderFromListParams, getRepository, ListParam } from '@things-factory/shell'\n\nimport { ActivityInstance } from '../activity-instance/activity-instance.js'\nimport { ActivityThread, ActivityThreadStatus } from './activity-thread.js'\nimport { myOpenThreadsWhere } from './my-open-threads.js'\nimport { assertMayReadThread } from '../../controllers/activity-read/assert-may-read.js'\nimport { ActivityApproval } from '../activity-approval/activity-approval.js'\nimport { ActivityThreadList } from './activity-thread-type.js'\nimport { ActivityThreadHistory } from './activity-thread-history.js'\nimport { TODO_INSTANCE_SORTS, todoOrderTerms } from './todo-order.js'\n\n\n/**\n * 「할 일」 목록의 정렬 — **기한이 없는 것은 뒤로 간다.**\n *\n * ── 무엇이 잘못되고 있었나 (2026-09-06) ────────────────────────────────────\n * 화면의 기본 정렬은 `dueAt` 오름차순이다. 급한 것부터 보라는 뜻인데, **기한이 없는 것이 맨 위에\n * 왔다.** 실측(sqlite): 9건 중 기한 없는 6건이 먼저 나오고 「3일 지남」 3건이 맨 아래였다.\n *\n * NULL 을 앞에 둘지 뒤에 둘지는 **DB 마다 다르다** — sqlite 는 오름차순에서 NULL 이 먼저, postgres 는\n * 나중이다. 그래서 같은 코드가 개발 환경과 운영 환경에서 다른 순서를 낸다.\n *\n * ── 왜 NULLS LAST 를 쓰지 않나 ─────────────────────────────────────────────\n * `ORDER BY ... NULLS LAST` 는 postgres · oracle 문법이다. mysql · mssql 에서는 구문 오류가 난다.\n * 이 프레임워크는 다섯 드라이버를 다 지켜야 한다.\n *\n * `CASE WHEN ... IS NULL THEN 1 ELSE 0 END` 는 표준 SQL 이고 다섯 곳에서 다 돈다. 컬럼 이름은\n * 손으로 적지 않고 TypeORM 의 메타데이터에서 꺼낸다 — 이 프로젝트의 명명 규칙이 snake_case 라\n * `dueAt` 은 실제로 `due_at` 이다(shell 의 NamingStrategy).\n *\n * ── 공용 함수를 고치지 않는다 ──────────────────────────────────────────────\n * `getQueryBuilderFromListParams` 는 136개 꾸러미가 함께 쓴다. 정렬은 이 목록의 사정이므로\n * 여기서 맡는다 — 그 함수에는 정렬을 넘기지 않고(빈 배열) 아래에서 직접 건다.\n */\n\nfunction applyTodoSortings(queryBuilder: any, sortings: { name: string; desc?: boolean }[]) {\n const terms = todoOrderTerms(sortings, name => {\n const alias = TODO_INSTANCE_SORTS.has(name) ? 'ai' : 'at'\n const metadata = getRepository(alias === 'ai' ? ActivityInstance : ActivityThread).metadata\n const column = metadata.findColumnWithPropertyName(name)\n\n if (!column) {\n return undefined\n }\n\n const escape = (part: string) => queryBuilder.connection.driver.escape(part)\n\n return `${escape(alias)}.${escape(column.databaseName)}`\n })\n\n terms.forEach(({ expression, direction, select }, index) => {\n /* 식은 select 에 이름 붙여 올린다 — orderBy 는 식을 못 받는다(todo-order 머리말). */\n if (select) {\n queryBuilder.addSelect(select, expression)\n }\n\n index === 0 ? queryBuilder.orderBy(expression, direction) : queryBuilder.addOrderBy(expression, direction)\n })\n}\n\n@Resolver(ActivityThread)\nexport class ActivityThreadQuery {\n @Query(returns => ActivityThread!, { nullable: true, description: 'To fetch a ActivityThread' })\n async activityThread(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<ActivityThread> {\n const { domain } = context.state\n\n const thread = await getRepository(ActivityThread).findOne({\n where: { domain: { id: domain.id }, id }\n })\n\n /* 없는 건은 없다고(null). 있는데 못 읽는 건은 이름 붙여 거절한다 — § assert-may-read.ts */\n if (thread) await assertMayReadThread(thread, context)\n\n return thread\n }\n\n @Directive('@privilege(category: \"activity-instance\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => ActivityThreadList, { description: 'To fetch multiple ActivityThreads' })\n async activityThreads(\n @Args(type => ListParam) params: ListParam,\n @Ctx() context: ResolverContext\n ): Promise<ActivityThreadList> {\n const { domain } = context.state\n\n const queryBuilder = getQueryBuilderFromListParams({\n domain,\n params,\n repository: getRepository(ActivityThread),\n searchables: ['name', 'description']\n })\n\n const [items, total] = await queryBuilder.getManyAndCount()\n\n return { items, total }\n }\n\n @Query(returns => ActivityThreadList, { description: 'To fetch my own ActivityThreads' })\n async todoList(\n @Args(type => ListParam) params: ListParam,\n @Ctx() context: ResolverContext\n ): Promise<ActivityThreadList> {\n var { domain, user } = context.state\n\n user = await getRepository(User).findOne({\n where: { id: user.id },\n relations: ['roles']\n })\n const roles = user.roles.filter(role => role.domainId === domain.id).map(role => role.id)\n\n const queryBuilder = getQueryBuilderFromListParams({\n repository: getRepository(ActivityThread),\n /* 정렬은 아래에서 직접 건다(applyTodoSortings 머리말) — 여기에 넘기면 NULL 자리를 못 정한다. */\n params: { ...params, sortings: [] },\n domain,\n alias: 'at',\n searchables: ['name', 'description'],\n filtersMap: {\n name: { columnName: 'name', relationColumn: 'activityInstance' },\n description: { columnName: 'description', relationColumn: 'activityInstance' },\n priority: { columnName: 'priority', relationColumn: 'activityInstance' }\n }\n })\n .innerJoinAndSelect('at.activityInstance', 'ai')\n /* 「내 앞에 있는 일」의 정의는 한 자리에 있다 — 달력도 같은 것을 읽는다. */\n .andWhere(myOpenThreadsWhere({ userId: user.id, roles }))\n\n applyTodoSortings(queryBuilder, params.sortings || [])\n\n const [items, total] = await queryBuilder.getManyAndCount()\n\n return { items, total }\n }\n\n @Query(returns => ActivityThreadList, { description: 'To fetch the tasks(ActivityThreads) which has done by me' })\n async doneList(\n @Args(type => ListParam) params: ListParam,\n @Ctx() context: ResolverContext\n ): Promise<ActivityThreadList> {\n var { domain, user } = context.state\n\n const status = [ActivityThreadStatus.Ended, ActivityThreadStatus.Aborted]\n\n const [items, total] = await getQueryBuilderFromListParams({\n repository: getRepository(ActivityThread),\n params,\n domain,\n alias: 'at',\n searchables: ['name', 'description'],\n filtersMap: {\n name: { columnName: 'name', relationColumn: 'activityInstance' },\n description: { columnName: 'description', relationColumn: 'activityInstance' },\n priority: { columnName: 'priority', relationColumn: 'activityInstance' }\n }\n })\n .andWhere('at.state IN (:...status)', { status })\n .andWhere('at.assignee = :user', { user: user.id })\n .getManyAndCount()\n\n return { items, total }\n }\n\n @FieldResolver(type => User)\n async assignee(@Root() activityThread: ActivityThread): Promise<User> {\n return activityThread.assigneeId\n ? activityThread.assignee || (await getRepository(User).findOneBy({ id: activityThread.assigneeId }))\n : null\n }\n\n @FieldResolver(type => ActivityInstance)\n async activityInstance(@Root() activityThread: ActivityThread): Promise<ActivityInstance> {\n return await getRepository(ActivityInstance).findOneBy({ id: activityThread.activityInstanceId })\n }\n\n @FieldResolver(type => [ActivityApproval])\n async activityApprovals(\n @Root() activityThread: ActivityThread,\n @Ctx() context: ResolverContext\n ): Promise<ActivityApproval[]> {\n return await getRepository(ActivityApproval).findBy({\n activityThread: { id: activityThread.id }\n })\n }\n\n @FieldResolver(type => [ActivityThreadHistory])\n async activityThreadHistories(\n @Root() activityThread: ActivityThread,\n @Ctx() context: ResolverContext\n ): Promise<ActivityThreadHistory[]> {\n return await getRepository(ActivityThreadHistory).find({\n where: {\n originalId: activityThread.id\n },\n order: {\n version: 'ASC'\n }\n })\n }\n\n @FieldResolver(type => Domain)\n async domain(@Root() activityThread: ActivityThread): Promise<Domain> {\n return await getRepository(Domain).findOneBy({ id: activityThread.domainId })\n }\n\n @FieldResolver(type => User)\n async updater(@Root() activityThread: ActivityThread): Promise<User> {\n return activityThread.updaterId && (await getRepository(User).findOneBy({ id: activityThread.updaterId }))\n }\n\n @FieldResolver(type => User)\n async creator(@Root() activityThread: ActivityThread): Promise<User> {\n return activityThread.creatorId && (await getRepository(User).findOneBy({ id: activityThread.creatorId }))\n }\n\n @FieldResolver(type => User)\n async terminator(@Root() activityThread: ActivityThread): Promise<User> {\n return activityThread.terminatorId && (await getRepository(User).findOneBy({ id: activityThread.terminatorId }))\n }\n}\n"]}
1
+ {"version":3,"file":"activity-thread-query.js","sourceRoot":"","sources":["../../../server/service/activity-thread/activity-thread-query.ts"],"names":[],"mappings":"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","sourcesContent":["import { Brackets } from 'typeorm'\nimport { Arg, Args, Ctx, Directive, FieldResolver, Query, Resolver, Root } from 'type-graphql'\n\nimport { User } from '@things-factory/auth-base'\nimport { Domain, getQueryBuilderFromListParams, getRepository, ListParam } from '@things-factory/shell'\n\nimport { ActivityInstance } from '../activity-instance/activity-instance.js'\nimport { ActivityThread, ActivityThreadStatus } from './activity-thread.js'\nimport { FINISHED, myOpenThreadsWhere, myThreadsOfOthersWhere, WAITING_ON_OTHERS } from './my-open-threads.js'\nimport { assertMayReadThread } from '../../controllers/activity-read/assert-may-read.js'\nimport { ActivityApproval } from '../activity-approval/activity-approval.js'\nimport { ActivityThreadList } from './activity-thread-type.js'\nimport { ActivityThreadHistory } from './activity-thread-history.js'\nimport { TODO_INSTANCE_SORTS, todoOrderTerms } from './todo-order.js'\n\n\n/**\n * 「할 일」 목록의 정렬 — **기한이 없는 것은 뒤로 간다.**\n *\n * ── 무엇이 잘못되고 있었나 (2026-09-06) ────────────────────────────────────\n * 화면의 기본 정렬은 `dueAt` 오름차순이다. 급한 것부터 보라는 뜻인데, **기한이 없는 것이 맨 위에\n * 왔다.** 실측(sqlite): 9건 중 기한 없는 6건이 먼저 나오고 「3일 지남」 3건이 맨 아래였다.\n *\n * NULL 을 앞에 둘지 뒤에 둘지는 **DB 마다 다르다** — sqlite 는 오름차순에서 NULL 이 먼저, postgres 는\n * 나중이다. 그래서 같은 코드가 개발 환경과 운영 환경에서 다른 순서를 낸다.\n *\n * ── 왜 NULLS LAST 를 쓰지 않나 ─────────────────────────────────────────────\n * `ORDER BY ... NULLS LAST` 는 postgres · oracle 문법이다. mysql · mssql 에서는 구문 오류가 난다.\n * 이 프레임워크는 다섯 드라이버를 다 지켜야 한다.\n *\n * `CASE WHEN ... IS NULL THEN 1 ELSE 0 END` 는 표준 SQL 이고 다섯 곳에서 다 돈다. 컬럼 이름은\n * 손으로 적지 않고 TypeORM 의 메타데이터에서 꺼낸다 — 이 프로젝트의 명명 규칙이 snake_case 라\n * `dueAt` 은 실제로 `due_at` 이다(shell 의 NamingStrategy).\n *\n * ── 공용 함수를 고치지 않는다 ──────────────────────────────────────────────\n * `getQueryBuilderFromListParams` 는 136개 꾸러미가 함께 쓴다. 정렬은 이 목록의 사정이므로\n * 여기서 맡는다 — 그 함수에는 정렬을 넘기지 않고(빈 배열) 아래에서 직접 건다.\n */\n\nfunction applyTodoSortings(queryBuilder: any, sortings: { name: string; desc?: boolean }[]) {\n const terms = todoOrderTerms(sortings, name => {\n const alias = TODO_INSTANCE_SORTS.has(name) ? 'ai' : 'at'\n const metadata = getRepository(alias === 'ai' ? ActivityInstance : ActivityThread).metadata\n const column = metadata.findColumnWithPropertyName(name)\n\n if (!column) {\n return undefined\n }\n\n const escape = (part: string) => queryBuilder.connection.driver.escape(part)\n\n return `${escape(alias)}.${escape(column.databaseName)}`\n })\n\n terms.forEach(({ expression, direction, select }, index) => {\n /* 식은 select 에 이름 붙여 올린다 — orderBy 는 식을 못 받는다(todo-order 머리말). */\n if (select) {\n queryBuilder.addSelect(select, expression)\n }\n\n index === 0 ? queryBuilder.orderBy(expression, direction) : queryBuilder.addOrderBy(expression, direction)\n })\n}\n\n@Resolver(ActivityThread)\nexport class ActivityThreadQuery {\n @Query(returns => ActivityThread!, { nullable: true, description: 'To fetch a ActivityThread' })\n async activityThread(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<ActivityThread> {\n const { domain } = context.state\n\n const thread = await getRepository(ActivityThread).findOne({\n where: { domain: { id: domain.id }, id }\n })\n\n /* 없는 건은 없다고(null). 있는데 못 읽는 건은 이름 붙여 거절한다 — § assert-may-read.ts */\n if (thread) await assertMayReadThread(thread, context)\n\n return thread\n }\n\n @Directive('@privilege(category: \"activity-instance\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => ActivityThreadList, { description: 'To fetch multiple ActivityThreads' })\n async activityThreads(\n @Args(type => ListParam) params: ListParam,\n @Ctx() context: ResolverContext\n ): Promise<ActivityThreadList> {\n const { domain } = context.state\n\n const queryBuilder = getQueryBuilderFromListParams({\n domain,\n params,\n repository: getRepository(ActivityThread),\n searchables: ['name', 'description']\n })\n\n const [items, total] = await queryBuilder.getManyAndCount()\n\n return { items, total }\n }\n\n @Query(returns => ActivityThreadList, { description: 'To fetch my own ActivityThreads' })\n async todoList(\n @Args(type => ListParam) params: ListParam,\n @Ctx() context: ResolverContext\n ): Promise<ActivityThreadList> {\n var { domain, user } = context.state\n\n user = await getRepository(User).findOne({\n where: { id: user.id },\n relations: ['roles']\n })\n const roles = user.roles.filter(role => role.domainId === domain.id).map(role => role.id)\n\n const queryBuilder = getQueryBuilderFromListParams({\n repository: getRepository(ActivityThread),\n /* 정렬은 아래에서 직접 건다(applyTodoSortings 머리말) — 여기에 넘기면 NULL 자리를 못 정한다. */\n params: { ...params, sortings: [] },\n domain,\n alias: 'at',\n searchables: ['name', 'description'],\n filtersMap: {\n name: { columnName: 'name', relationColumn: 'activityInstance' },\n description: { columnName: 'description', relationColumn: 'activityInstance' },\n priority: { columnName: 'priority', relationColumn: 'activityInstance' }\n }\n })\n .innerJoinAndSelect('at.activityInstance', 'ai')\n /* 「내 앞에 있는 일」의 정의는 한 자리에 있다 — 달력도 같은 것을 읽는다. */\n .andWhere(myOpenThreadsWhere({ userId: user.id, roles }))\n\n applyTodoSortings(queryBuilder, params.sortings || [])\n\n const [items, total] = await queryBuilder.getManyAndCount()\n\n return { items, total }\n }\n\n @Query(returns => ActivityThreadList, {\n description: 'To fetch the tasks(ActivityThreads) I submitted that wait on an approval - of work someone else put up'\n })\n async submittedList(\n @Args(type => ListParam) params: ListParam,\n @Ctx() context: ResolverContext\n ): Promise<ActivityThreadList> {\n const { domain, user } = context.state\n\n return await this.myThreadsOfOthers(params, domain, user.id, WAITING_ON_OTHERS)\n }\n\n @Query(returns => ActivityThreadList, {\n description: 'To fetch the tasks(ActivityThreads) I finished - of work someone else put up'\n })\n async doneList(\n @Args(type => ListParam) params: ListParam,\n @Ctx() context: ResolverContext\n ): Promise<ActivityThreadList> {\n const { domain, user } = context.state\n\n return await this.myThreadsOfOthers(params, domain, user.id, FINISHED)\n }\n\n /** 할 일의 「제출한 것」·「완료」 — 내가 올린 것은 상신함이 따라간다(myThreadsOfOthersWhere). */\n private async myThreadsOfOthers(\n params: ListParam,\n domain: Domain,\n userId: string,\n states: ActivityThreadStatus[]\n ): Promise<ActivityThreadList> {\n const [items, total] = await getQueryBuilderFromListParams({\n repository: getRepository(ActivityThread),\n params,\n domain,\n alias: 'at',\n searchables: ['name', 'description'],\n filtersMap: {\n name: { columnName: 'name', relationColumn: 'activityInstance' },\n description: { columnName: 'description', relationColumn: 'activityInstance' },\n priority: { columnName: 'priority', relationColumn: 'activityInstance' }\n }\n })\n .innerJoinAndSelect('at.activityInstance', 'ai')\n .andWhere(myThreadsOfOthersWhere({ userId, states }))\n .getManyAndCount()\n\n return { items, total }\n }\n\n @FieldResolver(type => User)\n async assignee(@Root() activityThread: ActivityThread): Promise<User> {\n return activityThread.assigneeId\n ? activityThread.assignee || (await getRepository(User).findOneBy({ id: activityThread.assigneeId }))\n : null\n }\n\n @FieldResolver(type => ActivityInstance)\n async activityInstance(@Root() activityThread: ActivityThread): Promise<ActivityInstance> {\n return await getRepository(ActivityInstance).findOneBy({ id: activityThread.activityInstanceId })\n }\n\n @FieldResolver(type => [ActivityApproval])\n async activityApprovals(\n @Root() activityThread: ActivityThread,\n @Ctx() context: ResolverContext\n ): Promise<ActivityApproval[]> {\n return await getRepository(ActivityApproval).findBy({\n activityThread: { id: activityThread.id }\n })\n }\n\n @FieldResolver(type => [ActivityThreadHistory])\n async activityThreadHistories(\n @Root() activityThread: ActivityThread,\n @Ctx() context: ResolverContext\n ): Promise<ActivityThreadHistory[]> {\n return await getRepository(ActivityThreadHistory).find({\n where: {\n originalId: activityThread.id\n },\n order: {\n version: 'ASC'\n }\n })\n }\n\n @FieldResolver(type => Domain)\n async domain(@Root() activityThread: ActivityThread): Promise<Domain> {\n return await getRepository(Domain).findOneBy({ id: activityThread.domainId })\n }\n\n @FieldResolver(type => User)\n async updater(@Root() activityThread: ActivityThread): Promise<User> {\n return activityThread.updaterId && (await getRepository(User).findOneBy({ id: activityThread.updaterId }))\n }\n\n @FieldResolver(type => User)\n async creator(@Root() activityThread: ActivityThread): Promise<User> {\n return activityThread.creatorId && (await getRepository(User).findOneBy({ id: activityThread.creatorId }))\n }\n\n @FieldResolver(type => User)\n async terminator(@Root() activityThread: ActivityThread): Promise<User> {\n return activityThread.terminatorId && (await getRepository(User).findOneBy({ id: activityThread.terminatorId }))\n }\n}\n"]}
@@ -1,10 +1,15 @@
1
1
  import { Brackets } from 'typeorm';
2
+ import { ActivityThreadStatus } from './activity-thread.js';
3
+ /** A thread I submitted, waiting on someone's judgment. */
4
+ export declare const WAITING_ON_OTHERS: ActivityThreadStatus[];
5
+ /** A thread that is over. */
6
+ export declare const FINISHED: ActivityThreadStatus[];
2
7
  /**
3
- * The work that is on my plate — one definition, two readers.
8
+ * The work that is on my plate — one definition, three readers.
4
9
  *
5
- * 할 일 목록 asks this, and so does the calendar. Written twice they drift: a new state, or a new
6
- * way of being assigned, lands in one and not the other, and the calendar quietly shows a
7
- * different week than the list it sits beside. Nothing errors.
10
+ * 할 일 목록 asks this, and so do the calendar and the badge (open-work). Written twice they drift:
11
+ * a new state, or a new way of being assigned, lands in one and not the other, and the badge says
12
+ * a different number than the list it opens. Nothing errors.
8
13
  *
9
14
  * Expects `at` (ActivityThread) and `ai` (ActivityInstance) to be joined already — the role branch
10
15
  * reads assigneeRole off the instance.
@@ -13,3 +18,17 @@ export declare function myOpenThreadsWhere({ userId, roles }: {
13
18
  userId: string;
14
19
  roles: string[];
15
20
  }): Brackets;
21
+ /**
22
+ * My threads in these states, of work **someone else** put up.
23
+ *
24
+ * What I put up myself is followed in 상신함 — the box of what I gave others to do. A post thread
25
+ * is mine only as the vehicle of my request: once submitted it waits on the approvers, and when it
26
+ * ends it is my request that ended. Listing it again under 할 일 put one fact in two boxes. While it
27
+ * is my turn - rejected and back with me - it stays in 할 일, which is myOpenThreadsWhere above.
28
+ *
29
+ * Expects `at` and `ai` joined.
30
+ */
31
+ export declare function myThreadsOfOthersWhere({ userId, states }: {
32
+ userId: string;
33
+ states: ActivityThreadStatus[];
34
+ }): Brackets;
@@ -1,32 +1,46 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FINISHED = exports.WAITING_ON_OTHERS = void 0;
3
4
  exports.myOpenThreadsWhere = myOpenThreadsWhere;
5
+ exports.myThreadsOfOthersWhere = myThreadsOfOthersWhere;
4
6
  const typeorm_1 = require("typeorm");
5
7
  const activity_thread_js_1 = require("./activity-thread.js");
6
8
  /**
7
- * Thread states that are **not** work waiting on someone.
9
+ * Thread states that are **not** my turn.
10
+ *
11
+ * Submitted and escalated wait on an approver: the thread is still assigned to me, but nothing I do
12
+ * moves it. Counting them made 할 일 say 1 to a person who had just put up an expenditure request
13
+ * and had nothing left to do (2026-10-16). They are the 「제출한 것」 group of the same box.
8
14
  *
9
15
  * Unassigned belongs here for the person branch only — a thread nobody holds is not on my plate
10
16
  * until I claim it, and the role branch below is what surfaces it to the people who could.
11
17
  */
12
- const CLOSED_OR_UNCLAIMED = [
18
+ const NOT_MY_TURN = [
13
19
  activity_thread_js_1.ActivityThreadStatus.Unassigned,
20
+ activity_thread_js_1.ActivityThreadStatus.Submitted,
21
+ activity_thread_js_1.ActivityThreadStatus.Escalated,
14
22
  activity_thread_js_1.ActivityThreadStatus.Ended,
15
23
  activity_thread_js_1.ActivityThreadStatus.Aborted
16
24
  ];
25
+ /** A thread I submitted, waiting on someone's judgment. */
26
+ exports.WAITING_ON_OTHERS = [activity_thread_js_1.ActivityThreadStatus.Submitted, activity_thread_js_1.ActivityThreadStatus.Escalated];
27
+ /** A thread that is over. */
28
+ exports.FINISHED = [activity_thread_js_1.ActivityThreadStatus.Ended, activity_thread_js_1.ActivityThreadStatus.Aborted];
17
29
  /**
18
- * The work that is on my plate — one definition, two readers.
30
+ * The work that is on my plate — one definition, three readers.
19
31
  *
20
- * 할 일 목록 asks this, and so does the calendar. Written twice they drift: a new state, or a new
21
- * way of being assigned, lands in one and not the other, and the calendar quietly shows a
22
- * different week than the list it sits beside. Nothing errors.
32
+ * 할 일 목록 asks this, and so do the calendar and the badge (open-work). Written twice they drift:
33
+ * a new state, or a new way of being assigned, lands in one and not the other, and the badge says
34
+ * a different number than the list it opens. Nothing errors.
23
35
  *
24
36
  * Expects `at` (ActivityThread) and `ai` (ActivityInstance) to be joined already — the role branch
25
37
  * reads assigneeRole off the instance.
26
38
  */
27
39
  function myOpenThreadsWhere({ userId, roles }) {
28
40
  return new typeorm_1.Brackets(qb => {
29
- qb.where('at.state NOT IN (:...closedOrUnclaimed)', { closedOrUnclaimed: CLOSED_OR_UNCLAIMED }).andWhere('at.assignee = :userId', { userId });
41
+ qb.where('at.state NOT IN (:...notMyTurn)', { notMyTurn: NOT_MY_TURN }).andWhere('at.assignee = :userId', {
42
+ userId
43
+ });
30
44
  /* 역할로 걸린 것은 아직 임자가 없다 — 그 역할을 가진 사람 모두의 할 일이다. */
31
45
  if (roles.length > 0) {
32
46
  qb.orWhere(new typeorm_1.Brackets(subQb => {
@@ -37,4 +51,21 @@ function myOpenThreadsWhere({ userId, roles }) {
37
51
  }
38
52
  });
39
53
  }
54
+ /**
55
+ * My threads in these states, of work **someone else** put up.
56
+ *
57
+ * What I put up myself is followed in 상신함 — the box of what I gave others to do. A post thread
58
+ * is mine only as the vehicle of my request: once submitted it waits on the approvers, and when it
59
+ * ends it is my request that ended. Listing it again under 할 일 put one fact in two boxes. While it
60
+ * is my turn - rejected and back with me - it stays in 할 일, which is myOpenThreadsWhere above.
61
+ *
62
+ * Expects `at` and `ai` joined.
63
+ */
64
+ function myThreadsOfOthersWhere({ userId, states }) {
65
+ return new typeorm_1.Brackets(qb => {
66
+ qb.where('at.assignee = :userId', { userId })
67
+ .andWhere('at.state IN (:...states)', { states })
68
+ .andWhere('(ai.creator IS NULL OR ai.creator != :userId)', { userId });
69
+ });
70
+ }
40
71
  //# sourceMappingURL=my-open-threads.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"my-open-threads.js","sourceRoot":"","sources":["../../../server/service/activity-thread/my-open-threads.ts"],"names":[],"mappings":";;AA0BA,gDAkBC;AA5CD,qCAAkC;AAElC,6DAA2D;AAE3D;;;;;GAKG;AACH,MAAM,mBAAmB,GAAG;IAC1B,yCAAoB,CAAC,UAAU;IAC/B,yCAAoB,CAAC,KAAK;IAC1B,yCAAoB,CAAC,OAAO;CAC7B,CAAA;AAED;;;;;;;;;GASG;AACH,SAAgB,kBAAkB,CAAC,EAAE,MAAM,EAAE,KAAK,EAAuC;IACvF,OAAO,IAAI,kBAAQ,CAAC,EAAE,CAAC,EAAE;QACvB,EAAE,CAAC,KAAK,CAAC,yCAAyC,EAAE,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,CAAC,CAAC,QAAQ,CACtG,uBAAuB,EACvB,EAAE,MAAM,EAAE,CACX,CAAA;QAED,kDAAkD;QAClD,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACrB,EAAE,CAAC,OAAO,CACR,IAAI,kBAAQ,CAAC,KAAK,CAAC,EAAE;gBACnB,KAAK;qBACF,KAAK,CAAC,gCAAgC,EAAE,EAAE,KAAK,EAAE,CAAC;qBAClD,QAAQ,CAAC,wBAAwB,EAAE,EAAE,UAAU,EAAE,yCAAoB,CAAC,UAAU,EAAE,CAAC,CAAA;YACxF,CAAC,CAAC,CACH,CAAA;QACH,CAAC;IACH,CAAC,CAAC,CAAA;AACJ,CAAC","sourcesContent":["import { Brackets } from 'typeorm'\n\nimport { ActivityThreadStatus } from './activity-thread.js'\n\n/**\n * Thread states that are **not** work waiting on someone.\n *\n * Unassigned belongs here for the person branch only — a thread nobody holds is not on my plate\n * until I claim it, and the role branch below is what surfaces it to the people who could.\n */\nconst CLOSED_OR_UNCLAIMED = [\n ActivityThreadStatus.Unassigned,\n ActivityThreadStatus.Ended,\n ActivityThreadStatus.Aborted\n]\n\n/**\n * The work that is on my plate — one definition, two readers.\n *\n * 할 일 목록 asks this, and so does the calendar. Written twice they drift: a new state, or a new\n * way of being assigned, lands in one and not the other, and the calendar quietly shows a\n * different week than the list it sits beside. Nothing errors.\n *\n * Expects `at` (ActivityThread) and `ai` (ActivityInstance) to be joined already — the role branch\n * reads assigneeRole off the instance.\n */\nexport function myOpenThreadsWhere({ userId, roles }: { userId: string; roles: string[] }): Brackets {\n return new Brackets(qb => {\n qb.where('at.state NOT IN (:...closedOrUnclaimed)', { closedOrUnclaimed: CLOSED_OR_UNCLAIMED }).andWhere(\n 'at.assignee = :userId',\n { userId }\n )\n\n /* 역할로 걸린 것은 아직 임자가 없다 — 그 역할을 가진 사람 모두의 할 일이다. */\n if (roles.length > 0) {\n qb.orWhere(\n new Brackets(subQb => {\n subQb\n .where('ai.assigneeRole IN (:...roles)', { roles })\n .andWhere('at.state = :unassigned', { unassigned: ActivityThreadStatus.Unassigned })\n })\n )\n }\n })\n}\n"]}
1
+ {"version":3,"file":"my-open-threads.js","sourceRoot":"","sources":["../../../server/service/activity-thread/my-open-threads.ts"],"names":[],"mappings":";;;AAsCA,gDAiBC;AAYD,wDAMC;AAzED,qCAAkC;AAElC,6DAA2D;AAE3D;;;;;;;;;GASG;AACH,MAAM,WAAW,GAAG;IAClB,yCAAoB,CAAC,UAAU;IAC/B,yCAAoB,CAAC,SAAS;IAC9B,yCAAoB,CAAC,SAAS;IAC9B,yCAAoB,CAAC,KAAK;IAC1B,yCAAoB,CAAC,OAAO;CAC7B,CAAA;AAED,2DAA2D;AAC9C,QAAA,iBAAiB,GAAG,CAAC,yCAAoB,CAAC,SAAS,EAAE,yCAAoB,CAAC,SAAS,CAAC,CAAA;AAEjG,6BAA6B;AAChB,QAAA,QAAQ,GAAG,CAAC,yCAAoB,CAAC,KAAK,EAAE,yCAAoB,CAAC,OAAO,CAAC,CAAA;AAElF;;;;;;;;;GASG;AACH,SAAgB,kBAAkB,CAAC,EAAE,MAAM,EAAE,KAAK,EAAuC;IACvF,OAAO,IAAI,kBAAQ,CAAC,EAAE,CAAC,EAAE;QACvB,EAAE,CAAC,KAAK,CAAC,iCAAiC,EAAE,EAAE,SAAS,EAAE,WAAW,EAAE,CAAC,CAAC,QAAQ,CAAC,uBAAuB,EAAE;YACxG,MAAM;SACP,CAAC,CAAA;QAEF,kDAAkD;QAClD,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACrB,EAAE,CAAC,OAAO,CACR,IAAI,kBAAQ,CAAC,KAAK,CAAC,EAAE;gBACnB,KAAK;qBACF,KAAK,CAAC,gCAAgC,EAAE,EAAE,KAAK,EAAE,CAAC;qBAClD,QAAQ,CAAC,wBAAwB,EAAE,EAAE,UAAU,EAAE,yCAAoB,CAAC,UAAU,EAAE,CAAC,CAAA;YACxF,CAAC,CAAC,CACH,CAAA;QACH,CAAC;IACH,CAAC,CAAC,CAAA;AACJ,CAAC;AAED;;;;;;;;;GASG;AACH,SAAgB,sBAAsB,CAAC,EAAE,MAAM,EAAE,MAAM,EAAsD;IAC3G,OAAO,IAAI,kBAAQ,CAAC,EAAE,CAAC,EAAE;QACvB,EAAE,CAAC,KAAK,CAAC,uBAAuB,EAAE,EAAE,MAAM,EAAE,CAAC;aAC1C,QAAQ,CAAC,0BAA0B,EAAE,EAAE,MAAM,EAAE,CAAC;aAChD,QAAQ,CAAC,+CAA+C,EAAE,EAAE,MAAM,EAAE,CAAC,CAAA;IAC1E,CAAC,CAAC,CAAA;AACJ,CAAC","sourcesContent":["import { Brackets } from 'typeorm'\n\nimport { ActivityThreadStatus } from './activity-thread.js'\n\n/**\n * Thread states that are **not** my turn.\n *\n * Submitted and escalated wait on an approver: the thread is still assigned to me, but nothing I do\n * moves it. Counting them made 할 일 say 1 to a person who had just put up an expenditure request\n * and had nothing left to do (2026-10-16). They are the 「제출한 것」 group of the same box.\n *\n * Unassigned belongs here for the person branch only — a thread nobody holds is not on my plate\n * until I claim it, and the role branch below is what surfaces it to the people who could.\n */\nconst NOT_MY_TURN = [\n ActivityThreadStatus.Unassigned,\n ActivityThreadStatus.Submitted,\n ActivityThreadStatus.Escalated,\n ActivityThreadStatus.Ended,\n ActivityThreadStatus.Aborted\n]\n\n/** A thread I submitted, waiting on someone's judgment. */\nexport const WAITING_ON_OTHERS = [ActivityThreadStatus.Submitted, ActivityThreadStatus.Escalated]\n\n/** A thread that is over. */\nexport const FINISHED = [ActivityThreadStatus.Ended, ActivityThreadStatus.Aborted]\n\n/**\n * The work that is on my plate — one definition, three readers.\n *\n * 할 일 목록 asks this, and so do the calendar and the badge (open-work). Written twice they drift:\n * a new state, or a new way of being assigned, lands in one and not the other, and the badge says\n * a different number than the list it opens. Nothing errors.\n *\n * Expects `at` (ActivityThread) and `ai` (ActivityInstance) to be joined already — the role branch\n * reads assigneeRole off the instance.\n */\nexport function myOpenThreadsWhere({ userId, roles }: { userId: string; roles: string[] }): Brackets {\n return new Brackets(qb => {\n qb.where('at.state NOT IN (:...notMyTurn)', { notMyTurn: NOT_MY_TURN }).andWhere('at.assignee = :userId', {\n userId\n })\n\n /* 역할로 걸린 것은 아직 임자가 없다 — 그 역할을 가진 사람 모두의 할 일이다. */\n if (roles.length > 0) {\n qb.orWhere(\n new Brackets(subQb => {\n subQb\n .where('ai.assigneeRole IN (:...roles)', { roles })\n .andWhere('at.state = :unassigned', { unassigned: ActivityThreadStatus.Unassigned })\n })\n )\n }\n })\n}\n\n/**\n * My threads in these states, of work **someone else** put up.\n *\n * What I put up myself is followed in 상신함 — the box of what I gave others to do. A post thread\n * is mine only as the vehicle of my request: once submitted it waits on the approvers, and when it\n * ends it is my request that ended. Listing it again under 할 일 put one fact in two boxes. While it\n * is my turn - rejected and back with me - it stays in 할 일, which is myOpenThreadsWhere above.\n *\n * Expects `at` and `ai` joined.\n */\nexport function myThreadsOfOthersWhere({ userId, states }: { userId: string; states: ActivityThreadStatus[] }): Brackets {\n return new Brackets(qb => {\n qb.where('at.assignee = :userId', { userId })\n .andWhere('at.state IN (:...states)', { states })\n .andWhere('(ai.creator IS NULL OR ai.creator != :userId)', { userId })\n })\n}\n"]}