import { Config, Controller, HTTPError, HTTPStatus, Inject, Injectable, Logging, Maybe, ResponseObject, Routing, SecurityContext, view, } from '@extollo/lib' import {User} from '../../models/User.model' import {one} from '@extollo/lib/lib/http/response/api' import {ResourceAction, ResourceConfiguration} from '../../cobalt' @Injectable() export class Dash2 extends Controller { @Inject() protected readonly logging!: Logging @Inject() protected readonly routing!: Routing @Inject() protected readonly security!: SecurityContext @Inject() protected readonly config!: Config public async index(): Promise { return view('dash2:home', { title: 'Home', ...(await this.appData()), }) } public async cobalt(): Promise { return view('dash2:cobalt', { ...(await this.appData()), }) } public async cobaltSettings(): Promise { const layout = this.request.safe('layoutname').string() const params: Record = this.request.input('params') as any || {} if ( layout === 'resource:form' && typeof params.resource === 'string' ) { return this.getResourceFormSettings(params.resource, params) } if ( layout === 'resource:list' && typeof params.resource === 'string' ) { return this.getResourceListSettings(params.resource, params) } return one({ layout, params, }) } public async cobaltResourceList(): Promise { return view('dash2:cobalt', { ...(await this.appData()), layout: 'resource:list', params: { resource: this.request.safe('key').string() }, }) } private async getResourceListSettings(resourceName: string, params: Record): Promise { const config = this.getResourceConfigOrFail(resourceName) return one({ actions: { top: [ { type: 'navigate', route: `/dash2/cobalt/resource/${resourceName}/form`, title: 'Create New', color: '#94AE89', icon: 'fa-solid fa-plus', }, ], inline: [ { type: 'navigate', route: `/dash2/cobalt/resource/${resourceName}/form`, title: 'Open', color: '#50808E', icon: 'fa-solid fa-eye', // fixme: gather }, { type: 'route', route: `/dash2/cobalt/resource/${resourceName}/form`, method: 'delete', title: 'Delete', color: '#B02E0C', icon: 'fa-solid fa-trash-can', // fixme: gather }, ], }, loadActions: [ { target: { sourceName: `resource:list:${resourceName}`, }, action: { type: 'route', method: 'GET', route: `/dash/cobalt/resource/${resourceName}`, successKey: 'success', resultKey: 'data', }, }, ], layoutChildren: [ { component: 'table', config: { sourceName: `resource:list:${resourceName}`, rowKey: 'records', fields: config.fields, }, }, ], }) } private async getResourceFormSettings(resourceName: string, params: Record): Promise { const config = this.getResourceConfigOrFail(resourceName) return one({ layoutChildren: [ { component: 'card', config: { display: config.display.singular, }, layoutChildren: [ { component: 'form', sourceName: `resource:form:${resourceName}`, layoutChildren: config.fields .filter(f => !f.hideOn?.form) .map(f => ({ component: 'field', config: f, })) }, ], }, ], }) } public async appData() { const resourceConfigs = this.config.get('cobalt.resources', []) as ResourceConfiguration[] const user = this.security.user() as User return { appData: { appUrl: this.routing.getAppUrl().toRemote, user: { firstName: user.firstName, lastName: user.lastName, username: user.username, photoUrl: user.photoUrl, initials: user.initials, }, }, resources: resourceConfigs .filter(c => c.supportedActions.includes(ResourceAction.read)) .map(c => ({ display: c.display.plural, href: `/dash2/cobalt/resource/${c.key}/list`, })), } } protected getResourceConfigOrFail(key: string): ResourceConfiguration { const config = this.getResourceConfig(key) if ( !config ) { throw new HTTPError(HTTPStatus.NOT_FOUND) } return config } protected getResourceConfig(key: string): Maybe { const configs = this.config.get('cobalt.resources') as ResourceConfiguration[] for ( const config of configs ) { if ( config.key === key ) { return config } } } }