Skip to content

Commit f0bbf9c

Browse files
authored
Merge pull request #172 from fleetbase/dev-v0.6.20
v0.6.20 ~ made improvements to order board, added filter by order type
2 parents 6144f0c + 4638cfd commit f0bbf9c

18 files changed

Lines changed: 921 additions & 223 deletions

File tree

addon/components/order/kanban.hbs

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1-
<Kanban
2-
@columns={{this.columns}}
3-
@onCardMove={{this.handleCardMove}}
4-
@headerOffset={{@headerOffset}}
5-
@columnIdPath="status"
6-
@subject="order"
7-
@cardTemplate="order/kanban-card"
8-
@onCreateCard={{transition-to "operations.orders.index.new"}}
9-
...attributes
10-
/>
1+
<div {{did-update this.handleArgsChange @orderConfig @orders}}>
2+
<Kanban
3+
@columns={{this.columns}}
4+
@onCardMove={{this.handleCardMove}}
5+
@headerOffset={{@headerOffset}}
6+
@columnIdPath="status"
7+
@subject="order"
8+
@cardTemplate="order/kanban-card"
9+
@onCreateCard={{transition-to "operations.orders.index.new"}}
10+
...attributes
11+
/>
12+
</div>

addon/components/order/kanban.js

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,16 @@ import { isArray } from '@ember/array';
66
import { debug } from '@ember/debug';
77
import { task } from 'ember-concurrency';
88
import titleize from 'ember-cli-string-helpers/utils/titleize';
9+
import smartHumanize from '@fleetbase/ember-ui/utils/smart-humanize';
10+
import isUuid from '@fleetbase/ember-core/utils/is-uuid';
911

1012
export default class OrderKanbanComponent extends Component {
1113
@service fetch;
1214
@service notifications;
1315
@service intl;
1416
@tracked statuses = [];
1517
@tracked orders = this.args.orders ?? [];
18+
@tracked orderConfig = this.args.orderConfig ?? null;
1619

1720
#defaultStatuses = {
1821
start: ['created', 'dispatched', 'started'],
@@ -48,7 +51,7 @@ export default class OrderKanbanComponent extends Component {
4851

4952
return final.map((status, index) => ({
5053
id: status,
51-
title: titleize(status),
54+
title: titleize(smartHumanize(status)),
5255
position: index,
5356
cards: this.#getOrdersByStatus(status, this.orders),
5457
}));
@@ -96,13 +99,34 @@ export default class OrderKanbanComponent extends Component {
9699
}
97100
}
98101

102+
@action handleArgsChange(el, [orderConfig, orders = []]) {
103+
if (isArray(orders)) {
104+
this.orders = orders;
105+
}
106+
107+
if (isUuid(orderConfig)) {
108+
this.orderConfig = orderConfig;
109+
} else {
110+
this.orderConfig = null;
111+
}
112+
this.loadStatuses.perform();
113+
}
114+
99115
#getOrdersByStatus(status, orders = []) {
100-
return orders.filter((order) => order.status === status);
116+
let filteredOrders = orders.filter((order) => order.status === status);
117+
if (this.orderConfig) {
118+
filteredOrders = filteredOrders.filter((order) => order.order_config_uuid === this.orderConfig);
119+
}
120+
121+
return filteredOrders;
101122
}
102123

