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;