@fleetbase/fleetops-engine 0.4.15 → 0.4.17

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 (220) hide show
  1. package/.php-cs-fixer.php +2 -0
  2. package/addon/components/activity-event-selector.hbs +35 -0
  3. package/addon/components/activity-event-selector.js +85 -0
  4. package/addon/components/activity-form-panel.hbs +23 -0
  5. package/addon/components/activity-form-panel.js +90 -0
  6. package/addon/components/activity-logic-builder.hbs +80 -0
  7. package/addon/components/activity-logic-builder.js +260 -0
  8. package/addon/components/contact-form-panel.hbs +1 -1
  9. package/addon/components/contact-panel.hbs +1 -1
  10. package/addon/components/custom-entity-form-panel.hbs +43 -0
  11. package/addon/components/custom-entity-form-panel.js +129 -0
  12. package/addon/components/custom-field-form-panel/options-input.hbs +12 -0
  13. package/addon/components/custom-field-form-panel/options-input.js +139 -0
  14. package/addon/components/custom-field-form-panel.hbs +77 -0
  15. package/addon/components/custom-field-form-panel.js +144 -0
  16. package/addon/components/custom-field.hbs +63 -41
  17. package/addon/components/custom-field.js +123 -25
  18. package/addon/components/driver-form-panel.hbs +1 -1
  19. package/addon/components/driver-panel.hbs +1 -1
  20. package/addon/components/edit-order-route-panel.hbs +1 -1
  21. package/addon/components/fleet-form-panel.hbs +1 -1
  22. package/addon/components/fleet-panel.hbs +1 -1
  23. package/addon/components/fuel-report-form-panel.hbs +1 -1
  24. package/addon/components/fuel-report-panel.hbs +1 -1
  25. package/addon/components/issue-form-panel.hbs +1 -1
  26. package/addon/components/issue-panel.hbs +1 -1
  27. package/addon/components/joint-graph.hbs +1 -0
  28. package/addon/components/joint-graph.js +103 -0
  29. package/addon/components/layout/fleet-ops-sidebar.hbs +3 -3
  30. package/addon/components/layout/fleet-ops-sidebar.js +1 -0
  31. package/addon/components/live-map.js +71 -28
  32. package/addon/components/modals/new-custom-field-group.hbs +5 -0
  33. package/addon/components/modals/new-order-config.hbs +3 -3
  34. package/addon/components/modals/order-new-activity.hbs +1 -1
  35. package/addon/components/order-config-manager/activity-flow.hbs +11 -0
  36. package/addon/components/order-config-manager/activity-flow.js +964 -0
  37. package/addon/components/order-config-manager/custom-fields.hbs +50 -0
  38. package/addon/components/order-config-manager/custom-fields.js +276 -0
  39. package/addon/components/order-config-manager/details.hbs +23 -0
  40. package/addon/components/order-config-manager/details.js +97 -0
  41. package/addon/components/order-config-manager/entities.hbs +54 -0
  42. package/addon/components/order-config-manager/entities.js +227 -0
  43. package/addon/components/order-config-manager-overlay.hbs +26 -0
  44. package/addon/components/order-config-manager-overlay.js +60 -0
  45. package/addon/components/order-config-manager.hbs +15 -0
  46. package/addon/components/order-config-manager.js +285 -0
  47. package/addon/components/order-flow.hbs +1 -0
  48. package/addon/components/order-flow.js +3 -0
  49. package/addon/components/place-form-panel.hbs +1 -1
  50. package/addon/components/place-panel.hbs +1 -1
  51. package/addon/components/vehicle-form-panel.hbs +1 -1
  52. package/addon/components/vehicle-panel.hbs +1 -1
  53. package/addon/components/vendor-form-panel.hbs +1 -1
  54. package/addon/components/vendor-panel.hbs +1 -1
  55. package/addon/controllers/application.js +5 -1
  56. package/addon/controllers/operations/order-config.js +42 -0
  57. package/addon/controllers/operations/orders/index/new.js +125 -21
  58. package/addon/controllers/operations/orders/index/view.js +87 -4
  59. package/addon/controllers/operations/orders/index.js +2 -2
  60. package/addon/engine.js +10 -1
  61. package/addon/initializers/load-jointjs.js +16 -0
  62. package/addon/routes/application.js +1 -1
  63. package/addon/routes/operations/order-config.js +28 -0
  64. package/addon/routes/operations/orders/index/new.js +2 -3
  65. package/addon/routes/operations/orders/index/view.js +1 -1
  66. package/addon/routes.js +1 -0
  67. package/addon/services/context-panel.js +65 -3
  68. package/addon/styles/fleetops-engine.css +268 -0
  69. package/addon/templates/application.hbs +1 -1
  70. package/addon/templates/operations/order-config.hbs +55 -0
  71. package/addon/templates/operations/orders/index/new.hbs +98 -339
  72. package/addon/templates/operations/orders/index/view.hbs +36 -96
  73. package/addon/templates/operations/orders/index.hbs +0 -1
  74. package/addon/utils/apply-context-component-arguments.js +4 -2
  75. package/addon/utils/create-custom-entity.js +22 -0
  76. package/addon/utils/create-flow-activity.js +31 -0
  77. package/addon/utils/get-custom-field-type-map.js +34 -0
  78. package/app/components/activity-event-selector.js +1 -0
  79. package/app/components/activity-form-panel.js +1 -0
  80. package/app/components/activity-logic-builder.js +1 -0
  81. package/app/components/custom-entity-form-panel.js +1 -0
  82. package/app/components/custom-field-form-panel/options-input.js +1 -0
  83. package/app/components/custom-field-form-panel.js +1 -0
  84. package/app/components/joint-graph.js +1 -0
  85. package/app/components/modals/new-custom-field-group.js +1 -0
  86. package/app/components/order-config-manager/activity-flow.js +1 -0
  87. package/app/components/order-config-manager/custom-fields.js +1 -0
  88. package/app/components/order-config-manager/details.js +1 -0
  89. package/app/components/order-config-manager/entities.js +1 -0
  90. package/app/components/order-config-manager-overlay.js +1 -0
  91. package/app/components/order-config-manager.js +1 -0
  92. package/app/components/order-flow.js +1 -0
  93. package/app/controllers/operations/order-config.js +1 -0
  94. package/app/routes/operations/order-config.js +1 -0
  95. package/app/templates/operations/order-config.js +1 -0
  96. package/app/utils/create-custom-entity.js +1 -0
  97. package/app/utils/create-flow-activity.js +1 -0
  98. package/app/utils/get-custom-field-type-map.js +1 -0
  99. package/composer.json +4 -3
  100. package/config/environment.js +1 -0
  101. package/extension.json +1 -1
  102. package/index.js +20 -0
  103. package/package.json +7 -5
  104. package/server/migrations/2023_04_27_053456_create_contacts_table.php +1 -2
  105. package/server/migrations/2023_04_27_053456_create_drivers_table.php +1 -2
  106. package/server/migrations/2023_04_27_053456_create_entities_table.php +1 -2
  107. package/server/migrations/2023_04_27_053456_create_fleet_drivers_table.php +1 -2
  108. package/server/migrations/2023_04_27_053456_create_fleets_table.php +1 -2
  109. package/server/migrations/2023_04_27_053456_create_fuel_reports_table.php +1 -2
  110. package/server/migrations/2023_04_27_053456_create_integrated_vendors_table.php +1 -2
  111. package/server/migrations/2023_04_27_053456_create_issues_table.php +1 -2
  112. package/server/migrations/2023_04_27_053456_create_orders_table.php +1 -2
  113. package/server/migrations/2023_04_27_053456_create_payloads_table.php +1 -2
  114. package/server/migrations/2023_04_27_053456_create_places_table.php +1 -2
  115. package/server/migrations/2023_04_27_053456_create_positions_table.php +1 -2
  116. package/server/migrations/2023_04_27_053456_create_proofs_table.php +1 -2
  117. package/server/migrations/2023_04_27_053456_create_purchase_rates_table.php +1 -2
  118. package/server/migrations/2023_04_27_053456_create_routes_table.php +1 -2
  119. package/server/migrations/2023_04_27_053456_create_service_areas_table.php +1 -2
  120. package/server/migrations/2023_04_27_053456_create_service_quote_items_table.php +1 -2
  121. package/server/migrations/2023_04_27_053456_create_service_quotes_table.php +1 -2
  122. package/server/migrations/2023_04_27_053456_create_service_rate_fees_table.php +1 -2
  123. package/server/migrations/2023_04_27_053456_create_service_rate_parcel_fees_table.php +1 -2
  124. package/server/migrations/2023_04_27_053456_create_service_rates_table.php +1 -2
  125. package/server/migrations/2023_04_27_053456_create_tracking_numbers_table.php +1 -2
  126. package/server/migrations/2023_04_27_053456_create_tracking_statuses_table.php +1 -2
  127. package/server/migrations/2023_04_27_053456_create_vehicles_table.php +1 -2
  128. package/server/migrations/2023_04_27_053456_create_vendors_table.php +1 -2
  129. package/server/migrations/2023_04_27_053456_create_waypoints_table.php +1 -2
  130. package/server/migrations/2023_04_27_053456_create_zones_table.php +1 -2
  131. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_companies_table.php +1 -2
  132. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_contacts_table.php +1 -2
  133. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_drivers_table.php +1 -2
  134. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_entities_table.php +1 -2
  135. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_fleet_drivers_table.php +1 -2
  136. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_fleets_table.php +1 -2
  137. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_fuel_reports_table.php +1 -2
  138. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_integrated_vendors_table.php +1 -2
  139. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_issues_table.php +1 -2
  140. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_orders_table.php +1 -2
  141. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_payloads_table.php +1 -2
  142. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_places_table.php +1 -2
  143. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_positions_table.php +1 -2
  144. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_proofs_table.php +1 -2
  145. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_purchase_rates_table.php +1 -2
  146. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_routes_table.php +1 -2
  147. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_service_areas_table.php +1 -2
  148. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_service_quote_items_table.php +1 -2
  149. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_service_quotes_table.php +1 -2
  150. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_service_rate_fees_table.php +1 -2
  151. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_service_rate_parcel_fees_table.php +1 -2
  152. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_service_rates_table.php +1 -2
  153. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_tracking_numbers_table.php +1 -2
  154. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_tracking_statuses_table.php +1 -2
  155. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_vehicles_table.php +1 -2
  156. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_vendors_table.php +1 -2
  157. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_waypoints_table.php +1 -2
  158. package/server/migrations/2023_04_27_053459_add_foreign_keys_to_zones_table.php +1 -2
  159. package/server/migrations/2023_09_14_074512_update_vehicles_table.php +1 -2
  160. package/server/migrations/2023_09_14_074619_create_vehicle_devices_table.php +35 -36
  161. package/server/migrations/2023_09_26_071205_add_online_column_to_vehicles_table.php +1 -2
  162. package/server/migrations/2023_09_26_083957_create_fleet_vehicles_table.php +1 -2
  163. package/server/migrations/2023_09_27_023757_add_column_to_fleets_table.php +1 -2
  164. package/server/migrations/2023_10_05_074811_update_vehicle.php +1 -2
  165. package/server/migrations/2023_10_25_093014_create_vehicle_device_events_table.php +1 -2
  166. package/server/migrations/2023_11_03_072503_refactor_issues_table_columns.php +1 -2
  167. package/server/migrations/2023_11_06_040645_refactor_fuel_reports_table.php +1 -2
  168. package/server/migrations/2023_11_09_041807_add_status_column_to_fuel_reports_table.php +1 -2
  169. package/server/migrations/2023_11_15_062814_add_comments_column_and_resolved_at_column_to_vehicle_device_events_table.php +1 -2
  170. package/server/migrations/2023_11_17_053001_add_category_uuid_to_entities_table.php +1 -2
  171. package/server/migrations/2023_11_28_074244_add_supplier_uuid_column_to_entities_table.php +1 -2
  172. package/server/migrations/2023_12_14_100209_add_meta_column_on_driver_table copy.php +1 -2
  173. package/server/migrations/2024_02_18_100209_add_avatar_url_columns_table.php +3 -4
  174. package/server/migrations/2024_02_27_093648_create_order_configs_table.php +43 -0
  175. package/server/migrations/2024_03_07_075508_add_order_config_uuid_column_to_orders_table.php +28 -0
  176. package/server/seeders/OrderConfigSeeder.php +151 -0
  177. package/server/src/Casts/OrderConfigEntities.php +53 -0
  178. package/server/src/Console/Commands/FixLegacyOrderConfigs.php +66 -0
  179. package/server/src/Events/DriverLocationChanged.php +1 -1
  180. package/server/src/Events/DriverSimulatedLocationChanged.php +1 -1
  181. package/server/src/Expansions/UserExpansion.php +4 -4
  182. package/server/src/Flow/Activity.php +232 -6
  183. package/server/src/Flow/Condition.php +84 -0
  184. package/server/src/Flow/Event.php +88 -0
  185. package/server/src/Flow/Flow.php +50 -0
  186. package/server/src/Flow/FlowResource.php +143 -0
  187. package/server/src/Flow/Logic.php +57 -1
  188. package/server/src/Http/Controllers/Api/v1/DriverController.php +2 -2
  189. package/server/src/Http/Controllers/Api/v1/IssueController.php +132 -0
  190. package/server/src/Http/Controllers/Api/v1/OrderController.php +130 -57
  191. package/server/src/Http/Controllers/Api/v1/OrganizationController.php +27 -0
  192. package/server/src/Http/Controllers/Api/v1/PlaceController.php +2 -3
  193. package/server/src/Http/Controllers/Controller.php +9 -0
  194. package/server/src/Http/Controllers/FleetOpsController.php +7 -0
  195. package/server/src/Http/Controllers/Internal/v1/OrderConfigController.php +5 -259
  196. package/server/src/Http/Controllers/Internal/v1/OrderController.php +56 -35
  197. package/server/src/Http/Controllers/Internal/v1/SettingController.php +20 -0
  198. package/server/src/Http/Filter/OrderConfigFilter.php +13 -0
  199. package/server/src/Http/Requests/CreateIssueRequest.php +19 -0
  200. package/server/src/Http/Requests/UpdateIssueRequest.php +7 -0
  201. package/server/src/Http/Resources/v1/Order.php +3 -0
  202. package/server/src/Http/Resources/v1/Payload.php +1 -1
  203. package/server/src/Listeners/HandleOrderCanceled.php +8 -4
  204. package/server/src/Listeners/HandleOrderDispatched.php +14 -12
  205. package/server/src/Models/Order.php +527 -31
  206. package/server/src/Models/OrderConfig.php +419 -0
  207. package/server/src/Models/Payload.php +8 -7
  208. package/server/src/Notifications/OrderAssigned.php +1 -1
  209. package/server/src/Notifications/OrderCanceled.php +1 -1
  210. package/server/src/Notifications/OrderDispatchFailed.php +1 -1
  211. package/server/src/Notifications/OrderDispatched.php +1 -1
  212. package/server/src/Notifications/OrderPing.php +1 -1
  213. package/server/src/Providers/FleetOpsServiceProvider.php +3 -1
  214. package/server/src/Providers/NotificationServiceProvider.php +2 -1
  215. package/server/src/Support/Utils.php +17 -0
  216. package/server/src/Traits/HasTrackingNumber.php +9 -9
  217. package/server/src/routes.php +19 -11
  218. package/translations/en-us.yaml +137 -0
  219. package/server/src/Flow/Config.php +0 -7
  220. package/server/src/Support/Flow.php +0 -653