103124
@task *loadStatuses() {
125+
const params = {};
126+
if (this.orderConfig) params.order_config_uuid = this.orderConfig;
127+
104128
try {
105-
const statuses = yield this.fetch.get('orders/statuses');
129+
const statuses = yield this.fetch.get('orders/statuses', params);
106130
this.statuses = isArray(statuses) ? statuses : [];
107131
} catch (err) {
108132
debug('Unable to load order statuses: ' + err.message);

addon/controllers/operations/orders/index.js

Lines changed: 50 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -63,57 +63,62 @@ export default class OperationsOrdersIndexController extends Controller {
6363
@tracked without_driver;
6464
@tracked status;
6565
@tracked type;
66+
@tracked orderConfig;
6667
@tracked bulkSearchValue = '';
6768
@tracked bulk_query = '';
6869
@tracked layout = 'map';
6970

7071
/** action buttons */
71-
@tracked actionButtons = [
72-
{
73-
icon: 'refresh',
74-
onClick: this.orderActions.refresh,
75-
helpText: this.intl.t('common.refresh'),
76-
},
77-
{
78-
text: this.intl.t('common.new'),
79-
type: 'primary',
80-
icon: 'plus',
81-
onClick: this.orderActions.transition.create,
82-
},
83-
{
84-
text: this.intl.t('common.export'),
85-
icon: 'long-arrow-up',
86-
iconClass: 'rotate-icon-45',
87-
wrapperClass: 'hidden md:flex',
88-
onClick: this.orderActions.export,
89-
},
90-
];
72+
get actionButtons() {
73+
return [
74+
{
75+
icon: 'refresh',
76+
onClick: this.orderActions.refresh,
77+
helpText: this.intl.t('common.refresh'),
78+
},
79+
{
80+
text: this.intl.t('common.new'),
81+
type: 'primary',
82+
icon: 'plus',
83+
onClick: this.orderActions.transition.create,
84+
},
85+
{
86+
text: this.intl.t('common.export'),
87+
icon: 'long-arrow-up',
88+
iconClass: 'rotate-icon-45',
89+
wrapperClass: 'hidden md:flex',
90+
onClick: this.orderActions.export,
91+
},
92+
];
93+
}
9194

9295
/** bulk actions */
93-
@tracked bulkActions = [
94-
{
95-
label: this.intl.t('common.cancel-resource', { resource: this.intl.t('resource.orders') }),
96-
icon: 'ban',
97-
fn: this.orderActions.bulkCancel,
98-
},
99-
{
100-
label: this.intl.t('common.delete-resource', { resource: this.intl.t('resource.orders') }),
101-
icon: 'trash',
102-
class: 'text-red-500',
103-
fn: this.orderActions.bulkDelete,
104-
},
105-
{ separator: true },
106-
{
107-
label: this.intl.t('common.dispatch-orders'),
108-
icon: 'rocket',
109-
fn: this.orderActions.bulkDispatch,
110-
},
111-
{
112-
label: this.intl.t('common.assign-driver'),
113-
icon: 'user-plus',
114-
fn: this.orderActions.bulkAssignDriver,
115-
},
116-
];
96+
get bulkActions() {
97+
return [
98+
{
99+
label: this.intl.t('common.cancel-resource', { resource: this.intl.t('resource.orders') }),
100+
icon: 'ban',
101+
fn: this.orderActions.bulkCancel,
102+
},
103+
{
104+
label: this.intl.t('common.delete-resource', { resource: this.intl.t('resource.orders') }),
105+
icon: 'trash',
106+
class: 'text-red-500',
107+
fn: this.orderActions.bulkDelete,
108+
},
109+
{ separator: true },
110+
{
111+
label: this.intl.t('common.dispatch-orders'),
112+
icon: 'rocket',
113+
fn: this.orderActions.bulkDispatch,
114+
},
115+
{
116+
label: this.intl.t('common.assign-driver'),
117+
icon: 'user-plus',
118+
fn: this.orderActions.bulkAssignDriver,
119+
},
120+
];
121+
}
117122

118123
/** columns */
119124
get columns() {
@@ -366,7 +371,7 @@ export default class OperationsOrdersIndexController extends Controller {
366371
ddButtonText: false,
367372
ddButtonIcon: 'ellipsis-h',
368373
ddButtonIconPrefix: 'fas',
369-
ddMenuLabel: this.intl.t('common.resource-actions', { resource: this.intl.t('resource.Order') }),
374+
ddMenuLabel: this.intl.t('common.resource-actions', { resource: this.intl.t('resource.order') }),
370375
cellClassNames: 'overflow-visible',
371376
wrapperClass: 'flex items-center justify-end mx-2',
372377
width: '12%',

addon/controllers/operations/orders/index/new.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,10 @@ export default class OperationsOrdersIndexNewController extends Controller {
6666
this.universe.trigger('fleet-ops.order.creating', order);
6767

6868
// Save custom field values
69-
const { created: customFieldValues } = yield order.cfManager.saveTo(order);
70-
order.custom_field_values.pushObjects(customFieldValues);
69+
if (order.cfManager) {
70+
const { created: customFieldValues } = yield order.cfManager.saveTo(order);
71+
order.custom_field_values.pushObjects(customFieldValues);
72+
}
7173

7274
// Save order
7375
const createdOrder = yield order.save();

addon/routes/operations/orders/index.js

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,6 @@ export default class OperationsOrdersIndexRoute extends Route {
3030
before: { refreshModel: true },
3131
type: { refreshModel: true },
3232
layout: { refreshModel: false },
33-
drawerOpen: { refreshModel: false },
34-
drawerTab: { refreshModel: false },
35-
orderPanelOpen: { refreshModel: false },
3633
};
3734

3835
model(params) {

addon/services/order-creation.js

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import Service, { inject as service } from '@ember/service';
22
import { tracked } from '@glimmer/tracking';
3-
import { later } from '@ember/runloop';
3+
import { next } from '@ember/runloop';
44

55
export default class OrderCreationService extends Service {
66
@service orderActions;
@@ -12,13 +12,9 @@ export default class OrderCreationService extends Service {
1212
const order = this.orderActions.createNewInstance(attrs);
1313
this.order = order;
1414

15-
later(
16-
this,
17-
() => {
18-
this.addContext('order', order);
19-
},
20-
0
21-
);
15+
next(() => {
16+
this.addContext('order', order);
17+
});
2218

2319
return order;
2420
}

addon/services/order-validation.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ export default class OrderValidationService extends Service {
2323
const hasWaypoints = order.payload.waypoints.length >= 2;
2424
const hasPickup = isNotEmpty(order.payload.pickup);
2525
const hasDropoff = isNotEmpty(order.payload.dropoff);
26-
const hasValidCustomFields = cfManager ? this.isCustomFieldsValid(cfManager) : false;
26+
const hasValidCustomFields = cfManager ? this.isCustomFieldsValid(cfManager) : true;
2727

2828
if (hasWaypoints) {
2929
return hasOrderConfig && hasOrderType && hasValidCustomFields;
@@ -37,13 +37,13 @@ export default class OrderValidationService extends Service {
3737
}
3838

3939
validateCustomFields(cfManager) {
40-
if (!cfManager) return false;
40+
if (!cfManager) return true;
4141

4242
return cfManager.validateRequired();
4343
}
4444

4545
isCustomFieldsValid(cfManager) {
46-
if (!cfManager) return false;
46+
if (!cfManager) return true;
4747

4848
const { isValid } = this.validateCustomFields(cfManager);
4949
return isValid;

addon/styles/fleetops-engine.css

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1654,3 +1654,38 @@ button.fleetops-btn-xxs,
16541654
padding-top: 0.2rem !important;
16551655
padding-bottom: 0.2rem !important;
16561656
}
1657+
1658+
/** css fix for operations index/kanban */
1659+
main.console-fleet-ops-operations-orders-index-index section.next-view-section {
1660+
max-width: 100vw;
1661+
min-width: 0;
1662+
}
1663+
1664+
main.console-fleet-ops-operations-orders-index-index section.next-view-section > .next-view-section-container {
1665+
display: flex;
1666+
flex-direction: column;
1667+
max-width: 100vw;
1668+
min-width: 0;
1669+
}
1670+
1671+
main.console-fleet-ops-operations-orders-index-index section.next-view-section > .next-view-section-container > .next-view-section-subheader {
1672+
flex: 0 0 auto;
1673+
width: 100%;
1674+
}
1675+
1676+
main.console-fleet-ops-operations-orders-index-index section.next-view-section > .next-view-section-container > .next-view-section-body {
1677+
flex: 1 1 auto;
1678+
min-width: 0;
1679+
overflow: auto;
1680+
}
1681+
1682+
main.console-fleet-ops-operations-orders-index-index section.next-view-section > .next-view-section-container > .next-view-section-body > .kanban-board {
1683+
display: flex;
1684+
}
1685+
1686+
.next-view-section-subheader .next-view-section-subheader-actions .order-board-type-filter.ember-power-select-trigger.ember-basic-dropdown-trigger {
1687+
height: 2rem;
1688+
align-items: center;
1689+
padding-left: 0.5rem;
1690+
padding-right: 2rem;
1691+
}

addon/templates/operations/orders/index.hbs

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,33 @@
5353
{{/if}}
5454

5555
{{#if (eq this.layout "kanban")}}
56-
<Layout::Section::Header @title={{t "menu.order-board"}} @actionsWrapperClass="space-x-1" />
56+
<Layout::Section::Header @title={{t "menu.order-board"}} @subtitle={{@model.length}} @subtitleClass="text-xs text-center font-semibold ml-2 w-6 h-6 rounded-full bg-blue-100 text-blue-900 dark:bg-blue-900 dark:text-blue-100 flex items-center justify-center" @actionsWrapperClass="space-x-1">
57+
<div class="flex flex-row items-center space-x-2">
58+
<div class="w-64">
59+
<div class="fleetbase-model-select fleetbase-power-select ember-model-select">
60+
<ModelSelect
61+
@modelName="order-config"
62+
@selectedModel={{or this.orderConfig this.type}}
63+
@placeholder={{t "order.fields.order-type-placeholder"}}
64+
@triggerClass="form-select form-input order-board-type-filter"
65+
@infiniteScroll={{false}}
66+
@renderInPlace={{true}}
67+
@allowClear={{true}}
68+
@onChange={{fn (mut this.orderConfig)}}
69+
@onChangeId={{fn (mut this.type)}}
70+
as |orderConfig|
71+
>
72+
<div class="text-sm">
73+
<div class="font-semibold normalize-in-trigger">{{orderConfig.name}}</div>
74+
<div class="hide-from-trigger">{{n-a orderConfig.description}}</div>
75+
</div>
76+
</ModelSelect>
77+
</div>
78+
</div>
79+
</div>
80+
</Layout::Section::Header>
5781
<Layout::Section::Body>
58-
<Order::Kanban @orders={{@model}} @headerOffset={{160}} />
82+
<Order::Kanban @orders={{@model}} @headerOffset={{160}} @orderConfig={{this.type}} />
5983
</Layout::Section::Body>
6084
{{/if}}
6185

addon/utils/setup-customer-portal.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import { setOwner } from '@ember/application';
44
import { debug } from '@ember/debug';
55

66
export default function setupCustomerPortal(app, engine, universe) {
7+
if (!customerPortalInstalled(app)) return;
8+
79
universe.afterBoot(function (u) {
810
const portal = u.getEngineInstance('@fleetbase/customer-portal-engine');
911
if (!portal) {
@@ -58,3 +60,8 @@ function createEngineBoundComponent(engineInstance, ComponentClass) {
5860
}
5961
};
6062
}
63+
64+
function customerPortalInstalled(app) {
65+
const extensions = app.extensions ?? [];
66+
return extensions.find(({ name }) => name === '@fleetbase/customer-portal-engine');
67+
}

0 commit comments

Comments
 (0)