feat(appstore): add remote app store templates with service upgrades and Redis/MariaDB platform support
This commit is contained in:
@@ -142,6 +142,12 @@ export class ObViewServices extends DeesElement {
|
||||
@state()
|
||||
accessor pendingTemplate: any = null;
|
||||
|
||||
@state()
|
||||
accessor appStoreState: appstate.IAppStoreState = {
|
||||
apps: [],
|
||||
upgradeableServices: [],
|
||||
};
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
@@ -159,7 +165,12 @@ export class ObViewServices extends DeesElement {
|
||||
});
|
||||
this.rxSubscriptions.push(backupsSub);
|
||||
|
||||
// No subscription needed — pendingAppTemplate is checked in render()
|
||||
const appStoreSub = appstate.appStoreStatePart
|
||||
.select((s) => s)
|
||||
.subscribe((newState) => {
|
||||
this.appStoreState = newState;
|
||||
});
|
||||
this.rxSubscriptions.push(appStoreSub);
|
||||
}
|
||||
|
||||
public static styles = [
|
||||
@@ -215,6 +226,7 @@ export class ObViewServices extends DeesElement {
|
||||
await Promise.all([
|
||||
appstate.servicesStatePart.dispatchAction(appstate.fetchServicesAction, null),
|
||||
appstate.servicesStatePart.dispatchAction(appstate.fetchPlatformServicesAction, null),
|
||||
appstate.appStoreStatePart.dispatchAction(appstate.fetchUpgradeableServicesAction, null),
|
||||
]);
|
||||
|
||||
// If a platform service was selected from the dashboard, navigate to its detail
|
||||
@@ -230,20 +242,6 @@ export class ObViewServices extends DeesElement {
|
||||
|
||||
}
|
||||
|
||||
updated(changedProperties: Map<string, any>) {
|
||||
super.updated(changedProperties);
|
||||
// Check for pending app template from the App Store after each update
|
||||
const uiState = appstate.uiStatePart.getState();
|
||||
if (uiState.pendingAppTemplate && !this.pendingTemplate) {
|
||||
this.pendingTemplate = uiState.pendingAppTemplate;
|
||||
appstate.uiStatePart.setState({
|
||||
...appstate.uiStatePart.getState(),
|
||||
pendingAppTemplate: undefined,
|
||||
});
|
||||
this.currentView = 'create';
|
||||
}
|
||||
}
|
||||
|
||||
public render(): TemplateResult {
|
||||
switch (this.currentView) {
|
||||
case 'create':
|
||||
@@ -277,7 +275,14 @@ export class ObViewServices extends DeesElement {
|
||||
default: return status;
|
||||
}
|
||||
};
|
||||
const mappedPlatformServices = this.servicesState.platformServices.map((ps) => ({
|
||||
// Split platform services into active (running or core) and inactive (not in use)
|
||||
const activePlatformServices = this.servicesState.platformServices.filter(
|
||||
(ps) => ps.status === 'running' || ps.status === 'starting' || ps.status === 'stopping' || ps.isCore,
|
||||
);
|
||||
const inactivePlatformServices = this.servicesState.platformServices.filter(
|
||||
(ps) => !ps.isCore && (ps.status === 'not-deployed' || ps.status === 'stopped' || ps.status === 'failed'),
|
||||
);
|
||||
const mappedActivePlatformServices = activePlatformServices.map((ps) => ({
|
||||
name: ps.displayName,
|
||||
status: displayStatus(ps.status),
|
||||
running: ps.status === 'running',
|
||||
@@ -313,17 +318,45 @@ export class ObViewServices extends DeesElement {
|
||||
></sz-services-list-view>
|
||||
<ob-sectionheading style="margin-top: 32px;">Platform Services</ob-sectionheading>
|
||||
<div style="max-width: 500px;">
|
||||
<sz-platform-services-card
|
||||
.services=${mappedPlatformServices}
|
||||
@service-click=${(e: CustomEvent) => {
|
||||
const type = e.detail.type || this.servicesState.platformServices.find(
|
||||
(ps) => ps.displayName === e.detail.name,
|
||||
)?.type;
|
||||
if (type) {
|
||||
this.navigateToPlatformDetail(type);
|
||||
}
|
||||
}}
|
||||
></sz-platform-services-card>
|
||||
${mappedActivePlatformServices.length > 0 ? html`
|
||||
<sz-platform-services-card
|
||||
.services=${mappedActivePlatformServices}
|
||||
@service-click=${(e: CustomEvent) => {
|
||||
const type = e.detail.type || this.servicesState.platformServices.find(
|
||||
(ps) => ps.displayName === e.detail.name,
|
||||
)?.type;
|
||||
if (type) {
|
||||
this.navigateToPlatformDetail(type);
|
||||
}
|
||||
}}
|
||||
></sz-platform-services-card>
|
||||
` : ''}
|
||||
${inactivePlatformServices.length > 0 ? html`
|
||||
<div style="
|
||||
background: var(--ci-shade-1, #09090b);
|
||||
border: 1px solid var(--ci-shade-2, #27272a);
|
||||
border-radius: 8px;
|
||||
padding: 20px;
|
||||
margin-top: ${mappedActivePlatformServices.length > 0 ? '12px' : '0'};
|
||||
opacity: 0.5;
|
||||
">
|
||||
<div style="font-size: 13px; color: var(--ci-shade-4, #71717a); margin-bottom: 12px;">Available — not in use</div>
|
||||
<div style="display: flex; flex-direction: column; gap: 12px;">
|
||||
${inactivePlatformServices.map((ps) => html`
|
||||
<div
|
||||
style="display: flex; justify-content: space-between; align-items: center; padding: 8px 0; cursor: pointer; transition: opacity 200ms ease;"
|
||||
@click=${() => this.navigateToPlatformDetail(ps.type)}
|
||||
>
|
||||
<div style="display: flex; align-items: center; gap: 10px;">
|
||||
<div style="width: 8px; height: 8px; border-radius: 50%; background: var(--ci-shade-3, #3f3f46); flex-shrink: 0;"></div>
|
||||
<span style="font-size: 14px; font-weight: 500; color: var(--ci-shade-4, #71717a);">${ps.displayName}</span>
|
||||
</div>
|
||||
<span style="font-size: 13px; color: var(--ci-shade-3, #3f3f46);">${displayStatus(ps.status)}</span>
|
||||
</div>
|
||||
`)}
|
||||
</div>
|
||||
</div>
|
||||
` : ''}
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
@@ -344,6 +377,8 @@ export class ObViewServices extends DeesElement {
|
||||
enableMongoDB: template.enableMongoDB || false,
|
||||
enableS3: template.enableS3 || false,
|
||||
enableClickHouse: template.enableClickHouse || false,
|
||||
enableRedis: template.enableRedis || false,
|
||||
enableMariaDB: template.enableMariaDB || false,
|
||||
};
|
||||
await appstate.servicesStatePart.dispatchAction(appstate.createServiceAction, {
|
||||
config: serviceConfig,
|
||||
@@ -368,12 +403,14 @@ export class ObViewServices extends DeesElement {
|
||||
<div><span style="color: var(--ci-shade-5, #a1a1aa);">Service Name:</span> <strong>${t.id}</strong></div>
|
||||
<div><span style="color: var(--ci-shade-5, #a1a1aa);">Category:</span> <strong>${t.category}</strong></div>
|
||||
</div>
|
||||
${t.enableMongoDB || t.enableS3 || t.enableClickHouse ? html`
|
||||
${t.enableMongoDB || t.enableS3 || t.enableClickHouse || t.enableRedis || t.enableMariaDB ? html`
|
||||
<div style="margin-top: 12px; font-size: 13px; color: var(--ci-shade-5, #a1a1aa);">
|
||||
Platform Services:
|
||||
${t.enableMongoDB ? html`<span style="margin-right: 8px;">MongoDB</span>` : ''}
|
||||
${t.enableS3 ? html`<span style="margin-right: 8px;">S3</span>` : ''}
|
||||
${t.enableClickHouse ? html`<span>ClickHouse</span>` : ''}
|
||||
${t.enableClickHouse ? html`<span style="margin-right: 8px;">ClickHouse</span>` : ''}
|
||||
${t.enableRedis ? html`<span style="margin-right: 8px;">Redis</span>` : ''}
|
||||
${t.enableMariaDB ? html`<span style="margin-right: 8px;">MariaDB</span>` : ''}
|
||||
</div>
|
||||
` : ''}
|
||||
</div>
|
||||
@@ -407,6 +444,8 @@ export class ObViewServices extends DeesElement {
|
||||
enableMongoDB: formConfig.enableMongoDB || false,
|
||||
enableS3: formConfig.enableS3 || false,
|
||||
enableClickHouse: formConfig.enableClickHouse || false,
|
||||
enableRedis: formConfig.enableRedis || false,
|
||||
enableMariaDB: formConfig.enableMariaDB || false,
|
||||
};
|
||||
await appstate.servicesStatePart.dispatchAction(appstate.createServiceAction, {
|
||||
config: serviceConfig,
|
||||
@@ -428,8 +467,49 @@ export class ObViewServices extends DeesElement {
|
||||
: defaultStats;
|
||||
const transformedLogs = parseLogs(this.servicesState.currentServiceLogs);
|
||||
|
||||
// Check if this service has an available upgrade
|
||||
const upgradeInfo = service
|
||||
? this.appStoreState.upgradeableServices.find((u) => u.serviceName === service.name)
|
||||
: null;
|
||||
|
||||
return html`
|
||||
<ob-sectionheading>Service Details</ob-sectionheading>
|
||||
${upgradeInfo ? html`
|
||||
<div style="
|
||||
background: linear-gradient(135deg, rgba(59, 130, 246, 0.1), rgba(139, 92, 246, 0.1));
|
||||
border: 1px solid rgba(59, 130, 246, 0.3);
|
||||
border-radius: 8px;
|
||||
padding: 16px;
|
||||
margin-bottom: 16px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
">
|
||||
<div>
|
||||
<div style="font-size: 14px; font-weight: 600; color: var(--ci-shade-7, #e4e4e7);">
|
||||
Update available: v${upgradeInfo.currentVersion} → v${upgradeInfo.latestVersion}
|
||||
</div>
|
||||
<div style="font-size: 12px; color: var(--ci-shade-4, #71717a); margin-top: 4px;">
|
||||
${upgradeInfo.hasMigration ? 'Migration script available' : 'Config-only upgrade'}
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
class="deploy-button"
|
||||
style="padding: 8px 16px; font-size: 13px;"
|
||||
@click=${async () => {
|
||||
await appstate.appStoreStatePart.dispatchAction(appstate.upgradeServiceAction, {
|
||||
serviceName: upgradeInfo.serviceName,
|
||||
targetVersion: upgradeInfo.latestVersion,
|
||||
});
|
||||
// Refresh service data
|
||||
appstate.servicesStatePart.dispatchAction(appstate.fetchServiceAction, {
|
||||
name: upgradeInfo.serviceName,
|
||||
});
|
||||
appstate.servicesStatePart.dispatchAction(appstate.fetchServicesAction, null);
|
||||
}}
|
||||
>Upgrade</button>
|
||||
</div>
|
||||
` : ''}
|
||||
<sz-service-detail-view
|
||||
.service=${transformedService}
|
||||
.logs=${transformedLogs}
|
||||
@@ -530,6 +610,8 @@ export class ObViewServices extends DeesElement {
|
||||
minio: { host: 'onebox-minio', port: 9000, version: 'latest', config: { consolePort: 9001, region: 'us-east-1' } },
|
||||
clickhouse: { host: 'onebox-clickhouse', port: 8123, version: 'latest', config: { nativePort: 9000, httpPort: 8123 } },
|
||||
caddy: { host: 'onebox-caddy', port: 80, version: '2-alpine', config: { httpsPort: 443, adminApi: 2019 } },
|
||||
mariadb: { host: 'onebox-mariadb', port: 3306, version: '11', config: { engine: 'InnoDB', authEnabled: true } },
|
||||
redis: { host: 'onebox-redis', port: 6379, version: '7-alpine', config: { appendonly: true, maxDatabases: 16 } },
|
||||
};
|
||||
const info = platformService
|
||||
? serviceInfo[platformService.type] || { host: 'unknown', port: 0, version: '', config: {} }
|
||||
|
||||
Reference in New Issue
Block a user