@fleetbase/dev-engine
Version:
Fleetbase Developers extension provides a module for managing developer resources such as API keys, webhooks, sockets, events and logs.
348 lines (319 loc) • 11.3 kB
JavaScript
import BaseController from '../base-controller';
import { tracked } from '@glimmer/tracking';
import { inject as service } from '@ember/service';
import { action, computed } from '@ember/object';
import { isBlank } from '@ember/utils';
import { timeout } from 'ember-concurrency';
import { task } from 'ember-concurrency-decorators';
import groupApiEvents from '@fleetbase/ember-core/utils/group-api-events';
import fromStore from '@fleetbase/ember-core/decorators/legacy-from-store';
import fetchFrom from '@fleetbase/ember-core/decorators/legacy-fetch-from';
export default class WebhooksIndexController extends BaseController {
currentUser;
intl;
modalsManager;
notifications;
store;
fetch;
hostRouter;
abilities;
/**
* Group api events by resource
*
* @var {Object}
*/
get groupedApiEvents() {
return groupApiEvents(this.webhookEvents);
}
/**
* The current page of data being viewed
*
* @var {Integer}
*/
page = 1;
/**
* The maximum number of items to show per page
*
* @var {Integer}
*/
limit;
/**
* The param to sort the data on, the param with prepended `-` is descending
*
* @var {String}
*/
sort;
/**
* The param to sort the data on, the param with prepended `-` is descending
*
* @var {String}
*/
query;
/**
* Queryable parameters for this controller's model
*
* @var {Array}
*/
queryParams = ['page', 'limit', 'sort', 'query'];
/**
* All webhook events
*
* @memberof WebhooksIndexController
* @var {Array}
*/
webhookEvents;
/**
* All api versions
*
* @memberof WebhooksIndexController
* @var {Array}
*/
apiVersions;
/**
* All api credentials.
*
* @memberof WebhooksIndexController
*/
apiCredentials;
/**
* Columns for table component.
*
* @var {Array}
*/
columns = [
{
label: this.intl.t('developers.common.url'),
valuePath: 'url',
width: '40%',
sortable: false,
cellComponent: 'table/cell/link-to',
permission: 'developers view webhook',
route: 'webhooks.view',
cellClassNames: 'no-underline',
},
{
label: this.intl.t('developers.common.status'),
valuePath: 'status',
width: '15%',
sortable: false,
cellComponent: 'table/cell/status',
},
{
label: this.intl.t('developers.common.mode'),
valuePath: 'mode',
width: '15%',
sortable: false,
cellComponent: 'table/cell/status',
},
{ label: this.intl.t('developers.common.version'), valuePath: 'version', width: '10%', sortable: false },
{ label: this.intl.t('developers.common.created'), valuePath: 'createdAt', sortable: false, width: '10%' },
{
label: '',
cellComponent: 'table/cell/dropdown',
ddButtonText: false,
ddButtonIcon: 'ellipsis-h',
ddButtonIconPrefix: 'fas',
ddMenuLabel: 'API Key Actions',
cellClassNames: 'overflow-visible',
wrapperClass: 'flex items-center justify-end mx-2',
width: '10%',
align: 'right',
actions: [
{
label: this.intl.t('developers.webhooks.index.view-logs'),
fn: this.viewWebhook,
permission: 'developers view webhook',
},
{
label: this.intl.t('developers.webhooks.index.edit-webhook'),
fn: this.editWebhook,
permission: 'developers update webhook',
},
{
label: this.intl.t('developers.webhooks.index.delete-webhook'),
fn: this.deleteWebhook,
permission: 'developers delete webhook',
},
],
sortable: false,
filterable: false,
resizable: false,
searchable: false,
},
];
/**
* The search task.
*
* @void
*/
*search({ target: { value } }) {
// if no query don't search
if (isBlank(value)) {
this.query = null;
return;
}
// timeout for typing
yield timeout(250);
// reset page for results
if (this.page > 1) {
this.page = 1;
}
// update the query param
this.query = value;
}
/**
* Toggles modal to create a new API key
*
* @void
*/
createWebhook() {
const formPermission = 'developers create webhook';
const webhook = this.store.createRecord('webhook-endpoint', {
events: [],
mode: this.currentUser.getOption('sandbox') ? 'test' : 'live',
});
this.editWebhook(webhook, {
title: this.intl.t('developers.webhooks.index.add-webhook'),
acceptButtonText: this.intl.t('developers.webhooks.index.add-webhook-button-text'),
acceptButtonIcon: 'check',
acceptButtonIconPrefix: 'fas',
acceptButtonDisabled: this.abilities.cannot(formPermission),
acceptButtonHelpText: this.abilities.cannot(formPermission) ? this.intl.t('common.unauthorized') : null,
formPermission,
webhook,
confirm: async (modal) => {
modal.startLoading();
if (this.abilities.cannot(formPermission)) {
return this.notifications.warning(this.intl.t('common.permissions-required-for-changes'));
}
try {
await webhook.save();
this.notifications.success(this.intl.t('developers.webhooks.index.new-webhook-success-message'));
return this.hostRouter.refresh();
} catch (error) {
this.notifications.serverError(error);
modal.stopLoading();
}
},
});
}
/**
* Triggers dialog to edit webhook
*
* @param {WebhookEndpointModel} webhook
* @param {Object} options
* @void
*/
async editWebhook(webhook, options = {}) {
await this.apiCredentials;
const formPermission = 'developers update webhook';
this.modalsManager.show('modals/webhook-form', {
title: this.intl.t('developers.webhooks.index.edit-webhook-endpoint'),
acceptButtonText: this.intl.t('developers.webhooks.index.edit-webhook-endpoint-button-text'),
acceptButtonIcon: 'save',
acceptButtonDisabled: this.abilities.cannot(formPermission),
acceptButtonHelpText: this.abilities.cannot(formPermission) ? this.intl.t('common.unauthorized') : null,
formPermission,
declineButtonIcon: 'times',
declineButtonIconPrefix: 'fas',
eventOptions: this.groupedApiEvents,
versionOptions: this.apiVersions,
apiCredentialOptions: this.apiCredentials,
webhook,
setVersion: ({ target }) => {
webhook.version = target.value || null;
},
setApiCredential: ({ target }) => {
webhook.api_credential_uuid = target.value || null;
},
searchEvents: (query) => {
if (typeof query !== 'string') {
return;
}
const resources = Object.keys(this.groupedApiEvents);
const filteredEvents = {};
resources.forEach((eventResource) => {
filteredEvents[eventResource] = this.groupedApiEvents[eventResource].filter((event) => {
return event.toLowerCase().includes(query.toLowerCase());
});
// if 0 events remove from filter
if (filteredEvents[eventResource].length === 0) {
delete filteredEvents[eventResource];
}
});
this.modalsManager.setOption('eventOptions', filteredEvents);
},
addEvent: (event) => {
if (webhook.events.includes(event)) {
return;
}
webhook.events.pushObject(event);
},
removeEvent: (event) => {
webhook.events.removeObject(event);
},
clearEvents: () => {
webhook.events.clear();
},
receiveAllEvents: () => {
webhook.events.pushObjects(this.webhookEvents);
},
confirm: async (modal) => {
modal.startLoading();
if (this.abilities.cannot(formPermission)) {
return this.notifications.warning(this.intl.t('common.permissions-required-for-changes'));
}
try {
await webhook.save();
this.notifications.success(this.intl.t('developers.webhooks.index.new-webhook-success-message'));
return this.hostRouter.refresh();
} catch (error) {
this.notifications.serverError(error);
modal.stopLoading();
}
},
...options,
});
}
/**
* Toggles dialog to delete webhook
*
* @param {WebhookEndpointModel} webhook
* @param {Object} options
* @void
*/
deleteWebhook(webhook, options = {}) {
this.modalsManager.confirm({
title: this.intl.t('developers.webhooks.index.delete-webhook-endpoint'),
body: this.intl.t('developers.webhooks.index.delete-webhook-endpoint-body'),
confirm: async (modal) => {
modal.startLoading();
try {
await webhook.destroyRecord();
this.notifications.success(this.intl.t('developers.webhooks.index.delete-webhook-success-message'));
return this.hostRouter.refresh();
} catch (error) {
this.notifications.serverError(error);
modal.stopLoading();
}
},
...options,
});
}
/**
* Transition to view the webhook
*
* @param {WebhookEndpointModel} webhook
* @return {Transition<Promise>}
* @memberof WebhooksIndexController
*/
viewWebhook(webhook) {
return this.hostRouter.transitionTo('console.developers.webhooks.view', webhook);
}
/**
* Reload data.
*/
reload() {
return this.hostRouter.refresh();
}
}