@@ -1,46 +1,144 @@
1
1
  import Component from '@glimmer/component';
2
2
  import { tracked } from '@glimmer/tracking';
3
+ import { inject as service } from '@ember/service';
3
4
  import { action } from '@ember/object';
4
- import { equal } from '@ember/object/computed';
5
+ import isObject from '@fleetbase/ember-core/utils/is-object';
6
+ import isModel from '@fleetbase/ember-core/utils/is-model';
7
+ import getCustomFieldTypeMap from '../utils/get-custom-field-type-map';
5
8
 
6
9
  export default class CustomFieldComponent extends Component {
7
- @tracked selectedPort;
8
- @tracked selectedVessel;
10
+ @service fetch;
11
+ @tracked orderConfig;
12
+ @tracked customField;
13
+ @tracked order;
14
+ @tracked customFieldComponent;
15
+ @tracked value;
16
+ @tracked file;
17
+ @tracked uploadedFile;
18
+ acceptedFileTypes = [
19
+ 'application/vnd.ms-excel',
20
+ 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
21
+ 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
22
+ 'application/msword',
23
+ 'application/pdf',
24
+ 'application/x-pdf',
25
+ 'image/jpeg',
26
+ 'image/png',
27
+ 'image/gif',
28
+ 'image/webp',
29
+ 'video/mp4',
30
+ 'video/quicktime',
31
+ 'video/x-msvideo',
32
+ 'video/x-flv',
33
+ 'video/x-ms-wmv',
34
+ 'audio/mpeg',
35
+ 'video/x-msvideo',
36
+ 'application/zip',
37
+ 'application/x-tar',
38
+ ];
9
39
 
10
- @equal('args.metaField.type', 'text') isTextInput;
11
- @equal('args.metaField.type', 'select') isSelectInput;
12
- @equal('args.metaField.type', 'vessel') isVesselInput;
13
- @equal('args.metaField.type', 'port') isPortInput;
14
- @equal('args.metaField.type', 'datetime') isDateTimeInput;
15
- @equal('args.metaField.type', 'boolean') isBooleanInput;
40
+ /**
41
+ * A map defining the available custom field types and their corresponding components.
42
+ */
43
+ customFieldTypeMap = getCustomFieldTypeMap();
16
44
 
17
- @action onToggle() {
18
- if (typeof this.args.onChange === 'function') {
19
- this.args.onChange(...arguments);
20
- }
45
+ constructor(owner, { customField, orderConfig, order }) {
46
+ super(...arguments);
47
+ this.customField = customField;
48
+ this.orderConfig = orderConfig;
49
+ this.order = order;
50
+ this.customFieldComponent = typeof customField.component === 'string' ? customField.component : 'input';
21
51
  }
22
52
 
23
- @action setDateValue(dateInstance) {
24
- const dateTime = dateInstance.toDate();
53
+ @action removeFile() {
54
+ if (isModel(this.uploadedFile)) {
55
+ this.uploadedFile.destroyRecord();
56
+ }
57
+
58
+ this.uploadedFile = undefined;
59
+ this.value = undefined;
25
60
 
26
61
  if (typeof this.args.onChange === 'function') {
27
- this.args.onChange(dateTime);
62
+ this.args.onChange(undefined, this.customField);
28
63
  }
29
64
  }
30
65
 
31
- @action selectPort(port) {
32
- this.selectedPort = port;
33
-
34
- if (typeof this.args.onChange === 'function') {
35
- this.args.onChange(port.portcode);
66
+ @action onFileAddedHandler(file) {
67
+ // since we have dropzone and upload button within dropzone validate the file state first
68
+ // as this method can be called twice from both functions
69
+ if (['queued', 'failed', 'timed_out', 'aborted'].indexOf(file.state) === -1) {
70
+ return;
36
71
  }
72
+
73
+ // set file for progress state
74
+ this.file = file;
75
+
76
+ // Queue and upload immediatley
77
+ this.fetch.uploadFile.perform(
78
+ file,
79
+ {
80
+ path: 'uploads/fleet-ops/order-files',
81
+ type: 'order_file',
82
+ },
83
+ (uploadedFile) => {
84
+ this.file = undefined;
85
+ this.value = `file:${uploadedFile.id}`;
86
+ this.uploadedFile = uploadedFile;
87
+ if (typeof this.args.onChange === 'function') {
88
+ this.args.onChange(this.value, this.customField);
89
+ }
90
+ },
91
+ () => {
92
+ // remove file from queue
93
+ if (file.queue && typeof file.queue.remove === 'function') {
94
+ file.queue.remove(file);
95
+ }
96
+ this.file = undefined;
97
+ }
98
+ );
37
99
  }
38
100
 
39
- @action selectVessel(vessel) {
40
- this.selectedVessel = vessel;
101
+ @action onChangeHandler(event, otherValue) {
102
+ const isRawInput = typeof event === 'string' || typeof event === 'number';
103
+ const isMoneyInput = this.customFieldComponent === 'money-input' && isObject(event);
104
+ const isEventInput = event instanceof window.Event;
105
+ const isDateTimeInput = this.customFieldComponent === 'date-time-input' && typeof otherValue === 'string';
41
106
 
42
- if (typeof this.args.onChange === 'function') {
43
- this.args.onChange(vessel.name);
107
+ if (isDateTimeInput) {
108
+ const value = otherValue;
109
+ this.value = value;
110
+
111
+ if (typeof this.args.onChange === 'function') {
112
+ this.args.onChange(value, this.customField);
113
+ }
114
+ return;
115
+ }
116
+
117
+ if (isRawInput) {
118
+ this.value = event;
119
+
120
+ if (typeof this.args.onChange === 'function') {
121
+ this.args.onChange(event, this.customField);
122
+ }
123
+ return;
124
+ }
125
+
126
+ if (isMoneyInput) {
127
+ const value = event.newValue;
128
+ if (typeof this.args.onChange === 'function') {
129
+ this.args.onChange(value, this.customField);
130
+ }
131
+ return;
132
+ }
133
+
134
+ if (isEventInput) {
135
+ const value = event.target.value;
136
+ this.value = value;
137
+
138
+ if (typeof this.args.onChange === 'function') {
139
+ this.args.onChange(value, this.customField);
140
+ }
141
+ return;
44
142
  }
45
143
  }
46
144
  }
@@ -59,7 +59,7 @@
59
59
  </div>
60
60
  </Overlay::Header>
61
61
 
62
- <Overlay::Body @wrapperClass="new-service-rate-overlay-body px-4 space-y-4 pt-4" @increaseInnerBodyHeightBy={{1000}}>
62
+ <Overlay::Body @wrapperClass="new-service-rate-overlay-body px-4 space-y-4 pt-4">
63
63
  <div class="flex-1 space-y-4">
64
64
  <div class="grid grid-cols-1 lg:grid-cols-2 gap-2 text-xs dark:text-gray-100">
65
65
  <InputGroup @name={{t "fleet-ops.common.name"}} @wrapperClass="col-span-2">
@@ -63,7 +63,7 @@
63
63
  </div>
64
64
  </div>
65
65
  </Overlay::Header>
66
- <Overlay::Body class="no-padding" @increaseInnerBodyHeightBy={{1000}}>
66
+ <Overlay::Body class="no-padding">
67
67
  <div class="section-header-actions w-full overflow-x-scroll lg:overflow-x-auto">
68
68
  <div class="ui-tabs mt-4">
69
69
  <nav>
@@ -4,7 +4,7 @@
4
4
  <Button @type="default" @icon="times" @helpText={{t "fleet-ops.common.cancel"}} @onClick={{this.onPressCancel}} />
5
5
  </Overlay::Header>
6
6
 
7
- <Overlay::Body @increaseInnerBodyHeightBy={{1000}}>
7
+ <Overlay::Body>
8
8
  <div class="p-4">
9
9
  <div class="flex flex-row justify-between mb-6">
10
10
  <div class="flex">
@@ -25,7 +25,7 @@
25
25
  </div>
26
26
  </Overlay::Header>
27
27
 
28
- <Overlay::Body @wrapperClass="new-service-rate-overlay-body px-4 space-y-4 pt-4" @increaseInnerBodyHeightBy={{1000}}>
28
+ <Overlay::Body @wrapperClass="new-service-rate-overlay-body px-4 space-y-4 pt-4">
29
29
  <div class="modal-body-container">
30
30
  <div class="flex flex-col text-xs dark:text-gray-100">
31
31
  <InputGroup @name={{t "fleet-ops.component.fleet-form-panel.fleet-name"}} @value={{this.fleet.name}} />
@@ -4,7 +4,7 @@
4
4
  <Button @type="default" @icon="times" @helpText={{if this.fleet.id "Cancel edit fleet" "Cancel new fleet"}} @onClick={{this.onPressCancel}} />
5
5
  </Overlay::Header>
6
6
 
7
- <Overlay::Body class="no-padding" @increaseInnerBodyHeightBy={{1000}}>
7
+ <Overlay::Body class="no-padding">
8
8
  <div class="section-header-actions w-full overflow-x-scroll lg:overflow-x-auto">
9
9
  <div class="ui-tabs mt-4">
10
10
  <nav>
@@ -31,7 +31,7 @@
31
31
  </div>
32
32
  </Overlay::Header>
33
33
 
34
- <Overlay::Body @wrapperClass="new-service-rate-overlay-body px-4 space-y-4 pt-4" @increaseInnerBodyHeightBy={{1000}}>
34
+ <Overlay::Body @wrapperClass="new-service-rate-overlay-body px-4 space-y-4 pt-4">
35
35
  <div class="grid grid-cols-1 text-xs dark:text-gray-100">
36
36
  <InputGroup @name={{t "fleet-ops.common.reporter"}}>
37
37
  <ModelSelect
@@ -13,7 +13,7 @@
13
13
  <Button @type="default" @icon="pen" @helpText={{t "fleet-ops.component.fuel-report-panel.edit-button"}} @onClick={{this.onEdit}} @wrapperClass="mr-2" />
14
14
  <Button @type="default" @icon="times" @helpText={{if this.fuelReport.id (t "fleet-ops.component.fuel-report-panel.cancel-edit-fuel-report")(t "fleet-ops.component.fuel-report-panel.cancel-new-fuel-report") }} @onClick={{this.onPressCancel}} />
15
15
  </Overlay::Header>
16
- <Overlay::Body class="no-padding" @increaseInnerBodyHeightBy={{1000}}>
16
+ <Overlay::Body class="no-padding">
17
17
  <div class="section-header-actions w-full overflow-x-scroll lg:overflow-x-auto">
18
18
  <div class="ui-tabs mt-4">
19
19
  <nav>
@@ -25,7 +25,7 @@
25
25
  </div>
26
26
  </Overlay::Header>
27
27
 
28
- <Overlay::Body @wrapperClass="new-service-rate-overlay-body px-4 pt-4" @increaseInnerBodyHeightBy={{1000}}>
28
+ <Overlay::Body @wrapperClass="new-service-rate-overlay-body px-4 pt-4">
29
29
  <div class="grid grid-cols-1 text-xs dark:text-gray-100">
30
30
  <InputGroup @name={{t "fleet-ops.component.issue-form-panel.reported-by"}}>
31
31
  <ModelSelect
@@ -13,7 +13,7 @@
13
13
  <Button @type="default" @icon="pen" @helpText={{t "fleet-ops.component.issue-panel.edit-issue"}} @onClick={{this.onEdit}} @wrapperClass="mr-2" />
14
14
  <Button @type="default" @icon="times" @helpText={{if this.issue.id (t "fleet-ops.component.issue-panel.cancel-edit-issue")(t "fleet-ops.component.issue-panel.cancel-new-issue") }} @onClick={{this.onPressCancel}} />
15
15
  </Overlay::Header>
16
- <Overlay::Body class="no-padding" @increaseInnerBodyHeightBy={{1000}}>
16
+ <Overlay::Body class="no-padding">
17
17
  <div class="section-header-actions w-full overflow-x-scroll lg:overflow-x-auto">
18
18
  <div class="ui-tabs mt-4">
19
19
  <nav>
@@ -0,0 +1 @@
1
+ <div id="paper" class="joint-js-paper" {{did-insert this.setupGraph}}>{{yield}}</div>
@@ -0,0 +1,103 @@
1
+ /* eslint-disable no-undef */
2
+ import Component from '@glimmer/component';
3
+ import { tracked } from '@glimmer/tracking';
4
+ import { action } from '@ember/object';
5
+
6
+ export default class JointGraphComponent extends Component {
7
+ @tracked el;
8
+ @tracked graph;
9
+ @tracked paper;
10
+ @tracked height = 400;
11
+ @tracked width = 800;
12
+ @tracked gridSize = 1;
13
+ @tracked fullSize = true;
14
+ @tracked panning = true;
15
+ @tracked responsive = true;
16
+ @tracked dragStartPosition = {};
17
+
18
+ constructor(owner, { height = 400, width = 800, gridSize = 1, fullSize = true, panning = true, responsive = true }) {
19
+ super(...arguments);
20
+ this.height = height;
21
+ this.width = width;
22
+ this.gridSize = gridSize;
23
+ this.fullSize = fullSize;
24
+ this.panning = panning;
25
+ this.responsive = responsive;
26
+ }
27
+
28
+ @action setupGraph(el) {
29
+ this.sizeGrid(el);
30
+ this.createGraph(el);
31
+ }
32
+
33
+ createGraph(el) {
34
+ const namespace = joint.shapes;
35
+ const graph = new joint.dia.Graph({}, { cellNamespace: namespace });
36
+ const paper = new joint.dia.Paper({
37
+ el,
38
+ model: graph,
39
+ width: this.width,
40
+ height: this.height,
41
+ gridSize: this.gridSize,
42
+ cellViewNamespace: namespace,
43
+ interactive: false,
44
+ });
45
+
46
+ this.el = el;
47
+ this.graph = graph;
48
+ this.paper = paper;
49
+ if (this.panning) {
50
+ this.createPanningHandler(paper);
51
+ }
52
+ if (this.responsive) {
53
+ this.createResponsiveHandler(paper);
54
+ }
55
+
56
+ if (typeof this.args.onSetup === 'function') {
57
+ this.args.onSetup({ paper, graph, el }, this);
58
+ }
59
+ }
60
+
61
+ getFullGridSize(el) {
62
+ const parentEl = el.parentElement;
63
+ const width = parentEl.offsetWidth;
64
+ const height = parentEl.offsetHeight;
65
+ return { width, height };
66
+ }
67
+
68
+ sizeGrid(el) {
69
+ if (this.fullSize) {
70
+ const { width, height } = this.getFullGridSize(el);
71
+ this.width = width;
72
+ this.height = height;
73
+ }
74
+ }
75
+
76
+ createResponsiveHandler(paper) {
77
+ window.addEventListener('resize', () => {
78
+ if (!this.el) {
79
+ return;
80
+ }
81
+ const { width, height } = this.getFullGridSize(this.el);
82
+ this.width = width;
83
+ this.height = height;
84
+ paper.setDimensions(width, height);
85
+ });
86
+ }
87
+
88
+ createPanningHandler(paper) {
89
+ paper.on('blank:pointerdown', (event, x, y) => {
90
+ this.dragStartPosition = { x, y };
91
+ });
92
+
93
+ paper.on('cell:pointerup blank:pointerup', () => {
94
+ this.dragStartPosition = undefined;
95
+ });
96
+
97
+ paper.el.addEventListener('mousemove', (event) => {
98
+ if (this.dragStartPosition) {
99
+ paper.translate(event.offsetX - this.dragStartPosition.x, event.offsetY - this.dragStartPosition.y);
100
+ }
101
+ });
102
+ }
103
+ }
@@ -12,9 +12,9 @@
12
12
  <Layout::Sidebar::Panel @open={{menuPanel.open}} @title={{menuPanel.title}}>
13
13
  {{#each menuPanel.items as |menuItem|}}
14
14
  {{#if menuItem.renderComponentInPlace}}
15
- {{component menuItem.component menuItem=menuItem title=menuItem.title route=(concat this.routePrefix menuItem.route) icon=menuItem.icon rightSideComponent=menuItem.rightSideComponent rightSideComponentContext=menuItem.rightSideComponentContext rightSideStatus=menuItem.rightSideStatus rightSideStatusText=menuItem.rightSideStatusText hideRightSideStatusDot=menuItem.hideRightSideStatusDot rightSideStatusClass=menuItem.rightSideStatusClass disableRightSideStatusHumanize=menuItem.disableRightSideStatusHumanize dropdownButton=menuItem.dropdownButton dropdownButtonActions=menuItem.dropdownButtonActions dropdownButtonIcon=menuItem.dropdownButtonIcon dropdownButtonIconPrefix=menuItem.dropdownButtonIconPrefix dropdownButtonText=menuItem.dropdownButtonText dropdownButtonCalculatePosition=menuItem.dropdownButtonCalculatePosition dropdownButtonRenderInPlace=menuItem.dropdownButtonRenderInPlace dropdownButtonMenuLabel=menuItem.dropdownButtonMenuLabel dropdownButtonWrapperClass=menuItem.dropdownButtonWrapperClass dropdownButtonTriggerClass=menuItem.dropdownButtonTriggerClass registerDropdownButtonAPI=menuItem.registerDropdownButtonAPI}}
15
+ {{component menuItem.component menuItem=menuItem title=menuItem.title onClick=menuItem.onClick route=(concat this.routePrefix menuItem.route) icon=menuItem.icon rightSideComponent=menuItem.rightSideComponent rightSideComponentContext=menuItem.rightSideComponentContext rightSideStatus=menuItem.rightSideStatus rightSideStatusText=menuItem.rightSideStatusText hideRightSideStatusDot=menuItem.hideRightSideStatusDot rightSideStatusClass=menuItem.rightSideStatusClass disableRightSideStatusHumanize=menuItem.disableRightSideStatusHumanize dropdownButton=menuItem.dropdownButton dropdownButtonActions=menuItem.dropdownButtonActions dropdownButtonIcon=menuItem.dropdownButtonIcon dropdownButtonIconPrefix=menuItem.dropdownButtonIconPrefix dropdownButtonText=menuItem.dropdownButtonText dropdownButtonCalculatePosition=menuItem.dropdownButtonCalculatePosition dropdownButtonRenderInPlace=menuItem.dropdownButtonRenderInPlace dropdownButtonMenuLabel=menuItem.dropdownButtonMenuLabel dropdownButtonWrapperClass=menuItem.dropdownButtonWrapperClass dropdownButtonTriggerClass=menuItem.dropdownButtonTriggerClass registerDropdownButtonAPI=menuItem.registerDropdownButtonAPI}}
16
16
  {{else}}
17
- <Layout::Sidebar::Item @route={{concat this.routePrefix menuItem.route}} @icon={{menuItem.icon}} @rightSideComponent={{menuItem.rightSideComponent}} @rightSideComponentContext={{menuItem.rightSideComponentContext}} @rightSideStatus={{menuItem.rightSideStatus}} @rightSideStatusText={{menuItem.rightSideStatusText}} @hideRightSideStatusDot={{menuItem.hideRightSideStatusDot}} @rightSideStatusClass={{menuItem.rightSideStatusClass}} @disableRightSideStatusHumanize={{menuItem.disableRightSideStatusHumanize}} @dropdownButton={{menuItem.dropdownButton}} @dropdownButtonActions={{menuItem.dropdownButtonActions}} @dropdownButtonIcon={{menuItem.dropdownButtonIcon}} @dropdownButtonIconPrefix={{menuItem.dropdownButtonIconPrefix}} @dropdownButtonText={{menuItem.dropdownButtonText}} @dropdownButtonCalculatePosition={{menuItem.dropdownButtonCalculatePosition}} @dropdownButtonRenderInPlace={{menuItem.dropdownButtonRenderInPlace}} @dropdownButtonMenuLabel={{menuItem.dropdownButtonMenuLabel}} @dropdownButtonWrapperClass={{menuItem.dropdownButtonWrapperClass}} @dropdownButtonTriggerClass={{menuItem.dropdownButtonTriggerClass}} @registerDropdownButtonAPI={{menuItem.registerDropdownButtonAPI}}>{{menuItem.title}}</Layout::Sidebar::Item>
17
+ <Layout::Sidebar::Item @onClick={{menuItem.onClick}} @route={{concat this.routePrefix menuItem.route}} @icon={{menuItem.icon}} @rightSideComponent={{menuItem.rightSideComponent}} @rightSideComponentContext={{menuItem.rightSideComponentContext}} @rightSideStatus={{menuItem.rightSideStatus}} @rightSideStatusText={{menuItem.rightSideStatusText}} @hideRightSideStatusDot={{menuItem.hideRightSideStatusDot}} @rightSideStatusClass={{menuItem.rightSideStatusClass}} @disableRightSideStatusHumanize={{menuItem.disableRightSideStatusHumanize}} @dropdownButton={{menuItem.dropdownButton}} @dropdownButtonActions={{menuItem.dropdownButtonActions}} @dropdownButtonIcon={{menuItem.dropdownButtonIcon}} @dropdownButtonIconPrefix={{menuItem.dropdownButtonIconPrefix}} @dropdownButtonText={{menuItem.dropdownButtonText}} @dropdownButtonCalculatePosition={{menuItem.dropdownButtonCalculatePosition}} @dropdownButtonRenderInPlace={{menuItem.dropdownButtonRenderInPlace}} @dropdownButtonMenuLabel={{menuItem.dropdownButtonMenuLabel}} @dropdownButtonWrapperClass={{menuItem.dropdownButtonWrapperClass}} @dropdownButtonTriggerClass={{menuItem.dropdownButtonTriggerClass}} @registerDropdownButtonAPI={{menuItem.registerDropdownButtonAPI}}>{{menuItem.title}}</Layout::Sidebar::Item>
18
18
  {{/if}}
19
19
  {{/each}}
20
20
  </Layout::Sidebar::Panel>
@@ -26,6 +26,6 @@
26
26
  {{/each}}
27
27
  </Layout::Sidebar::Panel>
28
28
  {{/each}}
29
- <Layout::Sidebar::Item @onClick={{this.onClickSettings}} @icon="cogs">{{t "fleet-ops.component.layout.fleet-ops-sidebar.settings"}}</Layout::Sidebar::Item>
29
+ {{!-- <Layout::Sidebar::Item @onClick={{this.onClickSettings}} @icon="cogs">{{t "fleet-ops.component.layout.fleet-ops-sidebar.settings"}}</Layout::Sidebar::Item> --}}
30
30
  {{yield}}
31
31
  <Spacer @height="10px" />
@@ -40,6 +40,7 @@ export default class LayoutFleetOpsSidebarComponent extends Component {
40
40
  { title: this.intl.t('fleet-ops.component.layout.fleet-ops-sidebar.dashboard'), icon: 'home', route: 'operations.orders' },
41
41
  { title: this.intl.t('fleet-ops.component.layout.fleet-ops-sidebar.service-rates'), icon: 'file-invoice-dollar', route: 'operations.service-rates' },
42
42
  { title: this.intl.t('fleet-ops.component.layout.fleet-ops-sidebar.scheduler'), icon: 'calendar-day', route: 'operations.scheduler' },
43
+ { title: this.intl.t('fleet-ops.component.layout.fleet-ops-sidebar.order-config'), icon: 'diagram-project', route: 'operations.order-config' },
43
44
  ];
44
45
 
45
46
  const resourcesItems = [
@@ -7,6 +7,7 @@ import { dasherize, camelize, classify } from '@ember/string';
7
7
  import { singularize } from 'ember-inflector';
8
8
  import { later } from '@ember/runloop';
9
9
  import { allSettled } from 'rsvp';
10
+ import { task } from 'ember-concurrency-decorators';
10
11
  import getWithDefault from '@fleetbase/ember-core/utils/get-with-default';
11
12
 
12
13
  /**
@@ -300,18 +301,18 @@ export default class LiveMapComponent extends Component {
300
301
 
301
302
  // load data and complete setup
302
303
  this.completeSetup([
303
- this.fetchLiveData('routes'),
304
- this.fetchLiveData('vehicles', {
304
+ this.loadLiveData.perform('routes'),
305
+ this.loadLiveData.perform('vehicles', {
305
306
  onLoaded: (vehicles) => {
306
307
  this.watchMovingObjects('vehicles', vehicles);
307
308
  },
308
309
  }),
309
- this.fetchLiveData('drivers', {
310
+ this.loadLiveData.perform('drivers', {
310
311
  onLoaded: (drivers) => {
311
312
  this.watchMovingObjects('drivers', drivers);
312
313
  },
313
314
  }),
314
- this.fetchLiveData('places'),
315
+ this.loadLiveData.perform('places'),
315
316
  ]);
316
317
  }
317
318
 
@@ -342,18 +343,18 @@ export default class LiveMapComponent extends Component {
342
343
  */
343
344
  reload() {
344
345
  this.completeSetup([
345
- this.fetchLiveData('routes'),
346
- this.fetchLiveData('vehicles', {
346
+ this.loadLiveData.perform('routes'),
347
+ this.loadLiveData.perform('vehicles', {
347
348
  onLoaded: (vehicles) => {
348
349
  this.watchMovingObjects('vehicles', vehicles);
349
350
  },
350
351
  }),
351
- this.fetchLiveData('drivers', {
352
+ this.loadLiveData.perform('drivers', {
352
353
  onLoaded: (drivers) => {
353
354
  this.watchMovingObjects('drivers', drivers);
354
355
  },
355
356
  }),
356
- this.fetchLiveData('places'),
357
+ this.loadLiveData.perform('places'),
357
358
  ]);
358
359
  }
359
360
 
@@ -477,9 +478,10 @@ export default class LiveMapComponent extends Component {
477
478
  const internalName = camelize(path);
478
479
  const callbackFnName = `on${internalName}Loaded`;
479
480
  const params = getWithDefault(options, 'params', {});
481
+ const url = `fleet-ops/live/${path}`;
480
482
 
481
483
  return this.fetch
482
- .get(`fleet-ops/live/${path}`, params, { normalizeToEmberData: true, normalizeModelType: singularize(internalName) })
484
+ .get(url, params, { normalizeToEmberData: true, normalizeModelType: singularize(internalName) })
483
485
  .then((data) => {
484
486
  this.triggerAction(callbackFnName);
485
487
  this.createVisibilityControl(internalName);
@@ -503,6 +505,54 @@ export default class LiveMapComponent extends Component {
503
505
  });
504
506
  }
505
507
 
508
+ /**
509
+ * Asynchronously loads live data for a specified path and updates the component's state.
510
+ * This function uses Ember Concurrency to handle the asynchronous operation, ensuring
511
+ * better handling of concurrency and potential task cancellation.
512
+ *
513
+ * @memberof LiveMapComponent
514
+ * @task
515
+ * @generator
516
+ * @param {string} path - The path for fetching live data.
517
+ * @param {Object} [options={}] - Configuration options for the data loading process.
518
+ * @param {Object} [options.params={}] - Additional parameters to include in the request.
519
+ * @param {Function} [options.onLoaded] - Callback function executed when data is successfully loaded.
520
+ * @param {Function} [options.onFailure] - Callback function executed in case of a failure in data loading.
521
+ * @returns {Promise<Object|undefined>} A promise that resolves with the fetched data, or undefined if an error occurs.
522
+ *
523
+ * @example
524
+ * // To load data and execute specific actions on load and failure
525
+ * this.loadLiveData.perform('some/path', {
526
+ * params: { key: 'value' },
527
+ * onLoaded: (data) => { console.log('Data loaded', data); },
528
+ * onFailure: (error) => { console.error('Failed to load data', error); }
529
+ * });
530
+ */
531
+ @task *loadLiveData(path, options = {}) {
532
+ const internalName = camelize(path);
533
+ const callbackFnName = `on${internalName}Loaded`;
534
+ const params = getWithDefault(options, 'params', {});
535
+ const url = `fleet-ops/live/${path}`;
536
+ const data = yield this.fetch.get(url, params, { normalizeToEmberData: true, normalizeModelType: singularize(internalName) }).catch((error) => {
537
+ if (typeof options.onFailure === 'function') {
538
+ options.onFailure(error);
539
+ }
540
+ });
541
+
542
+ if (data) {
543
+ this.triggerAction(callbackFnName);
544
+ this.createVisibilityControl(internalName);
545
+ this[internalName] = data;
546
+ this.cacheOriginalResources(internalName);
547
+
548
+ if (typeof options.onLoaded === 'function') {
549
+ options.onLoaded(data);
550
+ }
551
+ }
552
+
553
+ return data;
554
+ }
555
+
506
556
  /**
507
557
  * Creates or updates a visibility control for a specific element by name.
508
558
  *
@@ -1858,27 +1908,20 @@ export default class LiveMapComponent extends Component {
1858
1908
  * @returns {Promise} A promise that resolves to an array of service area records.
1859
1909
  * @memberof LiveMapComponent
1860
1910
  */
1861
- fetchServiceAreas() {
1862
- this.isLoading = true;
1863
-
1864
- return new Promise((resolve) => {
1865
- if (this.serviceAreas && typeof this.serviceAreas.getFromCache === 'function') {
1866
- const cachedRecords = this.serviceAreas.getFromCache('serviceAreas', 'service-area');
1911
+ @task *loadServiceAreas() {
1912
+ if (this.serviceAreas && typeof this.serviceAreas.getFromCache === 'function') {
1913
+ const cachedRecords = this.serviceAreas.getFromCache('serviceAreas', 'service-area');
1867
1914
 
1868
- if (cachedRecords) {
1869
- resolve(cachedRecords);
1870
- }
1915
+ if (cachedRecords) {
1916
+ return cachedRecords;
1871
1917
  }
1918
+ }
1872
1919
 
1873
- return this.store
1874
- .query('service-area', { with: ['zones'] })
1875
- .then((serviceAreaRecords) => {
1876
- this.appCache.setEmberData('serviceAreas', serviceAreaRecords);
1877
- resolve(serviceAreaRecords);
1878
- })
1879
- .finally(() => {
1880
- this.isLoading = false;
1881
- });
1882
- });
1920
+ const serviceAreaRecords = yield this.store.query('service-area', { with: ['zones'] });
1921
+ if (serviceAreaRecords) {
1922
+ this.appCache.setEmberData('serviceAreas', serviceAreaRecords);
1923
+ }
1924
+
1925
+ return serviceAreaRecords;
1883
1926
  }
1884
1927
  }
@@ -0,0 +1,5 @@
1
+ <Modal::Default @modalIsOpened={{@modalIsOpened}} @options={{@options}} @confirm={{@onConfirm}} @decline={{@onDecline}}>
2
+ <div class="modal-body-container">
3
+ <InputGroup @name={{t "fleet-ops.component.modals.new-custom-field-group.group-name"}} @value={{@options.customFieldGroup.name}} />
4
+ </div>
5
+ </Modal::Default>
@@ -1,9 +1,9 @@
1
1
  <Modal::Default @modalIsOpened={{@modalIsOpened}} @options={{@options}} @confirm={{@onConfirm}} @decline={{@onDecline}}>
2
2
  <div class="modal-body-container">
3
- <InputGroup @name={{t "fleet-ops.component.modals.new-order-config.name"}} @value={{@options.name}} />
4
- <InputGroup @name={{t "fleet-ops.component.modals.new-order-config.description"}} @value={{@options.description}} />
3
+ <InputGroup @name={{t "fleet-ops.component.modals.new-order-config.name"}} @value={{@options.orderConfig.name}} />
4
+ <InputGroup @name={{t "fleet-ops.component.modals.new-order-config.description"}} @value={{@options.orderConfig.description}} />
5
5
  <InputGroup @name={{t "fleet-ops.component.modals.new-order-config.tags"}}>
6
- <TagInput class="form-input" @placeholder={{t "fleet-ops.component.modals.new-order-config.add-tags"}} @allowSpacesInTags={{true}} @tags={{@options.tags}} @addTag={{@options.addTag}} @removeTagAtIndex={{@options.removeTag}} as |tag|>
6
+ <TagInput class="form-input" @placeholder={{t "fleet-ops.component.modals.new-order-config.add-tags"}} @allowSpacesInTags={{true}} @tags={{@options.orderConfig.tags}} @addTag={{@options.addTag}} @removeTagAtIndex={{@options.removeTag}} as |tag|>
7
7
  {{tag}}
8
8
  </TagInput>
9
9
  </InputGroup>
@@ -28,7 +28,7 @@
28
28
  {{activity.details}}
29
29
 
30
30
  {{#if (eq activity.code "dispatched")}}
31
- <InfoBlock class="warning xs mt-2" @icon="exclamation-triangle" @text={{t "fleet-ops.component.modals.order-new-activity.dispatch"}} />
31
+ <InfoBlock class="warning xs mt-2" @icon="exclamation-triangle" @textClass="text-yellow-900 focus:text-yellow-900" @text={{t "fleet-ops.component.modals.order-new-activity.dispatch"}} />
32
32
  {{/if}}
33
33
  </span>
34
34
  </label>
@@ -0,0 +1,11 @@
1
+ <div class="flex flex-row items-center px-6 py-2 space-x-2">
2
+ <Button @type="primary" @icon="save" @text={{t "fleet-ops.component.order-config-manager.activity-flow.save-activity-flow"}} @onClick={{perform this.save}} @isLoading={{not this.save.isIdle}} @disabled={{this.config.core_service}} />
3
+ <Button @type="default" @icon="rotate" @text="Reset" @onClick={{this.resetConfig}} @disabled={{this.config.core_service}} />
4
+ </div>
5
+ <div class="activity-flow-graph-container">
6
+ <div class="activity-flow-zoom-controls">
7
+ <Button @icon="plus" @onClick={{this.zoomIn}} />
8
+ <Button @icon="minus" @onClick={{this.zoomOut}} />
9
+ </div>
10
+ <JointGraph @onSetup={{this.initializeGraph}} />
11
+ </div>