feat: Add settings view for cloud provider configurations
- Implemented CloudlyViewSettings component for managing cloud provider settings including Hetzner, Cloudflare, AWS, DigitalOcean, Azure, and Google Cloud. - Added functionality to load, save, and test connections for each provider. - Enhanced UI with loading states and success/error notifications. feat: Create tasks view with execution history - Developed CloudlyViewTasks component to display and manage tasks and their executions. - Integrated auto-refresh functionality for task executions. - Added filtering and searching capabilities for tasks. feat: Implement execution details and task panel components - Created CloudlyExecutionDetails component to show detailed information about task executions including logs and metrics. - Developed CloudlyTaskPanel component to display individual tasks with execution status and actions to run or cancel tasks. feat: Utility functions for formatting and categorization - Added utility functions for formatting dates, durations, and cron expressions. - Implemented functions to retrieve category icons and hues for task categorization.
This commit is contained in:
142
ts_web/elements/views/images/index.ts
Normal file
142
ts_web/elements/views/images/index.ts
Normal file
@@ -0,0 +1,142 @@
|
||||
import * as plugins from '../../../plugins.js';
|
||||
import * as shared from '../../shared/index.js';
|
||||
|
||||
import { DeesElement, customElement, html, state, css, cssManager } from '@design.estate/dees-element';
|
||||
|
||||
import * as appstate from '../../../appstate.js';
|
||||
|
||||
@customElement('cloudly-view-images')
|
||||
export class CloudlyViewImages extends DeesElement {
|
||||
@state()
|
||||
private data: appstate.IDataState = {} as any;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
appstate.dataState
|
||||
.select((stateArg) => stateArg)
|
||||
.subscribe((dataArg) => {
|
||||
this.data = dataArg;
|
||||
});
|
||||
}
|
||||
|
||||
public static styles = [
|
||||
cssManager.defaultStyles,
|
||||
shared.viewHostCss,
|
||||
css``,
|
||||
];
|
||||
|
||||
public render() {
|
||||
return html`
|
||||
<cloudly-sectionheading>Images</cloudly-sectionheading>
|
||||
<dees-table
|
||||
heading1="Images"
|
||||
heading2="an image is needed for running a service"
|
||||
.data=${this.data.images}
|
||||
.displayFunction=${(image: plugins.interfaces.data.IImage) => {
|
||||
return { id: image.id, name: image.data.name, description: image.data.description, versions: image.data.versions.length };
|
||||
}}
|
||||
.dataActions=${[
|
||||
{
|
||||
name: 'create Image',
|
||||
type: ['header', 'footer'],
|
||||
iconName: 'plus',
|
||||
actionFunc: async () => {
|
||||
plugins.deesCatalog.DeesModal.createAndShow({
|
||||
heading: 'create new Image',
|
||||
content: html`
|
||||
<dees-form>
|
||||
<dees-input-text .label=${'name'} .key=${'data.name'} .value=${''}></dees-input-text>
|
||||
<dees-input-text .label=${'description'} .key=${'data.description'} .value=${''}></dees-input-text>
|
||||
</dees-form>
|
||||
`,
|
||||
menuOptions: [
|
||||
{ name: 'cancel', action: async (modalArg: any) => { await modalArg.destroy(); } },
|
||||
{ name: 'save', action: async (modalArg: any) => {
|
||||
const deesForm = modalArg.shadowRoot.querySelector('dees-form');
|
||||
const formData = await deesForm.collectFormData();
|
||||
await appstate.dataState.dispatchAction(appstate.createImageAction, { imageName: formData['data.name'] as string, description: formData['data.description'] as string });
|
||||
await modalArg.destroy();
|
||||
} },
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'edit',
|
||||
type: ['contextmenu', 'inRow', 'doubleClick'],
|
||||
iconName: 'penToSquare',
|
||||
actionFunc: async (dataArg: plugins.deesCatalog.ITableActionDataArg<plugins.interfaces.data.ISecretGroup>) => {
|
||||
const environmentsArray: Array<plugins.interfaces.data.ISecretGroup['data']['environments'][any] & { environment: string; }> = [];
|
||||
for (const environmentName of Object.keys(dataArg.item.data.environments)) {
|
||||
environmentsArray.push({ environment: environmentName, ...dataArg.item.data.environments[environmentName] });
|
||||
}
|
||||
await plugins.deesCatalog.DeesModal.createAndShow({
|
||||
heading: 'Edit Secret',
|
||||
content: html`
|
||||
<dees-form>
|
||||
<dees-input-text .key=${'id'} .disabled=${true} .label=${'ID'} .value=${dataArg.item.id}></dees-input-text>
|
||||
<dees-input-text .key=${'data.name'} .disabled=${false} .label=${'name'} .value=${dataArg.item.data.name}></dees-input-text>
|
||||
<dees-input-text .key=${'data.description'} .disabled=${false} .label=${'description'} .value=${dataArg.item.data.description}></dees-input-text>
|
||||
<dees-input-text .key=${'data.key'} .disabled=${false} .label=${'key'} .value=${dataArg.item.data.key}></dees-input-text>
|
||||
<dees-table .key=${'environments'} .heading1=${'Environments'} .heading2=${'double-click to edit values'}
|
||||
.data=${environmentsArray.map((itemArg) => ({ environment: itemArg.environment, value: itemArg.value }))}
|
||||
.editableFields=${['environment', 'value']}
|
||||
.dataActions=${[{ name: 'delete', iconName: 'trash', type: ['inRow'], actionFunc: async (actionDataArg: any) => { actionDataArg.table.data.splice(actionDataArg.table.data.indexOf(actionDataArg.item), 1); } }] as plugins.deesCatalog.ITableAction[]}>
|
||||
</dees-table>
|
||||
</dees-form>
|
||||
`,
|
||||
menuOptions: [
|
||||
{ name: 'Cancel', iconName: null, action: async (modalArg: any) => { await modalArg.destroy(); } },
|
||||
{ name: 'Save', iconName: null, action: async (modalArg: any) => { const data = await modalArg.shadowRoot.querySelector('dees-form').collectFormData(); console.log(data); } },
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'history',
|
||||
iconName: 'clockRotateLeft',
|
||||
type: ['contextmenu', 'inRow'],
|
||||
actionFunc: async (dataArg: plugins.deesCatalog.ITableActionDataArg<plugins.interfaces.data.ISecretGroup>) => {
|
||||
const historyArray: Array<{ environment: string; value: string; }> = [];
|
||||
for (const environment of Object.keys(dataArg.item.data.environments)) {
|
||||
for (const historyItem of dataArg.item.data.environments[environment].history) {
|
||||
historyArray.push({ environment, value: historyItem.value });
|
||||
}
|
||||
}
|
||||
await plugins.deesCatalog.DeesModal.createAndShow({
|
||||
heading: `history for ${dataArg.item.data.key}`,
|
||||
content: html`<dees-table .data=${historyArray} .dataActions=${[{ name: 'delete', iconName: 'trash', type: ['contextmenu', 'inRow'], actionFunc: async (itemArg: plugins.deesCatalog.ITableActionDataArg<(typeof historyArray)[0]>) => { console.log('delete', itemArg); }, }] as plugins.deesCatalog.ITableAction[]}></dees-table>`,
|
||||
menuOptions: [ { name: 'close', action: async (modalArg: any) => { await modalArg.destroy(); } } ],
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'delete',
|
||||
iconName: 'trash',
|
||||
type: ['contextmenu', 'inRow'],
|
||||
actionFunc: async (itemArg: plugins.deesCatalog.ITableActionDataArg<plugins.interfaces.data.IImage>) => {
|
||||
plugins.deesCatalog.DeesModal.createAndShow({
|
||||
heading: `Delete Image "${itemArg.item.data.name}"`,
|
||||
content: html`
|
||||
<div style="text-align:center">Do you really want to delete the image?</div>
|
||||
<div style="font-size: 0.8em; color: red; text-align:center; padding: 16px; margin-top: 24px; border: 1px solid #444; font-family: Intel One Mono; font-size: 16px;">${itemArg.item.id}</div>
|
||||
`,
|
||||
menuOptions: [
|
||||
{ name: 'cancel', action: async (modalArg: any) => { await modalArg.destroy(); } },
|
||||
{ name: 'delete', action: async (modalArg: any) => { await appstate.dataState.dispatchAction(appstate.deleteImageAction, { imageId: itemArg.item.id, }); await modalArg.destroy(); } },
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
] as plugins.deesCatalog.ITableAction[]}
|
||||
></dees-table>
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
'cloudly-view-images': CloudlyViewImages;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user