Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions addon/components/admin/tracking-page-settings.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<ContentPanel @title="Generic Tracking Page" @open={{true}} @wrapperClass="bordered-classic">
<div class="space-y-5">
<div class="flex items-start justify-between gap-4">
<div>
<div class="text-sm font-semibold">Enable the generic tracking page</div>
<div class="text-xs text-gray-600 dark:text-gray-300">Serves /track for every organization that allows it. Organizations can also run their own page from their Fleet-Ops settings.</div>
</div>
<Toggle @isToggled={{this.genericEnabled}} @onToggle={{fn (mut this.genericEnabled)}} />
</div>
<div>
<label for="admin-tracking-page-name" class="block text-sm font-semibold mb-1">Display name</label>
<input id="admin-tracking-page-name" type="text" class="form-input w-full" value={{this.displayName}} {{on "input" (fn this.setValue "displayName")}} />
<p class="mt-1 text-xs text-gray-600 dark:text-gray-300">Shown before a lookup. The logo comes from the instance branding.</p>
</div>
<div>
<label for="admin-tracking-page-accent" class="block text-sm font-semibold mb-1">Accent colour</label>
<div class="flex items-center gap-3">
<input id="admin-tracking-page-accent" type="color" class="h-10 w-14 rounded-md border border-gray-300 dark:border-gray-700 bg-transparent cursor-pointer" value={{this.accent}} {{on "input" (fn this.setValue "accent")}} />
<span class="font-mono text-sm">{{this.accent}}</span>
</div>
</div>
<div class="grid grid-cols-1 md:grid-cols-3 gap-4">
<div>
<label for="admin-tracking-page-phone" class="block text-sm font-semibold mb-1">Support phone</label>
<input id="admin-tracking-page-phone" type="tel" class="form-input w-full" value={{this.supportPhone}} {{on "input" (fn this.setValue "supportPhone")}} />
</div>
<div>
<label for="admin-tracking-page-email" class="block text-sm font-semibold mb-1">Support email</label>
<input id="admin-tracking-page-email" type="email" class="form-input w-full" value={{this.supportEmail}} {{on "input" (fn this.setValue "supportEmail")}} />
</div>
<div>
<label for="admin-tracking-page-website" class="block text-sm font-semibold mb-1">Website</label>
<input id="admin-tracking-page-website" type="url" class="form-input w-full" value={{this.website}} {{on "input" (fn this.setValue "website")}} />
</div>
</div>
<div class="flex items-start justify-between gap-4">
<div>
<div class="text-sm font-semibold">Show "Powered by Fleetbase"</div>
<div class="text-xs text-gray-600 dark:text-gray-300">The default for organizations that haven't chosen.</div>
</div>
<Toggle @isToggled={{this.poweredBy}} @onToggle={{fn (mut this.poweredBy)}} />
</div>
</div>
</ContentPanel>

<EmberWormhole @to="next-view-section-subheader-actions">
<Button
@type="primary"
@size="sm"
@icon="save"
@text="Save Changes"
@onClick={{perform this.saveSettings}}
@isLoading={{or this.saveSettings.isRunning this.loadSettings.isRunning}}
@disabled={{this.saveSettings.isRunning}}
/>
</EmberWormhole>
67 changes: 67 additions & 0 deletions addon/components/admin/tracking-page-settings.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import Component from '@glimmer/component';
import { inject as service } from '@ember/service';
import { tracked } from '@glimmer/tracking';
import { action } from '@ember/object';
import { task } from 'ember-concurrency';

