diff --git a/scripts/db/mongo-setup.js b/scripts/db/mongo-setup.js index eac8dd0c..1a629d6e 100644 --- a/scripts/db/mongo-setup.js +++ b/scripts/db/mongo-setup.js @@ -264,6 +264,20 @@ result = db.collectionConfig.insertOne({ update: true, }, }, + lifecycle: { + name: 'Lifecycle', + required: false, + type: 'select', + options: [ + { value: 'experimental', label: 'Experimental' }, + { value: 'production', label: 'Production' }, + { value: 'deprecated', label: 'Deprecated' }, + ], + hint: 'The lifecycle stage of the service', + mask: { + update: true, + }, + }, scmUrl: { name: 'SCM URL', required: false, @@ -273,6 +287,20 @@ result = db.collectionConfig.insertOne({ update: true, }, }, + type: { + name: 'Type', + required: false, + type: 'select', + options: [ + { value: 'service', label: 'Service' }, + { value: 'website', label: 'Website' }, + { value: 'library', label: 'Library' }, + ], + hint: 'The type of service', + mask: { + update: true, + }, + }, vaultConfig: { type: 'embeddedDoc', required: false, diff --git a/src/persistence/dto/collection-config.dto.ts b/src/persistence/dto/collection-config.dto.ts index 55c2b2ce..0541ce96 100644 --- a/src/persistence/dto/collection-config.dto.ts +++ b/src/persistence/dto/collection-config.dto.ts @@ -36,6 +36,11 @@ export type CollectionEdgeInstanceConfig = Omit< prototype: CollectionEdgePrototype; }; +export class CollectionFieldSelectOption { + value!: string; + label!: string; +} + export class CollectionFieldConfig { hint!: string; init?: 'uuid' | 'now'; @@ -54,13 +59,14 @@ export class CollectionFieldConfig { | 'embeddedDocArray' | 'json' | 'number' + | 'select' | 'string' | 'stringArray' | 'url'; unique?: boolean; uniqueParent?: boolean; value?: string | boolean; - valuePath?: string; + options?: CollectionFieldSelectOption[]; } export class CollectionFieldConfigMap { diff --git a/src/persistence/dto/intention-action-pointer.dto.ts b/src/persistence/dto/intention-action-pointer.dto.ts index 54bae946..d78c0d26 100644 --- a/src/persistence/dto/intention-action-pointer.dto.ts +++ b/src/persistence/dto/intention-action-pointer.dto.ts @@ -10,5 +10,7 @@ export class IntentionActionPointerDto { @IsString() @IsDefined() intention!: string; + + @IsOptional() source?: any; } diff --git a/src/persistence/dto/service.dto.ts b/src/persistence/dto/service.dto.ts index 67a44d55..c5a668f8 100644 --- a/src/persistence/dto/service.dto.ts +++ b/src/persistence/dto/service.dto.ts @@ -24,6 +24,14 @@ export class ServiceBaseDto extends CollectionBaseDto { @IsOptional() title?: string; + @IsString() + @IsOptional() + lifecycle?: string; + + @IsString() + @IsOptional() + type?: string; + @IsString() @IsOptional() scmUrl?: string; diff --git a/src/persistence/entity/service.entity.ts b/src/persistence/entity/service.entity.ts index 83023bff..93878911 100644 --- a/src/persistence/entity/service.entity.ts +++ b/src/persistence/entity/service.entity.ts @@ -32,6 +32,12 @@ export class ServiceEntity extends VertexPointerEntity { @Property({ nullable: true }) title?: string; + @Property({ nullable: true }) + lifecycle?: string; + + @Property({ nullable: true }) + type?: string; + @Property({ nullable: true }) scmUrl?: string; diff --git a/ui/src/app/graph/inspector-vertex-field/inspector-vertex-field.component.html b/ui/src/app/graph/inspector-vertex-field/inspector-vertex-field.component.html index ba96be9f..7644e62e 100644 --- a/ui/src/app/graph/inspector-vertex-field/inspector-vertex-field.component.html +++ b/ui/src/app/graph/inspector-vertex-field/inspector-vertex-field.component.html @@ -19,6 +19,9 @@ @case ('number') { {{value}} } + @case ('select') { + {{ selectValueToLabel(value) }} + } @case ('string') { {{value}} } diff --git a/ui/src/app/graph/inspector-vertex-field/inspector-vertex-field.component.ts b/ui/src/app/graph/inspector-vertex-field/inspector-vertex-field.component.ts index c200242c..d950fa3c 100644 --- a/ui/src/app/graph/inspector-vertex-field/inspector-vertex-field.component.ts +++ b/ui/src/app/graph/inspector-vertex-field/inspector-vertex-field.component.ts @@ -3,12 +3,22 @@ import { Component, Input } from '@angular/core'; import { CollectionFieldConfig } from '../../service/persistence/dto/collection-config.dto'; @Component({ - selector: 'app-inspector-vertex-field', - imports: [DatePipe], - templateUrl: './inspector-vertex-field.component.html', - styleUrl: './inspector-vertex-field.component.scss' + selector: 'app-inspector-vertex-field', + imports: [DatePipe], + templateUrl: './inspector-vertex-field.component.html', + styleUrl: './inspector-vertex-field.component.scss', }) export class InspectorVertexFieldComponent { @Input() public config: CollectionFieldConfig | undefined; @Input() public value: any; + + selectValueToLabel(value: any): string { + if (value) { + return ( + this.config?.options?.find((option) => option.value === value)?.label ?? + value + ); + } + return ''; + } } diff --git a/ui/src/app/graph/vertex-form-builder/vertex-form-builder.component.ts b/ui/src/app/graph/vertex-form-builder/vertex-form-builder.component.ts index 87c36256..068151e2 100644 --- a/ui/src/app/graph/vertex-form-builder/vertex-form-builder.component.ts +++ b/ui/src/app/graph/vertex-form-builder/vertex-form-builder.component.ts @@ -116,6 +116,13 @@ export class VertexFormBuilderComponent implements OnInit, OnChanges { ); } + if (f.type === 'select') { + fieldCtrls[f.key] = new FormControl( + data && data[f.key] ? data[f.key] : '', + validators, + ); + } + if (f.type === 'email') { validators.push(Validators.email); fieldCtrls[f.key] = new FormControl( diff --git a/ui/src/app/graph/vertex-form-field/vertex-form-field.component.html b/ui/src/app/graph/vertex-form-field/vertex-form-field.component.html index 5c4f3593..cb50c496 100644 --- a/ui/src/app/graph/vertex-form-field/vertex-form-field.component.html +++ b/ui/src/app/graph/vertex-form-field/vertex-form-field.component.html @@ -86,6 +86,21 @@ } } + @case ('select') { + + @if (field.name) { + {{field.name}} + } + + @for (option of field.options; track option) { + {{option.label}} + } + + @if (field.hint) { + {{field.hint}} + } + + } @case ('date') { @if (field.name) { diff --git a/ui/src/app/graph/vertex-form-field/vertex-form-field.component.ts b/ui/src/app/graph/vertex-form-field/vertex-form-field.component.ts index 6e24f447..1df87a2e 100644 --- a/ui/src/app/graph/vertex-form-field/vertex-form-field.component.ts +++ b/ui/src/app/graph/vertex-form-field/vertex-form-field.component.ts @@ -1,3 +1,4 @@ +import { CommonModule } from '@angular/common'; import { Component, EventEmitter, Input, Output } from '@angular/core'; import { FormGroup, FormsModule, ReactiveFormsModule } from '@angular/forms'; import { TextFieldModule } from '@angular/cdk/text-field'; @@ -6,23 +7,26 @@ import { MatInputModule } from '@angular/material/input'; import { MatFormFieldModule } from '@angular/material/form-field'; import { MatDatepickerModule } from '@angular/material/datepicker'; import { MatTooltipModule } from '@angular/material/tooltip'; +import { MatSelectModule } from '@angular/material/select'; import { CollectionFieldConfigNameMapped } from '../../service/graph.types'; @Component({ - selector: 'app-vertex-form-field', - templateUrl: './vertex-form-field.component.html', - styleUrls: ['./vertex-form-field.component.scss'], - imports: [ - FormsModule, - ReactiveFormsModule, - MatFormFieldModule, - MatCheckboxModule, - MatDatepickerModule, - MatInputModule, - MatTooltipModule, - TextFieldModule, - ] + selector: 'app-vertex-form-field', + templateUrl: './vertex-form-field.component.html', + styleUrls: ['./vertex-form-field.component.scss'], + imports: [ + CommonModule, + FormsModule, + ReactiveFormsModule, + MatFormFieldModule, + MatCheckboxModule, + MatDatepickerModule, + MatInputModule, + MatSelectModule, + MatTooltipModule, + TextFieldModule, + ], }) export class VertexFormFieldComponent { @Input() field!: CollectionFieldConfigNameMapped; diff --git a/ui/src/app/service/persistence/dto/collection-config.dto.ts b/ui/src/app/service/persistence/dto/collection-config.dto.ts index 55c2b2ce..0541ce96 100644 --- a/ui/src/app/service/persistence/dto/collection-config.dto.ts +++ b/ui/src/app/service/persistence/dto/collection-config.dto.ts @@ -36,6 +36,11 @@ export type CollectionEdgeInstanceConfig = Omit< prototype: CollectionEdgePrototype; }; +export class CollectionFieldSelectOption { + value!: string; + label!: string; +} + export class CollectionFieldConfig { hint!: string; init?: 'uuid' | 'now'; @@ -54,13 +59,14 @@ export class CollectionFieldConfig { | 'embeddedDocArray' | 'json' | 'number' + | 'select' | 'string' | 'stringArray' | 'url'; unique?: boolean; uniqueParent?: boolean; value?: string | boolean; - valuePath?: string; + options?: CollectionFieldSelectOption[]; } export class CollectionFieldConfigMap { diff --git a/ui/src/app/service/persistence/dto/intention-action-pointer.dto.ts b/ui/src/app/service/persistence/dto/intention-action-pointer.dto.ts index 54bae946..d78c0d26 100644 --- a/ui/src/app/service/persistence/dto/intention-action-pointer.dto.ts +++ b/ui/src/app/service/persistence/dto/intention-action-pointer.dto.ts @@ -10,5 +10,7 @@ export class IntentionActionPointerDto { @IsString() @IsDefined() intention!: string; + + @IsOptional() source?: any; } diff --git a/ui/src/app/service/persistence/dto/service.dto.ts b/ui/src/app/service/persistence/dto/service.dto.ts index 67a44d55..c5a668f8 100644 --- a/ui/src/app/service/persistence/dto/service.dto.ts +++ b/ui/src/app/service/persistence/dto/service.dto.ts @@ -24,6 +24,14 @@ export class ServiceBaseDto extends CollectionBaseDto { @IsOptional() title?: string; + @IsString() + @IsOptional() + lifecycle?: string; + + @IsString() + @IsOptional() + type?: string; + @IsString() @IsOptional() scmUrl?: string;