Skip to content
Open
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
13 changes: 11 additions & 2 deletions RELEASE.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
> v0.2.16 ~ "API key and webhook dialogs open from anywhere"
> v0.2.17 ~ "Extensions can add columns, actions and buttons to developer pages"

---
## Highlights

- **API key and webhook dialogs are reusable services.** New `api-key-actions` and `webhook-actions` services hold the create, edit and delete dialogs that lived in the index controllers, so other engines can open them — Fleetbase AI uses this to open **New API Key** and **New Webhook** from its confirmation cards. The Developers pages delegate to the same services, so they behave as before. ([#46](https://github.com/fleetbase/dev-engine/pull/46))
- **Resource view registries.** Extensions can add the following for `api-key`, `webhook`, `event`, `log` and `socket`:
- columns, row actions, bulk actions and toolbar buttons, through `developers:table:<resource>:<slot>`;
- header buttons and menu items on the detail pages, through `developers:details:<resource>:<slot>`.
- **API keys, webhooks, events, logs and sockets use the standard table layout.**
- **Fix: search on the events and logs pages was always disabled.**

---
## Upgrading
Needs fleetbase/ember-core v0.3.25 and fleetbase/ember-ui v0.4.5.

---
## Need help?
- [GitHub Discussions](https://github.com/fleetbase/fleetbase/discussions)
- [Discord](https://discord.gg/HnTqQ6zAVn)
---
58 changes: 57 additions & 1 deletion addon/controllers/api-keys/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export default class ApiKeysIndexController extends Controller {
*
* @var {Array}
*/
queryParams = ['page', 'limit', 'sort', 'query', 'view_api_key'];
queryParams = this.apiKeyActions.queryParamsFor(['page', 'limit', 'sort', 'query', 'view_api_key']);

/**
* Expiration options for api keys
Expand Down Expand Up @@ -105,13 +105,58 @@ export default class ApiKeysIndexController extends Controller {
return this.currentUser.getOption('testKey');
}

/**
* Header buttons. Extensions add to them through `developers:api-key:table:actions`.
*
* @var {Array}
*/
get actionButtons() {
return [
{
id: 'create',
type: 'primary',
icon: 'plus',
iconPrefix: 'fas',
text: this.intl.t('developers.common.new'),
onClick: this.createApiKey,
permission: 'developers create api-key',
},
{
id: 'export',
icon: 'long-arrow-up',
iconClass: 'rotate-icon-45',
text: this.intl.t('developers.common.export'),
onClick: this.exportApiKeys,
permission: 'developers export api-key',
},
];
}

/**
* Bulk actions for the selected rows. Extensions add to them through `developers:api-key:table:bulk-actions`.
*
* @var {Array}
*/
get bulkActions() {
return [
{
id: 'bulk-delete',
label: this.intl.t('developers.api-keys.index.delete-api'),
class: 'text-red-500',
fn: this.bulkDeleteApiCredentials,
permission: 'developers delete api-key',
},
];
}

/**
* Columns for table component.
*
* @var {Array}
*/
@tracked columns = [
{
id: 'name',
sticky: true,
label: this.intl.t('developers.common.name'),
valuePath: 'name',
Expand All @@ -122,13 +167,15 @@ export default class ApiKeysIndexController extends Controller {
sortable: false,
},
{
id: 'key',
label: this.intl.t('developers.api-keys.index.public-key'),
valuePath: 'key',
sortable: false,
resizable: true,
cellComponent: 'click-to-copy',
},
{
id: 'secret',
label: this.intl.t('developers.api-keys.index.secret-key'),
valuePath: 'secret',
sortable: false,
Expand All @@ -141,13 +188,15 @@ export default class ApiKeysIndexController extends Controller {
},
},
{
id: 'environment',
label: this.intl.t('developers.api-keys.index.enviroment'),
valuePath: 'environment',
sortable: false,
resizable: true,
cellComponent: 'table/cell/status',
},
{
id: 'expires-at',
label: this.intl.t('developers.api-keys.index.expiry'),
valuePath: 'expiresAt',
sortable: false,
Expand All @@ -156,6 +205,7 @@ export default class ApiKeysIndexController extends Controller {
cellClassNames: 'overflow-visible',
},
{
id: 'last-used',
label: this.intl.t('developers.api-keys.index.last-used'),
valuePath: 'lastUsed',
sortable: false,
Expand All @@ -164,6 +214,7 @@ export default class ApiKeysIndexController extends Controller {
cellClassNames: 'overflow-visible',
},
{
id: 'created-at',
label: this.intl.t('developers.common.created'),
valuePath: 'createdAt',
sortable: false,
Expand All @@ -172,6 +223,7 @@ export default class ApiKeysIndexController extends Controller {
cellClassNames: 'overflow-visible',
},
{
id: 'row-actions',
label: '',
cellComponent: 'table/cell/dropdown',
ddButtonText: false,
Expand All @@ -185,21 +237,25 @@ export default class ApiKeysIndexController extends Controller {
width: 60,
actions: [
{
id: 'edit-api-key',
label: this.intl.t('developers.api-keys.index.edit-key'),
fn: this.editApiKey,
permission: 'developers view api-key',
},
{
id: 'roll-api-key',
label: this.intl.t('developers.api-keys.index.roll-key'),
fn: this.rollApiKey,
permission: 'developers roll api-key',
},
{
id: 'view-request-logs',
label: this.intl.t('developers.api-keys.index.view-logs'),
fn: this.viewRequestLogs,
permission: 'developers view log',
},
{
id: 'delete-api-key',
label: this.intl.t('developers.api-keys.index.delete-key'),
fn: this.deleteApiKey,
className: 'text-red-700 hover:text-red-800',
Expand Down
27 changes: 27 additions & 0 deletions addon/controllers/base-controller.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import Controller from '@ember/controller';
import { inject as service } from '@ember/service';
import { action } from '@ember/object';
import { getOwner } from '@ember/application';
import lookupResourceView, { mergeHeaderButtons } from '@fleetbase/ember-ui/utils/resource-view';

export default class BaseController extends Controller {
/**
Expand Down Expand Up @@ -28,4 +30,29 @@ export default class BaseController extends Controller {
@action transitionToRoute(route, ...args) {
return this.universe.transitionToEngineRoute('@fleetbase/dev-engine', route, ...args);
}

/**
* The query params an index controller declares, plus the filter params of
* columns extensions registered under `developers:<resource>:table`.
*
* @param {String} resource e.g. 'event'
* @param {Array} baseQueryParams
* @returns {Array}
*/
registeredQueryParams(resource, baseQueryParams = []) {
return lookupResourceView(getOwner(this))?.queryParamsFor('developers', resource, baseQueryParams) ?? baseQueryParams;
}

/**
* A details page's header buttons, with what extensions registered under
* `developers:<resource>:details` merged in.
*
* @param {String} resource e.g. 'webhook'
* @param {Object} record The record the page shows
* @param {Array} buttons The page's own buttons
* @returns {Array}
*/
detailsActionButtons(resource, record, buttons = []) {
return mergeHeaderButtons(lookupResourceView(getOwner(this)), `developers:${resource}:details`, buttons, { resource: record, controller: this }, { withMenu: true });
}
}
6 changes: 5 additions & 1 deletion addon/controllers/events/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export default class EventsIndexController extends BaseController {
*
* @var {Array}
*/
queryParams = ['query', 'page', 'limit', 'sort', 'event', 'created_at'];
queryParams = this.registeredQueryParams('event', ['query', 'page', 'limit', 'sort', 'event', 'created_at']);

/**
* The current page of data being viewed
Expand Down Expand Up @@ -77,12 +77,14 @@ export default class EventsIndexController extends BaseController {
*/
@tracked columns = [
{
id: 'description',
sticky: true,
label: this.intl.t('developers.common.event'),
valuePath: 'description',
sortable: false,
},
{
id: 'event',
label: this.intl.t('developers.common.code'),
valuePath: 'event',
sortable: false,
Expand All @@ -91,13 +93,15 @@ export default class EventsIndexController extends BaseController {
filterOptions: this.webhookEvents,
},
{
id: 'public-id',
label: this.intl.t('developers.common.id'),
valuePath: 'public_id',
cellComponent: 'click-to-copy',
align: 'right',
sortable: false,
},
{
id: 'created-at',
label: this.intl.t('developers.common.date'),
valuePath: 'createdAt',
filterParam: 'created_at',
Expand Down
18 changes: 16 additions & 2 deletions addon/controllers/events/view.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,21 @@
import Controller from '@ember/controller';
import BaseController from '../base-controller';
import { inject as service } from '@ember/service';
import { action } from '@ember/object';

export default class EventsViewController extends Controller {
export default class EventsViewController extends BaseController {
@service intl;

/**
* Header buttons. Extensions add to them through `developers:event:details`.
*
* @var {Array}
*/
get actionButtons() {
return this.detailsActionButtons('event', this.model, [
{ id: 'back', icon: 'long-arrow-left', iconPrefix: 'fas', text: this.intl.t('developers.common.back'), onClick: this.goBack },
]);
}

@action goBack() {
return window.history.back();
}
Expand Down
9 changes: 8 additions & 1 deletion addon/controllers/logs/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export default class LogsIndexController extends BaseController {
*
* @var {Array}
*/
queryParams = ['query', 'page', 'limit', 'sort', 'version', 'key', 'method', 'created_at'];
queryParams = this.registeredQueryParams('log', ['query', 'page', 'limit', 'sort', 'version', 'key', 'method', 'created_at']);

/**
* The current page of data being viewed
Expand Down Expand Up @@ -100,26 +100,30 @@ export default class LogsIndexController extends BaseController {
@computed('apiCredentials.@each.id', 'apiVersions.[]') get columns() {
return [
{
id: 'description',
sticky: true,
label: this.intl.t('developers.common.description'),
valuePath: 'description',
sortable: false,
},
{
id: 'status',
label: this.intl.t('developers.common.status'),
valuePath: 'status',
sortable: false,
cellComponent: 'table/cell/status',
cellClassNames: 'uppercase',
},
{
id: 'public-id',
label: this.intl.t('developers.common.id'),
valuePath: 'public_id',
cellComponent: 'click-to-copy',
align: 'right',
sortable: false,
},
{
id: 'api-credential-name',
label: this.intl.t('developers.logs.index.api-credential'),
valuePath: 'api_credential_name',
cellComponent: 'click-to-copy',
Expand All @@ -132,20 +136,23 @@ export default class LogsIndexController extends BaseController {
filterOptions: this.apiCredentials,
},
{
id: 'method',
label: this.intl.t('developers.logs.index.http-method'),
valuePath: 'method',
filterable: true,
filterComponent: 'filter/multi-option',
filterOptions: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'],
},
{
id: 'version',
label: this.intl.t('developers.common.version'),
valuePath: 'version',
filterable: true,
filterComponent: 'filter/select',
filterOptions: this.apiVersions,
},
{
id: 'created-at',
label: this.intl.t('developers.common.date'),
valuePath: 'createdAt',
filterParam: 'created_at',
Expand Down
16 changes: 14 additions & 2 deletions addon/controllers/logs/view.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,19 @@
import Controller from '@ember/controller';
import BaseController from '../base-controller';
import { inject as service } from '@ember/service';
import { action } from '@ember/object';

export default class LogsViewController extends Controller {
export default class LogsViewController extends BaseController {
@service intl;

/**
* Header buttons. Extensions add to them through `developers:log:details`.
*
* @var {Array}
*/
get actionButtons() {
return this.detailsActionButtons('log', this.model, [{ id: 'back', icon: 'long-arrow-left', iconPrefix: 'fas', text: this.intl.t('developers.common.back'), onClick: this.goBack }]);
}

@action goBack() {
return window.history.back();
}
Expand Down
20 changes: 20 additions & 0 deletions addon/controllers/sockets/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,25 @@ export default class SocketsIndexController extends BaseController {
@service hostRouter;
@service abilities;

/**
* Header buttons. Extensions add to them through `developers:socket:table:actions`.
*
* @var {Array}
*/
get actionButtons() {
return [
{
id: 'listen-on-custom-channel',
type: 'magic',
icon: 'headphones',
iconPrefix: 'fas',
text: this.intl.t('developers.sockets.index.button-text'),
onClick: this.listenOnCustomChannel,
permission: 'developers view socket',
},
];
}

/**
* All columns applicable for orders
*
Expand All @@ -32,6 +51,7 @@ export default class SocketsIndexController extends BaseController {
cellClassNames: 'no-underline',
},
{
id: 'name',
label: this.intl.t('developers.sockets.index.channel'),
valuePath: 'name',
width: '88%',
Expand Down
Loading
Loading