Skip to content

Commit

Permalink
Merge pull request #88 from fleetbase/dev-v0.4.17
Browse files Browse the repository at this point in the history
v0.4.17
  • Loading branch information
roncodes authored Mar 11, 2024
2 parents fd68f8f + 3af3ab4 commit bd8fc66
Show file tree
Hide file tree
Showing 242 changed files with 7,836 additions and 1,904 deletions.
2 changes: 2 additions & 0 deletions .php-cs-fixer.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

$finder = PhpCsFixer\Finder::create()
->in(__DIR__ . DIRECTORY_SEPARATOR . 'server' . DIRECTORY_SEPARATOR . 'tests')
->in(__DIR__ . DIRECTORY_SEPARATOR . 'server' . DIRECTORY_SEPARATOR . 'seeders')
->in(__DIR__ . DIRECTORY_SEPARATOR . 'server' . DIRECTORY_SEPARATOR . 'migrations')
->in(__DIR__ . DIRECTORY_SEPARATOR . 'server' . DIRECTORY_SEPARATOR . 'src')
->append(['.php-cs-fixer.php']);

Expand Down
1 change: 1 addition & 0 deletions .stylelintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ module.exports = {
extends: ['stylelint-config-standard', 'stylelint-prettier/recommended'],
rules: {
'selector-class-pattern': null,
'no-descending-specificity': null,
'color-function-notation': null,
},
};
35 changes: 35 additions & 0 deletions addon/components/activity-event-selector.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<div class="activity-event-selector rounded-lg bg-gray-50 dark:bg-gray-800 border border-gray-200 dark:border-gray-700" ...attributes>
<div class="activity-event-selector-actions flex flex-row items-center justify-between px-4 py-2">
<div>
<div class="text-sm font-semibold">{{t "fleet-ops.component.activity-event-selector.activity-events"}}</div>
<Attach::Tooltip @class="clean" @animation="scale" @placement="top">
<InputInfo @text={{t "fleet-ops.component.activity-event-selector.activity-events"}} />
</Attach::Tooltip>
</div>
<div></div>
</div>
<div class="activity-event-selector-events-container">
<div class="px-4 mb-2">
<DropdownButton @text={{t "fleet-ops.component.activity-event-selector.select-event-to-add"}} @buttonClass="flex-row-reverse justify-between w-48" @icon="caret-down" @iconClass="mr-0i" @size="sm" @iconPrefix="fas" @triggerClass="hidden md:flex" @helpText={{t "fleet-ops.component.activity-event-selector.activity-events-select-events-info"}} as |dd|>
<div class="next-dd-menu mt-1 mx-0" aria-labelledby="user-menu">
<div class="p-1 overflow-y-scroll h-40">
{{#each-in this.availableEvents as |eventName event|}}
<a href="javascript:;" class="next-dd-item" {{on "click" (dropdown-fn dd this.addEvent eventName)}}>
<div class="py-0.5">
<div class="text-sm font-mono font-semibold mb-0.5">{{eventName}}</div>
<div class="text-xs">{{event.description}}</div>
</div>
</a>
{{/each-in}}
</div>
</div>
</DropdownButton>
</div>
{{#each this.events as |eventName index|}}
<div class="activity-event-selector-event">
<span>{{eventName}}</span>
<Button @type="danger" @icon="trash" @size="xs" @onClick={{fn this.removeEvent index}} />
</div>
{{/each}}
</div>
</div>
85 changes: 85 additions & 0 deletions addon/components/activity-event-selector.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';
import { action } from '@ember/object';
import contextComponentCallback from '../utils/context-component-callback';
import getWithDefault from '@fleetbase/ember-core/utils/get-with-default';

/**
* `ActivityEventSelectorComponent` manages the selection of events associated with an activity.
* It allows adding and removing events from a list of tracked events, and updating the context when changes occur.
*
* @extends Component
*
* @property {Array} events - The list of events currently selected for the activity.
* @property {Object} availableEvents - An object representing available events, each with a name and description.
*
* @example
* // To use this component, pass in an activity with a pre-defined list of events (if any):
* <ActivityEventSelectorComponent @activity={{this.activity}} />
*/
export default class ActivityEventSelectorComponent extends Component {
/**
* The list of events currently selected for the activity.
* This is a tracked property, and changes to it will update the component's template.
*
* @type {Array}
*/
@tracked events = [];

/**
* An object representing available events, each with a name and description.
* This property defines the events that can be selected for an activity.
*
* @type {Object}
*/
availableEvents = {
'order.dispatched': {
name: 'order.dispatched',
description: 'Triggers when an order is successfully dispatched.',
},
'order.failed': {
name: 'order.failed',
description: 'Triggers when an order fails due to an error or exception.',
},
'order.canceled': {
name: 'order.canceled',
description: 'Triggers when an order is canceled by a user, driver, or system process.',
},
};

/**
* Constructor for the component. Initializes the component's tracked events.
* @param {Object} owner - The owner of the component.
* @param {Object} args - Arguments passed to the component, should include `activity`.
*/
constructor(owner, { activity }) {
super(...arguments);
this.events = getWithDefault(activity, 'events', []);
}

/**
* Adds a new event to the list of tracked events.
* @param {Object} event - The event to add.
*/
@action addEvent(event) {
this.events = [event, ...this.events];
this.update();
}

/**
* Removes an event from the list of tracked events.
* @param {number} index - The index of the event to remove.
*/
@action removeEvent(index) {
this.events = this.events.filter((_, i) => i !== index);
this.update();
}

/**
* Triggers the contextComponentCallback with the updated list of events.
* This method is typically used to inform a parent component or context of the changes.
*/
@action update() {
contextComponentCallback(this, 'onChange', this.events);
}
}
23 changes: 23 additions & 0 deletions addon/components/activity-form-panel.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<Overlay @onLoad={{this.setOverlayContext}} @onOpen={{this.onOpen}} @onClose={{this.onClose}} @onToggle={{this.onToggle}} @position="right" @noBackdrop={{true}} @fullHeight={{true}} @isResizable={{or this.isResizable @isResizable}} @width={{or this.width @width "570px"}}>
<Overlay::Header @title={{if this.activity.status (concat (t "fleet-ops.component.activity-form-panel.title-concat") this.activity.status) (t "fleet-ops.component.activity-form-panel.new-activity-title") }} @hideStatusDot={{true}} @titleWrapperClass="leading-5">
<div class="flex flex-1 justify-end">
<Button @type="primary" @icon="save" @text={{t "common.save"}} @onClick={{this.save}} @wrapperClass="mr-2" />
<Button @type="default" @icon="times" @text={{t "fleet-ops.common.cancel"}} @onClick={{this.onPressCancel}} />
</div>
</Overlay::Header>

<Overlay::Body @wrapperClass="px-4 pt-4">
<InputGroup @name={{t "fleet-ops.component.activity-form-panel.key"}} @value={{this.activity.key}} @helpText={{t "fleet-ops.component.activity-form-panel.key-help"}} {{on "input" this.setActivityKey}} />
<InputGroup @name={{t "fleet-ops.component.activity-form-panel.code"}} @value={{this.activity.code}} @helpText={{t "fleet-ops.component.activity-form-panel.code-help"}} {{on "input" this.setActivityCode}} />
<InputGroup @name={{t "fleet-ops.component.activity-form-panel.status"}} @value={{this.activity.status}} @helpText={{t "fleet-ops.component.activity-form-panel.status-help"}} />
<InputGroup @name={{t "fleet-ops.component.activity-form-panel.details"}} @value={{this.activity.details}} @helpText={{t "fleet-ops.component.activity-form-panel.details-help"}} />
<InputGroup>
<Toggle @isToggled={{this.activity.complete}} @onToggle={{fn (mut this.activity.complete)}}>
<span class="dark:text-gray-100 text-sm ml-2">{{t "fleet-ops.component.activity-form-panel.completes-order"}}</span>
</Toggle>
</InputGroup>
<ActivityLogicBuilder @activity={{this.activity}} @onChange={{this.updateActivityLogic}} class="mb-4" />
<ActivityEventSelector @activity={{this.activity}} @onChange={{this.updateActivityEvents}} />
<Spacer @height="300px" />
</Overlay::Body>
</Overlay>
90 changes: 90 additions & 0 deletions addon/components/activity-form-panel.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';
import { action } from '@ember/object';
import { underscore, capitalize, w } from '@ember/string';
import contextComponentCallback from '../utils/context-component-callback';
import applyContextComponentArguments from '../utils/apply-context-component-arguments';

/**
* Component class for managing activity forms.
* This component facilitates the creation and editing of activities,
* allowing the setting of activity codes, keys, logic, and events.
*
* @extends Component
*/
export default class ActivityFormPanelComponent extends Component {
/**
* Tracked property for the activity being edited or created.
* @tracked
*/
@tracked activity;

/**
* Tracked property for the target activity, if applicable.
* @tracked
*/
@tracked targetActivity;

/**
* Constructor for ActivityFormPanelComponent.
* Applies context component arguments upon instantiation.
*/
constructor() {
super(...arguments);
applyContextComponentArguments(this);
}

/**
* Action method to save the activity. It triggers an optional onSave callback
* with the current state of the activity.
* @action
*/
@action save() {
contextComponentCallback(this, 'onSave', this.customEntity);
if (typeof this.onSave === 'function') {
this.onSave(this.activity);
}
}

/**
* Action method to set the activity code. It uses the underscore function to format
* the code and updates the status by capitalizing each word.
* @param {Event} event - The event object containing the new activity code.
* @action
*/
@action setActivityCode(event) {
const value = event.target.value;
const code = underscore(value);
this.activity.set('code', code);
this.activity.set('status', w(value.replace(/_/g, ' ')).map(capitalize).join(' '));
}

/**
* Action method to set the activity key. It converts the key to an underscored string.
* @param {Event} event - The event object containing the new activity key.
* @action
*/
@action setActivityKey(event) {
const value = event.target.value;
const key = underscore(value);
this.activity.set('key', key);
}

/**
* Action method to update the logic associated with the activity.
* @param {Array} logic - An array representing the activity logic.
* @action
*/
@action updateActivityLogic(logic = []) {
this.activity.set('logic', logic);
}

/**
* Action method to update the events associated with the activity.
* @param {Array} events - An array of events linked to the activity.
* @action
*/
@action updateActivityEvents(events = []) {
this.activity.set('events', events);
}
}
80 changes: 80 additions & 0 deletions addon/components/activity-logic-builder.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<div class="activity-logic-builder rounded-lg bg-gray-50 dark:bg-gray-800 border border-gray-200 dark:border-gray-700" ...attributes>
<div class="activity-logic-builder-actions flex flex-row items-center justify-between px-4 py-2">
<div>
<div class="text-sm font-semibold">{{t "fleet-ops.component.activity-logic-builder.activity-logic"}}</div>
<Attach::Tooltip @class="clean" @animation="scale" @placement="top">
<InputInfo @text={{t "fleet-ops.component.activity-logic-builder.activity-logic-help-text"}} />
</Attach::Tooltip>
</div>
<div>
<Button @type="magic" @icon="plus" @text={{t "fleet-ops.component.activity-logic-builder.add-logic"}} @onClick={{this.addLogic}} @helpText={{t "fleet-ops.component.activity-logic-builder.activity-logic-add-logic-help-text"}} />
</div>
</div>
<div class="activity-logic-builder-logic-container">
{{#each this.logic as |logic index|}}
<div class="activity-logic-builder-logic">
<div class="activity-logic-builder-condition-type-container space-x-2">
<DropdownButton @text={{smart-humanize logic.type}} @buttonClass="activity-logic-builder-condition-type flex-row-reverse justify-between" @icon="caret-down" @iconClass="mr-0i" @size="sm" @iconPrefix="fas" @triggerClass="hidden md:flex" @helpText={{t "fleet-ops.component.activity-logic-builder.activity-logic-select-logic-type-help-text"}} as |dd|>
<div class="next-dd-menu mt-1 mx-0" aria-labelledby="user-menu">
<div class="p-1 overflow-y-scroll h-40">
{{#each this.types as |type|}}
<a href="javascript:;" class="next-dd-item" {{on "click" (dropdown-fn dd this.selectLogicType type index)}}>
<div class="py-0.5">
<div class="text-sm font-semibold mb-0.5">{{smart-humanize type.type}}</div>
<div class="text-xs">{{type.description}}</div>
</div>
</a>
{{/each}}
</div>
</div>
</DropdownButton>
<Button class="activity-logic-builder-add-condition" @type="default" @size="xs" @icon="plus" @text="Add condition" @onClick={{fn this.addCondition index}} @helpText={{t "fleet-ops.component.activity-logic-builder.activity-logic-add-condition-help-text"}} />
<Button class="activity-logic-builder-add-condition" @type="danger" @size="xs" @icon="trash" @onClick={{fn this.removeLogic index}} />
</div>
<div class="activity-logic-builder-conditions">
{{#if logic.type}}
<div class="space-y-2">
{{#each logic.conditions as |condition conditionIndex|}}
<div class="flex flex-row">
<div class="activity-logic-builder-condition">
<div class="activity-logic-builder-condition-field">
<Input placeholder={{t "fleet-ops.component.activity-logic-builder.field"}} class="form-input" @value={{condition.field}} {{on "blur" this.trackConditionInputChanges}} />
</div>
<div class="activity-logic-builder-condition-operator">
{{#let (get this.operators condition.operator) as |operatorMap|}}
<DropdownButton @text={{operatorMap.symbol}} @textClass="text-xs" @buttonClass="flex-row-reverse justify-between" @icon="caret-down" @iconClass="mr-0i" @size="sm" @iconPrefix="fas" @triggerClass="hidden md:flex" as |dd|>
<div class="next-dd-menu mt-1 mx-0" aria-labelledby="user-menu">
<div class="p-1">
{{#each-in this.operators as |key|}}
<a href="javascript:;" class="next-dd-item" {{on "click" (dropdown-fn dd this.selectConditionOperator index conditionIndex key)}}>
<div class="flex-1 flex flex-row items-center">
<span>{{smart-humanize key}}</span>
</div>
<div>
{{#if (eq key condition.operator)}}
<FaIcon @icon="check" class="text-green-500" />
{{/if}}
</div>
</a>
{{/each-in}}
</div>
</div>
</DropdownButton>
{{/let}}
</div>
<div class="activity-logic-builder-condition-value">
<Input placeholder={{t "fleet-ops.component.activity-logic-builder.value"}} class="form-input" @value={{condition.value}} {{on "blur" this.trackConditionInputChanges}} />
</div>
</div>
<div class="px-1">
<Button @type="danger" @icon="trash" @onClick={{fn this.removeCondition index conditionIndex}} />
</div>
</div>
{{/each}}
</div>
{{/if}}
</div>
</div>
{{/each}}
</div>
</div>
Loading

0 comments on commit bd8fc66

Please sign in to comment.