fix(core): update
This commit is contained in:
202
ts_web/elements/cloudly-dashboard.ts
Normal file
202
ts_web/elements/cloudly-dashboard.ts
Normal file
@ -0,0 +1,202 @@
|
||||
import { commitinfo } from '../00_commitinfo_data.js';
|
||||
import * as plugins from '../plugins.js';
|
||||
|
||||
import * as appstate from '../appstate.js';
|
||||
|
||||
import {
|
||||
DeesElement,
|
||||
css,
|
||||
cssManager,
|
||||
customElement,
|
||||
html,
|
||||
state
|
||||
} from '@design.estate/dees-element';
|
||||
import { CloudlyViewBackups } from './cloudly-view-backups.js';
|
||||
import { CloudlyViewClusters } from './cloudly-view-clusters.js';
|
||||
import { CloudlyViewDbs } from './cloudly-view-dbs.js';
|
||||
import { CloudlyViewDeployments } from './cloudly-view-deployments.js';
|
||||
import { CloudlyViewDns } from './cloudly-view-dns.js';
|
||||
import { CloudlyViewImages } from './cloudly-view-images.js';
|
||||
import { CloudlyViewLogs } from './cloudly-view-logs.js';
|
||||
import { CloudlyViewMails } from './cloudly-view-mails.js';
|
||||
import { CloudlyViewOverview } from './cloudly-view-overview.js';
|
||||
import { CloudlyViewS3 } from './cloudly-view-s3.js';
|
||||
import { CloudlyViewSecretBundles } from './cloudly-view-secretbundles.js';
|
||||
import { CloudlyViewSecretGroups } from './cloudly-view-secretgroups.js';
|
||||
import { CloudlyViewServices } from './cloudly-view-services.js';
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
'cvault-dashboard': CloudlyDashboard;
|
||||
}
|
||||
}
|
||||
|
||||
@customElement('cloudly-dashboard')
|
||||
export class CloudlyDashboard extends DeesElement {
|
||||
@state() private jwt: string;
|
||||
@state() private data: appstate.IDataState = {
|
||||
secretGroups: [],
|
||||
secretBundles: [],
|
||||
clusters: [],
|
||||
};
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
const subcription = appstate.dataState
|
||||
.select((stateArg) => stateArg)
|
||||
.subscribe((dataArg) => {
|
||||
this.data = dataArg;
|
||||
});
|
||||
this.rxSubscriptions.push(subcription);
|
||||
}
|
||||
|
||||
public static styles = [
|
||||
cssManager.defaultStyles,
|
||||
css`
|
||||
.maincontainer {
|
||||
position: relative;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-weight: 400;
|
||||
font-size: 24px;
|
||||
font-family: 'Cal Sans';
|
||||
}
|
||||
`,
|
||||
];
|
||||
public render() {
|
||||
return html`
|
||||
<div class="maincontainer">
|
||||
<dees-simple-login name="cloudly v${commitinfo.version}">
|
||||
<dees-simple-appdash name="cloudly v${commitinfo.version}"
|
||||
.viewTabs=${[
|
||||
{
|
||||
name: 'Overview',
|
||||
element: CloudlyViewOverview,
|
||||
},
|
||||
{
|
||||
name: 'SecretGroups',
|
||||
element: CloudlyViewSecretGroups,
|
||||
},
|
||||
{
|
||||
name: 'SecretBundles',
|
||||
element: CloudlyViewSecretBundles,
|
||||
},
|
||||
{
|
||||
name: 'Clusters',
|
||||
element: CloudlyViewClusters,
|
||||
},
|
||||
{
|
||||
name: 'Images',
|
||||
element: CloudlyViewImages,
|
||||
},
|
||||
{
|
||||
name: 'Services',
|
||||
element: CloudlyViewServices,
|
||||
},
|
||||
{
|
||||
name: 'Deployments',
|
||||
element: CloudlyViewDeployments,
|
||||
},
|
||||
{
|
||||
name: 'DNS',
|
||||
element: CloudlyViewDns,
|
||||
},
|
||||
{
|
||||
name: 'Mails',
|
||||
element: CloudlyViewMails,
|
||||
},
|
||||
{
|
||||
name: 'Logs',
|
||||
element: CloudlyViewLogs,
|
||||
},
|
||||
{
|
||||
name: 's3',
|
||||
element: CloudlyViewS3,
|
||||
},
|
||||
{
|
||||
name: 'DBs',
|
||||
element: CloudlyViewDbs,
|
||||
},
|
||||
{
|
||||
name: 'Backups',
|
||||
element: CloudlyViewBackups,
|
||||
},
|
||||
{
|
||||
name: 'Fleet',
|
||||
element: CloudlyViewBackups,
|
||||
}
|
||||
] as plugins.deesCatalog.IView[]}
|
||||
></dees-simple-appdash>
|
||||
</dees-simple-login>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
public async firstUpdated() {
|
||||
const simpleLogin = this.shadowRoot.querySelector('dees-simple-login');
|
||||
simpleLogin.addEventListener('login', (e: CustomEvent) => {
|
||||
console.log(e.detail);
|
||||
this.login(e.detail.data.username, e.detail.data.password);
|
||||
});
|
||||
this.addEventListener('contextmenu', (eventArg) => {
|
||||
plugins.deesCatalog.DeesContextmenu.openContextMenuWithOptions(eventArg, [
|
||||
{
|
||||
name: 'About',
|
||||
iconName: 'mugHot',
|
||||
action: async () => {
|
||||
await plugins.deesCatalog.DeesModal.createAndShow({
|
||||
heading: 'About',
|
||||
content: html`configvault ${commitinfo.version}`,
|
||||
menuOptions: [
|
||||
{
|
||||
name: 'close',
|
||||
iconName: null,
|
||||
action: async (modalArg) => {
|
||||
await modalArg.destroy();
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
// lets deal with initial state
|
||||
const domtools = await this.domtoolsPromise;
|
||||
const loginState = appstate.loginStatePart.getState();
|
||||
console.log(loginState);
|
||||
if (loginState.jwt) {
|
||||
this.jwt = loginState.jwt;
|
||||
await simpleLogin.switchToSlottedContent();
|
||||
await appstate.dataState.dispatchAction(appstate.getDataAction, null);
|
||||
}
|
||||
}
|
||||
|
||||
private async login(username: string, password: string) {
|
||||
const domtools = await this.domtoolsPromise;
|
||||
console.log(`attempting to login...`);
|
||||
const simpleLogin = this.shadowRoot.querySelector('dees-simple-login');
|
||||
const form = simpleLogin.shadowRoot.querySelector('dees-form');
|
||||
form.setStatus('pending', 'Logging in...');
|
||||
const state = await appstate.loginStatePart.dispatchAction(appstate.loginAction, {
|
||||
username,
|
||||
password,
|
||||
});
|
||||
if (state.jwt) {
|
||||
console.log('got jwt');
|
||||
this.jwt = state.jwt;
|
||||
form.setStatus('success', 'Logged in!');
|
||||
await simpleLogin.switchToSlottedContent();
|
||||
await appstate.dataState.dispatchAction(appstate.getDataAction, null);
|
||||
} else {
|
||||
form.setStatus('error', 'Login failed!');
|
||||
await domtools.convenience.smartdelay.delayFor(2000);
|
||||
form.reset();
|
||||
}
|
||||
}
|
||||
|
||||
private async logout() {}
|
||||
}
|
133
ts_web/elements/cloudly-view-backups.ts
Normal file
133
ts_web/elements/cloudly-view-backups.ts
Normal file
@ -0,0 +1,133 @@
|
||||
import * as plugins from '../plugins.js';
|
||||
|
||||
import {
|
||||
DeesElement,
|
||||
customElement,
|
||||
html,
|
||||
state,
|
||||
css,
|
||||
cssManager,
|
||||
} from '@design.estate/dees-element';
|
||||
|
||||
import * as appstate from '../appstate.js';
|
||||
|
||||
@customElement('cloudly-view-backups')
|
||||
export class CloudlyViewBackups extends DeesElement {
|
||||
@state()
|
||||
private data: appstate.IDataState = {
|
||||
secretGroups: [],
|
||||
secretBundles: [],
|
||||
};
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
const subecription = appstate.dataState
|
||||
.select((stateArg) => stateArg)
|
||||
.subscribe((dataArg) => {
|
||||
this.data = dataArg;
|
||||
});
|
||||
this.rxSubscriptions.push(subecription);
|
||||
}
|
||||
|
||||
public static styles = [
|
||||
cssManager.defaultStyles,
|
||||
css`
|
||||
:host {
|
||||
display: block;
|
||||
margin: auto;
|
||||
max-width: 1280px;
|
||||
padding: 16px 16px;
|
||||
}
|
||||
`,
|
||||
];
|
||||
|
||||
public render() {
|
||||
return html`
|
||||
<cloudly-sectionheading>Backups</cloudly-sectionheading>
|
||||
<dees-table
|
||||
.heading1=${'Backups'}
|
||||
.heading2=${'decoded in client'}
|
||||
.data=${this.data.backups}
|
||||
.displayFunction=${(itemArg: plugins.interfaces.data.ICluster) => {
|
||||
return {
|
||||
id: itemArg.id,
|
||||
serverAmount: itemArg.data.servers.length,
|
||||
};
|
||||
}}
|
||||
.dataActions=${[
|
||||
{
|
||||
name: 'add configBundle',
|
||||
iconName: 'plus',
|
||||
type: ['header', 'footer'],
|
||||
actionFunc: async (dataActionArg) => {
|
||||
const modal = await plugins.deesCatalog.DeesModal.createAndShow({
|
||||
heading: 'Add ConfigBundle',
|
||||
content: html`
|
||||
<dees-form>
|
||||
<dees-input-text .key=${'id'} .label=${'ID'} .value=${''}></dees-input-text>
|
||||
<dees-input-text
|
||||
.key=${'data.secretGroupIds'}
|
||||
.label=${'secretGroupIds'}
|
||||
.value=${''}
|
||||
></dees-input-text>
|
||||
<dees-input-text
|
||||
.key=${'data.includedTags'}
|
||||
.label=${'includedTags'}
|
||||
.value=${''}
|
||||
></dees-input-text>
|
||||
</dees-form>
|
||||
`,
|
||||
menuOptions: [
|
||||
{ name: 'create', action: async (modalArg) => {} },
|
||||
{
|
||||
name: 'cancel',
|
||||
action: async (modalArg) => {
|
||||
modalArg.destroy();
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'delete',
|
||||
iconName: 'trash',
|
||||
type: ['contextmenu', 'inRow'],
|
||||
actionFunc: async (actionDataArg) => {
|
||||
plugins.deesCatalog.DeesModal.createAndShow({
|
||||
heading: `Delete ConfigBundle ${actionDataArg.item.id}`,
|
||||
content: html`
|
||||
<div style="text-align:center">
|
||||
Do you really want to delete the ConfigBundle?
|
||||
</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;"
|
||||
>
|
||||
${actionDataArg.item.id}
|
||||
</div>
|
||||
`,
|
||||
menuOptions: [
|
||||
{
|
||||
name: 'cancel',
|
||||
action: async (modalArg) => {
|
||||
await modalArg.destroy();
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'delete',
|
||||
action: async (modalArg) => {
|
||||
appstate.dataState.dispatchAction(appstate.deleteSecretBundleAction, {
|
||||
configBundleId: actionDataArg.item.id,
|
||||
});
|
||||
await modalArg.destroy();
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
] as plugins.deesCatalog.ITableAction[]}
|
||||
></dees-table>
|
||||
`;
|
||||
}
|
||||
}
|
140
ts_web/elements/cloudly-view-clusters.ts
Normal file
140
ts_web/elements/cloudly-view-clusters.ts
Normal file
@ -0,0 +1,140 @@
|
||||
import * as plugins from '../plugins.js';
|
||||
|
||||
import {
|
||||
DeesElement,
|
||||
customElement,
|
||||
html,
|
||||
state,
|
||||
css,
|
||||
cssManager,
|
||||
} from '@design.estate/dees-element';
|
||||
|
||||
import * as appstate from '../appstate.js';
|
||||
|
||||
@customElement('cloudly-view-clusters')
|
||||
export class CloudlyViewClusters extends DeesElement {
|
||||
@state()
|
||||
private data: appstate.IDataState = {
|
||||
secretGroups: [],
|
||||
secretBundles: [],
|
||||
};
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
const subecription = appstate.dataState
|
||||
.select((stateArg) => stateArg)
|
||||
.subscribe((dataArg) => {
|
||||
this.data = dataArg;
|
||||
});
|
||||
this.rxSubscriptions.push(subecription);
|
||||
}
|
||||
|
||||
public static styles = [
|
||||
cssManager.defaultStyles,
|
||||
css`
|
||||
:host {
|
||||
display: block;
|
||||
margin: auto;
|
||||
max-width: 1280px;
|
||||
padding: 16px 16px;
|
||||
}
|
||||
`,
|
||||
];
|
||||
|
||||
public render() {
|
||||
return html`
|
||||
<cloudly-sectionheading>Clusters</cloudly-sectionheading>
|
||||
<dees-table
|
||||
.heading1=${'Clusters'}
|
||||
.heading2=${'decoded in client'}
|
||||
.data=${this.data.clusters}
|
||||
.displayFunction=${(itemArg: plugins.interfaces.data.ICluster) => {
|
||||
console.log(itemArg);
|
||||
return {
|
||||
id: itemArg.id,
|
||||
serverAmount: itemArg.data.servers.length,
|
||||
};
|
||||
}}
|
||||
.dataActions=${[
|
||||
{
|
||||
name: 'add cluster',
|
||||
iconName: 'plus',
|
||||
type: ['header', 'footer'],
|
||||
actionFunc: async (dataActionArg) => {
|
||||
const modal = await plugins.deesCatalog.DeesModal.createAndShow({
|
||||
heading: 'Add Cluster',
|
||||
content: html`
|
||||
<dees-form>
|
||||
<dees-input-text
|
||||
.key=${'clusterName'}
|
||||
.label=${'cluster name'}
|
||||
.description=${'a descriptive name for the cluster'}
|
||||
.value=${''}
|
||||
></dees-input-text>
|
||||
</dees-form>
|
||||
`,
|
||||
menuOptions: [
|
||||
{
|
||||
name: 'create',
|
||||
action: async (modalArg) => {
|
||||
const data: {
|
||||
clusterName: string;
|
||||
} = (await modalArg.shadowRoot
|
||||
.querySelector('dees-form')
|
||||
.collectFormData()) as any;
|
||||
await appstate.dataState.dispatchAction(appstate.addClusterAction, data);
|
||||
await modalArg.destroy();
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'cancel',
|
||||
action: async (modalArg) => {
|
||||
modalArg.destroy();
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'delete',
|
||||
iconName: 'trash',
|
||||
type: ['contextmenu', 'inRow'],
|
||||
actionFunc: async (actionDataArg) => {
|
||||
plugins.deesCatalog.DeesModal.createAndShow({
|
||||
heading: `Delete ConfigBundle ${actionDataArg.item.id}`,
|
||||
content: html`
|
||||
<div style="text-align:center">
|
||||
Do you really want to delete the ConfigBundle?
|
||||
</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;"
|
||||
>
|
||||
${actionDataArg.item.id}
|
||||
</div>
|
||||
`,
|
||||
menuOptions: [
|
||||
{
|
||||
name: 'cancel',
|
||||
action: async (modalArg) => {
|
||||
await modalArg.destroy();
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'delete',
|
||||
action: async (modalArg) => {
|
||||
appstate.dataState.dispatchAction(appstate.deleteSecretBundleAction, {
|
||||
configBundleId: actionDataArg.item.id,
|
||||
});
|
||||
await modalArg.destroy();
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
] as plugins.deesCatalog.ITableAction[]}
|
||||
></dees-table>
|
||||
`;
|
||||
}
|
||||
}
|
133
ts_web/elements/cloudly-view-dbs.ts
Normal file
133
ts_web/elements/cloudly-view-dbs.ts
Normal file
@ -0,0 +1,133 @@
|
||||
import * as plugins from '../plugins.js';
|
||||
|
||||
import {
|
||||
DeesElement,
|
||||
customElement,
|
||||
html,
|
||||
state,
|
||||
css,
|
||||
cssManager,
|
||||
} from '@design.estate/dees-element';
|
||||
|
||||
import * as appstate from '../appstate.js';
|
||||
|
||||
@customElement('cloudly-view-dbs')
|
||||
export class CloudlyViewDbs extends DeesElement {
|
||||
@state()
|
||||
private data: appstate.IDataState = {
|
||||
secretGroups: [],
|
||||
secretBundles: [],
|
||||
};
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
const subecription = appstate.dataState
|
||||
.select((stateArg) => stateArg)
|
||||
.subscribe((dataArg) => {
|
||||
this.data = dataArg;
|
||||
});
|
||||
this.rxSubscriptions.push(subecription);
|
||||
}
|
||||
|
||||
public static styles = [
|
||||
cssManager.defaultStyles,
|
||||
css`
|
||||
:host {
|
||||
display: block;
|
||||
margin: auto;
|
||||
max-width: 1280px;
|
||||
padding: 16px 16px;
|
||||
}
|
||||
`,
|
||||
];
|
||||
|
||||
public render() {
|
||||
return html`
|
||||
<cloudly-sectionheading>DBs</cloudly-sectionheading>
|
||||
<dees-table
|
||||
.heading1=${'DBs'}
|
||||
.heading2=${'decoded in client'}
|
||||
.data=${this.data.dbs}
|
||||
.displayFunction=${(itemArg: plugins.interfaces.data.ICluster) => {
|
||||
return {
|
||||
id: itemArg.id,
|
||||
serverAmount: itemArg.data.servers.length,
|
||||
};
|
||||
}}
|
||||
.dataActions=${[
|
||||
{
|
||||
name: 'add configBundle',
|
||||
iconName: 'plus',
|
||||
type: ['header', 'footer'],
|
||||
actionFunc: async (dataActionArg) => {
|
||||
const modal = await plugins.deesCatalog.DeesModal.createAndShow({
|
||||
heading: 'Add ConfigBundle',
|
||||
content: html`
|
||||
<dees-form>
|
||||
<dees-input-text .key=${'id'} .label=${'ID'} .value=${''}></dees-input-text>
|
||||
<dees-input-text
|
||||
.key=${'data.secretGroupIds'}
|
||||
.label=${'secretGroupIds'}
|
||||
.value=${''}
|
||||
></dees-input-text>
|
||||
<dees-input-text
|
||||
.key=${'data.includedTags'}
|
||||
.label=${'includedTags'}
|
||||
.value=${''}
|
||||
></dees-input-text>
|
||||
</dees-form>
|
||||
`,
|
||||
menuOptions: [
|
||||
{ name: 'create', action: async (modalArg) => {} },
|
||||
{
|
||||
name: 'cancel',
|
||||
action: async (modalArg) => {
|
||||
modalArg.destroy();
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'delete',
|
||||
iconName: 'trash',
|
||||
type: ['contextmenu', 'inRow'],
|
||||
actionFunc: async (actionDataArg) => {
|
||||
plugins.deesCatalog.DeesModal.createAndShow({
|
||||
heading: `Delete ConfigBundle ${actionDataArg.item.id}`,
|
||||
content: html`
|
||||
<div style="text-align:center">
|
||||
Do you really want to delete the ConfigBundle?
|
||||
</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;"
|
||||
>
|
||||
${actionDataArg.item.id}
|
||||
</div>
|
||||
`,
|
||||
menuOptions: [
|
||||
{
|
||||
name: 'cancel',
|
||||
action: async (modalArg) => {
|
||||
await modalArg.destroy();
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'delete',
|
||||
action: async (modalArg) => {
|
||||
appstate.dataState.dispatchAction(appstate.deleteSecretBundleAction, {
|
||||
configBundleId: actionDataArg.item.id,
|
||||
});
|
||||
await modalArg.destroy();
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
] as plugins.deesCatalog.ITableAction[]}
|
||||
></dees-table>
|
||||
`;
|
||||
}
|
||||
}
|
133
ts_web/elements/cloudly-view-deployments.ts
Normal file
133
ts_web/elements/cloudly-view-deployments.ts
Normal file
@ -0,0 +1,133 @@
|
||||
import * as plugins from '../plugins.js';
|
||||
|
||||
import {
|
||||
DeesElement,
|
||||
customElement,
|
||||
html,
|
||||
state,
|
||||
css,
|
||||
cssManager,
|
||||
} from '@design.estate/dees-element';
|
||||
|
||||
import * as appstate from '../appstate.js';
|
||||
|
||||
@customElement('cloudly-view-deployments')
|
||||
export class CloudlyViewDeployments extends DeesElement {
|
||||
@state()
|
||||
private data: appstate.IDataState = {
|
||||
secretGroups: [],
|
||||
secretBundles: [],
|
||||
};
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
const subecription = appstate.dataState
|
||||
.select((stateArg) => stateArg)
|
||||
.subscribe((dataArg) => {
|
||||
this.data = dataArg;
|
||||
});
|
||||
this.rxSubscriptions.push(subecription);
|
||||
}
|
||||
|
||||
public static styles = [
|
||||
cssManager.defaultStyles,
|
||||
css`
|
||||
:host {
|
||||
display: block;
|
||||
margin: auto;
|
||||
max-width: 1280px;
|
||||
padding: 16px 16px;
|
||||
}
|
||||
`,
|
||||
];
|
||||
|
||||
public render() {
|
||||
return html`
|
||||
<cloudly-sectionheading>Deployments</cloudly-sectionheading>
|
||||
<dees-table
|
||||
.heading1=${'Deployments'}
|
||||
.heading2=${'decoded in client'}
|
||||
.data=${this.data.deployments}
|
||||
.displayFunction=${(itemArg: plugins.interfaces.data.ICluster) => {
|
||||
return {
|
||||
id: itemArg.id,
|
||||
serverAmount: itemArg.data.servers.length,
|
||||
};
|
||||
}}
|
||||
.dataActions=${[
|
||||
{
|
||||
name: 'add configBundle',
|
||||
iconName: 'plus',
|
||||
type: ['header', 'footer'],
|
||||
actionFunc: async (dataActionArg) => {
|
||||
const modal = await plugins.deesCatalog.DeesModal.createAndShow({
|
||||
heading: 'Add ConfigBundle',
|
||||
content: html`
|
||||
<dees-form>
|
||||
<dees-input-text .key=${'id'} .label=${'ID'} .value=${''}></dees-input-text>
|
||||
<dees-input-text
|
||||
.key=${'data.secretGroupIds'}
|
||||
.label=${'secretGroupIds'}
|
||||
.value=${''}
|
||||
></dees-input-text>
|
||||
<dees-input-text
|
||||
.key=${'data.includedTags'}
|
||||
.label=${'includedTags'}
|
||||
.value=${''}
|
||||
></dees-input-text>
|
||||
</dees-form>
|
||||
`,
|
||||
menuOptions: [
|
||||
{ name: 'create', action: async (modalArg) => {} },
|
||||
{
|
||||
name: 'cancel',
|
||||
action: async (modalArg) => {
|
||||
modalArg.destroy();
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'delete',
|
||||
iconName: 'trash',
|
||||
type: ['contextmenu', 'inRow'],
|
||||
actionFunc: async (actionDataArg) => {
|
||||
plugins.deesCatalog.DeesModal.createAndShow({
|
||||
heading: `Delete ConfigBundle ${actionDataArg.item.id}`,
|
||||
content: html`
|
||||
<div style="text-align:center">
|
||||
Do you really want to delete the ConfigBundle?
|
||||
</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;"
|
||||
>
|
||||
${actionDataArg.item.id}
|
||||
</div>
|
||||
`,
|
||||
menuOptions: [
|
||||
{
|
||||
name: 'cancel',
|
||||
action: async (modalArg) => {
|
||||
await modalArg.destroy();
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'delete',
|
||||
action: async (modalArg) => {
|
||||
appstate.dataState.dispatchAction(appstate.deleteSecretBundleAction, {
|
||||
configBundleId: actionDataArg.item.id,
|
||||
});
|
||||
await modalArg.destroy();
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
] as plugins.deesCatalog.ITableAction[]}
|
||||
></dees-table>
|
||||
`;
|
||||
}
|
||||
}
|
133
ts_web/elements/cloudly-view-dns.ts
Normal file
133
ts_web/elements/cloudly-view-dns.ts
Normal file
@ -0,0 +1,133 @@
|
||||
import * as plugins from '../plugins.js';
|
||||
|
||||
import {
|
||||
DeesElement,
|
||||
customElement,
|
||||
html,
|
||||
state,
|
||||
css,
|
||||
cssManager,
|
||||
} from '@design.estate/dees-element';
|
||||
|
||||
import * as appstate from '../appstate.js';
|
||||
|
||||
@customElement('cloudly-view-dns')
|
||||
export class CloudlyViewDns extends DeesElement {
|
||||
@state()
|
||||
private data: appstate.IDataState = {
|
||||
secretGroups: [],
|
||||
secretBundles: [],
|
||||
};
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
const subecription = appstate.dataState
|
||||
.select((stateArg) => stateArg)
|
||||
.subscribe((dataArg) => {
|
||||
this.data = dataArg;
|
||||
});
|
||||
this.rxSubscriptions.push(subecription);
|
||||
}
|
||||
|
||||
public static styles = [
|
||||
cssManager.defaultStyles,
|
||||
css`
|
||||
:host {
|
||||
display: block;
|
||||
margin: auto;
|
||||
max-width: 1280px;
|
||||
padding: 16px 16px;
|
||||
}
|
||||
`,
|
||||
];
|
||||
|
||||
public render() {
|
||||
return html`
|
||||
<cloudly-sectionheading>DNS</cloudly-sectionheading>
|
||||
<dees-table
|
||||
.heading1=${'DNS'}
|
||||
.heading2=${'decoded in client'}
|
||||
.data=${this.data.deployments}
|
||||
.displayFunction=${(itemArg: plugins.interfaces.data.ICluster) => {
|
||||
return {
|
||||
id: itemArg.id,
|
||||
serverAmount: itemArg.data.servers.length,
|
||||
};
|
||||
}}
|
||||
.dataActions=${[
|
||||
{
|
||||
name: 'add configBundle',
|
||||
iconName: 'plus',
|
||||
type: ['header', 'footer'],
|
||||
actionFunc: async (dataActionArg) => {
|
||||
const modal = await plugins.deesCatalog.DeesModal.createAndShow({
|
||||
heading: 'Add ConfigBundle',
|
||||
content: html`
|
||||
<dees-form>
|
||||
<dees-input-text .key=${'id'} .label=${'ID'} .value=${''}></dees-input-text>
|
||||
<dees-input-text
|
||||
.key=${'data.secretGroupIds'}
|
||||
.label=${'secretGroupIds'}
|
||||
.value=${''}
|
||||
></dees-input-text>
|
||||
<dees-input-text
|
||||
.key=${'data.includedTags'}
|
||||
.label=${'includedTags'}
|
||||
.value=${''}
|
||||
></dees-input-text>
|
||||
</dees-form>
|
||||
`,
|
||||
menuOptions: [
|
||||
{ name: 'create', action: async (modalArg) => {} },
|
||||
{
|
||||
name: 'cancel',
|
||||
action: async (modalArg) => {
|
||||
modalArg.destroy();
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'delete',
|
||||
iconName: 'trash',
|
||||
type: ['contextmenu', 'inRow'],
|
||||
actionFunc: async (actionDataArg) => {
|
||||
plugins.deesCatalog.DeesModal.createAndShow({
|
||||
heading: `Delete ConfigBundle ${actionDataArg.item.id}`,
|
||||
content: html`
|
||||
<div style="text-align:center">
|
||||
Do you really want to delete the ConfigBundle?
|
||||
</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;"
|
||||
>
|
||||
${actionDataArg.item.id}
|
||||
</div>
|
||||
`,
|
||||
menuOptions: [
|
||||
{
|
||||
name: 'cancel',
|
||||
action: async (modalArg) => {
|
||||
await modalArg.destroy();
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'delete',
|
||||
action: async (modalArg) => {
|
||||
appstate.dataState.dispatchAction(appstate.deleteSecretBundleAction, {
|
||||
configBundleId: actionDataArg.item.id,
|
||||
});
|
||||
await modalArg.destroy();
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
] as plugins.deesCatalog.ITableAction[]}
|
||||
></dees-table>
|
||||
`;
|
||||
}
|
||||
}
|
367
ts_web/elements/cloudly-view-images.ts
Normal file
367
ts_web/elements/cloudly-view-images.ts
Normal file
@ -0,0 +1,367 @@
|
||||
import * as plugins from '../plugins.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 = {
|
||||
secretGroups: [],
|
||||
secretBundles: [],
|
||||
};
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
appstate.dataState
|
||||
.select((stateArg) => stateArg)
|
||||
.subscribe((dataArg) => {
|
||||
this.data = dataArg;
|
||||
});
|
||||
}
|
||||
|
||||
public static styles = [
|
||||
cssManager.defaultStyles,
|
||||
css`
|
||||
:host {
|
||||
display: block;
|
||||
margin: auto;
|
||||
max-width: 1280px;
|
||||
padding: 16px 16px;
|
||||
}
|
||||
`,
|
||||
];
|
||||
|
||||
public render() {
|
||||
return html`
|
||||
<cloudly-sectionheading>Images</cloudly-sectionheading>
|
||||
<dees-table
|
||||
heading1="SecretGroups"
|
||||
heading2="decoded in client"
|
||||
.data=${this.data.images}
|
||||
.displayFunction=${(secretGroup: plugins.interfaces.data.ISecretGroup) => {
|
||||
return {
|
||||
name: secretGroup.data.name,
|
||||
priority: secretGroup.data.priority,
|
||||
tags: html`<dees-chips
|
||||
.selectionMode=${'none'}
|
||||
.selectableChips=${secretGroup.data.tags}
|
||||
></dees-chips>`,
|
||||
key: secretGroup.data.key,
|
||||
history: (() => {
|
||||
const allHistory = [];
|
||||
for (const environment in secretGroup.data.environments) {
|
||||
allHistory.push(...secretGroup.data.environments[environment].history);
|
||||
}
|
||||
return allHistory.length;
|
||||
})(),
|
||||
};
|
||||
}}
|
||||
.dataActions=${[
|
||||
{
|
||||
name: 'add SecretGroup',
|
||||
type: ['header', 'footer'],
|
||||
iconName: 'plus',
|
||||
actionFunc: async () => {
|
||||
plugins.deesCatalog.DeesModal.createAndShow({
|
||||
heading: 'create new SecretGroup',
|
||||
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-input-text
|
||||
.label=${'Secret Key (data.key)'}
|
||||
.key=${'data.key'}
|
||||
.value=${''}
|
||||
></dees-input-text>
|
||||
<dees-table
|
||||
.heading1=${'Environments'}
|
||||
.heading2=${'keys need to be unique'}
|
||||
key="environments"
|
||||
.data=${[
|
||||
{
|
||||
environment: 'production',
|
||||
value: '',
|
||||
},
|
||||
{
|
||||
environment: 'staging',
|
||||
value: '',
|
||||
},
|
||||
]}
|
||||
.dataActions=${[
|
||||
{
|
||||
name: 'add environment',
|
||||
iconName: 'plus',
|
||||
type: ['footer'],
|
||||
actionFunc: async (dataArg) => {
|
||||
dataArg.table.data.push({
|
||||
environment: 'new environment',
|
||||
value: '',
|
||||
});
|
||||
dataArg.table.requestUpdate('data');
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'delete environment',
|
||||
iconName: 'trash',
|
||||
type: ['inRow'],
|
||||
actionFunc: async (dataArg) => {
|
||||
dataArg.table.data.splice(dataArg.table.data.indexOf(dataArg.item), 1);
|
||||
dataArg.table.requestUpdate('data');
|
||||
},
|
||||
},
|
||||
] as plugins.deesCatalog.ITableAction[]}
|
||||
.editableFields=${['environment', 'value']}
|
||||
></dees-table>
|
||||
</dees-form>
|
||||
`,
|
||||
menuOptions: [
|
||||
{
|
||||
name: 'cancel',
|
||||
action: async (modalArg) => {
|
||||
await modalArg.destroy();
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'save',
|
||||
action: async (modalArg) => {
|
||||
const deesForm = modalArg.shadowRoot.querySelector('dees-form');
|
||||
const formData = await deesForm.collectFormData();
|
||||
console.log(`Prepare saving of data:`);
|
||||
console.log(formData);
|
||||
const environments: plugins.interfaces.data.ISecretGroup['data']['environments'] =
|
||||
{};
|
||||
for (const itemArg of formData['environments'] as any[]) {
|
||||
environments[itemArg.environment] = {
|
||||
value: itemArg.value,
|
||||
history: [],
|
||||
lastUpdated: Date.now(),
|
||||
};
|
||||
}
|
||||
await appstate.dataState.dispatchAction(appstate.createSecretGroupAction, {
|
||||
id: null,
|
||||
data: {
|
||||
name: formData['data.name'] as string,
|
||||
description: formData['data.description'] as string,
|
||||
key: formData['data.key'] as string,
|
||||
environments,
|
||||
tags: [],
|
||||
},
|
||||
});
|
||||
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) => {
|
||||
return {
|
||||
environment: itemArg.environment,
|
||||
value: itemArg.value,
|
||||
};
|
||||
})}
|
||||
.editableFields=${['environment', 'value']}
|
||||
.dataActions=${[
|
||||
{
|
||||
name: 'delete',
|
||||
iconName: 'trash',
|
||||
type: ['inRow'],
|
||||
actionFunc: async (actionDataArg) => {
|
||||
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) => {
|
||||
await modalArg.destroy();
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Save',
|
||||
iconName: null,
|
||||
action: async (modalArg) => {
|
||||
const data = await modalArg.shadowRoot
|
||||
.querySelector('dees-form')
|
||||
.collectFormData();
|
||||
console.log(data);
|
||||
const updatedSecretGroup: plugins.interfaces.data.ISecretGroup = {
|
||||
id: dataArg.item.id,
|
||||
data: {
|
||||
name: data['data.name'] as string,
|
||||
description: data['data.description'] as string,
|
||||
key: data['data.key'] as string,
|
||||
environments: {},
|
||||
tags: dataArg.item.data.tags,
|
||||
},
|
||||
};
|
||||
const environments: plugins.interfaces.data.ISecretGroup['data']['environments'] =
|
||||
{};
|
||||
for (const itemArg of data['environments'] as any[]) {
|
||||
}
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
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) => {
|
||||
await modalArg.destroy();
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'delete',
|
||||
iconName: 'trash',
|
||||
type: ['contextmenu', 'inRow'],
|
||||
actionFunc: async (
|
||||
itemArg: plugins.deesCatalog.ITableActionDataArg<plugins.interfaces.data.ISecretGroup>
|
||||
) => {
|
||||
plugins.deesCatalog.DeesModal.createAndShow({
|
||||
heading: `Delete ${itemArg.item.data.key}`,
|
||||
content: html`
|
||||
<div style="text-align:center">Do you really want to delete the secret?</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.data.key}
|
||||
</div>
|
||||
`,
|
||||
menuOptions: [
|
||||
{
|
||||
name: 'cancel',
|
||||
action: async (modalArg) => {
|
||||
await modalArg.destroy();
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'delete',
|
||||
action: async (modalArg) => {
|
||||
console.log(`Delete ${itemArg.item.id}`);
|
||||
await appstate.dataState.dispatchAction(appstate.deleteSecretGroupAction, {
|
||||
secretGroupId: itemArg.item.id,
|
||||
});
|
||||
await modalArg.destroy();
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
] as plugins.deesCatalog.ITableAction[]}
|
||||
></dees-table>
|
||||
`;
|
||||
}
|
||||
}
|
133
ts_web/elements/cloudly-view-logs.ts
Normal file
133
ts_web/elements/cloudly-view-logs.ts
Normal file
@ -0,0 +1,133 @@
|
||||
import * as plugins from '../plugins.js';
|
||||
|
||||
import {
|
||||
DeesElement,
|
||||
customElement,
|
||||
html,
|
||||
state,
|
||||
css,
|
||||
cssManager,
|
||||
} from '@design.estate/dees-element';
|
||||
|
||||
import * as appstate from '../appstate.js';
|
||||
|
||||
@customElement('cloudly-view-logs')
|
||||
export class CloudlyViewLogs extends DeesElement {
|
||||
@state()
|
||||
private data: appstate.IDataState = {
|
||||
secretGroups: [],
|
||||
secretBundles: [],
|
||||
};
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
const subecription = appstate.dataState
|
||||
.select((stateArg) => stateArg)
|
||||
.subscribe((dataArg) => {
|
||||
this.data = dataArg;
|
||||
});
|
||||
this.rxSubscriptions.push(subecription);
|
||||
}
|
||||
|
||||
public static styles = [
|
||||
cssManager.defaultStyles,
|
||||
css`
|
||||
:host {
|
||||
display: block;
|
||||
margin: auto;
|
||||
max-width: 1280px;
|
||||
padding: 16px 16px;
|
||||
}
|
||||
`,
|
||||
];
|
||||
|
||||
public render() {
|
||||
return html`
|
||||
<cloudly-sectionheading>Logs</cloudly-sectionheading>
|
||||
<dees-table
|
||||
.heading1=${'Logs'}
|
||||
.heading2=${'decoded in client'}
|
||||
.data=${this.data.deployments}
|
||||
.displayFunction=${(itemArg: plugins.interfaces.data.ICluster) => {
|
||||
return {
|
||||
id: itemArg.id,
|
||||
serverAmount: itemArg.data.servers.length,
|
||||
};
|
||||
}}
|
||||
.dataActions=${[
|
||||
{
|
||||
name: 'add configBundle',
|
||||
iconName: 'plus',
|
||||
type: ['header', 'footer'],
|
||||
actionFunc: async (dataActionArg) => {
|
||||
const modal = await plugins.deesCatalog.DeesModal.createAndShow({
|
||||
heading: 'Add ConfigBundle',
|
||||
content: html`
|
||||
<dees-form>
|
||||
<dees-input-text .key=${'id'} .label=${'ID'} .value=${''}></dees-input-text>
|
||||
<dees-input-text
|
||||
.key=${'data.secretGroupIds'}
|
||||
.label=${'secretGroupIds'}
|
||||
.value=${''}
|
||||
></dees-input-text>
|
||||
<dees-input-text
|
||||
.key=${'data.includedTags'}
|
||||
.label=${'includedTags'}
|
||||
.value=${''}
|
||||
></dees-input-text>
|
||||
</dees-form>
|
||||
`,
|
||||
menuOptions: [
|
||||
{ name: 'create', action: async (modalArg) => {} },
|
||||
{
|
||||
name: 'cancel',
|
||||
action: async (modalArg) => {
|
||||
modalArg.destroy();
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'delete',
|
||||
iconName: 'trash',
|
||||
type: ['contextmenu', 'inRow'],
|
||||
actionFunc: async (actionDataArg) => {
|
||||
plugins.deesCatalog.DeesModal.createAndShow({
|
||||
heading: `Delete ConfigBundle ${actionDataArg.item.id}`,
|
||||
content: html`
|
||||
<div style="text-align:center">
|
||||
Do you really want to delete the ConfigBundle?
|
||||
</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;"
|
||||
>
|
||||
${actionDataArg.item.id}
|
||||
</div>
|
||||
`,
|
||||
menuOptions: [
|
||||
{
|
||||
name: 'cancel',
|
||||
action: async (modalArg) => {
|
||||
await modalArg.destroy();
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'delete',
|
||||
action: async (modalArg) => {
|
||||
appstate.dataState.dispatchAction(appstate.deleteSecretBundleAction, {
|
||||
configBundleId: actionDataArg.item.id,
|
||||
});
|
||||
await modalArg.destroy();
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
] as plugins.deesCatalog.ITableAction[]}
|
||||
></dees-table>
|
||||
`;
|
||||
}
|
||||
}
|
133
ts_web/elements/cloudly-view-mails.ts
Normal file
133
ts_web/elements/cloudly-view-mails.ts
Normal file
@ -0,0 +1,133 @@
|
||||
import * as plugins from '../plugins.js';
|
||||
|
||||
import {
|
||||
DeesElement,
|
||||
customElement,
|
||||
html,
|
||||
state,
|
||||
css,
|
||||
cssManager,
|
||||
} from '@design.estate/dees-element';
|
||||
|
||||
import * as appstate from '../appstate.js';
|
||||
|
||||
@customElement('cloudly-view-mails')
|
||||
export class CloudlyViewMails extends DeesElement {
|
||||
@state()
|
||||
private data: appstate.IDataState = {
|
||||
secretGroups: [],
|
||||
secretBundles: [],
|
||||
};
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
const subecription = appstate.dataState
|
||||
.select((stateArg) => stateArg)
|
||||
.subscribe((dataArg) => {
|
||||
this.data = dataArg;
|
||||
});
|
||||
this.rxSubscriptions.push(subecription);
|
||||
}
|
||||
|
||||
public static styles = [
|
||||
cssManager.defaultStyles,
|
||||
css`
|
||||
:host {
|
||||
display: block;
|
||||
margin: auto;
|
||||
max-width: 1280px;
|
||||
padding: 16px 16px;
|
||||
}
|
||||
`,
|
||||
];
|
||||
|
||||
public render() {
|
||||
return html`
|
||||
<cloudly-sectionheading>Mails</cloudly-sectionheading>
|
||||
<dees-table
|
||||
.heading1=${'Mails'}
|
||||
.heading2=${'decoded in client'}
|
||||
.data=${this.data.deployments}
|
||||
.displayFunction=${(itemArg: plugins.interfaces.data.ICluster) => {
|
||||
return {
|
||||
id: itemArg.id,
|
||||
serverAmount: itemArg.data.servers.length,
|
||||
};
|
||||
}}
|
||||
.dataActions=${[
|
||||
{
|
||||
name: 'add configBundle',
|
||||
iconName: 'plus',
|
||||
type: ['header', 'footer'],
|
||||
actionFunc: async (dataActionArg) => {
|
||||
const modal = await plugins.deesCatalog.DeesModal.createAndShow({
|
||||
heading: 'Add ConfigBundle',
|
||||
content: html`
|
||||
<dees-form>
|
||||
<dees-input-text .key=${'id'} .label=${'ID'} .value=${''}></dees-input-text>
|
||||
<dees-input-text
|
||||
.key=${'data.secretGroupIds'}
|
||||
.label=${'secretGroupIds'}
|
||||
.value=${''}
|
||||
></dees-input-text>
|
||||
<dees-input-text
|
||||
.key=${'data.includedTags'}
|
||||
.label=${'includedTags'}
|
||||
.value=${''}
|
||||
></dees-input-text>
|
||||
</dees-form>
|
||||
`,
|
||||
menuOptions: [
|
||||
{ name: 'create', action: async (modalArg) => {} },
|
||||
{
|
||||
name: 'cancel',
|
||||
action: async (modalArg) => {
|
||||
modalArg.destroy();
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'delete',
|
||||
iconName: 'trash',
|
||||
type: ['contextmenu', 'inRow'],
|
||||
actionFunc: async (actionDataArg) => {
|
||||
plugins.deesCatalog.DeesModal.createAndShow({
|
||||
heading: `Delete ConfigBundle ${actionDataArg.item.id}`,
|
||||
content: html`
|
||||
<div style="text-align:center">
|
||||
Do you really want to delete the ConfigBundle?
|
||||
</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;"
|
||||
>
|
||||
${actionDataArg.item.id}
|
||||
</div>
|
||||
`,
|
||||
menuOptions: [
|
||||
{
|
||||
name: 'cancel',
|
||||
action: async (modalArg) => {
|
||||
await modalArg.destroy();
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'delete',
|
||||
action: async (modalArg) => {
|
||||
appstate.dataState.dispatchAction(appstate.deleteSecretBundleAction, {
|
||||
configBundleId: actionDataArg.item.id,
|
||||
});
|
||||
await modalArg.destroy();
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
] as plugins.deesCatalog.ITableAction[]}
|
||||
></dees-table>
|
||||
`;
|
||||
}
|
||||
}
|
71
ts_web/elements/cloudly-view-overview.ts
Normal file
71
ts_web/elements/cloudly-view-overview.ts
Normal file
@ -0,0 +1,71 @@
|
||||
import * as plugins from '../plugins.js';
|
||||
|
||||
import {
|
||||
DeesElement,
|
||||
customElement,
|
||||
html,
|
||||
state,
|
||||
css,
|
||||
cssManager,
|
||||
} from '@design.estate/dees-element';
|
||||
|
||||
import * as appstate from '../appstate.js';
|
||||
|
||||
@customElement('cloudly-view-overview')
|
||||
export class CloudlyViewOverview extends DeesElement {
|
||||
@state()
|
||||
private data: appstate.IDataState = {
|
||||
secretGroups: [],
|
||||
secretBundles: [],
|
||||
};
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
const subecription = appstate.dataState
|
||||
.select((stateArg) => stateArg)
|
||||
.subscribe((dataArg) => {
|
||||
this.data = dataArg;
|
||||
});
|
||||
this.rxSubscriptions.push(subecription);
|
||||
}
|
||||
|
||||
public static styles = [
|
||||
cssManager.defaultStyles,
|
||||
css`
|
||||
:host {
|
||||
display: block;
|
||||
margin: auto;
|
||||
max-width: 1280px;
|
||||
padding: 8px 16px;
|
||||
}
|
||||
.clusterGrid {
|
||||
display: grid;
|
||||
grid-template-columns: ${cssManager.cssGridColumns(3, 8)};
|
||||
grid-gap: 16px;
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
`,
|
||||
];
|
||||
|
||||
public render() {
|
||||
return html`
|
||||
<cloudly-sectionheading>Overview</cloudly-sectionheading>
|
||||
${this.data.clusters.length === 0 ? html`
|
||||
You need to create at least one cluster to see an overview.
|
||||
`: html``}
|
||||
${this.data.clusters.map(
|
||||
(clusterArg) => html`
|
||||
<dees-label .label=${'cluster: ' + clusterArg.data.name}></dees-label>
|
||||
<div class="clusterGrid">
|
||||
<dees-chart-area .label=${'System Usage'}></dees-chart-area>
|
||||
<dees-chart-area .label=${'Internet Traffic'}></dees-chart-area>
|
||||
<dees-chart-area .label=${'Requests'}></dees-chart-area>
|
||||
<dees-chart-area .label=${'WebSocket Connections'}></dees-chart-area>
|
||||
<dees-chart-log class="services" .label=${'Deployed Services'}></dees-chart-log>
|
||||
<dees-chart-log class="eventLog" .label=${'Event Log'}></dees-chart-log>
|
||||
</div>
|
||||
`
|
||||
)}
|
||||
`;
|
||||
}
|
||||
}
|
133
ts_web/elements/cloudly-view-s3.ts
Normal file
133
ts_web/elements/cloudly-view-s3.ts
Normal file
@ -0,0 +1,133 @@
|
||||
import * as plugins from '../plugins.js';
|
||||
|
||||
import {
|
||||
DeesElement,
|
||||
customElement,
|
||||
html,
|
||||
state,
|
||||
css,
|
||||
cssManager,
|
||||
} from '@design.estate/dees-element';
|
||||
|
||||
import * as appstate from '../appstate.js';
|
||||
|
||||
@customElement('cloudly-view-s3')
|
||||
export class CloudlyViewS3 extends DeesElement {
|
||||
@state()
|
||||
private data: appstate.IDataState = {
|
||||
secretGroups: [],
|
||||
secretBundles: [],
|
||||
};
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
const subecription = appstate.dataState
|
||||
.select((stateArg) => stateArg)
|
||||
.subscribe((dataArg) => {
|
||||
this.data = dataArg;
|
||||
});
|
||||
this.rxSubscriptions.push(subecription);
|
||||
}
|
||||
|
||||
public static styles = [
|
||||
cssManager.defaultStyles,
|
||||
css`
|
||||
:host {
|
||||
display: block;
|
||||
margin: auto;
|
||||
max-width: 1280px;
|
||||
padding: 16px 16px;
|
||||
}
|
||||
`,
|
||||
];
|
||||
|
||||
public render() {
|
||||
return html`
|
||||
<cloudly-sectionheading>S3</cloudly-sectionheading>
|
||||
<dees-table
|
||||
.heading1=${'S3'}
|
||||
.heading2=${'decoded in client'}
|
||||
.data=${this.data.s3}
|
||||
.displayFunction=${(itemArg: plugins.interfaces.data.ICluster) => {
|
||||
return {
|
||||
id: itemArg.id,
|
||||
serverAmount: itemArg.data.servers.length,
|
||||
};
|
||||
}}
|
||||
.dataActions=${[
|
||||
{
|
||||
name: 'add configBundle',
|
||||
iconName: 'plus',
|
||||
type: ['header', 'footer'],
|
||||
actionFunc: async (dataActionArg) => {
|
||||
const modal = await plugins.deesCatalog.DeesModal.createAndShow({
|
||||
heading: 'Add ConfigBundle',
|
||||
content: html`
|
||||
<dees-form>
|
||||
<dees-input-text .key=${'id'} .label=${'ID'} .value=${''}></dees-input-text>
|
||||
<dees-input-text
|
||||
.key=${'data.secretGroupIds'}
|
||||
.label=${'secretGroupIds'}
|
||||
.value=${''}
|
||||
></dees-input-text>
|
||||
<dees-input-text
|
||||
.key=${'data.includedTags'}
|
||||
.label=${'includedTags'}
|
||||
.value=${''}
|
||||
></dees-input-text>
|
||||
</dees-form>
|
||||
`,
|
||||
menuOptions: [
|
||||
{ name: 'create', action: async (modalArg) => {} },
|
||||
{
|
||||
name: 'cancel',
|
||||
action: async (modalArg) => {
|
||||
modalArg.destroy();
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'delete',
|
||||
iconName: 'trash',
|
||||
type: ['contextmenu', 'inRow'],
|
||||
actionFunc: async (actionDataArg) => {
|
||||
plugins.deesCatalog.DeesModal.createAndShow({
|
||||
heading: `Delete ConfigBundle ${actionDataArg.item.id}`,
|
||||
content: html`
|
||||
<div style="text-align:center">
|
||||
Do you really want to delete the ConfigBundle?
|
||||
</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;"
|
||||
>
|
||||
${actionDataArg.item.id}
|
||||
</div>
|
||||
`,
|
||||
menuOptions: [
|
||||
{
|
||||
name: 'cancel',
|
||||
action: async (modalArg) => {
|
||||
await modalArg.destroy();
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'delete',
|
||||
action: async (modalArg) => {
|
||||
appstate.dataState.dispatchAction(appstate.deleteSecretBundleAction, {
|
||||
configBundleId: actionDataArg.item.id,
|
||||
});
|
||||
await modalArg.destroy();
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
] as plugins.deesCatalog.ITableAction[]}
|
||||
></dees-table>
|
||||
`;
|
||||
}
|
||||
}
|
173
ts_web/elements/cloudly-view-secretbundles.ts
Normal file
173
ts_web/elements/cloudly-view-secretbundles.ts
Normal file
@ -0,0 +1,173 @@
|
||||
import * as plugins from '../plugins.js';
|
||||
|
||||
import {
|
||||
DeesElement,
|
||||
customElement,
|
||||
html,
|
||||
state,
|
||||
css,
|
||||
cssManager,
|
||||
} from '@design.estate/dees-element';
|
||||
|
||||
import * as appstate from '../appstate.js';
|
||||
|
||||
@customElement('cloudly-view-secretbundles')
|
||||
export class CloudlyViewSecretBundles extends DeesElement {
|
||||
@state()
|
||||
private data: appstate.IDataState = {
|
||||
secretGroups: [],
|
||||
secretBundles: [],
|
||||
};
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
const subecription = appstate.dataState
|
||||
.select((stateArg) => stateArg)
|
||||
.subscribe((dataArg) => {
|
||||
this.data = dataArg;
|
||||
});
|
||||
this.rxSubscriptions.push(subecription);
|
||||
}
|
||||
|
||||
public static styles = [
|
||||
cssManager.defaultStyles,
|
||||
css`
|
||||
:host {
|
||||
display: block;
|
||||
margin: auto;
|
||||
max-width: 1280px;
|
||||
padding: 16px 16px;
|
||||
}
|
||||
`,
|
||||
];
|
||||
|
||||
public render() {
|
||||
return html`
|
||||
<cloudly-sectionheading>SecretBundles</cloudly-sectionheading>
|
||||
<dees-table
|
||||
.heading1=${'SecretBundles'}
|
||||
.heading2=${'decoded in client'}
|
||||
.data=${this.data.secretBundles}
|
||||
.displayFunction=${(itemArg: plugins.interfaces.data.ISecretBundle) => {
|
||||
return {
|
||||
name: itemArg.data.name,
|
||||
secretGroups: (() => {
|
||||
const secretGroupIds = itemArg.data.includedSecretGroupIds;
|
||||
let secretGroupNames: string[] = [];
|
||||
for (const secretGroupId of secretGroupIds) {
|
||||
const secretGroup = this.data.secretGroups.find(
|
||||
(secretGroupArg) => secretGroupArg.id === secretGroupId
|
||||
);
|
||||
if (secretGroup) {
|
||||
secretGroupNames.push(secretGroup.data.name);
|
||||
}
|
||||
}
|
||||
return secretGroupNames.join(', ');
|
||||
})(),
|
||||
tags: html`<dees-chips
|
||||
.selectionMode=${'none'}
|
||||
.selectableChips=${itemArg.data.includedTags}
|
||||
></dees-chips>`,
|
||||
};
|
||||
}}
|
||||
.dataActions=${[
|
||||
{
|
||||
name: 'add SecretBundle',
|
||||
iconName: 'plus',
|
||||
type: ['header', 'footer'],
|
||||
actionFunc: async (dataActionArg) => {
|
||||
const modal = await plugins.deesCatalog.DeesModal.createAndShow({
|
||||
heading: 'Add SecretBundle',
|
||||
content: html`
|
||||
<dees-form>
|
||||
<dees-input-text .key=${'id'} .label=${'ID'} .value=${''}></dees-input-text>
|
||||
<dees-input-text
|
||||
.key=${'data.secretGroupIds'}
|
||||
.label=${'secretGroupIds'}
|
||||
.value=${''}
|
||||
></dees-input-text>
|
||||
<dees-input-text
|
||||
.key=${'data.includedTags'}
|
||||
.label=${'includedTags'}
|
||||
.value=${''}
|
||||
></dees-input-text>
|
||||
</dees-form>
|
||||
`,
|
||||
menuOptions: [
|
||||
{ name: 'create', action: async (modalArg) => {} },
|
||||
{
|
||||
name: 'cancel',
|
||||
action: async (modalArg) => {
|
||||
modalArg.destroy();
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'delete',
|
||||
iconName: 'trash',
|
||||
type: ['contextmenu', 'inRow'],
|
||||
actionFunc: async (actionDataArg) => {
|
||||
plugins.deesCatalog.DeesModal.createAndShow({
|
||||
heading: `Delete ConfigBundle ${actionDataArg.item.id}`,
|
||||
content: html`
|
||||
<div style="text-align:center">
|
||||
Do you really want to delete the ConfigBundle?
|
||||
</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;"
|
||||
>
|
||||
${actionDataArg.item.id}
|
||||
</div>
|
||||
`,
|
||||
menuOptions: [
|
||||
{
|
||||
name: 'cancel',
|
||||
action: async (modalArg) => {
|
||||
await modalArg.destroy();
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'delete',
|
||||
action: async (modalArg) => {
|
||||
appstate.dataState.dispatchAction(appstate.deleteSecretBundleAction, {
|
||||
configBundleId: actionDataArg.item.id,
|
||||
});
|
||||
await modalArg.destroy();
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'edit',
|
||||
iconName: 'edit',
|
||||
type: ['doubleClick', 'contextmenu', 'inRow'],
|
||||
actionFunc: async (actionDataArg) => {
|
||||
const modal = await plugins.deesCatalog.DeesModal.createAndShow({
|
||||
heading: 'Edit SecretBundle',
|
||||
content: html`
|
||||
<dees-form>
|
||||
<dees-input-text .label=${'purpose'}></dees-input-text>
|
||||
</dees-form>
|
||||
`,
|
||||
menuOptions: [
|
||||
{ name: 'save', action: async (modalArg) => {} },
|
||||
{
|
||||
name: 'cancel',
|
||||
action: async (modalArg) => {
|
||||
modalArg.destroy();
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
] as plugins.deesCatalog.ITableAction[]}
|
||||
></dees-table>
|
||||
`;
|
||||
}
|
||||
}
|
367
ts_web/elements/cloudly-view-secretgroups.ts
Normal file
367
ts_web/elements/cloudly-view-secretgroups.ts
Normal file
@ -0,0 +1,367 @@
|
||||
import * as plugins from '../plugins.js';
|
||||
|
||||
import { DeesElement, customElement, html, state, css, cssManager } from '@design.estate/dees-element';
|
||||
|
||||
import * as appstate from '../appstate.js';
|
||||
|
||||
@customElement('cloudly-view-secretsgroups')
|
||||
export class CloudlyViewSecretGroups extends DeesElement {
|
||||
@state()
|
||||
private data: appstate.IDataState = {
|
||||
secretGroups: [],
|
||||
secretBundles: [],
|
||||
};
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
appstate.dataState
|
||||
.select((stateArg) => stateArg)
|
||||
.subscribe((dataArg) => {
|
||||
this.data = dataArg;
|
||||
});
|
||||
}
|
||||
|
||||
public static styles = [
|
||||
cssManager.defaultStyles,
|
||||
css`
|
||||
:host {
|
||||
display: block;
|
||||
margin: auto;
|
||||
max-width: 1280px;
|
||||
padding: 16px 16px;
|
||||
}
|
||||
`,
|
||||
];
|
||||
|
||||
public render() {
|
||||
return html`
|
||||
<cloudly-sectionheading>SecretGroups</cloudly-sectionheading>
|
||||
<dees-table
|
||||
heading1="SecretGroups"
|
||||
heading2="decoded in client"
|
||||
.data=${this.data.secretGroups}
|
||||
.displayFunction=${(secretGroup: plugins.interfaces.data.ISecretGroup) => {
|
||||
return {
|
||||
name: secretGroup.data.name,
|
||||
priority: secretGroup.data.priority,
|
||||
tags: html`<dees-chips
|
||||
.selectionMode=${'none'}
|
||||
.selectableChips=${secretGroup.data.tags}
|
||||
></dees-chips>`,
|
||||
key: secretGroup.data.key,
|
||||
history: (() => {
|
||||
const allHistory = [];
|
||||
for (const environment in secretGroup.data.environments) {
|
||||
allHistory.push(...secretGroup.data.environments[environment].history);
|
||||
}
|
||||
return allHistory.length;
|
||||
})(),
|
||||
};
|
||||
}}
|
||||
.dataActions=${[
|
||||
{
|
||||
name: 'add SecretGroup',
|
||||
type: ['header', 'footer'],
|
||||
iconName: 'plus',
|
||||
actionFunc: async () => {
|
||||
plugins.deesCatalog.DeesModal.createAndShow({
|
||||
heading: 'create new SecretGroup',
|
||||
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-input-text
|
||||
.label=${'Secret Key (data.key)'}
|
||||
.key=${'data.key'}
|
||||
.value=${''}
|
||||
></dees-input-text>
|
||||
<dees-table
|
||||
.heading1=${'Environments'}
|
||||
.heading2=${'keys need to be unique'}
|
||||
key="environments"
|
||||
.data=${[
|
||||
{
|
||||
environment: 'production',
|
||||
value: '',
|
||||
},
|
||||
{
|
||||
environment: 'staging',
|
||||
value: '',
|
||||
},
|
||||
]}
|
||||
.dataActions=${[
|
||||
{
|
||||
name: 'add environment',
|
||||
iconName: 'plus',
|
||||
type: ['footer'],
|
||||
actionFunc: async (dataArg) => {
|
||||
dataArg.table.data.push({
|
||||
environment: 'new environment',
|
||||
value: '',
|
||||
});
|
||||
dataArg.table.requestUpdate('data');
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'delete environment',
|
||||
iconName: 'trash',
|
||||
type: ['inRow'],
|
||||
actionFunc: async (dataArg) => {
|
||||
dataArg.table.data.splice(dataArg.table.data.indexOf(dataArg.item), 1);
|
||||
dataArg.table.requestUpdate('data');
|
||||
},
|
||||
},
|
||||
] as plugins.deesCatalog.ITableAction[]}
|
||||
.editableFields=${['environment', 'value']}
|
||||
></dees-table>
|
||||
</dees-form>
|
||||
`,
|
||||
menuOptions: [
|
||||
{
|
||||
name: 'cancel',
|
||||
action: async (modalArg) => {
|
||||
await modalArg.destroy();
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'save',
|
||||
action: async (modalArg) => {
|
||||
const deesForm = modalArg.shadowRoot.querySelector('dees-form');
|
||||
const formData = await deesForm.collectFormData();
|
||||
console.log(`Prepare saving of data:`);
|
||||
console.log(formData);
|
||||
const environments: plugins.interfaces.data.ISecretGroup['data']['environments'] =
|
||||
{};
|
||||
for (const itemArg of formData['environments'] as any[]) {
|
||||
environments[itemArg.environment] = {
|
||||
value: itemArg.value,
|
||||
history: [],
|
||||
lastUpdated: Date.now(),
|
||||
};
|
||||
}
|
||||
await appstate.dataState.dispatchAction(appstate.createSecretGroupAction, {
|
||||
id: null,
|
||||
data: {
|
||||
name: formData['data.name'] as string,
|
||||
description: formData['data.description'] as string,
|
||||
key: formData['data.key'] as string,
|
||||
environments,
|
||||
tags: [],
|
||||
},
|
||||
});
|
||||
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) => {
|
||||
return {
|
||||
environment: itemArg.environment,
|
||||
value: itemArg.value,
|
||||
};
|
||||
})}
|
||||
.editableFields=${['environment', 'value']}
|
||||
.dataActions=${[
|
||||
{
|
||||
name: 'delete',
|
||||
iconName: 'trash',
|
||||
type: ['inRow'],
|
||||
actionFunc: async (actionDataArg) => {
|
||||
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) => {
|
||||
await modalArg.destroy();
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Save',
|
||||
iconName: null,
|
||||
action: async (modalArg) => {
|
||||
const data = await modalArg.shadowRoot
|
||||
.querySelector('dees-form')
|
||||
.collectFormData();
|
||||
console.log(data);
|
||||
const updatedSecretGroup: plugins.interfaces.data.ISecretGroup = {
|
||||
id: dataArg.item.id,
|
||||
data: {
|
||||
name: data['data.name'] as string,
|
||||
description: data['data.description'] as string,
|
||||
key: data['data.key'] as string,
|
||||
environments: {},
|
||||
tags: dataArg.item.data.tags,
|
||||
},
|
||||
};
|
||||
const environments: plugins.interfaces.data.ISecretGroup['data']['environments'] =
|
||||
{};
|
||||
for (const itemArg of data['environments'] as any[]) {
|
||||
}
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
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) => {
|
||||
await modalArg.destroy();
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'delete',
|
||||
iconName: 'trash',
|
||||
type: ['contextmenu', 'inRow'],
|
||||
actionFunc: async (
|
||||
itemArg: plugins.deesCatalog.ITableActionDataArg<plugins.interfaces.data.ISecretGroup>
|
||||
) => {
|
||||
plugins.deesCatalog.DeesModal.createAndShow({
|
||||
heading: `Delete ${itemArg.item.data.key}`,
|
||||
content: html`
|
||||
<div style="text-align:center">Do you really want to delete the secret?</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.data.key}
|
||||
</div>
|
||||
`,
|
||||
menuOptions: [
|
||||
{
|
||||
name: 'cancel',
|
||||
action: async (modalArg) => {
|
||||
await modalArg.destroy();
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'delete',
|
||||
action: async (modalArg) => {
|
||||
console.log(`Delete ${itemArg.item.id}`);
|
||||
await appstate.dataState.dispatchAction(appstate.deleteSecretGroupAction, {
|
||||
secretGroupId: itemArg.item.id,
|
||||
});
|
||||
await modalArg.destroy();
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
] as plugins.deesCatalog.ITableAction[]}
|
||||
></dees-table>
|
||||
`;
|
||||
}
|
||||
}
|
133
ts_web/elements/cloudly-view-services.ts
Normal file
133
ts_web/elements/cloudly-view-services.ts
Normal file
@ -0,0 +1,133 @@
|
||||
import * as plugins from '../plugins.js';
|
||||
|
||||
import {
|
||||
DeesElement,
|
||||
customElement,
|
||||
html,
|
||||
state,
|
||||
css,
|
||||
cssManager,
|
||||
} from '@design.estate/dees-element';
|
||||
|
||||
import * as appstate from '../appstate.js';
|
||||
|
||||
@customElement('cloudly-view-services')
|
||||
export class CloudlyViewServices extends DeesElement {
|
||||
@state()
|
||||
private data: appstate.IDataState = {
|
||||
secretGroups: [],
|
||||
secretBundles: [],
|
||||
};
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
const subecription = appstate.dataState
|
||||
.select((stateArg) => stateArg)
|
||||
.subscribe((dataArg) => {
|
||||
this.data = dataArg;
|
||||
});
|
||||
this.rxSubscriptions.push(subecription);
|
||||
}
|
||||
|
||||
public static styles = [
|
||||
cssManager.defaultStyles,
|
||||
css`
|
||||
:host {
|
||||
display: block;
|
||||
margin: auto;
|
||||
max-width: 1280px;
|
||||
padding: 16px 16px;
|
||||
}
|
||||
`,
|
||||
];
|
||||
|
||||
public render() {
|
||||
return html`
|
||||
<cloudly-sectionheading>Services</cloudly-sectionheading>
|
||||
<dees-table
|
||||
.heading1=${'Services'}
|
||||
.heading2=${'decoded in client'}
|
||||
.data=${this.data.services}
|
||||
.displayFunction=${(itemArg: plugins.interfaces.data.ICluster) => {
|
||||
return {
|
||||
id: itemArg.id,
|
||||
serverAmount: itemArg.data.servers.length,
|
||||
};
|
||||
}}
|
||||
.dataActions=${[
|
||||
{
|
||||
name: 'add configBundle',
|
||||
iconName: 'plus',
|
||||
type: ['header', 'footer'],
|
||||
actionFunc: async (dataActionArg) => {
|
||||
const modal = await plugins.deesCatalog.DeesModal.createAndShow({
|
||||
heading: 'Add ConfigBundle',
|
||||
content: html`
|
||||
<dees-form>
|
||||
<dees-input-text .key=${'id'} .label=${'ID'} .value=${''}></dees-input-text>
|
||||
<dees-input-text
|
||||
.key=${'data.secretGroupIds'}
|
||||
.label=${'secretGroupIds'}
|
||||
.value=${''}
|
||||
></dees-input-text>
|
||||
<dees-input-text
|
||||
.key=${'data.includedTags'}
|
||||
.label=${'includedTags'}
|
||||
.value=${''}
|
||||
></dees-input-text>
|
||||
</dees-form>
|
||||
`,
|
||||
menuOptions: [
|
||||
{ name: 'create', action: async (modalArg) => {} },
|
||||
{
|
||||
name: 'cancel',
|
||||
action: async (modalArg) => {
|
||||
modalArg.destroy();
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'delete',
|
||||
iconName: 'trash',
|
||||
type: ['contextmenu', 'inRow'],
|
||||
actionFunc: async (actionDataArg) => {
|
||||
plugins.deesCatalog.DeesModal.createAndShow({
|
||||
heading: `Delete ConfigBundle ${actionDataArg.item.id}`,
|
||||
content: html`
|
||||
<div style="text-align:center">
|
||||
Do you really want to delete the ConfigBundle?
|
||||
</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;"
|
||||
>
|
||||
${actionDataArg.item.id}
|
||||
</div>
|
||||
`,
|
||||
menuOptions: [
|
||||
{
|
||||
name: 'cancel',
|
||||
action: async (modalArg) => {
|
||||
await modalArg.destroy();
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'delete',
|
||||
action: async (modalArg) => {
|
||||
appstate.dataState.dispatchAction(appstate.deleteSecretBundleAction, {
|
||||
configBundleId: actionDataArg.item.id,
|
||||
});
|
||||
await modalArg.destroy();
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
},
|
||||
] as plugins.deesCatalog.ITableAction[]}
|
||||
></dees-table>
|
||||
`;
|
||||
}
|
||||
}
|
4
ts_web/elements/index.ts
Normal file
4
ts_web/elements/index.ts
Normal file
@ -0,0 +1,4 @@
|
||||
export * from './shared/index.js';
|
||||
export * from './cloudly-dashboard.js';
|
||||
export * from './cloudly-view-secretgroups.js';
|
||||
export * from './cloudly-view-secretbundles.js';
|
33
ts_web/elements/shared/cloudly-sectionheading.ts
Normal file
33
ts_web/elements/shared/cloudly-sectionheading.ts
Normal file
@ -0,0 +1,33 @@
|
||||
import * as plugins from '../../plugins.js';
|
||||
|
||||
import {
|
||||
customElement,
|
||||
html,
|
||||
DeesElement,
|
||||
property,
|
||||
type TemplateResult,
|
||||
cssManager,
|
||||
css,
|
||||
unsafeCSS,
|
||||
type CSSResult,
|
||||
state,
|
||||
} from '@design.estate/dees-element';
|
||||
|
||||
@customElement('cloudly-sectionheading')
|
||||
export class CloudlySectionheading extends DeesElement {
|
||||
public static styles = [
|
||||
cssManager.defaultStyles,
|
||||
css`
|
||||
h1 {
|
||||
font-family: 'Cal Sans';
|
||||
letter-spacing: 0.025em;
|
||||
}
|
||||
`,
|
||||
]
|
||||
|
||||
public render() {
|
||||
return html`
|
||||
<h1><slot></slot></h1>
|
||||
`;
|
||||
}
|
||||
}
|
1
ts_web/elements/shared/index.ts
Normal file
1
ts_web/elements/shared/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './cloudly-sectionheading.js';
|
Reference in New Issue
Block a user