/**
* Instance-wide defaults for the generic customer tracking page: whether it is on, and the
* branding it shows before a lookup (and for companies without their own).
*/
export default class AdminTrackingPageSettingsComponent extends Component {
@service fetch;
@service notifications;
@tracked genericEnabled = true;
@tracked displayName = '';
@tracked accent = '#1F5FA8';
@tracked supportPhone = '';
@tracked supportEmail = '';
@tracked website = '';
@tracked poweredBy = true;

constructor() {
super(...arguments);
this.loadSettings.perform();
}

@task *loadSettings() {
try {
const settings = yield this.fetch.get('fleet-ops/settings/admin-tracking-page-settings');
this.genericEnabled = settings?.generic_page?.enabled ?? true;
this.displayName = settings?.branding?.display_name ?? '';
this.accent = settings?.branding?.accent ?? '#1F5FA8';
this.supportPhone = settings?.branding?.support_phone ?? '';
this.supportEmail = settings?.branding?.support_email ?? '';
this.website = settings?.branding?.website ?? '';
this.poweredBy = settings?.branding?.powered_by ?? true;
} catch (error) {
this.notifications.serverError(error);
}
}

@action setValue(property, event) {
this[property] = event.target.value;
}

@task *saveSettings() {
try {
yield this.fetch.post('fleet-ops/settings/admin-tracking-page-settings', {
trackingPage: {
generic_page: { enabled: this.genericEnabled },
branding: {
display_name: this.displayName,
accent: this.accent,
support_phone: this.supportPhone,
support_email: this.supportEmail,
website: this.website,
powered_by: this.poweredBy,
},
},
});

this.notifications.success('Tracking page defaults saved.');
} catch (error) {
this.notifications.serverError(error);
}
}
}
14 changes: 11 additions & 3 deletions addon/components/layout/fleet-ops-sidebar.js
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,13 @@ export default class LayoutFleetOpsSidebarComponent extends Component {
this.createItem('menu.routing', 'route', 'settings.routing', 'fleet-ops view routing-settings', 'fleet-ops see routing-settings'),
this.createItem('menu.orchestrator', 'circle-nodes', 'settings.orchestrator', 'fleet-ops view routing-settings', 'fleet-ops see routing-settings'),
this.createItem('menu.scheduling', 'calendar-days', 'settings.scheduling', 'fleet-ops view scheduling-settings', 'fleet-ops see scheduling-settings'),
this.createItem(
'tracking-page.settings.menu',
'magnifying-glass-location',
'settings.tracking-page',
'fleet-ops view tracking-page-settings',
'fleet-ops see tracking-page-settings'
),
this.createItem('menu.telematics-settings', 'satellite-dish', 'settings.telematics', 'fleet-ops view telematics-settings', 'fleet-ops see telematics-settings'),
this.createItem('menu.custom-fields', 'pen-to-square', 'settings.custom-fields', 'fleet-ops list custom-field', 'fleet-ops see custom-field'),
this.createItem('menu.avatars', 'icons', 'settings.avatars', 'fleet-ops list avatar', 'fleet-ops see avatar'),
Expand Down Expand Up @@ -406,9 +413,10 @@ export default class LayoutFleetOpsSidebarComponent extends Component {
'settings.routing': 5,
'settings.orchestrator': 6,
'settings.scheduling': 7,
'settings.telematics': 8,
'settings.custom-fields': 9,
'settings.avatars': 10,
'settings.tracking-page': 8,
'settings.telematics': 9,
'settings.custom-fields': 10,
'settings.avatars': 11,
};

return priorities[route] ?? 0;
Expand Down
21 changes: 21 additions & 0 deletions addon/components/tracking-page/settings-preview.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<div class="tp-preview" style={{this.style}} aria-hidden="true">
<div class="tp-preview-header">
<span class="tp-preview-monogram">{{this.monogram}}</span>
<span class="tp-preview-name">{{@displayName}}</span>
</div>
<div class="tp-preview-body">
<span class="tp-preview-chip">{{t "tracking-page.settings.preview-chip"}}</span>
<div class="tp-preview-headline">{{t "tracking-page.settings.preview-headline"}}</div>
<div class="tp-preview-sub">{{t "tracking-page.settings.preview-sub"}}</div>
<div class="tp-preview-steps">
<span class="tp-preview-step tp-preview-step-done"></span>
<span class="tp-preview-step tp-preview-step-done"></span>
<span class="tp-preview-step tp-preview-step-done"></span>
<span class="tp-preview-step"></span>
</div>
<span class="tp-preview-button">{{t "tracking-page.settings.preview-button"}}</span>
</div>
{{#if @poweredBy}}
<div class="tp-preview-footer">{{t "tracking-page.settings.preview-powered-by"}}</div>
{{/if}}
</div>
23 changes: 23 additions & 0 deletions addon/components/tracking-page/settings-preview.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import Component from '@glimmer/component';
import { htmlSafe } from '@ember/template';

/**
* A small phone-sized preview of the customer tracking page, themed from the settings being edited.
*/
export default class TrackingPageSettingsPreviewComponent extends Component {
get style() {
return htmlSafe(this.args.themeStyle ?? '');
}

get monogram() {
const words = (this.args.displayName ?? '').split(/\s+/);
let monogram = '';
for (const word of words) {
if (word && monogram.length < 2) {
monogram += word[0].toUpperCase();
}
}

return monogram;
}
}
6 changes: 6 additions & 0 deletions addon/controllers/settings/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ export default class SettingsIndexController extends Controller {
description: 'Keep commerce, metadata, and visual conventions aligned.',
links: [
{ label: 'Payments', route: 'settings.payments', icon: 'cash-register', description: 'Payment setup for operational commerce workflows.' },
{
label: 'Tracking Page',
route: 'settings.tracking-page',
icon: 'magnifying-glass-location',
description: 'The page your customers use to follow deliveries: address, branding and how they verify.',
},
{
label: 'Telematics',
route: 'settings.telematics',
Expand Down
Loading
Loading