diff --git a/docs/core/card-view.component.md b/docs/core/card-view.component.md
index b31eeeec57..0172055ed0 100644
--- a/docs/core/card-view.component.md
+++ b/docs/core/card-view.component.md
@@ -74,6 +74,11 @@ Defining properties from Typescript:
key: 'mental-stability',
default: 0.0
}),
+ new CardViewKeyValuePairsItemModel({
+ label: 'Variables',
+ value: [],
+ key: 'key-value-pairs'
+ }),
...
]
```
@@ -99,6 +104,7 @@ You define the property list, the [`CardViewComponent`](../core/card-view.compon
- [**CardViewBoolItemModel**](#card-bool-item) - _for bool items (checkbox)_
- [**CardViewIntItemModel**](#card-int-item) - _for integer items_
- [**CardViewFloatItemModel**](#card-float-item) - _for float items_
+- [**CardViewKeyValuePairsItemModel**](#card-key-values-pairs-item) - _for key-value-pairs items_
Each of these types implements the [Card View Item interface](card-view-item.interface.md):
@@ -287,6 +293,23 @@ const floatItemProperty = new CardViewFloatItemModel(options);
| displayValue\* | float | | The value to display |
| editable | boolean | false | Toggles whether the item is editable |
+#### Card Key Value Pairs Item
+
+[`CardViewKeyValuePairsItemModel`](../../lib/core/card-view/models/card-view-keyvaluepairs.model.ts) is a property type for key-value properties.
+
+```ts
+const keyValuePairsItemProperty = new CardViewKeyValuePairsItemModel(options);
+```
+
+| Name | Type | Default | Description |
+| ---- | ---- | ------- | ----------- |
+| label\* | string | | Item label |
+| key\* | string | | Identifying key (important when editing the item) |
+| editable | boolean | false | Toggles whether the item is editable |
+| value\* | `[{ name: '', value: '' }, ...]` | | The original data value for the item |
+
+
+
## See also
- [Card View Update service](card-view-update.service.md)
diff --git a/lib/core/card-view/card-view.module.ts b/lib/core/card-view/card-view.module.ts
index ae5f2e068f..303932e299 100644
--- a/lib/core/card-view/card-view.module.ts
+++ b/lib/core/card-view/card-view.module.ts
@@ -21,6 +21,7 @@ import { FormsModule } from '@angular/forms';
import {
MatButtonModule,
MatDatepickerModule,
+ MatTableModule,
MatIconModule,
MatInputModule,
MatCheckboxModule,
@@ -37,6 +38,7 @@ import { CardViewDateItemComponent } from './components/card-view-dateitem/card-
import { CardViewItemDispatcherComponent } from './components/card-view-item-dispatcher/card-view-item-dispatcher.component';
import { CardViewMapItemComponent } from './components/card-view-mapitem/card-view-mapitem.component';
import { CardViewTextItemComponent } from './components/card-view-textitem/card-view-textitem.component';
+import { CardViewKeyValuePairsItemComponent } from './components/card-view-keyvaluepairsitem/card-view-keyvaluepairsitem.component';
@NgModule({
imports: [
@@ -48,6 +50,7 @@ import { CardViewTextItemComponent } from './components/card-view-textitem/card-
MatNativeDateModule,
MatCheckboxModule,
MatInputModule,
+ MatTableModule,
MatIconModule,
MatButtonModule,
MatDatetimepickerModule,
@@ -59,6 +62,7 @@ import { CardViewTextItemComponent } from './components/card-view-textitem/card-
CardViewDateItemComponent,
CardViewMapItemComponent,
CardViewTextItemComponent,
+ CardViewKeyValuePairsItemComponent,
CardViewItemDispatcherComponent,
CardViewContentProxyDirective
],
@@ -66,14 +70,16 @@ import { CardViewTextItemComponent } from './components/card-view-textitem/card-
CardViewBoolItemComponent,
CardViewDateItemComponent,
CardViewMapItemComponent,
- CardViewTextItemComponent
+ CardViewTextItemComponent,
+ CardViewKeyValuePairsItemComponent
],
exports: [
CardViewComponent,
CardViewBoolItemComponent,
CardViewDateItemComponent,
CardViewMapItemComponent,
- CardViewTextItemComponent
+ CardViewTextItemComponent,
+ CardViewKeyValuePairsItemComponent
]
})
export class CardViewModule {}
diff --git a/lib/core/card-view/components/card-view-keyvaluepairsitem/card-view-keyvaluepairsitem.component.html b/lib/core/card-view/components/card-view-keyvaluepairsitem/card-view-keyvaluepairsitem.component.html
new file mode 100644
index 0000000000..c4e71ce7a9
--- /dev/null
+++ b/lib/core/card-view/components/card-view-keyvaluepairsitem/card-view-keyvaluepairsitem.component.html
@@ -0,0 +1,58 @@
+
{{ property.label | translate }}
+
+
+
+ {{ 'CORE.CARDVIEW.KEYVALUEPAIRS.ADD' | translate }}
+
+
+
+
+
+
+ {{ 'CORE.CARDVIEW.KEYVALUEPAIRS.NAME' | translate }}
+ {{item.name}}
+
+
+ {{ 'CORE.CARDVIEW.KEYVALUEPAIRS.VALUE' | translate }}
+ {{item.value}}
+
+
+
+
+
+
+
+
+
+
+
{{ 'CORE.CARDVIEW.KEYVALUEPAIRS.NAME' | translate }}
+
{{ 'CORE.CARDVIEW.KEYVALUEPAIRS.VALUE' | translate }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/lib/core/card-view/components/card-view-keyvaluepairsitem/card-view-keyvaluepairsitem.component.scss b/lib/core/card-view/components/card-view-keyvaluepairsitem/card-view-keyvaluepairsitem.component.scss
new file mode 100644
index 0000000000..84caf9ce97
--- /dev/null
+++ b/lib/core/card-view/components/card-view-keyvaluepairsitem/card-view-keyvaluepairsitem.component.scss
@@ -0,0 +1,22 @@
+.card-view {
+ &__key-value-pairs {
+ &__col {
+ display: inline-block;
+ width: 39%;
+
+ .mat-form-field {
+ width: 100%;
+ }
+ }
+
+ &__read-only {
+ .mat-table {
+ box-shadow: none;
+ }
+
+ .mat-header-row, .mat-row {
+ padding: 0;
+ }
+ }
+ }
+}
diff --git a/lib/core/card-view/components/card-view-keyvaluepairsitem/card-view-keyvaluepairsitem.component.spec.ts b/lib/core/card-view/components/card-view-keyvaluepairsitem/card-view-keyvaluepairsitem.component.spec.ts
new file mode 100644
index 0000000000..c81e8cccd2
--- /dev/null
+++ b/lib/core/card-view/components/card-view-keyvaluepairsitem/card-view-keyvaluepairsitem.component.spec.ts
@@ -0,0 +1,176 @@
+/*!
+ * @license
+ * Copyright 2016 Alfresco Software, Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { ComponentFixture, TestBed, async } from '@angular/core/testing';
+import { By } from '@angular/platform-browser';
+import { CardViewKeyValuePairsItemModel } from '../../models/card-view-keyvaluepairs.model';
+import { CardViewKeyValuePairsItemComponent } from './card-view-keyvaluepairsitem.component';
+import { setupTestBed } from '../../../testing/setupTestBed';
+import { CoreTestingModule } from '../../../testing/core.testing.module';
+import { CardViewUpdateService } from '../../services/card-view-update.service';
+
+describe('CardViewKeyValuePairsItemComponent', () => {
+
+ let fixture: ComponentFixture;
+ let component: CardViewKeyValuePairsItemComponent;
+ let cardViewUpdateService;
+ const mockEmptyData = [{ name: '', value: '' }];
+ const mockData = [{ name: 'test-name', value: 'test-value' }];
+
+ setupTestBed({
+ imports: [CoreTestingModule]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(CardViewKeyValuePairsItemComponent);
+ cardViewUpdateService = TestBed.get(CardViewUpdateService);
+ component = fixture.componentInstance;
+ component.property = new CardViewKeyValuePairsItemModel({
+ label: 'Key Value Pairs',
+ value: [],
+ key: 'key-value-pairs',
+ editable: true
+ });
+ component.editable = true;
+ });
+
+ afterEach(() => {
+ fixture.destroy();
+ });
+
+ describe('Component', () => {
+
+ it('should render the label', () => {
+ fixture.detectChanges();
+
+ const labelValue = fixture.debugElement.query(By.css('.adf-property-label'));
+ expect(labelValue).not.toBeNull();
+ expect(labelValue.nativeElement.innerText).toBe('Key Value Pairs');
+ });
+
+ it('should render readOnly table is editable property is FALSE', () => {
+ component.property = new CardViewKeyValuePairsItemModel({
+ label: 'Key Value Pairs',
+ value: mockData,
+ key: 'key-value-pairs'
+ });
+
+ component.ngOnChanges();
+ fixture.detectChanges();
+
+ const table = fixture.debugElement.query(By.css('.card-view__key-value-pairs__read-only'));
+ const form = fixture.debugElement.query(By.css('.card-view__key-value-pairs'));
+
+ expect(table).not.toBeNull();
+ expect(form).toBeNull();
+ });
+
+ it('should add new item on ADD button click', () => {
+ component.ngOnChanges();
+ fixture.detectChanges();
+
+ const addButton = fixture.debugElement.query(By.css('.card-view__key-value-pairs__add-btn'));
+ addButton.triggerEventHandler('click', null);
+ fixture.detectChanges();
+
+ expect(JSON.stringify(component.values)).toBe(JSON.stringify(mockEmptyData));
+
+ const content = fixture.debugElement.query(By.css('.card-view__key-value-pairs'));
+ expect(content).not.toBeNull();
+
+ let nameInput = fixture.debugElement.query(By.css(`[data-automation-id="card-${component.property.key}-name-input-0"]`));
+ let valueInput = fixture.debugElement.query(By.css(`[data-automation-id="card-${component.property.key}-value-input-0"]`));
+ expect(nameInput).not.toBeNull();
+ expect(valueInput).not.toBeNull();
+
+ });
+
+ it('should remove an item from list on REMOVE button click', () => {
+ spyOn(cardViewUpdateService, 'update');
+ component.ngOnChanges();
+ fixture.detectChanges();
+
+ const addButton = fixture.debugElement.query(By.css('.card-view__key-value-pairs__add-btn'));
+ addButton.triggerEventHandler('click', null);
+ fixture.detectChanges();
+
+ const removeButton = fixture.debugElement.query(By.css('.card-view__key-value-pairs__remove-btn'));
+ removeButton.triggerEventHandler('click', null);
+ fixture.detectChanges();
+
+ expect(component.values.length).toBe(0);
+ const content = fixture.debugElement.query(By.css('.card-view__key-value-pairs'));
+ expect(content).toBeNull();
+
+ expect(cardViewUpdateService.update).toHaveBeenCalled();
+ expect(component.property.value.length).toBe(0);
+ });
+
+ it('should update property on input blur', async(() => {
+ spyOn(cardViewUpdateService, 'update');
+ component.ngOnChanges();
+ fixture.detectChanges();
+
+ const addButton = fixture.debugElement.query(By.css('.card-view__key-value-pairs__add-btn'));
+ addButton.triggerEventHandler('click', null);
+ fixture.detectChanges();
+
+ let nameInput = fixture.debugElement.query(By.css(`[data-automation-id="card-${component.property.key}-name-input-0"]`));
+ let valueInput = fixture.debugElement.query(By.css(`[data-automation-id="card-${component.property.key}-value-input-0"]`));
+
+ nameInput.nativeElement.value = mockData[0].name;
+ nameInput.nativeElement.dispatchEvent(new Event('input'));
+ valueInput.nativeElement.value = mockData[0].value;
+ valueInput.nativeElement.dispatchEvent(new Event('input'));
+
+ fixture.whenStable().then(() => {
+ fixture.detectChanges();
+
+ valueInput.triggerEventHandler('blur', null);
+ fixture.detectChanges();
+
+ expect(cardViewUpdateService.update).toHaveBeenCalled();
+ expect(JSON.stringify(component.property.value)).toBe(JSON.stringify(mockData));
+ });
+ }));
+
+ it('should not update property if at least one input is empty on blur', async(() => {
+ spyOn(cardViewUpdateService, 'update');
+ component.ngOnChanges();
+ fixture.detectChanges();
+
+ const addButton = fixture.debugElement.query(By.css('.card-view__key-value-pairs__add-btn'));
+ addButton.triggerEventHandler('click', null);
+ fixture.detectChanges();
+
+ let valueInput = fixture.debugElement.query(By.css(`[data-automation-id="card-${component.property.key}-value-input-0"]`));
+
+ valueInput.nativeElement.value = mockData[0].value;
+ valueInput.nativeElement.dispatchEvent(new Event('input'));
+
+ fixture.whenStable().then(() => {
+ fixture.detectChanges();
+
+ valueInput.triggerEventHandler('blur', null);
+ fixture.detectChanges();
+
+ expect(cardViewUpdateService.update).not.toHaveBeenCalled();
+ });
+ }));
+
+ });
+});
diff --git a/lib/core/card-view/components/card-view-keyvaluepairsitem/card-view-keyvaluepairsitem.component.ts b/lib/core/card-view/components/card-view-keyvaluepairsitem/card-view-keyvaluepairsitem.component.ts
new file mode 100644
index 0000000000..cab8beacb9
--- /dev/null
+++ b/lib/core/card-view/components/card-view-keyvaluepairsitem/card-view-keyvaluepairsitem.component.ts
@@ -0,0 +1,75 @@
+/*!
+ * @license
+ * Copyright 2016 Alfresco Software, Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { Component, Input, OnChanges } from '@angular/core';
+import { CardViewUpdateService } from '../../services/card-view-update.service';
+import { CardViewKeyValuePairsItemModel } from '../../models/card-view.models';
+import { CardViewKeyValuePairsItemType } from '../../interfaces/card-view.interfaces';
+import { MatTableDataSource } from '@angular/material';
+
+@Component({
+ selector: 'adf-card-view-boolitem',
+ templateUrl: './card-view-keyvaluepairsitem.component.html',
+ styleUrls: ['./card-view-keyvaluepairsitem.component.scss']
+})
+
+export class CardViewKeyValuePairsItemComponent implements OnChanges {
+
+ @Input()
+ property: CardViewKeyValuePairsItemModel;
+
+ @Input()
+ editable: boolean = false;
+
+ values: CardViewKeyValuePairsItemType[];
+ matTableValues: MatTableDataSource;
+
+ constructor(private cardViewUpdateService: CardViewUpdateService) {}
+
+ ngOnChanges() {
+ this.values = this.property.value || [];
+ this.matTableValues = new MatTableDataSource(this.values);
+ }
+
+ isEditable(): boolean {
+ return this.editable && this.property.editable;
+ }
+
+ add(): void {
+ this.values.push({ name: '', value: '' });
+ }
+
+ remove(index: number): void {
+ this.values.splice(index, 1);
+ this.save(true);
+ }
+
+ onBlur(value): void {
+ if (value.length) {
+ this.save();
+ }
+ }
+
+ save(remove?: boolean): void {
+ const validValues = this.values.filter(i => i.name.length && i.value.length);
+
+ if (remove || validValues.length) {
+ this.cardViewUpdateService.update(this.property, validValues);
+ this.property.value = validValues;
+ }
+ }
+}
diff --git a/lib/core/card-view/components/card-view.components.ts b/lib/core/card-view/components/card-view.components.ts
index 3187f44ff6..be4ab5d798 100644
--- a/lib/core/card-view/components/card-view.components.ts
+++ b/lib/core/card-view/components/card-view.components.ts
@@ -21,3 +21,4 @@ export * from './card-view-dateitem/card-view-dateitem.component';
export * from './card-view-item-dispatcher/card-view-item-dispatcher.component';
export * from './card-view-mapitem/card-view-mapitem.component';
export * from './card-view-textitem/card-view-textitem.component';
+export * from './card-view-keyvaluepairsitem/card-view-keyvaluepairsitem.component';
diff --git a/lib/core/card-view/interfaces/card-view-keyvaluepairsitem-properties.interface.ts b/lib/core/card-view/interfaces/card-view-keyvaluepairsitem-properties.interface.ts
new file mode 100644
index 0000000000..3cd011e045
--- /dev/null
+++ b/lib/core/card-view/interfaces/card-view-keyvaluepairsitem-properties.interface.ts
@@ -0,0 +1,27 @@
+/*!
+ * @license
+ * Copyright 2016 Alfresco Software, Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { CardViewItemProperties } from './card-view-item-properties.interface';
+
+export interface CardViewKeyValuePairsItemType {
+ name: string;
+ value: string;
+}
+
+export interface CardViewKeyValuePairsItemProperties extends CardViewItemProperties {
+ value: CardViewKeyValuePairsItemType[];
+}
diff --git a/lib/core/card-view/interfaces/card-view.interfaces.ts b/lib/core/card-view/interfaces/card-view.interfaces.ts
index a28204cf4c..137ae05b8b 100644
--- a/lib/core/card-view/interfaces/card-view.interfaces.ts
+++ b/lib/core/card-view/interfaces/card-view.interfaces.ts
@@ -22,3 +22,4 @@ export * from './card-view-textitem-properties.interface';
export * from './card-view-dateitem-properties.interface';
export * from './card-view-boolitem-properties.interface';
export * from './card-view-textitem-pipe-property.interface';
+export * from './card-view-keyvaluepairsitem-properties.interface';
diff --git a/lib/core/card-view/models/card-view-keyvaluepairs.model.ts b/lib/core/card-view/models/card-view-keyvaluepairs.model.ts
new file mode 100644
index 0000000000..1c986f2021
--- /dev/null
+++ b/lib/core/card-view/models/card-view-keyvaluepairs.model.ts
@@ -0,0 +1,33 @@
+/*!
+ * @license
+ * Copyright 2016 Alfresco Software, Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { CardViewItem } from '../interfaces/card-view-item.interface';
+import { DynamicComponentModel } from '../../services/dynamic-component-mapper.service';
+import { CardViewBaseItemModel } from './card-view-baseitem.model';
+import { CardViewKeyValuePairsItemProperties } from '../interfaces/card-view.interfaces';
+
+export class CardViewKeyValuePairsItemModel extends CardViewBaseItemModel implements CardViewItem, DynamicComponentModel {
+ type: string = 'keyvaluepairs';
+
+ constructor(obj: CardViewKeyValuePairsItemProperties) {
+ super(obj);
+ }
+
+ get displayValue() {
+ return this.value;
+ }
+}
diff --git a/lib/core/card-view/models/card-view.models.ts b/lib/core/card-view/models/card-view.models.ts
index 0d16dc6552..e29adc1f4c 100644
--- a/lib/core/card-view/models/card-view.models.ts
+++ b/lib/core/card-view/models/card-view.models.ts
@@ -23,3 +23,4 @@ export * from './card-view-floatitem.model';
export * from './card-view-intitem.model';
export * from './card-view-mapitem.model';
export * from './card-view-textitem.model';
+export * from './card-view-keyvaluepairs.model';
diff --git a/lib/core/card-view/public-api.ts b/lib/core/card-view/public-api.ts
index 68ec4b151c..0ae9787d11 100644
--- a/lib/core/card-view/public-api.ts
+++ b/lib/core/card-view/public-api.ts
@@ -20,7 +20,8 @@ export {
CardViewBoolItemComponent,
CardViewDateItemComponent,
CardViewMapItemComponent,
- CardViewTextItemComponent
+ CardViewTextItemComponent,
+ CardViewKeyValuePairsItemComponent
} from './components/card-view.components';
export * from './interfaces/card-view.interfaces';
diff --git a/lib/core/card-view/services/card-item-types.service.ts b/lib/core/card-view/services/card-item-types.service.ts
index e237d44005..ba12c44678 100644
--- a/lib/core/card-view/services/card-item-types.service.ts
+++ b/lib/core/card-view/services/card-item-types.service.ts
@@ -20,6 +20,7 @@ import { CardViewDateItemComponent } from '../components/card-view-dateitem/card
import { CardViewMapItemComponent } from '../components/card-view-mapitem/card-view-mapitem.component';
import { CardViewTextItemComponent } from '../components/card-view-textitem/card-view-textitem.component';
import { CardViewBoolItemComponent } from '../components/card-view-boolitem/card-view-boolitem.component';
+import { CardViewKeyValuePairsItemComponent } from '../components/card-view-keyvaluepairsitem/card-view-keyvaluepairsitem.component';
import { DynamicComponentMapper, DynamicComponentResolveFunction, DynamicComponentResolver } from '../../services/dynamic-component-mapper.service';
@Injectable()
@@ -34,6 +35,7 @@ export class CardItemTypeService extends DynamicComponentMapper {
'date': DynamicComponentResolver.fromType(CardViewDateItemComponent),
'datetime': DynamicComponentResolver.fromType(CardViewDateItemComponent),
'bool': DynamicComponentResolver.fromType(CardViewBoolItemComponent),
- 'map': DynamicComponentResolver.fromType(CardViewMapItemComponent)
+ 'map': DynamicComponentResolver.fromType(CardViewMapItemComponent),
+ 'keyvaluepairs': DynamicComponentResolver.fromType(CardViewKeyValuePairsItemComponent)
};
}
diff --git a/lib/core/i18n/en.json b/lib/core/i18n/en.json
index 4fc92119f6..8a1303806c 100644
--- a/lib/core/i18n/en.json
+++ b/lib/core/i18n/en.json
@@ -138,6 +138,11 @@
"CLIENT": "ClientId"
},
"CARDVIEW": {
+ "KEYVALUEPAIRS": {
+ "ADD": "Add new",
+ "NAME": "Name",
+ "VALUE": "Value"
+ },
"VALIDATORS": {
"FLOAT_VALIDATION_ERROR": "Use a number format",
"INT_VALIDATION_ERROR": "Use an integer format"