@fleetbase/fleetops-engine 0.6.70 → 0.6.71

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 (144) hide show
  1. package/RELEASE.md +21 -47
  2. package/addon/components/order/details/activity.hbs +8 -6
  3. package/addon/components/order/details/activity.js +9 -0
  4. package/addon/components/order/details.hbs +29 -0
  5. package/addon/components/order/details.js +26 -0
  6. package/addon/components/order/form/details.hbs +30 -4
  7. package/addon/components/order/form/details.js +46 -0
  8. package/addon/components/order/form/route.hbs +4 -2
  9. package/addon/components/order/form/route.js +11 -0
  10. package/addon/components/order/form.hbs +12 -0
  11. package/addon/components/order/form.js +21 -1
  12. package/addon/components/order/kanban.js +72 -0
  13. package/addon/components/order-config-manager/activity-flow.js +45 -10
  14. package/addon/components/order-config-manager/lifecycle.hbs +250 -0
  15. package/addon/components/order-config-manager/lifecycle.js +358 -0
  16. package/addon/components/order-config-manager.js +5 -1
  17. package/addon/controllers/analytics/reports/index.js +10 -1
  18. package/addon/controllers/connectivity/devices/index/details.js +1 -0
  19. package/addon/controllers/connectivity/devices/index.js +8 -2
  20. package/addon/controllers/connectivity/events/index.js +31 -1
  21. package/addon/controllers/connectivity/sensors/index/details.js +1 -1
  22. package/addon/controllers/connectivity/sensors/index.js +37 -1
  23. package/addon/controllers/maintenance/equipment/index/details.js +2 -2
  24. package/addon/controllers/maintenance/equipment/index.js +28 -9
  25. package/addon/controllers/maintenance/inspection-forms/index.js +32 -12
  26. package/addon/controllers/maintenance/inspection-submissions/index/details.js +2 -1
  27. package/addon/controllers/maintenance/inspection-submissions/index.js +49 -9
  28. package/addon/controllers/maintenance/maintenances/index/details.js +2 -0
  29. package/addon/controllers/maintenance/maintenances/index.js +20 -1
  30. package/addon/controllers/maintenance/parts/index/details.js +2 -2
  31. package/addon/controllers/maintenance/parts/index.js +28 -8
  32. package/addon/controllers/maintenance/schedules/index.js +33 -4
  33. package/addon/controllers/maintenance/work-orders/index/details.js +3 -3
  34. package/addon/controllers/maintenance/work-orders/index.js +39 -8
  35. package/addon/controllers/management/contacts/customers.js +13 -0
  36. package/addon/controllers/management/contacts/index.js +43 -1
  37. package/addon/controllers/management/drivers/index/details.js +1 -0
  38. package/addon/controllers/management/drivers/index.js +32 -2
  39. package/addon/controllers/management/fleets/index/details.js +1 -0
  40. package/addon/controllers/management/fleets/index.js +39 -1
  41. package/addon/controllers/management/fuel-reports/index.js +22 -2
  42. package/addon/controllers/management/fuel-transactions/index.js +43 -7
  43. package/addon/controllers/management/issues/index/details.js +1 -0
  44. package/addon/controllers/management/issues/index.js +22 -2
  45. package/addon/controllers/management/places/index.js +36 -1
  46. package/addon/controllers/management/trailers/index/details.js +1 -0
  47. package/addon/controllers/management/trailers/index.js +50 -2
  48. package/addon/controllers/management/vehicles/index/details.js +1 -0
  49. package/addon/controllers/management/vehicles/index.js +33 -2
  50. package/addon/controllers/management/vendors/index.js +26 -2
  51. package/addon/controllers/operations/orders/index/details.js +31 -4
  52. package/addon/controllers/operations/orders/index.js +59 -4
  53. package/addon/controllers/operations/service-rates/index.js +15 -1
  54. package/addon/extension.js +32 -0
  55. package/addon/routes/operations/orders/index/details.js +1 -0
  56. package/addon/services/contact-actions.js +1 -0
  57. package/addon/services/customer-actions.js +2 -1
  58. package/addon/services/device-actions.js +1 -0
  59. package/addon/services/device-event-actions.js +1 -0
  60. package/addon/services/driver-actions.js +4 -13
  61. package/addon/services/equipment-actions.js +1 -0
  62. package/addon/services/fleet-actions.js +1 -0
  63. package/addon/services/fuel-report-actions.js +1 -0
  64. package/addon/services/inspection-form-actions.js +1 -0
  65. package/addon/services/inspection-submission-actions.js +1 -0
  66. package/addon/services/integrated-vendor-actions.js +1 -0
  67. package/addon/services/issue-actions.js +1 -0
  68. package/addon/services/maintenance-actions.js +1 -0
  69. package/addon/services/maintenance-schedule-actions.js +2 -1
  70. package/addon/services/order-actions.js +7 -0
  71. package/addon/services/order-presentation.js +129 -0
  72. package/addon/services/part-actions.js +1 -0
  73. package/addon/services/place-actions.js +1 -0
  74. package/addon/services/sensor-actions.js +1 -0
  75. package/addon/services/service-area-actions.js +1 -0
  76. package/addon/services/service-rate-actions.js +1 -0
  77. package/addon/services/telematic-actions.js +1 -0
  78. package/addon/services/trailer-actions.js +4 -14
  79. package/addon/services/vehicle-actions.js +4 -13
  80. package/addon/services/vendor-actions.js +1 -0
  81. package/addon/services/work-order-actions.js +1 -0
  82. package/addon/services/zone-actions.js +1 -0
  83. package/addon/templates/analytics/reports/index/details.hbs +1 -0
  84. package/addon/templates/analytics/reports/index.hbs +1 -0
  85. package/addon/templates/connectivity/devices/index/details.hbs +1 -0
  86. package/addon/templates/connectivity/devices/index.hbs +1 -0
  87. package/addon/templates/connectivity/events/index.hbs +1 -0
  88. package/addon/templates/connectivity/sensors/index/details.hbs +1 -0
  89. package/addon/templates/connectivity/sensors/index.hbs +1 -0
  90. package/addon/templates/maintenance/equipment/index/details.hbs +1 -0
  91. package/addon/templates/maintenance/equipment/index.hbs +2 -0
  92. package/addon/templates/maintenance/inspection-forms/index/details.hbs +1 -0
  93. package/addon/templates/maintenance/inspection-forms/index.hbs +1 -0
  94. package/addon/templates/maintenance/inspection-submissions/index/details.hbs +1 -0
  95. package/addon/templates/maintenance/inspection-submissions/index.hbs +1 -0
  96. package/addon/templates/maintenance/maintenances/index/details.hbs +1 -0
  97. package/addon/templates/maintenance/maintenances/index.hbs +1 -0
  98. package/addon/templates/maintenance/parts/index/details.hbs +1 -0
  99. package/addon/templates/maintenance/parts/index.hbs +2 -0
  100. package/addon/templates/maintenance/schedules/index/details.hbs +1 -0
  101. package/addon/templates/maintenance/schedules/index.hbs +2 -0
  102. package/addon/templates/maintenance/work-orders/index/details.hbs +1 -0
  103. package/addon/templates/maintenance/work-orders/index.hbs +1 -0
  104. package/addon/templates/management/contacts/customers/details.hbs +1 -0
  105. package/addon/templates/management/contacts/customers.hbs +1 -0
  106. package/addon/templates/management/contacts/index/details.hbs +1 -0
  107. package/addon/templates/management/contacts/index.hbs +1 -0
  108. package/addon/templates/management/contacts.hbs +1 -0
  109. package/addon/templates/management/drivers/index/details.hbs +1 -0
  110. package/addon/templates/management/drivers/index.hbs +2 -0
  111. package/addon/templates/management/fleets/index/details.hbs +1 -0
  112. package/addon/templates/management/fleets/index.hbs +1 -0
  113. package/addon/templates/management/fuel-reports/index/details.hbs +1 -0
  114. package/addon/templates/management/fuel-reports/index.hbs +1 -0
  115. package/addon/templates/management/fuel-transactions/index.hbs +1 -0
  116. package/addon/templates/management/issues/index/details.hbs +1 -0
  117. package/addon/templates/management/issues/index.hbs +1 -0
  118. package/addon/templates/management/places/index/details.hbs +1 -0
  119. package/addon/templates/management/places/index.hbs +1 -0
  120. package/addon/templates/management/trailers/index/details.hbs +1 -0
  121. package/addon/templates/management/trailers/index.hbs +2 -0
  122. package/addon/templates/management/vehicles/index/details.hbs +1 -0
  123. package/addon/templates/management/vehicles/index.hbs +2 -0
  124. package/addon/templates/management/vendors/index/details.hbs +1 -0
  125. package/addon/templates/management/vendors/index.hbs +2 -0
  126. package/addon/templates/management/vendors/integrated.hbs +1 -0
  127. package/addon/templates/operations/orders/index/details.hbs +1 -0
  128. package/addon/templates/operations/orders/index.hbs +1 -0
  129. package/addon/templates/operations/service-rates/index/details.hbs +1 -0
  130. package/addon/templates/operations/service-rates/index.hbs +1 -0
  131. package/addon/utils/normalize-order-config-flow.js +6 -1
  132. package/app/services/order-presentation.js +1 -0
  133. package/composer.json +1 -1
  134. package/extension.json +1 -1
  135. package/package.json +3 -3
  136. package/server/src/Http/Controllers/Internal/v1/OrderController.php +34 -4
  137. package/server/src/Models/Order.php +35 -3
  138. package/server/src/Models/OrderConfig.php +129 -0
  139. package/server/src/Models/TrackingNumber.php +8 -4
  140. package/server/tests/Feature/Http/Internal/OrderControllerActivityFlowsTest.php +72 -0
  141. package/server/tests/Feature/Http/Internal/OrderControllerCreateRecordTest.php +26 -0
  142. package/server/tests/OrderConfigLifecycleTest.php +120 -0
  143. package/server/tests/Unit/Events/OrderDispatchFailedTest.php +2 -1
  144. package/translations/en-us.yaml +60 -0
