diff --git a/client/src/app/core/translate/translation-parser.ts b/client/src/app/core/translate/translation-parser.ts
index 9beeadaab..f8215248c 100644
--- a/client/src/app/core/translate/translation-parser.ts
+++ b/client/src/app/core/translate/translation-parser.ts
@@ -2,12 +2,12 @@ import { TranslateDefaultParser, TranslateStore } from '@ngx-translate/core';
import { ConfigService } from '../services/config.service';
import { Injectable } from '@angular/core';
-interface CustomTranslation {
+export interface CustomTranslation {
original: string;
translation: string;
}
-type CustomTranslations = CustomTranslation[];
+export type CustomTranslations = CustomTranslation[];
/**
* Custom translate parser. Intercepts and use custom translations from the configservice.
diff --git a/client/src/app/site/config/components/config-field/config-field.component.html b/client/src/app/site/config/components/config-field/config-field.component.html
index f0bb07ce2..c7ad43af0 100644
--- a/client/src/app/site/config/components/config-field/config-field.component.html
+++ b/client/src/app/site/config/components/config-field/config-field.component.html
@@ -69,6 +69,11 @@
{{ configItem.label | translate }}
+
+
+
+
+
diff --git a/client/src/app/site/config/components/config-field/config-field.component.ts b/client/src/app/site/config/components/config-field/config-field.component.ts
index e04d9e63f..ba5a661ee 100644
--- a/client/src/app/site/config/components/config-field/config-field.component.ts
+++ b/client/src/app/site/config/components/config-field/config-field.component.ts
@@ -54,7 +54,7 @@ export class ConfigFieldComponent extends BaseComponent implements OnInit {
*/
@Input()
public set item(value: ViewConfig) {
- if (value.hasConstantsInfo) {
+ if (value && value.hasConstantsInfo) {
this.configItem = value;
if (this.form) {
@@ -155,10 +155,7 @@ export class ConfigFieldComponent extends BaseComponent implements OnInit {
if (this.configItem.inputType === 'datetimepicker') {
value = Date.parse(value);
}
- // TODO: Solve this via a custom input form.
- if (this.configItem.inputType === 'translations') {
- value = JSON.parse(value);
- }
+
this.debounceTimeout = null;
this.repo.update({ value: value }, this.configItem).then(() => {
this.error = null;
@@ -215,7 +212,7 @@ export class ConfigFieldComponent extends BaseComponent implements OnInit {
* @returns wheather it should be excluded or not
*/
public isExcludedType(type: string): boolean {
- const excluded = ['boolean', 'markupText', 'text'];
+ const excluded = ['boolean', 'markupText', 'text', 'translations'];
return excluded.includes(type);
}
}
diff --git a/client/src/app/site/config/components/config-list/config-list.component.spec.ts b/client/src/app/site/config/components/config-list/config-list.component.spec.ts
index 14a13fee2..24f611883 100644
--- a/client/src/app/site/config/components/config-list/config-list.component.spec.ts
+++ b/client/src/app/site/config/components/config-list/config-list.component.spec.ts
@@ -3,6 +3,7 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { E2EImportsModule } from '../../../../../e2e-imports.module';
import { ConfigListComponent } from './config-list.component';
import { ConfigFieldComponent } from '../config-field/config-field.component';
+import { CustomTranslationComponent } from '../custom-translation/custom-translation.component';
describe('ConfigListComponent', () => {
let component: ConfigListComponent;
@@ -11,7 +12,7 @@ describe('ConfigListComponent', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [E2EImportsModule],
- declarations: [ConfigListComponent, ConfigFieldComponent]
+ declarations: [ConfigListComponent, ConfigFieldComponent, CustomTranslationComponent]
}).compileComponents();
}));
diff --git a/client/src/app/site/config/components/custom-translation/custom-translation.component.html b/client/src/app/site/config/components/custom-translation/custom-translation.component.html
new file mode 100644
index 000000000..031522523
--- /dev/null
+++ b/client/src/app/site/config/components/custom-translation/custom-translation.component.html
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
diff --git a/client/src/app/site/config/components/custom-translation/custom-translation.component.scss b/client/src/app/site/config/components/custom-translation/custom-translation.component.scss
new file mode 100644
index 000000000..e69de29bb
diff --git a/client/src/app/site/config/components/custom-translation/custom-translation.component.spec.ts b/client/src/app/site/config/components/custom-translation/custom-translation.component.spec.ts
new file mode 100644
index 000000000..d48e687d6
--- /dev/null
+++ b/client/src/app/site/config/components/custom-translation/custom-translation.component.spec.ts
@@ -0,0 +1,26 @@
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { CustomTranslationComponent } from './custom-translation.component';
+import { E2EImportsModule } from 'e2e-imports.module';
+
+describe('CustomTranslationComponent', () => {
+ let component: CustomTranslationComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ imports: [E2EImportsModule],
+ declarations: [CustomTranslationComponent]
+ }).compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(CustomTranslationComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/client/src/app/site/config/components/custom-translation/custom-translation.component.ts b/client/src/app/site/config/components/custom-translation/custom-translation.component.ts
new file mode 100644
index 000000000..9cbd8e661
--- /dev/null
+++ b/client/src/app/site/config/components/custom-translation/custom-translation.component.ts
@@ -0,0 +1,118 @@
+import { Component, forwardRef } from '@angular/core';
+
+import { CustomTranslation, CustomTranslations } from 'app/core/translate/translation-parser';
+import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
+
+/**
+ * Custom translations as custom form component
+ *
+ * @example:
+ * ```html
+ *
+ * ```
+ */
+@Component({
+ selector: 'os-custom-translation',
+ templateUrl: './custom-translation.component.html',
+ styleUrls: ['./custom-translation.component.scss'],
+ providers: [
+ {
+ provide: NG_VALUE_ACCESSOR,
+ useExisting: forwardRef(() => CustomTranslationComponent),
+ multi: true
+ }
+ ]
+})
+export class CustomTranslationComponent implements ControlValueAccessor {
+ /**
+ * Holds the custom translations in a list
+ */
+ public translations: CustomTranslations = [];
+
+ /**
+ * Empty constructor
+ */
+ public constructor() {}
+
+ /**
+ * Helper function to determine which information to give to the parent form
+ */
+ private propagateChange = (_: any) => {};
+
+ /**
+ * The value from the FormControl
+ *
+ * @param obj the value from the parent form. Type "any" is required by the interface
+ */
+ public writeValue(obj: any): void {
+ if (obj) {
+ this.translations = obj;
+ }
+ }
+
+ /**
+ * Hands changes back to the parent form
+ *
+ * @param fn the function to propagate the changes
+ */
+ public registerOnChange(fn: any): void {
+ this.propagateChange = fn;
+ }
+
+ /**
+ * To satisfy the interface.
+ *
+ * @param fn
+ */
+ public registerOnTouched(fn: any): void {}
+
+ /**
+ * To satisfy the interface
+ *
+ * @param isDisabled
+ */
+ public setDisabledState?(isDisabled: boolean): void {}
+
+ /**
+ * Detects changes to the "original" word
+ *
+ * @param value the value that was typed
+ * @param index the index of the change
+ */
+ public onChangeOriginal(value: string, index: number): void {
+ this.translations[index].original = value;
+ this.propagateChange(this.translations);
+ }
+
+ /**
+ * Detects changes to the translation
+ * @param value the value that was typed
+ * @param index the index of the change
+ */
+ public onChangeTranslation(value: string, index: number): void {
+ this.translations[index].translation = value;
+ this.propagateChange(this.translations);
+ }
+
+ /**
+ * Removes a custom translation
+ * @param index the translation to remove
+ */
+ public onRemoveTranslation(index: number): void {
+ this.translations.splice(index, 1);
+ this.propagateChange(this.translations);
+ }
+
+ /**
+ * Adds a new custom translation to the list and to the server
+ */
+ public onAddNewTranslation(): void {
+ const newCustomTranslation: CustomTranslation = {
+ original: 'New',
+ translation: 'New'
+ };
+
+ this.translations.push(newCustomTranslation);
+ this.propagateChange(this.translations);
+ }
+}
diff --git a/client/src/app/site/config/config.module.ts b/client/src/app/site/config/config.module.ts
index 2230cba92..2d935b995 100644
--- a/client/src/app/site/config/config.module.ts
+++ b/client/src/app/site/config/config.module.ts
@@ -4,9 +4,11 @@ import { SharedModule } from '../../shared/shared.module';
import { ConfigRoutingModule } from './config-routing.module';
import { ConfigListComponent } from './components/config-list/config-list.component';
import { ConfigFieldComponent } from './components/config-field/config-field.component';
+import { CustomTranslationComponent } from './components/custom-translation/custom-translation.component';
@NgModule({
imports: [CommonModule, ConfigRoutingModule, SharedModule],
- declarations: [ConfigListComponent, ConfigFieldComponent]
+ declarations: [ConfigListComponent, ConfigFieldComponent, CustomTranslationComponent],
+ entryComponents: [CustomTranslationComponent]
})
export class ConfigModule {}
diff --git a/client/src/app/site/config/models/view-config.ts b/client/src/app/site/config/models/view-config.ts
index a41758125..508e9c1f1 100644
--- a/client/src/app/site/config/models/view-config.ts
+++ b/client/src/app/site/config/models/view-config.ts
@@ -112,7 +112,9 @@ export class ViewConfig extends BaseViewModel {
* like the type="color" input...
*/
public getDebouncingTimeout(): number {
- if (this.inputType === 'string' || this.inputType === 'text' || this.inputType === 'markupText') {
+ if (this.inputType === 'markupText' || this.inputType === 'translations') {
+ return 2500;
+ } else if (this.inputType === 'string' || this.inputType === 'text') {
return 1000;
} else {
return 100;