import { Component, inject, signal, OnInit } from '@angular/core'; import { Router, RouterLink } from '@angular/router'; import { FormsModule } from '@angular/forms'; import { ApiService } from '../../core/services/api.service'; import { ToastService } from '../../core/services/toast.service'; import { IServiceCreate, IDomainDetail } from '../../core/types/api.types'; import { CardComponent, CardHeaderComponent, CardTitleComponent, CardDescriptionComponent, CardContentComponent, CardFooterComponent, } from '../../ui/card/card.component'; import { ButtonComponent } from '../../ui/button/button.component'; import { InputComponent } from '../../ui/input/input.component'; import { LabelComponent } from '../../ui/label/label.component'; import { CheckboxComponent } from '../../ui/checkbox/checkbox.component'; import { AlertComponent, AlertDescriptionComponent } from '../../ui/alert/alert.component'; import { SeparatorComponent } from '../../ui/separator/separator.component'; interface EnvVar { key: string; value: string; } @Component({ selector: 'app-service-create', standalone: true, imports: [ FormsModule, RouterLink, CardComponent, CardHeaderComponent, CardTitleComponent, CardDescriptionComponent, CardContentComponent, CardFooterComponent, ButtonComponent, InputComponent, LabelComponent, CheckboxComponent, AlertComponent, AlertDescriptionComponent, SeparatorComponent, ], template: `
Back to Services

Deploy Service

Deploy a new Docker service

Service Configuration Configure your service settings

Lowercase letters, numbers, and hyphens only

e.g., nginx:latest, registry.example.com/image:tag

@for (d of domains(); track d.domain.domain) { } @if (domainWarning()) { {{ domainWarning() }} }

Environment Variables

Configure environment variables for your service

@if (envVars().length > 0) {
@for (env of envVars(); track $index; let i = $index) {
}
}

Platform Services

Enable managed infrastructure for your service

A dedicated database will be created and credentials injected as MONGODB_URI

A dedicated bucket will be created and credentials injected as S3_* and AWS_* env vars

@if (form.enableMongoDB || form.enableS3) { Platform services will be auto-deployed if not already running. Credentials are automatically injected as environment variables. }

Push images directly to this Onebox instance

@if (form.useOneboxRegistry) {
}
`, }) export class ServiceCreateComponent implements OnInit { private api = inject(ApiService); private router = inject(Router); private toast = inject(ToastService); form: IServiceCreate = { name: '', image: '', port: 80, domain: '', useOneboxRegistry: false, registryImageTag: 'latest', autoUpdateOnPush: false, enableMongoDB: false, enableS3: false, }; envVars = signal([]); domains = signal([]); loading = signal(false); domainWarning = signal(null); ngOnInit(): void { this.loadDomains(); } async loadDomains(): Promise { try { const response = await this.api.getDomains(); if (response.success && response.data) { this.domains.set(response.data); } } catch { // Silent fail - domain autocomplete is optional } } addEnvVar(): void { this.envVars.update(vars => [...vars, { key: '', value: '' }]); } removeEnvVar(index: number): void { this.envVars.update(vars => vars.filter((_, i) => i !== index)); } validateDomain(): void { if (!this.form.domain) { this.domainWarning.set(null); return; } const domain = this.domains().find(d => d.domain.domain === this.form.domain); if (!domain) { this.domainWarning.set('This domain is not in your domain list. DNS and SSL may not be configured automatically.'); } else if (domain.domain.isObsolete) { this.domainWarning.set('This domain is marked as obsolete.'); } else { this.domainWarning.set(null); } } async onSubmit(): Promise { if (!this.form.name || !this.form.image || !this.form.port) { this.toast.error('Please fill in all required fields'); return; } this.loading.set(true); // Build env vars object const envVarsObj: Record = {}; for (const env of this.envVars()) { if (env.key && env.value) { envVarsObj[env.key] = env.value; } } const data: IServiceCreate = { ...this.form, envVars: Object.keys(envVarsObj).length > 0 ? envVarsObj : undefined, }; try { const response = await this.api.createService(data); if (response.success) { this.toast.success(`Service "${this.form.name}" deployed successfully`); this.router.navigate(['/services']); } else { this.toast.error(response.error || 'Failed to deploy service'); } } catch { this.toast.error('Failed to deploy service'); } finally { this.loading.set(false); } } }