@@ -34,7 +34,17 @@ export default class OrderConfigManagerActivityFlowComponent extends Component {
34
34
  * An array of activity codes that should not be modified.
35
35
  * @type {Array.<string>}
36
36
  */
37
- @tracked immutableActivities = ['created', 'dispatched', 'started'];
37
+ /**
38
+ * Activities that cannot be edited or removed. Configs with their own lifecycle
39
+ * (`meta.lifecycle`) are not bound to the default dispatch activities.
40
+ */
41
+ get immutableActivities() {
42
+ return this.lifecycle ? [] : ['created', 'dispatched', 'started'];
43
+ }
44
+
45
+ get lifecycle() {
46
+ return this.config?.meta?.lifecycle ?? null;
47
+ }
38
48
 
39
49
  /**
40
50
  * The configuration data for the activity flow.
@@ -180,6 +190,12 @@ export default class OrderConfigManagerActivityFlowComponent extends Component {
180
190
  this.clearGraph({
181
191
  onAfter: () => {
182
192
  this.flow = {};
193
+ // A configured lifecycle resets to its saved flow, never to the default dispatch flow.
194
+ if (this.lifecycle && this.config?.flow && Object.keys(this.config.flow).length) {
195
+ this.deserializeFlow(this.config.flow);
196
+ return;
197
+ }
198
+
183
199
  const defaultActivities = this.getDefaultActivities();
184
200
  this.addActivityToGraph(defaultActivities);
185
201
  },
@@ -361,7 +377,7 @@ export default class OrderConfigManagerActivityFlowComponent extends Component {
361
377
  }
362
378
  });
363
379
 
364
- const rootCode = getOrderConfigFlowRootCode(deserializedFlow);
380
+ const rootCode = getOrderConfigFlowRootCode(deserializedFlow, this.lifecycle?.initial);
365
381
  if (rootCode && deserializedFlow[rootCode]) {
366
382
  this.addDeserializedActivityToGraph(deserializedFlow[rootCode]);
367
383
  }
@@ -439,6 +455,10 @@ export default class OrderConfigManagerActivityFlowComponent extends Component {
439
455
  * and creates links from the parent to each child. It then calls itself to add any children of the current child activities.
440
456
  * Finally, it repositions all child activities to maintain visual consistency.
441
457
  *
458
+ * A flow is a graph, not a tree: an activity may be reachable from several parents, and a
459
+ * configured lifecycle can loop back (e.g. active -> extended -> active). An activity that is
460
+ * already on the graph only gets a link from this parent; it is never placed or walked twice.
461
+ *
442
462
  * @param {Object} parentActivity - The parent activity to which child activities will be added.
443
463
  * @param {Array} [childActivities=[]] - An array of child activity objects to be added. Defaults to an empty array.
444
464
  */
@@ -447,6 +467,11 @@ export default class OrderConfigManagerActivityFlowComponent extends Component {
447
467
  return;
448
468
  }
449
469
  childActivities.forEach((childActivityObject) => {
470
+ if (childActivityObject.get('node')) {
471
+ this.addLinkToGraph(parentActivity, childActivityObject);
472
+ return;
473
+ }
474
+
450
475
  const childPositionals = this.getActivityPositioning(childActivityObject, parentActivity);
451
476
  const childActivity = this.createActivityNode(childActivityObject, childPositionals);
452
477
  childActivity.set('parentId', parentActivity.get('id'));
@@ -823,16 +848,26 @@ export default class OrderConfigManagerActivityFlowComponent extends Component {
823
848
  const addButton = this.createAddActivityButton(activity, { x: width });
824
849
  let tools = [];
825
850
 
826
- if (activity.get('code') === 'created' || activity.get('code') === 'dispatched') {
827
- tools = [];
828
- }
851
+ const code = activity.get('code');
852
+ const canUpdate = this.abilities.can('fleet-ops update order-config');
829
853
 
830
- if (activity.get('code') === 'started' && this.abilities.can('fleet-ops update order-config')) {
831
- tools = [addButton];
832
- }
854
+ if (this.lifecycle) {
855
+ // The configured initial activity is the root: it can gain children but not be removed.
856
+ if (canUpdate) {
857
+ tools = code === this.lifecycle.initial ? [addButton] : [removeButton, addButton];
858
+ }
859
+ } else {
860
+ if (code === 'created' || code === 'dispatched') {
861
+ tools = [];
862
+ }
863
+
864
+ if (code === 'started' && canUpdate) {
865
+ tools = [addButton];
866
+ }
833
867
 
834
- if (!this.immutableActivities.includes(activity.get('code')) && this.abilities.can('fleet-ops update order-config')) {
835
- tools = [removeButton, addButton];
868
+ if (!this.immutableActivities.includes(code) && canUpdate) {
869
+ tools = [removeButton, addButton];
870
+ }
836
871
  }
837
872
 
838
873
  const activityNodeView = activityNode.findView(this.paper);
@@ -0,0 +1,250 @@
1
+ <div class="px-6 py-2 space-y-4">
2
+ <ContentPanel @title={{t "order-config-manager.lifecycle.title"}} @open={{true}} @wrapperClass="bordered-classic">
3
+ <p class="text-sm text-gray-600 dark:text-gray-300 mb-4">{{t "order-config-manager.lifecycle.description"}}</p>
4
+
5
+ <div class="mb-4">
6
+ <Toggle
7
+ @label={{t "order-config-manager.lifecycle.enable"}}
8
+ @helpText={{t "order-config-manager.lifecycle.enable-help"}}
9
+ @isToggled={{this.enabled}}
10
+ @disabled={{or (not this.canEdit) this.save.isRunning}}
11
+ @onToggle={{this.toggleEnabled}}
12
+ />
13
+ </div>
14
+
15
+ {{#if this.enabled}}
16
+ <div class="mb-6">
17
+ <div class="flex items-center justify-between mb-1">
18
+ <div class="text-sm font-semibold dark:text-gray-100">{{t "order-config-manager.lifecycle.activities"}}</div>
19
+ {{#if (and this.canEdit this.hasActivities)}}
20
+ <button type="button" class="text-xs text-blue-600 dark:text-blue-400 hover:underline" {{on "click" this.startBlankFlow}}>{{t "order-config-manager.lifecycle.blank-flow"}}</button>
21
+ {{/if}}
22
+ </div>
23
+ <p class="text-xs text-gray-500 dark:text-gray-400 mb-3">{{t "order-config-manager.lifecycle.activities-help"}}</p>
24
+
25
+ {{#if this.hasActivities}}
26
+ <div class="space-y-2">
27
+ {{#each this.activityRows as |activity|}}
28
+ <div class="rounded-md border border-gray-200 dark:border-gray-700 p-3 grid grid-cols-1 lg:grid-cols-12 gap-2 items-end" data-activity-code={{activity.code}}>
29
+ <InputGroup @name={{t "order-config-manager.lifecycle.activity-label"}} @wrapperClass="mb-0 lg:col-span-3">
30
+ <Input class="form-input w-full" @value={{activity.status}} disabled={{not this.canEdit}} {{on "input" (fn this.setActivityField activity.code "status")}} />
31
+ </InputGroup>
32
+ <InputGroup @name={{t "order-config-manager.lifecycle.activity-code"}} @wrapperClass="mb-0 lg:col-span-2">
33
+ <div class="form-input bg-gray-100 dark:bg-gray-800 text-gray-600 dark:text-gray-300 truncate" title={{activity.code}}>{{activity.code}}{{#if activity.isInitial}} <span class="text-xs text-green-600 dark:text-green-400">({{t "order-config-manager.lifecycle.initial-short"}})</span>{{/if}}</div>
34
+ </InputGroup>
35
+ <InputGroup @name={{t "order-config-manager.lifecycle.activity-details"}} @wrapperClass="mb-0 lg:col-span-3">
36
+ <Input class="form-input w-full" @value={{activity.details}} disabled={{not this.canEdit}} {{on "input" (fn this.setActivityField activity.code "details")}} />
37
+ </InputGroup>
38
+ <InputGroup @name={{t "order-config-manager.lifecycle.activity-next"}} @wrapperClass="mb-0 lg:col-span-3">
39
+ <div class="fleetbase-model-select fleetbase-power-select ember-model-select">
40
+ <PowerSelectMultiple
41
+ @options={{this.activities}}
42
+ @selected={{activity.next}}
43
+ @onChange={{fn this.setNextActivities activity.code}}
44
+ @searchEnabled={{true}}
45
+ @searchField="label"
46
+ @placeholder={{t "order-config-manager.lifecycle.select-activities"}}
47
+ @triggerClass="form-select form-input"
48
+ @disabled={{not this.canEdit}}
49
+ as |next|
50
+ >
51
+ {{next.label}}
52
+ </PowerSelectMultiple>
53
+ </div>
54
+ </InputGroup>
55
+ <div class="flex items-center justify-end space-x-2 lg:col-span-1">
56
+ <input type="color" value={{activity.color}} title={{t "order-config-manager.lifecycle.activity-color"}} class="h-9 w-9 rounded border border-gray-300 dark:border-gray-700 bg-transparent" disabled={{not this.canEdit}} {{on "input" (fn this.setActivityField activity.code "color")}} />
57
+ {{#if this.canEdit}}
58
+ <Button @type="danger" @size="sm" @icon="trash" @helpText={{t "order-config-manager.lifecycle.remove-activity"}} @onClick={{fn this.removeActivity activity.code}} />
59
+ {{/if}}
60
+ </div>
61
+ </div>
62
+ {{/each}}
63
+ </div>
64
+ {{else}}
65
+ <div class="rounded-md border border-dashed border-gray-300 dark:border-gray-700 px-3 py-4 text-sm text-gray-500 dark:text-gray-400 text-center">{{t "order-config-manager.lifecycle.no-activities"}}</div>
66
+ {{/if}}
67
+
68
+ {{#if this.canEdit}}
69
+ <div class="mt-3 rounded-md border border-blue-200 dark:border-blue-800 p-3">
70
+ <div class="text-sm font-semibold mb-2">{{t "order-config-manager.lifecycle.add-activity"}}</div>
71
+ <div class="grid grid-cols-1 lg:grid-cols-12 gap-2 items-end">
72
+ <InputGroup @name={{t "order-config-manager.lifecycle.activity-label"}} @required={{true}} @wrapperClass="mb-0 lg:col-span-3">
73
+ <Input class="form-input w-full" placeholder={{t "order-config-manager.lifecycle.activity-label-placeholder"}} @value={{this.newActivity.status}} {{on "input" (fn this.setNewActivityField "status")}} />
74
+ </InputGroup>
75
+ <InputGroup @name={{t "order-config-manager.lifecycle.activity-code"}} @helpText={{t "order-config-manager.lifecycle.activity-code-help"}} @wrapperClass="mb-0 lg:col-span-2">
76
+ <Input class="form-input w-full" placeholder={{or this.newActivityCode (t "order-config-manager.lifecycle.activity-code-placeholder")}} @value={{this.newActivity.code}} {{on "input" (fn this.setNewActivityField "code")}} />
77
+ </InputGroup>
78
+ <InputGroup @name={{t "order-config-manager.lifecycle.activity-details"}} @wrapperClass="mb-0 lg:col-span-4">
79
+ <Input class="form-input w-full" placeholder={{t "order-config-manager.lifecycle.activity-details-placeholder"}} @value={{this.newActivity.details}} {{on "input" (fn this.setNewActivityField "details")}} />
80
+ </InputGroup>
81
+ <div class="flex items-center justify-end space-x-2 lg:col-span-3">
82
+ <input type="color" value={{this.newActivity.color}} title={{t "order-config-manager.lifecycle.activity-color"}} class="h-9 w-9 rounded border border-gray-300 dark:border-gray-700 bg-transparent" {{on "input" (fn this.setNewActivityField "color")}} />
83
+ <Button @type="primary" @icon="plus" @text={{t "order-config-manager.lifecycle.add-activity"}} @disabled={{not this.canAddActivity}} @onClick={{this.addActivity}} />
84
+ </div>
85
+ </div>
86
+ {{#if this.newActivityCodeTaken}}
87
+ <div class="mt-1 text-xs text-red-600 dark:text-red-400">{{t "order-config-manager.lifecycle.problem-duplicate-code" code=this.newActivityCode}}</div>
88
+ {{/if}}
89
+ </div>
90
+ {{/if}}
91
+ </div>
92
+
93
+ <div class="grid grid-cols-1 lg:grid-cols-2 gap-x-6 gap-y-2">
94
+ <InputGroup @name={{t "order-config-manager.lifecycle.initial"}} @required={{true}} @helpText={{t "order-config-manager.lifecycle.initial-help"}}>
95
+ <div class="fleetbase-model-select fleetbase-power-select ember-model-select">
96
+ <PowerSelect
97
+ @options={{this.activities}}
98
+ @selected={{this.selectedInitial}}
99
+ @onChange={{fn this.setActivity "initial"}}
100
+ @searchEnabled={{true}}
101
+ @searchField="label"
102
+ @placeholder={{t "order-config-manager.lifecycle.select-activity"}}
103
+ @triggerClass="form-select form-input"
104
+ @disabled={{not this.canEdit}}
105
+ as |activity|
106
+ >
107
+ <span>{{activity.label}}</span>
108
+ <span class="ml-2 text-xs text-gray-500">{{activity.code}}</span>
109
+ </PowerSelect>
110
+ </div>
111
+ </InputGroup>
112
+
113
+ <InputGroup @name={{t "order-config-manager.lifecycle.terminal"}} @helpText={{t "order-config-manager.lifecycle.terminal-help"}}>
114
+ <div class="fleetbase-model-select fleetbase-power-select ember-model-select">
115
+ <PowerSelectMultiple
116
+ @options={{this.activities}}
117
+ @selected={{this.selectedTerminal}}
118
+ @onChange={{this.setTerminal}}
119
+ @searchEnabled={{true}}
120
+ @searchField="label"
121
+ @placeholder={{t "order-config-manager.lifecycle.select-activities"}}
122
+ @triggerClass="form-select form-input"
123
+ @disabled={{not this.canEdit}}
124
+ as |activity|
125
+ >
126
+ {{activity.label}}
127
+ </PowerSelectMultiple>
128
+ </div>
129
+ </InputGroup>
130
+
131
+ <InputGroup @name={{t "order-config-manager.lifecycle.completed"}} @helpText={{t "order-config-manager.lifecycle.completed-help"}}>
132
+ <div class="fleetbase-model-select fleetbase-power-select ember-model-select">
133
+ <PowerSelect
134
+ @options={{this.activities}}
135
+ @selected={{this.selectedCompleted}}
136
+ @onChange={{fn this.setActivity "completed"}}
137
+ @searchEnabled={{true}}
138
+ @searchField="label"
139
+ @allowClear={{true}}
140
+ @placeholder={{t "order-config-manager.lifecycle.select-activity"}}
141
+ @triggerClass="form-select form-input"
142
+ @disabled={{not this.canEdit}}
143
+ as |activity|
144
+ >
145
+ <span>{{activity.label}}</span>
146
+ <span class="ml-2 text-xs text-gray-500">{{activity.code}}</span>
147
+ </PowerSelect>
148
+ </div>
149
+ </InputGroup>
150
+
151
+ <InputGroup @name={{t "order-config-manager.lifecycle.canceled"}} @helpText={{t "order-config-manager.lifecycle.canceled-help"}}>
152
+ <div class="fleetbase-model-select fleetbase-power-select ember-model-select">
153
+ <PowerSelect
154
+ @options={{this.activities}}
155
+ @selected={{this.selectedCanceled}}
156
+ @onChange={{fn this.setActivity "canceled"}}
157
+ @searchEnabled={{true}}
158
+ @searchField="label"
159
+ @allowClear={{true}}
160
+ @placeholder={{t "order-config-manager.lifecycle.select-activity"}}
161
+ @triggerClass="form-select form-input"
162
+ @disabled={{not this.canEdit}}
163
+ as |activity|
164
+ >
165
+ <span>{{activity.label}}</span>
166
+ <span class="ml-2 text-xs text-gray-500">{{activity.code}}</span>
167
+ </PowerSelect>
168
+ </div>
169
+ </InputGroup>
170
+
171
+ </div>
172
+
173
+ <div class="flex flex-col space-y-2 pt-2">
174
+ <Toggle
175
+ @label={{t "order-config-manager.lifecycle.dispatch"}}
176
+ @helpText={{t "order-config-manager.lifecycle.dispatch-help"}}
177
+ @isToggled={{this.lifecycle.dispatch}}
178
+ @disabled={{not this.canEdit}}
179
+ @onToggle={{fn this.setFlag "dispatch"}}
180
+ />
181
+ <Toggle
182
+ @label={{t "order-config-manager.lifecycle.strict-transitions"}}
183
+ @helpText={{t "order-config-manager.lifecycle.strict-transitions-help"}}
184
+ @isToggled={{this.lifecycle.strict_transitions}}
185
+ @disabled={{not this.canEdit}}
186
+ @onToggle={{fn this.setFlag "strict_transitions"}}
187
+ />
188
+ </div>
189
+
190
+ {{#if this.problems.length}}
191
+ <div class="mt-2 rounded-md border border-red-300 dark:border-red-700 px-3 py-2 text-sm">
192
+ <div class="font-semibold text-red-700 dark:text-red-400 mb-1">{{t "order-config-manager.lifecycle.problems-title"}}</div>
193
+ <ul class="list-disc pl-5 text-red-700 dark:text-red-400">
194
+ {{#each this.problems as |problem|}}<li>{{problem}}</li>{{/each}}
195
+ </ul>
196
+ </div>
197
+ {{/if}}
198
+ {{else}}
199
+ <p class="text-sm text-gray-600 dark:text-gray-300">{{t "order-config-manager.lifecycle.default-lifecycle"}}</p>
200
+ {{/if}}
201
+
202
+ {{#if this.canEdit}}
203
+ <div class="flex justify-end pt-4">
204
+ <Button
205
+ @type="primary"
206
+ @icon="save"
207
+ @text={{t "common.save-changes"}}
208
+ @onClick={{perform this.save}}
209
+ @isLoading={{this.save.isRunning}}
210
+ @disabled={{not this.canSave}}
211
+ @permission="fleet-ops update order-config"
212
+ />
213
+ </div>
214
+ {{/if}}
215
+ </ContentPanel>
216
+
217
+ {{#if this.saved}}
218
+ <ContentPanel @title={{t "order-config-manager.lifecycle.summary"}} @open={{true}} @wrapperClass="bordered-classic">
219
+ <dl class="grid grid-cols-1 md:grid-cols-2 gap-x-6 gap-y-1 text-sm">
220
+ <div class="flex"><dt class="w-40 shrink-0 text-gray-500">{{t "order-config-manager.lifecycle.summary-initial"}}</dt><dd>{{or
221
+ (get (this.option this.saved.initial) "label")
222
+ (t "order-config-manager.lifecycle.none")
223
+ }}</dd></div>
224
+ <div class="flex"><dt class="w-40 shrink-0 text-gray-500">{{t "order-config-manager.lifecycle.summary-completed"}}</dt><dd>{{or
225
+ (get (this.option this.saved.completed) "label")
226
+ (t "order-config-manager.lifecycle.none")
227
+ }}</dd></div>
228
+ <div class="flex"><dt class="w-40 shrink-0 text-gray-500">{{t "order-config-manager.lifecycle.summary-canceled"}}</dt><dd>{{or
229
+ (get (this.option this.saved.canceled) "label")
230
+ (t "order-config-manager.lifecycle.none")
231
+ }}</dd></div>
232
+ <div class="flex"><dt class="w-40 shrink-0 text-gray-500">{{t "order-config-manager.lifecycle.summary-terminal"}}</dt><dd>{{#if this.saved.terminal.length}}{{#each
233
+ this.saved.terminal
234
+ as |code index|
235
+ }}{{if index ", "}}{{get (this.option code) "label"}}{{/each}}{{else}}{{t "order-config-manager.lifecycle.none"}}{{/if}}</dd></div>
236
+ <div class="flex"><dt class="w-40 shrink-0 text-gray-500">{{t "order-config-manager.lifecycle.summary-dispatch"}}</dt><dd>{{if
237
+ this.saved.dispatch
238
+ (t "order-config-manager.lifecycle.yes")
239
+ (t "order-config-manager.lifecycle.no")
240
+ }}</dd></div>
241
+ <div class="flex"><dt class="w-40 shrink-0 text-gray-500">{{t "order-config-manager.lifecycle.summary-strict"}}</dt><dd>{{if
242
+ this.saved.strict_transitions
243
+ (t "order-config-manager.lifecycle.yes")
244
+ (t "order-config-manager.lifecycle.no")
245
+ }}</dd></div>
246
+ </dl>
247
+ </ContentPanel>
248
+ {{/if}}
249
+
250
+ </div>