@masterteam/task-schedule 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# `@masterteam/task-schedule`
|
|
2
|
+
|
|
3
|
+
Syncfusion Gantt based task-schedule package with external model switching.
|
|
4
|
+
|
|
5
|
+
## Public API
|
|
6
|
+
|
|
7
|
+
- `TaskSchedule` component (`mt-task-schedule`)
|
|
8
|
+
- `TaskScheduleShell` component (`mt-task-schedule-shell`)
|
|
9
|
+
- `TaskScheduleImportModal` component (`mt-task-schedule-import-modal`)
|
|
10
|
+
- `TASK_SCHEDULE_DATA_ADAPTER` injection token
|
|
11
|
+
- `TaskScheduleDataAdapter` interface
|
|
12
|
+
- `TaskScheduleBackendAdapter` (default built-in adapter)
|
|
13
|
+
- `TaskScheduleModelType`
|
|
14
|
+
- `TaskScheduleContext`
|
|
15
|
+
- `TASK_SCHEDULE_DEFAULT_PDF_FONT`
|
|
16
|
+
|
|
17
|
+
## Inputs
|
|
18
|
+
|
|
19
|
+
- `modelType`: `'default' | 'edit' | 'baseline' | 'criticalPath' | 'critical-path' | 'resources' | 'unscheduled' | 'phaseGate' | 'phase-gate' | 'custom'`
|
|
20
|
+
- `context`: object with required `levelId` and `levelDataId` for runtime tree loading, plus optional `customViewId`, etc.
|
|
21
|
+
- `dateFormat`: default `dd/MM/yyyy`
|
|
22
|
+
- `height`: default `760px`
|
|
23
|
+
- `langCode`: `'en' | 'ar' | null` (optional; auto-resolves from context/localStorage/document)
|
|
24
|
+
- `pdfFontData`: optional base64 TTF string for PDF export font
|
|
25
|
+
- `pdfRtlFontData`: optional base64 TTF string used in RTL/Arabic PDF export
|
|
26
|
+
- `pdfFontSize`: optional PDF font size (default `11`)
|
|
27
|
+
|
|
28
|
+
## Outputs
|
|
29
|
+
|
|
30
|
+
- `toolbarAction`
|
|
31
|
+
- `actionBegin`
|
|
32
|
+
- `actionCompleted`
|
|
33
|
+
- `loaded`
|
|
34
|
+
- `loadError`
|
|
35
|
+
|
|
36
|
+
`TaskScheduleDataAdapter` optional import methods:
|
|
37
|
+
|
|
38
|
+
- `importTasks(context, file)`
|
|
39
|
+
- `applyImportedTasks(context, payload)`
|
|
40
|
+
- `setBaseline(context, payload?)`
|
|
41
|
+
- `exportTasks(context)`
|
|
42
|
+
|
|
43
|
+
## Usage
|
|
44
|
+
|
|
45
|
+
```ts
|
|
46
|
+
import { Component, signal } from '@angular/core';
|
|
47
|
+
import {
|
|
48
|
+
TASK_SCHEDULE_DATA_ADAPTER,
|
|
49
|
+
TaskSchedule,
|
|
50
|
+
TaskScheduleDataAdapter,
|
|
51
|
+
TaskScheduleModelType,
|
|
52
|
+
} from '@masterteam/task-schedule';
|
|
53
|
+
|
|
54
|
+
@Component({
|
|
55
|
+
standalone: true,
|
|
56
|
+
imports: [TaskSchedule],
|
|
57
|
+
selector: 'app-task-schedule-host',
|
|
58
|
+
template: `
|
|
59
|
+
<mt-task-schedule
|
|
60
|
+
[modelType]="modelType()"
|
|
61
|
+
[context]="{ levelId: 12, levelDataId: 18 }"
|
|
62
|
+
[langCode]="'en'"
|
|
63
|
+
/>
|
|
64
|
+
`,
|
|
65
|
+
providers: [
|
|
66
|
+
{
|
|
67
|
+
provide: TASK_SCHEDULE_DATA_ADAPTER,
|
|
68
|
+
useExisting: TaskScheduleApiAdapterService,
|
|
69
|
+
},
|
|
70
|
+
],
|
|
71
|
+
})
|
|
72
|
+
export class TaskScheduleHostComponent {
|
|
73
|
+
readonly modelType = signal<TaskScheduleModelType>('default');
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
The component uses `TaskScheduleBackendAdapter` by default.
|
|
78
|
+
|
|
79
|
+
Backend routes used:
|
|
80
|
+
|
|
81
|
+
- Runtime tree: `GET /api/levels/{levelId}/{levelDataId}/schedule/tree`
|
|
82
|
+
- Custom view config: `GET /api/schedulemanager/{levelId}/schedule/{customViewId}`
|
|
83
|
+
- Team members (edit/resources mode): `GET /api/levels/{levelId}/TeamMember`
|
|
84
|
+
|
|
85
|
+
Edit mutations require `levelId`:
|
|
86
|
+
|
|
87
|
+
- `POST /api/tasks/{levelId}/create`
|
|
88
|
+
- `PUT /api/tasks/{levelId}/update/{taskId}`
|
|
89
|
+
- `DELETE /api/tasks/{levelId}/delete/{taskId}`
|
|
90
|
+
- `PUT /api/tasks/{levelId}/bulkUpdate`
|
|
91
|
+
- `PUT /api/tasks/{levelId}/updateParent/{taskId}`
|
|
92
|
+
- `PUT /api/tasks/{levelId}/reorder`
|
|
93
|
+
- `PUT /api/tasks/{levelId}/updatePlanningModuleProgress`
|
|
94
|
+
|
|
95
|
+
Context options for backend routing:
|
|
96
|
+
|
|
97
|
+
- `apiBaseUrl`: optional base URL prefix
|
|
98
|
+
- `schemaId`: optional legacy API schema id (used for old `/tasks/{schemaId}/{levelId}/...` routes)
|
|
99
|
+
- `customViewId`: used in `custom` mode to load schedule-manager view columns
|
|
100
|
+
- `resources`: optional static resource list override
|
|
101
|
+
- `endpoints`: optional endpoint template overrides (`scheduleTree`, `scheduleViewById`, `teamMembers`, `createTask`, etc.)
|
|
102
|
+
- `endpoints.setBaseline`: optional override for baseline endpoint (legacy default: `/api/levels/{schemaId}/{levelId}/tasks/setBaseline`)
|
|
103
|
+
- `endpoints.exportTasks`: optional override for export endpoint (legacy default: `/api/tasks/levels/{levelId}/export`)
|
|
104
|
+
- `requestHeaders`: optional additional headers
|
|
105
|
+
- `pdfFonts`: optional `{ regular?: string; arabic?: string; size?: number }` base64 font config for PDF export
|
|
106
|
+
|
|
107
|
+
When no PDF font is provided, package fallback uses embedded `TASK_SCHEDULE_DEFAULT_PDF_FONT`.
|
|
108
|
+
|
|
109
|
+
## Import Modal
|
|
110
|
+
|
|
111
|
+
Use `mt-task-schedule-import-modal` to import `.mpp`/`.xer` files and apply tasks (replace or append).
|
|
112
|
+
The modal is Tailwind-based and uses `@masterteam/components` (`mt-button`, `mt-entity-preview`).
|
|
113
|
+
Imported rows support inline editing before apply (task name, planned/actual dates, assignee, progress) with per-row selection.
|
|
114
|
+
|
|
115
|
+
## Shell Component
|
|
116
|
+
|
|
117
|
+
Use `mt-task-schedule-shell` as the package-level host that combines:
|
|
118
|
+
|
|
119
|
+
- mode switcher
|
|
120
|
+
- Set Baseline action (adapter `setBaseline`)
|
|
121
|
+
- Import modal orchestration
|
|
122
|
+
- Export tasks action (adapter `exportTasks`)
|
|
123
|
+
|
|
124
|
+
Shell parity control inputs:
|
|
125
|
+
|
|
126
|
+
- `allowEditMode`
|
|
127
|
+
- `allowImport`
|
|
128
|
+
- `allowSetBaseline`
|
|
129
|
+
- `hasTasks`
|
|
130
|
+
- `baselinePending`
|
|
131
|
+
|
|
132
|
+
Use one adapter service per selector/source if needed. The component does not use NGXS.
|
|
133
|
+
|
|
134
|
+
See `PARITY_REPORT.md` for legacy-to-package migration coverage.
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
/*! tailwindcss v4.2.1 | MIT License | https://tailwindcss.com */
|
|
2
|
+
@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-space-y-reverse:0;--tw-border-style:solid;--tw-font-weight:initial;--tw-tracking:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000}}}@layer theme{:root,:host{--font-sans:ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--color-amber-50:oklch(98.7% .022 95.277);--color-amber-200:oklch(92.4% .12 95.746);--color-amber-800:oklch(47.3% .137 46.201);--color-slate-50:oklch(98.4% .003 247.858);--color-slate-100:oklch(96.8% .007 247.896);--color-slate-200:oklch(92.9% .013 255.508);--color-slate-300:oklch(86.9% .022 252.894);--color-slate-400:oklch(70.4% .04 256.788);--color-slate-500:oklch(55.4% .046 257.417);--color-slate-600:oklch(44.6% .043 257.281);--color-slate-700:oklch(37.2% .044 257.287);--color-slate-900:oklch(20.8% .042 265.755);--color-white:#fff;--spacing:.25rem;--container-6xl:72rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-base:1rem;--text-base--line-height:calc(1.5 / 1);--font-weight-medium:500;--font-weight-semibold:600;--tracking-wide:.025em;--radius-md:.375rem;--radius-lg:.5rem;--radius-xl:.75rem;--radius-2xl:1rem;--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab, currentcolor 50%, transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.visible{visibility:visible}.fixed{position:fixed}.relative{position:relative}.static{position:static}.inset-0{inset:calc(var(--spacing) * 0)}.start{inset-inline-start:var(--spacing)}.z-\[1000\]{z-index:1000}.block{display:block}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.inline-flex{display:inline-flex}.max-h-\[28rem\]{max-height:28rem}.w-full{width:100%}.max-w-6xl{max-width:var(--container-6xl)}.max-w-\[22rem\]{max-width:22rem}.min-w-0{min-width:calc(var(--spacing) * 0)}.min-w-\[1180px\]{min-width:1180px}.cursor-pointer{cursor:pointer}.grid-cols-\[40px_minmax\(220px\,2fr\)_minmax\(130px\,1fr\)_minmax\(130px\,1fr\)_minmax\(130px\,1fr\)_minmax\(130px\,1fr\)_minmax\(190px\,1\.1fr\)_minmax\(120px\,0\.8fr\)\]{grid-template-columns:40px minmax(220px,2fr) minmax(130px,1fr) minmax(130px,1fr) minmax(130px,1fr) minmax(130px,1fr) minmax(190px,1.1fr) minmax(120px,.8fr)}.flex-wrap{flex-wrap:wrap}.place-items-center{place-items:center}.items-center{align-items:center}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.gap-2{gap:calc(var(--spacing) * 2)}.gap-3{gap:calc(var(--spacing) * 3)}:where(.space-y-1>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 1) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 1) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-4>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 4) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 4) * calc(1 - var(--tw-space-y-reverse)))}.gap-x-2{column-gap:calc(var(--spacing) * 2)}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.rounded-2xl{border-radius:var(--radius-2xl)}.rounded-lg{border-radius:var(--radius-lg)}.rounded-md{border-radius:var(--radius-md)}.rounded-xl{border-radius:var(--radius-xl)}.border{border-style:var(--tw-border-style);border-width:1px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-dashed{--tw-border-style:dashed;border-style:dashed}.border-amber-200{border-color:var(--color-amber-200)}.border-slate-100{border-color:var(--color-slate-100)}.border-slate-200{border-color:var(--color-slate-200)}.border-slate-300{border-color:var(--color-slate-300)}.bg-amber-50{background-color:var(--color-amber-50)}.bg-slate-50{background-color:var(--color-slate-50)}.bg-slate-100{background-color:var(--color-slate-100)}.bg-slate-900\/40{background-color:#0f172b66}@supports (color:color-mix(in lab, red, red)){.bg-slate-900\/40{background-color:color-mix(in oklab, var(--color-slate-900) 40%, transparent)}}.bg-white{background-color:var(--color-white)}.p-4{padding:calc(var(--spacing) * 4)}.p-5{padding:calc(var(--spacing) * 5)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.px-5{padding-inline:calc(var(--spacing) * 5)}.py-1{padding-block:calc(var(--spacing) * 1)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-3{padding-block:calc(var(--spacing) * 3)}.py-4{padding-block:calc(var(--spacing) * 4)}.text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-wide{--tw-tracking:var(--tracking-wide);letter-spacing:var(--tracking-wide)}.text-amber-800{color:var(--color-amber-800)}.text-slate-400{color:var(--color-slate-400)}.text-slate-500{color:var(--color-slate-500)}.text-slate-600{color:var(--color-slate-600)}.text-slate-700{color:var(--color-slate-700)}.text-slate-900{color:var(--color-slate-900)}.uppercase{text-transform:uppercase}.shadow-2xl{--tw-shadow:0 25px 50px -12px var(--tw-shadow-color,#00000040);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.ring-1{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.ring-slate-200{--tw-ring-color:var(--color-slate-200)}.outline-none{--tw-outline-style:none;outline-style:none}@media (hover:hover){.hover\:border-slate-400:hover{border-color:var(--color-slate-400)}}.focus\:border-slate-400:focus{border-color:var(--color-slate-400)}}@keyframes enter{0%{opacity:var(--p-enter-opacity,1);transform:translate3d(var(--p-enter-translate-x,0), var(--p-enter-translate-y,0), 0) scale3d(var(--p-enter-scale,1), var(--p-enter-scale,1), var(--p-enter-scale,1)) rotate(var(--p-enter-rotate,0))}}@keyframes leave{to{opacity:var(--p-leave-opacity,1);transform:translate3d(var(--p-leave-translate-x,0), var(--p-leave-translate-y,0), 0) scale3d(var(--p-leave-scale,1), var(--p-leave-scale,1), var(--p-leave-scale,1)) rotate(var(--p-leave-rotate,0))}}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}
|