@fleetbase/fleetops-engine 0.4.22 → 0.4.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/addon/components/admin/navigator-app.hbs +0 -76
  2. package/addon/components/admin/navigator-app.js +0 -58
  3. package/addon/components/driver-onboard-settings.hbs +29 -0
  4. package/addon/components/driver-onboard-settings.js +75 -0
  5. package/addon/components/entity-field-editing-settings.hbs +79 -0
  6. package/addon/components/entity-field-editing-settings.js +106 -0
  7. package/addon/components/layout/fleet-ops-sidebar/driver-listing.hbs +1 -1
  8. package/addon/components/layout/fleet-ops-sidebar/driver-listing.js +12 -0
  9. package/addon/components/layout/fleet-ops-sidebar.hbs +2 -3
  10. package/addon/components/layout/fleet-ops-sidebar.js +3 -0
  11. package/addon/routes/settings/navigator-app.js +3 -0
  12. package/addon/routes/settings.js +3 -0
  13. package/addon/routes.js +3 -0
  14. package/addon/styles/fleetops-engine.css +24 -0
  15. package/addon/templates/settings/navigator-app.hbs +11 -0
  16. package/addon/templates/settings.hbs +1 -0
  17. package/app/components/driver-onboard-settings.js +1 -0
  18. package/app/components/entity-field-editing-settings.js +1 -0
  19. package/app/routes/settings/navigator-app.js +1 -0
  20. package/app/routes/settings.js +1 -0
  21. package/app/templates/settings/navigator-app.js +1 -0
  22. package/app/templates/settings.js +1 -0
  23. package/composer.json +2 -2
  24. package/extension.json +1 -1
  25. package/package.json +2 -2
  26. package/server/src/Console/Commands/FixInvalidPolymorphicRelationTypeNamespaces.php +1 -1
  27. package/server/src/Http/Controllers/Api/v1/DriverController.php +7 -3
  28. package/server/src/Http/Controllers/Api/v1/NavigatorController.php +35 -0
  29. package/server/src/Http/Controllers/Api/v1/OrderController.php +6 -9
  30. package/server/src/Http/Controllers/Api/v1/OrganizationController.php +23 -5
  31. package/server/src/Http/Controllers/FleetOpsController.php +0 -6
  32. package/server/src/Http/Controllers/Internal/v1/NavigatorController.php +8 -0
  33. package/server/src/Http/Controllers/Internal/v1/SettingController.php +51 -5
  34. package/server/src/Http/Filter/OrderFilter.php +1 -1
  35. package/server/src/Http/Requests/CreateContactRequest.php +1 -1
  36. package/server/src/Http/Requests/CreateDriverRequest.php +1 -1
  37. package/server/src/Http/Requests/CreateEntityRequest.php +1 -1
  38. package/server/src/Http/Requests/CreateIssueRequest.php +15 -0
  39. package/server/src/Http/Requests/CreatePlaceRequest.php +1 -3
  40. package/server/src/Http/Requests/CreateVehicleRequest.php +1 -1
  41. package/server/src/Http/Resources/v1/Driver.php +1 -1
  42. package/server/src/Support/Utils.php +4 -4
  43. package/server/src/routes.php +7 -0
  44. package/translations/en-us.yaml +28 -3
@@ -5,80 +5,4 @@
5
5
  <InputInfo>{{t "fleet-ops.component.admin.navigator-app.message" htmlSafe=true companyName=@app.name}}</InputInfo>
6
6
  </Attach::Tooltip>
7
7
  </InputGroup>
