-
-
+
+
diff --git a/apps/back-office/src/app/dashboard/pages/reference-data/reference-data.component.ts b/apps/back-office/src/app/dashboard/pages/reference-data/reference-data.component.ts
index f5d1b00c8e..c9348a50eb 100644
--- a/apps/back-office/src/app/dashboard/pages/reference-data/reference-data.component.ts
+++ b/apps/back-office/src/app/dashboard/pages/reference-data/reference-data.component.ts
@@ -27,6 +27,7 @@ import {
ApiConfigurationQueryResponse,
EditReferenceDataMutationResponse,
paginationStrategy,
+ containsFieldsValidator,
} from '@oort-front/shared';
import { Apollo, QueryRef } from 'apollo-angular';
import { EDIT_REFERENCE_DATA } from './graphql/mutations';
@@ -93,7 +94,7 @@ export class ReferenceDataComponent
public apiConfigurationsQuery!: QueryRef
;
/** List of query variables */
public queryVariables: string[] = [];
- /** Value fields */
+ /** Value fields to be displayed */
public valueFields: NonNullable = [];
/** Payload */
public payload: any;
@@ -140,6 +141,8 @@ export class ReferenceDataComponent
private addChipListTimeoutListener!: NodeJS.Timeout;
/** Outside click listener for inline edition */
private inlineEditionOutsideClickListener!: any;
+ /** Saves the original fields fetched from the reference data */
+ private dataFields: NonNullable = [];
/** size style of editor */
public style: any = {};
@@ -148,6 +151,20 @@ export class ReferenceDataComponent
return this.referenceForm.get('query') as FormControl | null;
}
+ /** @returns the fieldsControl form control */
+ get fieldsControl() {
+ const arrayControl = this.fb.array([]);
+ this.valueFields.forEach((value) => {
+ arrayControl.push(
+ this.fb.nonNullable.control(
+ value,
+ containsFieldsValidator(this.dataFields)
+ )
+ );
+ });
+ return arrayControl;
+ }
+
/** @returns name of reference model */
get name(): AbstractControl | null {
return this.referenceForm.get('name');
@@ -251,12 +268,7 @@ export class ReferenceDataComponent
}
};
- const handleQueryChange = (queryStr: string, resetFields = true) => {
- // Clear the fields
- if (resetFields) {
- clearFields();
- }
-
+ const handleQueryChange = (queryStr: string) => {
// Update the query variables
try {
const query = gql(queryStr ?? '');
@@ -277,6 +289,7 @@ export class ReferenceDataComponent
const clearFields = () => {
this.payload = null;
this.valueFields = [];
+ this.dataFields = [];
form.get('fields')?.setValue([], { emitEvent: false });
};
@@ -332,7 +345,7 @@ export class ReferenceDataComponent
.subscribe(setPaginationValidators);
// Initialize the query variables
- handleQueryChange(this.queryControl?.value, false);
+ handleQueryChange(this.queryControl?.value);
}, 100);
return form;
@@ -390,6 +403,11 @@ export class ReferenceDataComponent
? this.referenceData?.data
: [];
this.referenceForm = this.getRefDataForm();
+ if (!this.dataFields.length) {
+ this.dataFields =
+ this.referenceForm?.get('fields')?.value || [];
+ this.getFields(true);
+ }
this.valueFields = this.referenceForm?.get('fields')?.value || [];
this.loadApiConfigurations(
this.referenceForm?.get('type')?.value
@@ -809,8 +827,12 @@ export class ReferenceDataComponent
return array.map((it) => Object.values(it).toString()).join('\n');
}
- /** Uses the API Configuration to get the fields and parse their types. */
- public async getFields() {
+ /**
+ * Uses the API Configuration to get the fields and parse their types.
+ *
+ * @param init if starting component don't mark form as dirt, but get payload only
+ */
+ public async getFields(init = false) {
const apiConfID = this.referenceForm.value.apiConfiguration;
const path = this.referenceForm.value.path;
const query = this.referenceForm.value.query;
@@ -855,10 +877,15 @@ export class ReferenceDataComponent
query,
type
);
- this.valueFields = result.fields;
+ const fieldsCopy = cloneDeep(this.valueFields);
+ const manualFields = fieldsCopy.filter((field) => field.manual);
+ this.dataFields = result.fields;
+ this.valueFields = this.dataFields.concat(manualFields);
this.payload = result.payload;
this.referenceForm?.get('fields')?.setValue(this.valueFields);
- this.referenceForm.get('fields')?.markAsDirty();
+ if (!init) {
+ this.referenceForm.get('fields')?.markAsDirty();
+ }
} catch (e) {
if (e instanceof HttpErrorResponse) {
this.snackBar.openSnackBar(e.message, { error: true });
@@ -875,6 +902,7 @@ export class ReferenceDataComponent
onRemoveField(field: any) {
this.valueFields = this.valueFields.filter((x) => x.name !== field.name);
this.referenceForm?.get('fields')?.setValue(this.valueFields);
+ this.setReferenceFormValue();
}
/**
@@ -970,6 +998,7 @@ export class ReferenceDataComponent
'components.referenceData.fields.new'
),
type: 'string',
+ manual: true,
},
];
diff --git a/libs/shared/src/i18n/en.json b/libs/shared/src/i18n/en.json
index b5a752e2aa..d3a14abc2c 100644
--- a/libs/shared/src/i18n/en.json
+++ b/libs/shared/src/i18n/en.json
@@ -2509,7 +2509,8 @@
"help": "The fields are calculated based on the attributes of the first item in the payload.",
"missingConfig": "Can't fetch fields. Missing configuration: {{config}}",
"noFields": "No fields found",
- "title": "Field"
+ "title": "Field",
+ "noFound": "Field not found in the payload of the reference data."
},
"graphQLFilter": "GraphQL query parameters",
"pagination": {
diff --git a/libs/shared/src/i18n/fr.json b/libs/shared/src/i18n/fr.json
index 23dcd230d3..95db436299 100644
--- a/libs/shared/src/i18n/fr.json
+++ b/libs/shared/src/i18n/fr.json
@@ -2523,7 +2523,8 @@
"help": "Les champs sont calculés en fonction des attributs du premier élément dans la réponse de l'API",
"missingConfig": "Impossible de récupérer les champs. Configuration manquante : {{config}}",
"noFields": "Aucun champ trouvé",
- "title": "Champ"
+ "title": "Champ",
+ "noFound": "Champ introuvable dans la charge utile des données de référence."
},
"graphQLFilter": "Paramètres de la requête GraphQL",
"pagination": {
diff --git a/libs/shared/src/index.ts b/libs/shared/src/index.ts
index e0573fadb0..2337f6de43 100644
--- a/libs/shared/src/index.ts
+++ b/libs/shared/src/index.ts
@@ -144,3 +144,6 @@ export * from './lib/const/tinymce.const';
// === ENUM ===
export * from './lib/components/dashboard-filter/enums/dashboard-filters.enum';
+
+// === VALIDATORS ===
+export * from './lib/utils/validators/public-api';
diff --git a/libs/shared/src/lib/models/reference-data.model.ts b/libs/shared/src/lib/models/reference-data.model.ts
index d8a39856de..781ef2adcc 100644
--- a/libs/shared/src/lib/models/reference-data.model.ts
+++ b/libs/shared/src/lib/models/reference-data.model.ts
@@ -26,7 +26,12 @@ export interface ReferenceData {
apiConfiguration?: ApiConfiguration;
graphQLTypeName?: string;
query?: string;
- fields?: { name: string; type: string; graphQLFieldName?: string }[];
+ fields?: {
+ name: string;
+ type: string;
+ graphQLFieldName?: string;
+ manual?: boolean;
+ }[];
valueField?: string;
path?: string;
data?: any;
diff --git a/libs/shared/src/lib/utils/validators/containsFields.validator.ts b/libs/shared/src/lib/utils/validators/containsFields.validator.ts
new file mode 100644
index 0000000000..792d74b4fd
--- /dev/null
+++ b/libs/shared/src/lib/utils/validators/containsFields.validator.ts
@@ -0,0 +1,21 @@
+import { AbstractControl, ValidatorFn, ValidationErrors } from '@angular/forms';
+import { ReferenceData } from '../../models/reference-data.model';
+
+/**
+ * Checks if array of reference data fetched fields contains the field (current control value)
+ *
+ * @param fields array the all the available fields
+ * @returns null if the field is available, otherwise returns a validation error
+ */
+export function containsFieldsValidator(
+ fields: NonNullable
+): ValidatorFn {
+ return (control: AbstractControl): ValidationErrors | null => {
+ if (!control.value) {
+ // if there is no value, it should be valid
+ return null;
+ }
+ const hasField = fields.some((field) => field.name === control.value.name);
+ return hasField ? null : { invalidField: true };
+ };
+}
diff --git a/libs/shared/src/lib/utils/validators/public-api.ts b/libs/shared/src/lib/utils/validators/public-api.ts
new file mode 100644
index 0000000000..e933c92b64
--- /dev/null
+++ b/libs/shared/src/lib/utils/validators/public-api.ts
@@ -0,0 +1 @@
+export * from './containsFields.validator';