diff --git a/src/app/bulk-edit/bulk-edit-editor/bulk-edit-editor.component.ts b/src/app/bulk-edit/bulk-edit-editor/bulk-edit-editor.component.ts
index c4ef2c0c0..5cae86a48 100644
--- a/src/app/bulk-edit/bulk-edit-editor/bulk-edit-editor.component.ts
+++ b/src/app/bulk-edit/bulk-edit-editor/bulk-edit-editor.component.ts
@@ -63,7 +63,8 @@ import { MatButton } from '@angular/material/button';
import { MatToolbar } from '@angular/material/toolbar';
import {
decodeSourceCodeValue,
- isSourceCodeProfileDataType
+ getSourceCodeEditorOptionsForDataType,
+ isCodeEditorProfileDataType
} from '@mdm/shared/source-code/source-code-value';
@Component({
@@ -361,14 +362,19 @@ export class BulkEditEditorComponent implements OnInit {
};
}
- if (isSourceCodeProfileDataType(field.dataType as string)) {
+ if (isCodeEditorProfileDataType(field.dataType as string)) {
+ const sourceCodeEditorOptions = getSourceCodeEditorOptionsForDataType(
+ field.dataType as string
+ );
+
column.cellEditor = 'sourceCodeCellEditor';
column.cellEditorParams = {
+ ...sourceCodeEditorOptions,
onFilePickerOpen: () => this.setStopEditingWhenCellsLoseFocus(false),
onFilePickerClose: () => this.setStopEditingWhenCellsLoseFocus(true)
};
column.valueFormatter = (params) => {
- const value = decodeSourceCodeValue(params.value);
+ const value = decodeSourceCodeValue(params.value, sourceCodeEditorOptions);
return value.source ? `${value.language}: ${value.source}` : '';
};
}
diff --git a/src/app/bulk-edit/bulk-edit-editor/cell-editors/source-code-cell-editor/source-code-cell-editor.component.html b/src/app/bulk-edit/bulk-edit-editor/cell-editors/source-code-cell-editor/source-code-cell-editor.component.html
index da167943b..d5a001317 100644
--- a/src/app/bulk-edit/bulk-edit-editor/cell-editors/source-code-cell-editor/source-code-cell-editor.component.html
+++ b/src/app/bulk-edit/bulk-edit-editor/cell-editors/source-code-cell-editor/source-code-cell-editor.component.html
@@ -28,6 +28,7 @@
Language
diff --git a/src/app/bulk-edit/bulk-edit-editor/cell-editors/source-code-cell-editor/source-code-cell-editor.component.ts b/src/app/bulk-edit/bulk-edit-editor/cell-editors/source-code-cell-editor/source-code-cell-editor.component.ts
index 97058050c..b352d584a 100644
--- a/src/app/bulk-edit/bulk-edit-editor/cell-editors/source-code-cell-editor/source-code-cell-editor.component.ts
+++ b/src/app/bulk-edit/bulk-edit-editor/cell-editors/source-code-cell-editor/source-code-cell-editor.component.ts
@@ -45,12 +45,16 @@ import {
import {
decodeSourceCodeValue,
defaultSourceCodeLanguage,
- encodeSourceCodeValue
+ encodeSourceCodeValue,
+ SourceCodeValueFormat
} from '@mdm/shared/source-code/source-code-value';
export type PopupPosition = 'under' | 'over';
interface SourceCodeCellEditorParams {
+ fixedLanguage?: string
+ pinLanguage?: boolean
+ valueFormat?: SourceCodeValueFormat
onFilePickerOpen?: () => void
onFilePickerClose?: () => void
}
@@ -82,7 +86,11 @@ export class SourceCodeCellEditorComponent implements ICellEditorAngularComp, On
agInit(params: ICellEditorParams & SourceCodeCellEditorParams): void {
this.params = params;
this.originalValue = this.params.value ?? '';
- const value = decodeSourceCodeValue(this.params.value);
+ const value = decodeSourceCodeValue(this.params.value, {
+ fixedLanguage: this.params.fixedLanguage,
+ pinLanguage: this.params.pinLanguage,
+ valueFormat: this.params.valueFormat
+ });
this.language = value.language;
this.source = value.source;
}
@@ -107,7 +115,7 @@ export class SourceCodeCellEditorComponent implements ICellEditorAngularComp, On
return encodeSourceCodeValue({
language: this.language,
source: this.source
- });
+ }, this.params.valueFormat);
}
isPopup(): boolean {
@@ -119,11 +127,13 @@ export class SourceCodeCellEditorComponent implements ICellEditorAngularComp, On
}
onLanguageChange() {
+ this.applyPinnedLanguage();
this.hasChanged = true;
}
onSourceChange(value: string) {
this.source = value;
+ this.applyPinnedLanguage();
this.hasChanged = true;
}
@@ -139,23 +149,29 @@ export class SourceCodeCellEditorComponent implements ICellEditorAngularComp, On
const file = target.files[0];
const extension = file.name.split('.').pop();
- const language = this.supportedLanguages.find(
- lang => lang.fileExt === extension
- );
- if (!language) {
- this.importFileName = '';
- target.value = '';
- return;
+ if (!this.params.pinLanguage) {
+ const language = this.supportedLanguages.find(
+ lang => lang.fileExt === extension
+ );
+
+ if (!language) {
+ this.importFileName = '';
+ target.value = '';
+ return;
+ }
+
+ this.language = language.value;
}
this.importFileName = file.name;
- this.language = language.value;
+ this.applyPinnedLanguage();
this.hasChanged = true;
const reader = new FileReader();
reader.onload = () => {
this.source = reader.result?.toString() ?? '';
+ this.applyPinnedLanguage();
this.hasChanged = true;
};
reader.readAsText(file);
@@ -196,4 +212,10 @@ export class SourceCodeCellEditorComponent implements ICellEditorAngularComp, On
stopEvent(event: Event) {
event.stopPropagation();
}
+
+ private applyPinnedLanguage() {
+ if (this.params.pinLanguage && this.params.fixedLanguage) {
+ this.language = this.params.fixedLanguage;
+ }
+ }
}
diff --git a/src/app/modals/edit-profile-section/edit-profile-section.component.html b/src/app/modals/edit-profile-section/edit-profile-section.component.html
index dcef0e800..1cc66bb5f 100644
--- a/src/app/modals/edit-profile-section/edit-profile-section.component.html
+++ b/src/app/modals/edit-profile-section/edit-profile-section.component.html
@@ -43,12 +43,15 @@ {{ profileSection.label }}
id="{{ field.fieldName }}"
[inEditMode]="!field.uneditable"
[rootElement]="data.catalogueItem"
- *ngIf="field.dataType === 'text' && !isSourceCode(field)"
+ *ngIf="field.dataType === 'text' && !isCodeEditor(field)"
>
{{ profileSection.label }}
field.dataType !== 'folder' &&
field.dataType !== 'model' &&
field.dataType != 'text' &&
- !isSourceCode(field) &&
+ !isCodeEditor(field) &&
field.dataType != 'date' &&
field.dataType != 'datetime' &&
field.dataType != 'boolean' &&
diff --git a/src/app/modals/edit-profile-section/edit-profile-section.component.ts b/src/app/modals/edit-profile-section/edit-profile-section.component.ts
index f68adeb4d..ce743e181 100644
--- a/src/app/modals/edit-profile-section/edit-profile-section.component.ts
+++ b/src/app/modals/edit-profile-section/edit-profile-section.component.ts
@@ -45,7 +45,11 @@ import { MatTooltip } from '@angular/material/tooltip';
import { FormsModule } from '@angular/forms';
import { NgIf, NgFor, NgClass } from '@angular/common';
import { SourceCodeEditorComponent } from '@mdm/shared/source-code/source-code-editor.component';
-import { isSourceCodeProfileDataType } from '@mdm/shared/source-code/source-code-value';
+import {
+ getSourceCodeEditorOptionsForDataType,
+ isCodeEditorProfileDataType,
+ SourceCodeValueFormat
+} from '@mdm/shared/source-code/source-code-value';
@Component({
selector: '[mdm-edit-profile-section]',
@@ -147,8 +151,26 @@ export class EditProfileSectionComponent implements OnInit {
return items.sort((a, b) => (a > b ? 1 : a === b ? 0 : -1));
}
- isSourceCode(field: ProfileField): boolean {
- return isSourceCodeProfileDataType(field.dataType as string);
+ isCodeEditor(field: ProfileField): boolean {
+ return isCodeEditorProfileDataType(field.dataType as string);
+ }
+
+ codeEditorFixedLanguage(field: ProfileField): string | undefined {
+ return getSourceCodeEditorOptionsForDataType(
+ field.dataType as string
+ ).fixedLanguage;
+ }
+
+ codeEditorPinLanguage(field: ProfileField): boolean {
+ return !!getSourceCodeEditorOptionsForDataType(
+ field.dataType as string
+ ).pinLanguage;
+ }
+
+ codeEditorValueFormat(field: ProfileField): SourceCodeValueFormat {
+ return getSourceCodeEditorOptionsForDataType(
+ field.dataType as string
+ ).valueFormat ?? 'sourcecode';
}
showAddElementToMarkdown(field: ProfileField) {
diff --git a/src/app/shared/profile-section/profile-section.component.html b/src/app/shared/profile-section/profile-section.component.html
index b96fb506c..e48e756d0 100644
--- a/src/app/shared/profile-section/profile-section.component.html
+++ b/src/app/shared/profile-section/profile-section.component.html
@@ -44,12 +44,15 @@
id="{{ field.fieldName }}"
[inEditMode]="false"
[rootElement]="rootObject"
- *ngIf="field.dataType === 'text' && !isSourceCode(field.dataType)"
+ *ngIf="field.dataType === 'text' && !isCodeEditor(field.dataType)"
>
Language
();
@Input() inEditMode = true;
+ @Input() fixedLanguage?: string;
+ @Input() pinLanguage = false;
+ @Input() valueFormat: SourceCodeValueFormat = 'sourcecode';
language = defaultSourceCodeLanguage;
source = '';
@@ -83,8 +87,17 @@ export class SourceCodeEditorComponent implements OnChanges, OnDestroy {
private copiedTimeout?: ReturnType;
ngOnChanges(changes: SimpleChanges): void {
- if (changes.value) {
- const decoded = decodeSourceCodeValue(this.value);
+ if (
+ changes.value
+ || changes.fixedLanguage
+ || changes.pinLanguage
+ || changes.valueFormat
+ ) {
+ const decoded = decodeSourceCodeValue(this.value, {
+ fixedLanguage: this.fixedLanguage,
+ pinLanguage: this.pinLanguage,
+ valueFormat: this.valueFormat
+ });
this.language = decoded.language;
this.source = decoded.source;
this.highlightedSource = this.highlightSource();
@@ -113,12 +126,14 @@ export class SourceCodeEditorComponent implements OnChanges, OnDestroy {
}
onLanguageChange() {
+ this.applyPinnedLanguage();
this.highlightedSource = this.highlightSource();
this.emitValue();
}
onSourceChange(value: string) {
this.source = value;
+ this.applyPinnedLanguage();
this.highlightedSource = this.highlightSource();
this.emitValue();
}
@@ -132,22 +147,29 @@ export class SourceCodeEditorComponent implements OnChanges, OnDestroy {
const file = target.files[0];
const extension = file.name.split('.').pop();
- const language = this.supportedLanguages.find(
- lang => lang.fileExt === extension
- );
- if (!language) {
- this.importFileName = '';
- target.value = '';
- return;
+ if (!this.pinLanguage) {
+ const language = this.supportedLanguages.find(
+ lang => lang.fileExt === extension
+ );
+
+ if (!language) {
+ this.importFileName = '';
+ target.value = '';
+ return;
+ }
+
+ this.language = language.value;
}
this.importFileName = file.name;
- this.language = language.value;
+ this.applyPinnedLanguage();
const reader = new FileReader();
reader.onload = () => {
this.source = reader.result?.toString() ?? '';
+ this.applyPinnedLanguage();
+ this.highlightedSource = this.highlightSource();
this.emitValue();
};
reader.readAsText(file);
@@ -168,10 +190,17 @@ export class SourceCodeEditorComponent implements OnChanges, OnDestroy {
}
private emitValue() {
+ this.applyPinnedLanguage();
this.valueChange.emit(encodeSourceCodeValue({
language: this.language,
source: this.source
- }));
+ }, this.valueFormat));
+ }
+
+ private applyPinnedLanguage() {
+ if (this.pinLanguage && this.fixedLanguage) {
+ this.language = this.fixedLanguage;
+ }
}
private highlightSource(): string {
diff --git a/src/app/shared/source-code/source-code-value.ts b/src/app/shared/source-code/source-code-value.ts
index d7aae16f4..a7f7f766b 100644
--- a/src/app/shared/source-code/source-code-value.ts
+++ b/src/app/shared/source-code/source-code-value.ts
@@ -20,32 +20,62 @@ export interface SourceCodeValue {
source: string
}
+export type SourceCodeValueFormat = 'sourcecode' | 'plain';
+
+export interface SourceCodeEditorOptions {
+ fixedLanguage?: string
+ pinLanguage?: boolean
+ valueFormat?: SourceCodeValueFormat
+}
+
export const defaultSourceCodeLanguage = 'text';
-export const encodeSourceCodeValue = (value: SourceCodeValue): string =>
- JSON.stringify({
+export const encodeSourceCodeValue = (
+ value: SourceCodeValue,
+ valueFormat: SourceCodeValueFormat = 'sourcecode'
+): string => {
+ if (valueFormat === 'plain') {
+ return value.source ?? '';
+ }
+
+ return JSON.stringify({
language: value.language || defaultSourceCodeLanguage,
source: value.source ?? ''
});
+};
+
+export const decodeSourceCodeValue = (
+ value?: string,
+ options?: SourceCodeEditorOptions
+): SourceCodeValue => {
+ const language = options?.fixedLanguage || defaultSourceCodeLanguage;
-export const decodeSourceCodeValue = (value?: string): SourceCodeValue => {
if (!value) {
return {
- language: defaultSourceCodeLanguage,
+ language,
source: ''
};
}
+ if (options?.valueFormat === 'plain') {
+ return {
+ language,
+ source: value
+ };
+ }
+
try {
const parsed = JSON.parse(value);
return {
- language: parsed.language || defaultSourceCodeLanguage,
+ language: options?.pinLanguage
+ ? language
+ : parsed.language || language,
source: parsed.source ?? parsed.representation ?? ''
};
}
catch {
return {
- language: defaultSourceCodeLanguage,
+ language,
source: value
};
}
@@ -53,3 +83,22 @@ export const decodeSourceCodeValue = (value?: string): SourceCodeValue => {
export const isSourceCodeProfileDataType = (dataType?: string): boolean =>
dataType === 'sourcecode';
+
+export const isCodeEditorProfileDataType = (dataType?: string): boolean =>
+ dataType === 'sourcecode' || dataType === 'json';
+
+export const getSourceCodeEditorOptionsForDataType = (
+ dataType?: string
+): SourceCodeEditorOptions => {
+ if (dataType === 'json') {
+ return {
+ fixedLanguage: 'json',
+ pinLanguage: true,
+ valueFormat: 'plain'
+ };
+ }
+
+ return {
+ valueFormat: 'sourcecode'
+ };
+};