8
- </ContentPanel>
9
-
10
- <ContentPanel @title={{t "fleet-ops.component.admin.navigator-app.settings"}} @open={{true}} @pad={{true}} @panelBodyClass="bg-white dark:bg-gray-800">
11
- <InputGroup>
12
- <div class="flex items-center">
13
- <Toggle @isToggled={{this.isEntityFieldsEditable}} @onToggle={{this.enableEditableEntityFields}} />
14
- <div class="ml-2">{{t "fleet-ops.component.admin.navigator-app.select-input"}}</div>
15
- </div>
16
- </InputGroup>
17
- {{#if this.isEntityFieldsEditable}}
18
- <OrderConfigManager @onConfigChanged={{this.onConfigChanged}} as |Action Context|>
19
- <div class="mt-2">
20
- <InputGroup @name="Select order config" @helpText="Apply entity editing settings for an order config.">
21
- <DropdownButton
22
- class="order-config-select-button mr-2"
23
- @disabled={{not Context.configs}}
24
- @text={{if Context.currentConfig.name Context.currentConfig.name (t "fleet-ops.component.order-config-manager.select-order-config")}}
25
- @textClass="text-sm mr-2"
26
- @buttonClass="flex-row-reverse w-44 justify-between"
27
- @icon="caret-down"
28
- @iconClass="mr-0i"
29
- @size="sm"
30
- @iconPrefix="fas"
31
- @triggerClass="hidden md:flex"
32
- as |dd|
33
- >
34
- <div class="next-dd-menu mt-1 mx-0" aria-labelledby="user-menu">
35
- <div class="p-1">
36
- {{#each Context.configs as |orderConfig|}}
37
- <a href="javascript:;" class="next-dd-item" {{on "click" (dropdown-fn dd Context.selectConfig orderConfig)}}>
38
- <div class="flex-1 flex flex-row items-center">
39
- <div class="w-6">
40
- <FaIcon @icon="cogs" />
41
- </div>
42
- <span>{{orderConfig.name}}</span>
43
- </div>
44
- <div>
45
- {{#if (eq Context.currentConfig.id orderConfig.id)}}
46
- <FaIcon @icon="check" class="text-green-500" />
47
- {{/if}}
48
- </div>
49
- </a>
50
- {{/each}}
51
- </div>
52
- </div>
53
- </DropdownButton>
54
- </InputGroup>
55
- </div>
56
- </OrderConfigManager>
57
- {{#if this.selectedOrderConfig}}
58
- <div class="bg-gray-400 border-gray-600 rounded-lg px-4 py-2 dark:bg-gray-700 dark:border-gray-800">
59
- {{#let (get (get this.entityEditingSettings this.selectedOrderConfig.id) "editable_entity_fields") as |editableEntityFields|}}
60
- {{#each this.entityFields as |entityField|}}
61
- <div class="mt-1">
62
- <Checkbox
63
- @value={{includes entityField editableEntityFields}}
64
- @label={{smart-humanize entityField}}
65
- @onToggle={{fn this.toggleFieldEditable entityField}}
66
- @helpText={{t "fleet-ops.component.admin.visibility-controls.checkbox-text"}}
67
- />
68
- </div>
69
- {{/each}}
70
- {{/let}}
71
- </div>
72
- <div class="mt-3 flex items-center">
73
- <Button
74
- @type="primary"
75
- @size="lg"
76
- @icon="save"
77
- @text={{t "fleet-ops.common.save-changes"}}
78
- @onClick={{perform this.saveEntityEditingSettings}}
79
- @isLoading={{not this.saveEntityEditingSettings.isIdle}}
80
- />
81
- </div>
82
- {{/if}}
83
- {{/if}}
84
8
  </ContentPanel>
@@ -1,62 +1,15 @@
1
1
  import Component from '@glimmer/component';
2
2
  import { tracked } from '@glimmer/tracking';
3
3
  import { inject as service } from '@ember/service';
4
- import { action } from '@ember/object';
5
- import { isArray } from '@ember/array';
6
4
  import { task } from 'ember-concurrency-decorators';
7
5
 
8
6
  export default class NavigatorAppControlsComponent extends Component {
9
7
  @service fetch;
10
- @tracked isLoading = false;
11
8
  @tracked url;
12
- @tracked selectedOrderConfig;
13
- @tracked entityFields = ['name', 'description', 'sku', 'height', 'width', 'length', 'weight', 'declared_value', 'sale_price'];
14
- @tracked entityEditingSettings = {};
15
- @tracked isEntityFieldsEditable = false;
16
9
 
17
10
  constructor() {
18
11
  super(...arguments);
19
12
  this.getAppLinkUrl.perform();
20
- this.getEntityEditableSettings.perform();
21
- }
22
-
23
- @action enableEditableEntityFields(isEntityFieldsEditable) {
24
- this.isEntityFieldsEditable = isEntityFieldsEditable;
25
- }
26
-
27
- @action onConfigChanged(orderConfig) {
28
- this.selectedOrderConfig = orderConfig;
29
- }
30
-
31
- @action toggleFieldEditable(fieldName, isEditable) {
32
- const editableFields = this.entityEditingSettings[this.selectedOrderConfig.id]?.editable_entity_fields;
33
- if (isArray(editableFields)) {
34
- if (isEditable) {
35
- editableFields.pushObject(fieldName);
36
- } else {
37
- editableFields.removeObject(fieldName);
38
- }
39
- } else {
40
- this.entityEditingSettings = {
41
- ...this.entityEditingSettings,
42
- [this.selectedOrderConfig.id]: {
43
- editable_entity_fields: [],
44
- },
45
- };
46
- return this.toggleFieldEditable(...arguments);
47
- }
48
-
49
- this.updateEditableEntityFieldsForOrderConfig(editableFields);
50
- }
51
-
52
- updateEditableEntityFieldsForOrderConfig(editableFields = [], orderConfig = null) {
53
- orderConfig = orderConfig === null ? this.selectedOrderConfig : orderConfig;
54
- this.entityEditingSettings = {
55
- ...this.entityEditingSettings,
56
- [orderConfig.id]: {
57
- editable_entity_fields: editableFields,
58
- },
59
- };
60
13
  }
61
14
 
62
15
  @task *getAppLinkUrl() {
@@ -66,15 +19,4 @@ export default class NavigatorAppControlsComponent extends Component {
66
19
  this.url = linkUrl;
67
20
  }
68
21
  }
69
-
70
- @task *getEntityEditableSettings() {
71
- const { entityEditingSettings, isEntityFieldsEditable } = yield this.fetch.get('fleet-ops/settings/entity-editing-settings');
72
- this.entityEditingSettings = entityEditingSettings;
73
- this.isEntityFieldsEditable = isEntityFieldsEditable;
74
- }
75
-
76
- @task *saveEntityEditingSettings() {
77
- const { entityEditingSettings, isEntityFieldsEditable } = this;
78
- yield this.fetch.post('fleet-ops/settings/entity-editing-settings', { entityEditingSettings, isEntityFieldsEditable });
79
- }
80
22
  }
@@ -0,0 +1,29 @@
1
+ <ContentPanel @title={{t "fleet-ops.component.driver-onboard-settings.driver-onboard-settings"}} @open={{true}} @pad={{true}} @panelBodyClass="bg-white dark:bg-gray-800 mb-4">
2
+ {{#if this.driverOnboardSettingsLoaded}}
3
+ <InputGroup>
4
+ <div class="flex items-center">
5
+ <Toggle @isToggled={{this.driverOnboardSettings.enableDriverOnboardFromApp}} @onToggle={{this.enableDriverOnboard}} @label={{t "fleet-ops.component.driver-onboard-settings.enable-driver-onboard-from-app"}} @helpText={{t "fleet-ops.component.driver-onboard-settings.enable-driver-onboard-from-app-help-text"}} />
6
+ </div>
7
+ </InputGroup>
8
+ {{#if this.driverOnboardSettings.enableDriverOnboardFromApp}}
9
+ <InputGroup @name={{t "fleet-ops.component.driver-onboard-settings.select-onboard-method"}} @helpText={{t "fleet-ops.component.driver-onboard-settings.select-onboard-method-help-text"}}>
10
+ <Select class="w-full flex-1" @value={{this.driverOnboardSettings.driverOnboardAppMethod}} @options={{this.driverOnboardMethods}} @placeholder={{t "fleet-ops.component.driver-onboard-settings.select-onboard-method"}} @onSelect={{this.selectDriverOnboardMethod}} />
11
+ </InputGroup>
12
+ <InputGroup>
13
+ <div class="flex items-center">
14
+ <Toggle @isToggled={{this.driverOnboardSettings.driverMustProvideOnboardDocuments}} @onToggle={{this.enableDriverOnboardDocuments}} @label={{t "fleet-ops.component.driver-onboard-settings.require-driver-to-upload-onboard-documents"}} @helpText={{t "fleet-ops.component.driver-onboard-settings.require-driver-to-upload-onboard-documents-help-text"}} />
15
+ </div>
16
+ </InputGroup>
17
+ {{#if this.driverOnboardSettings.driverMustProvideOnboardDocuments}}
18
+ <InputGroup>
19
+ <ArrayInput @data={{this.driverOnboardSettings.requiredOnboardDocuments}} @placeholder={{t "fleet-ops.component.driver-onboard-settings.enter-document-name"}} @onDataChanged={{this.onOnboardDocumentsChanged}} @addButtonText={{t "fleet-ops.component.driver-onboard-settings.add-onboard-document"}}>
20
+ <InputLabel @labelText={{t "fleet-ops.component.driver-onboard-settings.required-onboard-documents"}} @helpText={{t "fleet-ops.component.driver-onboard-settings.required-onboard-documents-help-text"}} />
21
+ </ArrayInput>
22
+ </InputGroup>
23
+ {{/if}}
24
+ {{/if}}
25
+ <div class="mt-3 flex items-center mb-4">
26
+ <Button @type="primary" @size="lg" @icon="save" @text={{t "fleet-ops.common.save-changes"}} @onClick={{perform this.saveDriverOnboardSettings}} @isLoading={{not this.saveDriverOnboardSettings.isIdle}} />
27
+ </div>
28
+ {{/if}}
29
+ </ContentPanel>
@@ -0,0 +1,75 @@
1
+ import Component from '@glimmer/component';
2
+ import { tracked } from '@glimmer/tracking';
3
+ import { inject as service } from '@ember/service';
4
+ import { action } from '@ember/object';
5
+ import { task } from 'ember-concurrency-decorators';
6
+
7
+ export default class DriverOnboardSettingsComponent extends Component {
8
+ @service fetch;
9
+ @service currentUser;
10
+ @tracked companyId;
11
+ @tracked driverOnboardSettingsLoaded = false;
12
+ @tracked driverOnboardSettings = {};
13
+ @tracked driverOnboardMethods = ['invite', 'button'];
14
+
15
+ constructor() {
16
+ super(...arguments);
17
+ this.companyId = this.currentUser.companyId;
18
+ this.getDriverOnboardSettings.perform();
19
+ }
20
+
21
+ @action enableDriverOnboard(enableDriverOnboardFromApp) {
22
+ this.updateDriverOnboardSettings({ enableDriverOnboardFromApp });
23
+ }
24
+
25
+ @action enableDriverOnboardDocuments(driverMustProvideOnboardDocuments) {
26
+ this.updateDriverOnboardSettings({ driverMustProvideOnboardDocuments });
27
+ }
28
+
29
+ @action selectDriverOnboardMethod(driverOnboardAppMethod) {
30
+ this.updateDriverOnboardSettings({ driverOnboardAppMethod });
31
+ }
32
+
33
+ @action onOnboardDocumentsChanged(requiredOnboardDocuments) {
34
+ requiredOnboardDocuments = requiredOnboardDocuments.filter((documentName) => typeof documentName === 'string');
35
+ this.updateDriverOnboardSettings({ requiredOnboardDocuments });
36
+ }
37
+
38
+ @task *saveDriverOnboardSettings() {
39
+ const { driverOnboardSettings } = this;
40
+ const driverOnboardSettingsResponse = yield this.fetch.post('fleet-ops/settings/driver-onboard-settings', { driverOnboardSettings });
41
+ if (driverOnboardSettings?.enableDriverOnboardFromApp == false) this.driverOnboardSettings = driverOnboardSettingsResponse?.driverOnboardSettings;
42
+ }
43
+
44
+ @task *getDriverOnboardSettings() {
45
+ const companyId = this.currentUser.companyId;
46
+ const { driverOnboardSettings } = yield this.fetch.get(`fleet-ops/settings/driver-onboard-settings/${companyId}`);
47
+ this.driverOnboardSettings = driverOnboardSettings;
48
+
49
+ if (this.companyDoesntHaveDriverOnboardSettings()) {
50
+ this.updateDriverOnboardSettings({
51
+ enableDriverOnboardFromApp: false,
52
+ driverOnboardAppMethod: 'invite',
53
+ driverMustProvideOnboardDocuments: false,
54
+ requiredOnboardDocuments: [],
55
+ });
56
+ }
57
+
58
+ this.driverOnboardSettingsLoaded = true;
59
+ }
60
+
61
+ companyDoesntHaveDriverOnboardSettings() {
62
+ const companyId = this.driverOnboardSettings.companyId;
63
+ return companyId === undefined;
64
+ }
65
+
66
+ updateDriverOnboardSettings(props = {}) {
67
+ const companyId = this.currentUser.companyId;
68
+ const driverOnboardSettings = this.driverOnboardSettings ?? {};
69
+ this.driverOnboardSettings = {
70
+ companyId: companyId,
71
+ ...driverOnboardSettings,
72
+ ...props,
73
+ };
74
+ }
75
+ }
@@ -0,0 +1,79 @@
1
+ <ContentPanel @title={{t "fleet-ops.component.entity-field-editing-settings.entitiy-field-editing-settings"}} @open={{true}} @pad={{true}} @panelBodyClass="bg-white dark:bg-gray-800 mb-4">
2
+ <OrderConfigManager @onConfigChanged={{this.onConfigChanged}} as |Action Context|>
3
+ <div>
4
+ <InputGroup
5
+ @name={{t "fleet-ops.component.entity-field-editing-settings.select-order-config"}}
6
+ @helpText={{t "fleet-ops.component.entity-field-editing-settings.select-order-config-help-text"}}
7
+ >
8
+ <DropdownButton
9
+ class="order-config-select-button mr-2"
10
+ @disabled={{not Context.configs}}
11
+ @text={{if Context.currentConfig.name Context.currentConfig.name (t "fleet-ops.component.entity-field-editing-settings.select-order-config")}}
12
+ @textClass="text-sm mr-2"
13
+ @buttonClass="flex-row-reverse w-44 justify-between"
14
+ @icon="caret-down"
15
+ @iconClass="mr-0i"
16
+ @size="sm"
17
+ @iconPrefix="fas"
18
+ @triggerClass="hidden md:flex"
19
+ as |dd|
20
+ >
21
+ <div class="next-dd-menu mt-1 mx-0" aria-labelledby="user-menu">
22
+ <div class="p-1">
23
+ {{#each Context.configs as |orderConfig|}}
24
+ <a href="javascript:;" class="next-dd-item" {{on "click" (dropdown-fn dd Context.selectConfig orderConfig)}}>
25
+ <div class="flex-1 flex flex-row items-center">
26
+ <div class="w-6">
27
+ <FaIcon @icon="cogs" />
28
+ </div>
29
+ <span>{{orderConfig.name}}</span>
30
+ </div>
31
+ <div>
32
+ {{#if (eq Context.currentConfig.id orderConfig.id)}}
33
+ <FaIcon @icon="check" class="text-green-500" />
34
+ {{/if}}
35
+ </div>
36
+ </a>
37
+ {{/each}}
38
+ </div>
39
+ </div>
40
+ </DropdownButton>
41
+ </InputGroup>
42
+ </div>
43
+ </OrderConfigManager>
44
+ {{#if this.selectedOrderConfig}}
45
+ {{#let (get this.entityEditingSettings this.selectedOrderConfig.id) as |orderConfigEntityEditingSettings|}}
46
+ <InputGroup>
47
+ <div class="flex items-center">
48
+ <Toggle
49
+ @isToggled={{orderConfigEntityEditingSettings.is_editable}}
50
+ @onToggle={{this.enableEditableEntityFields}}
51
+ @label={{t "fleet-ops.component.entity-field-editing-settings.enable-driver-to-edit-entity-fields"}}
52
+ @helpText={{t "fleet-ops.component.entity-field-editing-settings.enable-driver-to-edit-entity-fields-help-text"}}
53
+ />
54
+ </div>
55
+ </InputGroup>
56
+ {{#if orderConfigEntityEditingSettings.is_editable}}
57
+ <div class="bg-gray-400 border-gray-600 rounded-lg px-4 py-2 dark:bg-gray-700 dark:border-gray-800">
58
+ {{#let (get (get this.entityEditingSettings this.selectedOrderConfig.id) "editable_entity_fields") as |editableEntityFields|}}
59
+ {{#each this.entityFields as |entityField|}}
60
+ <div class="mt-1">
61
+ <Checkbox @value={{includes entityField editableEntityFields}} @label={{smart-humanize entityField}} @onToggle={{fn this.toggleFieldEditable entityField}} />
62
+ </div>
63
+ {{/each}}
64
+ {{/let}}
65
+ </div>
66
+ {{/if}}
67
+ <div class="mt-4 flex items-center">
68
+ <Button
69
+ @type="primary"
70
+ @size="lg"
71
+ @icon="save"
72
+ @text={{t "fleet-ops.common.save-changes"}}
73
+ @onClick={{perform this.saveEntityEditingSettings}}
74
+ @isLoading={{not this.saveEntityEditingSettings.isIdle}}
75
+ />
76
+ </div>
77
+ {{/let}}
78
+ {{/if}}
79
+ </ContentPanel>
@@ -0,0 +1,106 @@
1
+ import Component from '@glimmer/component';
2
+ import { tracked } from '@glimmer/tracking';
3
+ import { inject as service } from '@ember/service';
4
+ import { action } from '@ember/object';
5
+ import { isArray } from '@ember/array';
6
+ import { isNone } from '@ember/utils';
7
+ import { task } from 'ember-concurrency-decorators';
8
+
9
+ export default class EntityFieldEditingSettingsComponent extends Component {
10
+ @service notifications;
11
+ @service fetch;
12
+ @tracked selectedOrderConfig;
13
+ @tracked entityFields = ['name', 'description', 'sku', 'height', 'width', 'length', 'weight', 'declared_value', 'sale_price'];
14
+ @tracked entityEditingSettings = {};
15
+ @tracked settingsLoaded = false;
16
+
17
+ constructor() {
18
+ super(...arguments);
19
+ this.getEntityEditableSettings.perform();
20
+ }
21
+
22
+ @action onConfigChanged(orderConfig) {
23
+ if (!isNone(this.selectedOrderConfig) && this.orderConfigDoesntHaveSettings(orderConfig)) {
24
+ this.createSettingsForOrderConfig(orderConfig);
25
+ }
26
+ this.selectedOrderConfig = orderConfig;
27
+ }
28
+
29
+ @action enableEditableEntityFields(isEditable) {
30
+ const orderConfig = this.selectedOrderConfig;
31
+ if (orderConfig) {
32
+ if (this.orderConfigDoesntHaveSettings(orderConfig)) {
33
+ this.createSettingsForOrderConfig(orderConfig, isEditable);
34
+ } else {
35
+ const orderConfigSettings = this.entityEditingSettings[orderConfig.id] ?? {};
36
+ this.entityEditingSettings = {
37
+ ...this.entityEditingSettings,
38
+ [orderConfig.id]: {
39
+ ...orderConfigSettings,
40
+ is_editable: isEditable,
41
+ },
42
+ };
43
+ }
44
+ }
45
+ }
46
+
47
+ @action toggleFieldEditable(fieldName, isEditable) {
48
+ const editableFields = this.entityEditingSettings[this.selectedOrderConfig.id]?.editable_entity_fields;
49
+ if (isArray(editableFields)) {
50
+ if (isEditable) {
51
+ editableFields.pushObject(fieldName);
52
+ } else {
53
+ editableFields.removeObject(fieldName);
54
+ }
55
+ } else {
56
+ this.entityEditingSettings = {
57
+ ...this.entityEditingSettings,
58
+ [this.selectedOrderConfig.id]: {
59
+ ...this.entityEditingSettings[this.selectedOrderConfig.id],
60
+ editable_entity_fields: [],
61
+ },
62
+ };
63
+ return this.toggleFieldEditable(...arguments);
64
+ }
65
+
66
+ this.updateEditableEntityFieldsForOrderConfig(editableFields);
67
+ }
68
+
69
+ @task *getEntityEditableSettings() {
70
+ const { entityEditingSettings } = yield this.fetch.get('fleet-ops/settings/entity-editing-settings');
71
+ this.entityEditingSettings = entityEditingSettings;
72
+ this.settingsLoaded = true;
73
+ }
74
+
75
+ @task *saveEntityEditingSettings() {
76
+ const { entityEditingSettings } = this;
77
+ yield this.fetch.post('fleet-ops/settings/entity-editing-settings', { entityEditingSettings });
78
+ }
79
+
80
+ orderConfigDoesntHaveSettings(orderConfig) {
81
+ return isNone(this.entityEditingSettings[orderConfig.id]);
82
+ }
83
+
84
+ createSettingsForOrderConfig(orderConfig, isEditable = false) {
85
+ if (this.orderConfigDoesntHaveSettings(orderConfig)) {
86
+ this.entityEditingSettings = {
87
+ ...this.entityEditingSettings,
88
+ [orderConfig.id]: {
89
+ editable_entity_fields: [],
90
+ is_editable: isEditable,
91
+ },
92
+ };
93
+ }
94
+ }
95
+
96
+ updateEditableEntityFieldsForOrderConfig(editableFields = [], orderConfig = null) {
97
+ orderConfig = orderConfig === null ? this.selectedOrderConfig : orderConfig;
98
+ this.entityEditingSettings = {
99
+ ...this.entityEditingSettings,
100
+ [orderConfig.id]: {
101
+ ...this.entityEditingSettings[orderConfig.id],
102
+ editable_entity_fields: editableFields,
103
+ },
104
+ };
105
+ }
106
+ }
@@ -1,4 +1,4 @@
1
- <Layout::Sidebar::Panel @open={{true}} @title={{@title}} @titleIcon={{@icon}} @hideCaret={{true}} @toggleOnCaretOnly={{true}} @onClickPanelTitle={{this.transitionToRoute}} @wrapperClass="next-driver-listing">
1
+ <Layout::Sidebar::Panel @open={{true}} @title={{@title}} @titleIcon={{@icon}} @hideCaret={{true}} @toggleOnCaretOnly={{true}} @onClickPanelTitle={{this.transitionToRoute}} @wrapperClass="next-driver-listing" @dropdownButton={{this.displayPanelDropdown}} @dropdownButtonActions={{this.panelDropdownButtonActions}} @dropdownButtonRenderInPlace={{false}} @dropdownHorizontalPosition="left" @dropdownButtonMenuLabel={{t "fleet-ops.component.layout.fleet-ops-sidebar.drivers"}}>
2
2
  {{#each this.drivers as |driver|}}
3
3
  <Layout::Sidebar::Item @icon="circle" @iconSize="2xs" @iconClass={{if driver.online "text-green-500" "text-yellow-200"}} @onClick={{fn this.onDriverClicked driver}} class="driver-nav-item" @dropdownButton={{true}} @dropdownButtonActions={{this.dropdownButtonActions}} @dropdownContext={{driver}} @dropdownButtonIcon={{@itemDropdownButtonIcon}} @dropdownButtonIconPrefix={{@itemDropdownButtonIconPrefix}} @dropdownButtonText={{@itemDropdownButtonText}} @dropdownButtonCalculatePosition={{@itemDropdownButtonCalculatePosition}} @dropdownButtonRenderInPlace={{false}} @dropdownButtonMenuLabel={{driver.name}} @dropdownButtonWrapperClass={{@itemDropdownButtonWrapperClass}} @dropdownButtonTriggerClass={{@itemDropdownButtonTriggerClass}} @dropdownHorizontalPosition="left" @registerDropdownButtonAPI={{@itemRegisterDropdownButtonAPI}} @rightSideComponent={{@itemRightSideComponent}} @rightSideComponentContext={{@itemRightSideComponentContext}} @rightSideStatus={{@itemRightSideStatus}} @rightSideStatusText={{@itemRightSideStatusText}} @hideRightSideStatusDot={{@itemHideRightSideStatusDot}} @rightSideStatusClass={{@itemRightSideStatusClass}} @disableRightSideStatusHumanize={{@itemDisableRightSideStatusHumanize}}>{{driver.name}}</Layout::Sidebar::Item>
4
4
  {{/each}}
@@ -18,6 +18,18 @@ export default class LayoutFleetOpsSidebarDriverListingComponent extends Compone
18
18
  this.fetchDrivers.perform();
19
19
  }
20
20
 
21
+ displayPanelDropdown = true;
22
+
23
+ panelDropdownButtonActions = [
24
+ {
25
+ label: 'Create new driver...',
26
+ onClick: () => {
27
+ const driver = this.store.createRecord('driver');
28
+ this.contextPanel.focus(driver);
29
+ },
30
+ },
31
+ ];
32
+
21
33
  dropdownButtonActions = [
22
34
  {
23
35
  label: 'View driver details...',
@@ -9,7 +9,7 @@
9
9
  {{/if}}
10
10
  {{/each}}
11
11
  {{#each this.menuPanels as |menuPanel|}}
12
- <Layout::Sidebar::Panel @open={{menuPanel.open}} @title={{menuPanel.title}}>
12
+ <Layout::Sidebar::Panel @open={{menuPanel.open}} @title={{menuPanel.title}} @titleIcon={{menuPanel.icon}} @hideCaret={{menuPanel.hideCaret}} @toggleOnCaretOnly={{menuPanel.toggleOnCaretOnly}} @onClickPanelTitle={{menuPanel.onClickPanelTitle}} @wrapperClass={{menuPanel.wrapperClass}} @dropdownButton={{menuPanel.dropdownButton}} @dropdownButtonActions={{menuPanel.dropdownButtonActions}} @dropdownButtonRenderInPlace={{menuPanel.dropdownButtonRenderInPlace}} @dropdownHorizontalPosition={{menuPanel.dropdownHorizontalPosition}} @dropdownButtonMenuLabel={{menuPanel.dropdownButtonMenuLabel}}>
13
13
  {{#each menuPanel.items as |menuItem|}}
14
14
  {{#if menuItem.renderComponentInPlace}}
15
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}}
@@ -20,12 +20,11 @@
20
20
  </Layout::Sidebar::Panel>
21
21
  {{/each}}
22
22
  {{#each this.universeMenuPanels as |menuPanel|}}
23
- <Layout::Sidebar::Panel @open={{menuPanel.open}} @title={{menuPanel.title}}>
23
+ <Layout::Sidebar::Panel @open={{menuPanel.open}} @title={{menuPanel.title}} @titleIcon={{menuPanel.icon}} @hideCaret={{menuPanel.hideCaret}} @toggleOnCaretOnly={{menuPanel.toggleOnCaretOnly}} @onClickPanelTitle={{menuPanel.onClickPanelTitle}} @wrapperClass={{menuPanel.wrapperClass}} @dropdownButton={{menuPanel.dropdownButton}} @dropdownButtonActions={{menuPanel.dropdownButtonActions}} @dropdownButtonRenderInPlace={{menuPanel.dropdownButtonRenderInPlace}} @dropdownHorizontalPosition={{menuPanel.dropdownHorizontalPosition}} @dropdownButtonMenuLabel={{menuPanel.dropdownButtonMenuLabel}}>
24
24
  {{#each menuPanel.items as |menuItem|}}
25
25
  <Layout::Sidebar::Item @onClick={{fn this.universe.transitionMenuItem (concat this.routePrefix "virtual") menuItem}} @menuItem={{menuItem}} @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>
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> --}}
30
29
  {{yield}}
31
30
  <Spacer @height="10px" />
@@ -66,6 +66,8 @@ export default class LayoutFleetOpsSidebarComponent extends Component {
66
66
  { title: this.intl.t('fleet-ops.component.layout.fleet-ops-sidebar.issues'), icon: 'triangle-exclamation', route: 'management.issues' },
67
67
  ];
68
68
 
69
+ const settingsItems = [{ title: this.intl.t('fleet-ops.component.layout.fleet-ops-sidebar.navigator-app'), icon: 'location-arrow', route: 'settings.navigator-app' }];
70
+
69
71
  const createPanel = (title, routePrefix, items = []) => ({
70
72
  title,
71
73
  open: true,
@@ -81,6 +83,7 @@ export default class LayoutFleetOpsSidebarComponent extends Component {
81
83
  this.menuPanels = [
82
84
  createPanel(this.intl.t('fleet-ops.component.layout.fleet-ops-sidebar.operations'), 'operations', operationsItems),
83
85
  createPanel(this.intl.t('fleet-ops.component.layout.fleet-ops-sidebar.resources'), 'management', resourcesItems),
86
+ createPanel(this.intl.t('fleet-ops.component.layout.fleet-ops-sidebar.settings'), 'settings', settingsItems),
84
87
  ].filter((panel) => {
85
88
  const isVisible = panel.visible && panel.items.length > 0;
86
89
  return isVisible;
@@ -0,0 +1,3 @@
1
+ import Route from '@ember/routing/route';
2
+
3
+ export default class SettingsNavigatorAppRoute extends Route {}
@@ -0,0 +1,3 @@
1
+ import Route from '@ember/routing/route';
2
+
3
+ export default class SettingsRoute extends Route {}
package/addon/routes.js CHANGED
@@ -1,6 +1,9 @@
1
1
  import buildRoutes from 'ember-engines/routes';
2
2
 
3
3
  export default buildRoutes(function () {
4
+ this.route('settings', function () {
5
+ this.route('navigator-app');
6
+ });
4
7
  this.route('virtual', { path: '/:slug/:view' });
5
8
  this.route('operations', { path: '/' }, function () {
6
9
  this.route('dispatch');
@@ -61,6 +61,30 @@ body[data-theme='dark'] .scheduler-left-sidebar {
61
61
  padding-left: 3.5rem;
62
62
  }
63
63
 
64
+ /** content panel dropdown button */
65
+ .next-sidebar .next-sidebar-panel-container.next-driver-listing > .next-sidebar-panel > .next-content-panel > .next-content-panel-header.next-sidebar-panel-toggle {
66
+ padding-right: 0.25rem;
67
+ }
68
+
69
+ .next-sidebar
70
+ .next-sidebar-panel-container.next-driver-listing
71
+ > .next-sidebar-panel
72
+ > .next-content-panel
73
+ > .next-content-panel-header.next-sidebar-panel-toggle
74
+ .ember-basic-dropdown
75
+ button,
76
+ .next-sidebar
77
+ .next-sidebar-panel-container.next-driver-listing
78
+ > .next-sidebar-panel
79
+ > .next-content-panel
80
+ > .next-content-panel-header.next-sidebar-panel-toggle
81
+ .ember-basic-dropdown-trigger
82
+ button {
83
+ padding: 0.15rem 0.625rem;
84
+ font-size: 10px;
85
+ line-height: 0.5;
86
+ }
87
+
64
88
  .multi-drop-select-container .fleetbase-model-select.fleetbase-power-select.ember-model-select > .ember-model-select__loading {
65
89
  background: none;
66
90
  border: none;
@@ -0,0 +1,11 @@
1
+ <Layout::Section::Header @title={{t "fleet-ops.settings.navigator-app.navigator-app-settings"}} />
2
+
3
+ <Layout::Section::Body class="overflow-y-scroll h-full">
4
+ <div class="container mx-auto h-screen">
5
+ <div class="max-w-3xl my-10 mx-auto space-y-6">
6
+ <EntityFieldEditingSettings />
7
+ <DriverOnboardSettings />
8
+ </div>
9
+ </div>
10
+ <Spacer @height="600px" />
11
+ </Layout::Section::Body>
@@ -0,0 +1 @@
1
+ {{outlet}}
@@ -0,0 +1 @@
1
+ export { default } from '@fleetbase/fleetops-engine/components/driver-onboard-settings';
@@ -0,0 +1 @@
1
+ export { default } from '@fleetbase/fleetops-engine/components/entity-field-editing-settings';
@@ -0,0 +1 @@
1
+ export { default } from '@fleetbase/fleetops-engine/routes/settings/navigator-app';
@@ -0,0 +1 @@
1
+ export { default } from '@fleetbase/fleetops-engine/routes/settings';
@@ -0,0 +1 @@
1
+ export { default } from '@fleetbase/fleetops-engine/templates/settings/navigator-app';
@@ -0,0 +1 @@
1
+ export { default } from '@fleetbase/fleetops-engine/templates/settings';
package/composer.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fleetbase/fleetops-api",
3
- "version": "0.4.22",
3
+ "version": "0.4.24",
4
4
  "description": "Fleet & Transport Management Extension for Fleetbase",
5
5
  "keywords": [
6
6
  "fleetbase-extension",
@@ -22,7 +22,7 @@
22
22
  ],
23
23
  "require": {
24
24
  "php": "^8.0",
25
- "fleetbase/core-api": "^1.4.14",
25
+ "fleetbase/core-api": "^1.4.16",
26
26
  "barryvdh/laravel-dompdf": "^2.0",
27
27
  "brick/geo": "0.7.2",
28
28
  "cknow/laravel-money": "^7.1",
package/extension.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "Fleet-Ops",
3
- "version": "0.4.22",
3
+ "version": "0.4.24",
4
4
  "description": "Fleet & Transport Management Extension for Fleetbase",
5
5
  "repository": "https://github.com/fleetbase/fleetops",
6
6
  "license": "MIT",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fleetbase/fleetops-engine",
3
- "version": "0.4.22",
3
+ "version": "0.4.24",
4
4
  "description": "Fleet & Transport Management Extension for Fleetbase",
5
5
  "fleetbase": {
6
6
  "route": "fleet-ops"
@@ -43,7 +43,7 @@
43
43
  "dependencies": {
44
44
  "@babel/core": "^7.23.2",
45
45
  "@fleetbase/ember-core": "^0.2.8",
46
- "@fleetbase/ember-ui": "^0.2.11",
46
+ "@fleetbase/ember-ui": "^0.2.12",
47
47
  "@fleetbase/fleetops-data": "^0.1.14",
48
48
  "@fleetbase/leaflet-routing-machine": "^3.2.16",
49
49
  "@fortawesome/ember-fontawesome": "^0.4.1",
@@ -36,7 +36,7 @@ class FixInvalidPolymorphicRelationTypeNamespaces extends Command
36
36
  ['model' => \Fleetbase\FleetOps\Models\Order::class, 'columns' => ['customer_type', 'facilitator_type']],
37
37
  ['model' => \Fleetbase\FleetOps\Models\Place::class, 'columns' => ['owner_type']],
38
38
  ['model' => \Fleetbase\FleetOps\Models\Entity::class, 'columns' => ['customer_type']],
39
- ['model' => \Fleetbase\FleetOps\Models\PurchaseRate::class, 'columns' => ['customer_type']],
39
+ ['model' => \Fleetbase\FleetOps\Models\PurchaseRate::class, 'columns' => ['customer_type']]
40
40
  ];
41
41
 
42
42
  foreach ($models as $modelConfig) {
@@ -44,6 +44,9 @@ class DriverController extends Controller
44
44
  // get request input
45
45
  $input = $request->except(['name', 'password', 'email', 'phone', 'location', 'altitude', 'heading', 'speed', 'meta']);
46
46
 
47
+ // Add default status
48
+ $input['status'] = 'active';
49
+
47
50
  // get user details for driver
48
51
  $userDetails = $request->only(['name', 'password', 'email', 'phone', 'timezone']);
49
52
 
@@ -500,7 +503,7 @@ class DriverController extends Controller
500
503
  return response()->apiError($e->getMessage());
501
504
  }
502
505
 
503
- // $driver->update(['auth_token' => $token->plainTextToken]);
506
+ $driver->update(['auth_token' => $token->plainTextToken]);
504
507
  $driver->token = $token->plainTextToken;
505
508
 
506
509
  return new DriverResource($driver);
@@ -597,7 +600,8 @@ class DriverController extends Controller
597
600
  }
598
601
 
599
602
  // Assign user to company and update their session
600
- $user->assignCompany($company);
603
+ $user->update(['company_uuid' => $company->uuid]);
604
+
601
605
  Auth::setSession($user);
602
606
 
603
607
  return new Organization($company);
@@ -772,4 +776,4 @@ class DriverController extends Controller
772
776
 
773
777
  return $phone;
774
778
  }
775
- }
779
+ }
@@ -0,0 +1,35 @@
1
+ <?php
2
+
3
+ namespace Fleetbase\FleetOps\Http\Controllers\Api\v1;
4
+
5
+ use Fleetbase\Http\Controllers\Controller;
6
+ use Fleetbase\Models\Setting;
7
+
8
+ class NavigatorController extends Controller
9
+ {
10
+ /**
11
+ * Retrieve the driver onboard settings.
12
+ *
13
+ * This method retrieves the driver onboard settings for the current company session. If no company session
14
+ * is found in the request, an error response is returned. The method retrieves the company ID from the session,
15
+ * then fetches the saved driver onboard settings. If settings for the current company are found, they are returned,
16
+ * otherwise, default settings are provided.
17
+ *
18
+ * @return \Illuminate\Http\JsonResponse
19
+ */
20
+
21
+ /**
22
+ * Retrieve driver onboard settings.
23
+ *
24
+ * @return \Illuminate\Http\JsonResponse
25
+ */
26
+ public function getDriverOnboardSettings($companyId)
27
+ {
28
+ $driverOnboardSettings = Setting::where('key', 'fleet-ops.driver-onboard-settings.' . $companyId)->value('value');
29
+ if (!$driverOnboardSettings) {
30
+ $driverOnboardSettings = [];
31
+ }
32
+
33
+ return response()->json(['driverOnboardSettings' => $driverOnboardSettings]);
34
+ }
35
+ }
@@ -434,6 +434,7 @@ class OrderController extends Controller
434
434
  public function query(Request $request)
435
435
  {
436
436
  $results = Order::queryWithRequest($request, function (&$query, $request) {
437
+ $query->where('company_uuid', session('company'));
437
438
  if ($request->has('payload')) {
438
439
  $query->whereHas('payload', function ($q) use ($request) {
439
440
  $q->where('public_id', $request->input('payload'));
@@ -495,9 +496,9 @@ class OrderController extends Controller
495
496
  });
496
497
  }
497
498
 
498
- if ($request->has('on')) {
499
- $on = Carbon::fromString($request->input('on'));
500
-
499
+ if ($request->filled('on')) {
500
+ $on = Carbon::parse($request->input('on'));
501
+
501
502
  $query->where(function ($q) use ($on) {
502
503
  $q->whereDate('created_at', $on);
503
504
  $q->orWhereDate('scheduled_at', $on);
@@ -1401,14 +1402,10 @@ class OrderController extends Controller
1401
1402
 
1402
1403
  // Get entity editing settings
1403
1404
  $savedEntityEditingSettings = Setting::where('key', 'fleet-ops.entity-editing-settings')->value('value');
1404
-
1405
1405
  if ($orderConfigId && $savedEntityEditingSettings) {
1406
- $resolvedEntityEditingSettings = data_get($savedEntityEditingSettings, $orderConfigId, []);
1407
- if ($resolvedEntityEditingSettings) {
1408
- $entityEditingSettings = data_get($resolvedEntityEditingSettings, 'editable_entity_fields', []);
1409
- }
1406
+ $entityEditingSettings = data_get($savedEntityEditingSettings, $orderConfigId, []);
1410
1407
  }
1411
1408
 
1412
1409
  return response()->json($entityEditingSettings);
1413
1410
  }
1414
- }
1411
+ }
@@ -5,6 +5,8 @@ namespace Fleetbase\FleetOps\Http\Controllers\Api\v1;
5
5
  use Fleetbase\Http\Controllers\Controller;
6
6
  use Fleetbase\Http\Resources\Organization;
7
7
  use Fleetbase\Models\Company;
8
+ use Fleetbase\Models\Setting;
9
+ use Illuminate\Http\Request;
8
10
 
9
11
  class OrganizationController extends Controller
10
12
  {
@@ -13,15 +15,31 @@ class OrganizationController extends Controller
13
15
  *
14
16
  * @return Organization
15
17
  */
16
- public function listOrganizations()
18
+ public function listOrganizations(Request $request)
17
19
  {
18
- $companies = Company::whereHas('users')->take(10)->get()->map(function ($company) {
20
+ $limit = $request->input('limit', 10);
21
+ $withDriverOnboardEnabled = $request->boolean('with_driver_onboard');
22
+
23
+ $companies = Company::whereHas('users')->get()->map(function ($company) {
19
24
  return [
20
- 'name' => $company->name,
21
- 'id' => $company->public_id,
25
+ 'name' => $company->name,
26
+ 'uuid' => $company->uuid,
22
27
  ];
23
28
  });
24
29
 
25
- return response()->json($companies);
30
+ if ($withDriverOnboardEnabled) {
31
+ $driverOnboardSettings = Setting::where('key', 'fleet-ops.driver-onboard-settings')->value('value');
32
+
33
+ $companies = $companies->filter(function ($company) use ($driverOnboardSettings) {
34
+ return $driverOnboardSettings && isset($driverOnboardSettings[$company['uuid']]) && data_get($driverOnboardSettings[$company['uuid']], 'enableDriverOnboardFromApp') === true;
35
+ });
36
+ }
37
+
38
+ // limit
39
+ $companies = $companies->take($limit);
40
+
41
+ $companiesArray = $companies->values()->toArray();
42
+
43
+ return response()->json($companiesArray);
26
44
  }
27
45
  }
@@ -11,10 +11,4 @@ class FleetOpsController extends FleetbaseController
11
11
  * The package namespace used to resolve from.
12
12
  */
13
13
  public string $namespace = '\\Fleetbase\\FleetOps';
14
-
15
- public function test()
16
- {
17
- $order = Order::where('public_id', '')->first();
18
- dd($order->config()->getNextActivity());
19
- }
20
14
  }
@@ -6,6 +6,7 @@ use Fleetbase\Http\Controllers\Controller;
6
6
  use Fleetbase\Http\Resources\Organization;
7
7
  use Fleetbase\Models\ApiCredential;
8
8
  use Fleetbase\Models\Company;
9
+ use Fleetbase\Models\Setting;
9
10
  use Fleetbase\Models\User;
10
11
  use Illuminate\Http\Request;
11
12
  use Illuminate\Support\Str;
@@ -76,4 +77,11 @@ class NavigatorController extends Controller
76
77
 
77
78
  return new Organization($organization);
78
79
  }
80
+
81
+ public function getDriverOnboardSettings()
82
+ {
83
+ $onBoardSettings = Setting::where('key', 'fleet-ops.driver-onboard')->value('value');
84
+
85
+ return response()->json($onBoardSettings);
86
+ }
79
87
  }
@@ -48,23 +48,69 @@ class SettingController extends Controller
48
48
  return response()->json(['visibilitySettings' => $visibilitySettings]);
49
49
  }
50
50
 
51
+ /**
52
+ * Save entity editing settings.
53
+ *
54
+ * @return \Illuminate\Http\JsonResponse
55
+ */
51
56
  public function saveEntityEditingSettings(Request $request)
52
57
  {
53
58
  $entityEditingSettings = $request->input('entityEditingSettings', []);
54
- $isEntityFieldsEditable = $request->boolean('isEntityFieldsEditable');
55
59
 
56
60
  // Save entity editing settings
57
61
  Setting::configure('fleet-ops.entity-editing-settings', $entityEditingSettings);
58
- Setting::configure('fleet-ops.entity-fields-editable', $isEntityFieldsEditable);
59
62
 
60
- return response()->json(['entityEditingSettings' => $entityEditingSettings, 'isEntityFieldsEditable' => $isEntityFieldsEditable]);
63
+ return response()->json(['entityEditingSettings' => $entityEditingSettings]);
61
64
  }
62
65
 
66
+ /**
67
+ * Retrieve entity editing settings.
68
+ *
69
+ * @return \Illuminate\Http\JsonResponse
70
+ */
63
71
  public function getEntityEditingSettings()
64
72
  {
65
73
  $entityEditingSettings = Setting::where('key', 'fleet-ops.entity-editing-settings')->value('value');
66
- $isEntityFieldsEditable = Setting::where('key', 'fleet-ops.entity-fields-editable')->value('value');
74
+ if (!$entityEditingSettings) {
75
+ $entityEditingSettings = [];
76
+ }
77
+
78
+ return response()->json(['entityEditingSettings' => $entityEditingSettings]);
79
+ }
80
+
81
+ /**
82
+ * Retrieve driver onboard settings.
83
+ *
84
+ * @return \Illuminate\Http\JsonResponse
85
+ */
86
+ public function getDriverOnboardSettings($companyId)
87
+ {
88
+ $driverOnboardSettings = Setting::where('key', 'fleet-ops.driver-onboard-settings.' . $companyId)->value('value');
89
+ if (!$driverOnboardSettings) {
90
+ $driverOnboardSettings = [];
91
+ }
92
+
93
+ return response()->json(['driverOnboardSettings' => $driverOnboardSettings]);
94
+ }
95
+
96
+ /**
97
+ * Save driver onboard settings.
98
+ *
99
+ * @return \Illuminate\Http\JsonResponse
100
+ */
101
+ public function savedDriverOnboardSettings(Request $request)
102
+ {
103
+ $driverOnboardSettings = $request->input('driverOnboardSettings', []);
104
+
105
+ if ($driverOnboardSettings['enableDriverOnboardFromApp'] == false) {
106
+ $driverOnboardSettings['driverMustProvideOnboardDoucments'] = false;
107
+ $driverOnboardSettings['requiredOnboardDocuments'] = [];
108
+ $driverOnboardSettings['driverOnboardAppMethod'] = '';
109
+ $driverOnboardSettings['enableDriverOnboardFromApp'] = false;
110
+ }
111
+
112
+ Setting::configure('fleet-ops.driver-onboard-settings.' . $driverOnboardSettings['companyId'], $driverOnboardSettings);
67
113
 
68
- return response()->json(['entityEditingSettings' => $entityEditingSettings, 'isEntityFieldsEditable' => $isEntityFieldsEditable]);
114
+ return response()->json(['driverOnboardSettings' => $driverOnboardSettings]);
69
115
  }
70
116
  }
@@ -38,7 +38,7 @@ class OrderFilter extends Filter
38
38
 
39
39
  public function queryForPublic()
40
40
  {
41
- $this->builder->where('company_uuid', $this->session->get('company'))->whereHas('trackingNumber')->whereHas('payload');
41
+ $this->builder->where('company_uuid', $this->session->get('company'));
42
42
  }
43
43
 
44
44
  public function unassigned(bool $unassigned)
@@ -14,7 +14,7 @@ class CreateContactRequest extends FleetbaseRequest
14
14
  */
15
15
  public function authorize()
16
16
  {
17
- return request()->session()->has('storefront_key') || request()->session()->has('api_credential');
17
+ return request()->session()->has('storefront_key') || request()->session()->has('api_credential') || request()->session()->has('is_sanctum_token');;
18
18
  }
19
19
 
20
20
  /**
@@ -15,7 +15,7 @@ class CreateDriverRequest extends FleetbaseRequest
15
15
  */
16
16
  public function authorize()
17
17
  {
18
- return request()->is('navigator/v1/*') || request()->session()->has('api_credential');
18
+ return request()->is('navigator/v1/*') || request()->session()->has('api_credential') || request()->session()->has('is_sanctum_token');
19
19
  }
20
20
 
21
21
  /**
@@ -14,7 +14,7 @@ class CreateEntityRequest extends FleetbaseRequest
14
14
  */
15
15
  public function authorize()
16
16
  {
17
- return request()->session()->has('api_credential');
17
+ return request()->session()->has('api_credential') || request()->session()->has('is_sanctum_token');;
18
18
  }
19
19
 
20
20
  /**
@@ -6,6 +6,21 @@ use Fleetbase\Http\Requests\FleetbaseRequest;
6
6
 
7
7
  class CreateIssueRequest extends FleetbaseRequest
8
8
  {
9
+ /**
10
+ * Determine if the user is authorized to make this request.
11
+ *
12
+ * @return bool
13
+ */
14
+ public function authorize()
15
+ {
16
+ return request()->session()->has('api_credential') || request()->session()->has('is_sanctum_token');;
17
+ }
18
+
19
+ /**
20
+ * Get the validation rules that apply to the request.
21
+ *
22
+ * @return array
23
+ */
9
24
  public function rules()
10
25
  {
11
26
  return [
@@ -16,9 +16,7 @@ class CreatePlaceRequest extends FleetbaseRequest
16
16
  */
17
17
  public function authorize()
18
18
  {
19
- return request()
20
- ->session()
21
- ->has('api_credential');
19
+ return request()->session()->has('api_credential') || request()->session()->has('is_sanctum_token');;
22
20
  }
23
21
 
24
22
  /**
@@ -14,7 +14,7 @@ class CreateVehicleRequest extends FleetbaseRequest
14
14
  */
15
15
  public function authorize()
16
16
  {
17
- return request()->session()->has('api_credential');
17
+ return request()->session()->has('api_credential') || request()->session()->has('is_sanctum_token');;
18
18
  }
19
19
 
20
20
  /**
@@ -53,7 +53,7 @@ class Driver extends FleetbaseResource
53
53
  'city' => data_get($this, 'city', Utils::getCapitalCityFromCountryCode($this->country)),
54
54
  'online' => data_get($this, 'online', false),
55
55
  'status' => $this->status,
56
- 'token' => data_get($this, 'token'),
56
+ 'token' => $this->auth_token,
57
57
  'meta' => $this->meta,
58
58
  'updated_at' => $this->updated_at,
59
59
  'created_at' => $this->created_at,
@@ -851,8 +851,8 @@ class Utils extends FleetbaseUtils
851
851
  * Calculates driving distance and time between two points using Vincenty's formula.
852
852
  * Returns distance in meters and time in seconds.
853
853
  *
854
- * @param \Fleetbase\FleetOps\Models\Place|\Fleetbase\LaravelMysqlSpatial\Types\Point|array $origin
855
- * @param \Fleetbase\FleetOps\Models\Place|\Fleetbase\LaravelMysqlSpatial\Types\Point|array $destination
854
+ * @param \Fleetbase\FleetOps\Models\Place|Point|array $origin
855
+ * @param \Fleetbase\FleetOps\Models\Place|Point|array $destination
856
856
  */
857
857
  public static function calculateDrivingDistanceAndTime($origin, $destination): DistanceMatrix
858
858
  {
@@ -870,8 +870,8 @@ class Utils extends FleetbaseUtils
870
870
  * Calculates driving distance and time between two points using Vincenty's formula.
871
871
  * Returns distance in meters and time in seconds.
872
872
  *
873
- * @param \Fleetbase\FleetOps\Models\Place|\Fleetbase\LaravelMysqlSpatial\Types\Point|array $origin
874
- * @param \Fleetbase\FleetOps\Models\Place|\Fleetbase\LaravelMysqlSpatial\Types\Point|array $destination
873
+ * @param \Fleetbase\FleetOps\Models\Place|Point|array $origin
874
+ * @param \Fleetbase\FleetOps\Models\Place|Point|array $destination
875
875
  */
876
876
  public static function getPreliminaryDistanceMatrix($origin, $destination): DistanceMatrix
877
877
  {
@@ -179,6 +179,11 @@ Route::prefix(config('fleetops.api.routing.prefix', null))->namespace('Fleetbase
179
179
  $router->group(['prefix' => 'labels'], function () use ($router) {
180
180
  $router->get('{id}', 'LabelController@getLabel');
181
181
  });
182
+
183
+ // navigator routes
184
+ $router->group(['prefix' => 'onboard'], function () use ($router) {
185
+ $router->get('driver-onboard-settings/{companyId}', 'NavigatorController@getDriverOnboardSettings');
186
+ });
182
187
  });
183
188
 
184
189
  /*
@@ -435,6 +440,8 @@ Route::prefix(config('fleetops.api.routing.prefix', null))->namespace('Fleetbase
435
440
  $router->post('visibility', 'SettingController@saveVisibilitySettings');
436
441
  $router->get('entity-editing-settings', 'SettingController@getEntityEditingSettings');
437
442
  $router->post('entity-editing-settings', 'SettingController@saveEntityEditingSettings');
443
+ $router->post('driver-onboard-settings', 'SettingController@savedDriverOnboardSettings');
444
+ $router->get('driver-onboard-settings/{companyId}', 'SettingController@getDriverOnboardSettings');
438
445
  }
439
446
  );
440
447
  $router->group(
@@ -94,7 +94,6 @@ fleet-ops:
94
94
  total: Total
95
95
  back: Back
96
96
  done: Done
97
-
98
97
  component:
99
98
  activity-logic-builder:
100
99
  activity-logic: Activity Logic
@@ -238,7 +237,11 @@ fleet-ops:
238
237
  message: Use this URL to link the official Navigator app to this {companyName} instance. Opening this URL on a mobile device will open the Navigator app and update it's configuration and branding.
239
238
  settings: Entity Settings
240
239
  select-input: Allow driver to update entity details
241
-
240
+ driver-settings: Driver Settings
241
+ description: Enable driver on-board
242
+ upload-document: Require driver to upload documents
243
+ upload-body: Add documents
244
+ document: Document
242
245
  visibility-controls:
243
246
  title: Visibility Controls
244
247
  message: Visibility controls allow you to disable sections of Fleet-Ops. Toggle the checkbox to enable or disable sections to hide in Fleet-ops.
@@ -249,6 +252,25 @@ fleet-ops:
249
252
  vehicles : Vehicles
250
253
  drivers : Drivers
251
254
  places : Places
255
+ entity-field-editing-settings:
256
+ entitiy-field-editing-settings: Entity Field Editing Settings
257
+ entity-field-editing-settings-help-text: These settings determine which fields of an entity are editable by a driver via Navigator App
258
+ select-order-config: Select Order Config
259
+ select-order-config-help-text: Select an order config which these settings will apply to
260
+ enable-driver-to-edit-entity-fields: Allow driver to edit entity details
261
+ enable-driver-to-edit-entity-fields-help-text: Enabling this toggle grants the driver permission to modify specific entity fields chosen below.
262
+ driver-onboard-settings:
263
+ driver-onboard-settings: Driver Onboard Settings
264
+ enable-driver-onboard-from-app: Enable driver onboard from Navigator App
265
+ enable-driver-onboard-from-app-help-text: Enabling this setting allows drivers to independently onboard (create their own account) via the Navigator App.
266
+ select-onboard-method: Select driver onboard method
267
+ select-onboard-method-help-text: This setting determines how drivers are permitted to create their accounts through the Navigator App. Choose 'Invite' if drivers need to receive an email invitation to create their account. Select 'Button' if you wish to enable a button within the app that allows anyone to create a driver account.
268
+ require-driver-to-upload-onboard-documents: Require driver to upload onboard documents
269
+ require-driver-to-upload-onboard-documents-help-text: This setting enforces documents that a driver must provide before their account can be created.
270
+ required-onboard-documents: Required onboard documents
271
+ required-onboard-documents-help-text: Input all the onboard documents required for a driver to provide below using the "Add onboard document" button.
272
+ enter-document-name: Enter document name
273
+ add-onboard-document: Add onboard document
252
274
  cell:
253
275
  driver-name:
254
276
  not-assigned: No driver assigned
@@ -265,6 +287,7 @@ fleet-ops:
265
287
  loading-vehicle: Loading fleet vehicles...
266
288
  layout:
267
289
  fleet-ops-sidebar:
290
+ navigator-app: Navigator App
268
291
  resources: Resources
269
292
  operations: Operations
270
293
  dashboard: Dashboard
@@ -1511,4 +1534,6 @@ fleet-ops:
1511
1534
  zone-label: Zone
1512
1535
  zone-help-text: Restrict this service to order request originating from a specific zone.
1513
1536
  zone-placeholder: Restrict to zone
1514
-
1537
+ settings:
1538
+ navigator-app:
1539
+ navigator-app-settings: Navigator App Settings