From 2153cde92b5773ae098a0b11854896bf3319678a Mon Sep 17 00:00:00 2001
From: Denys Korobeinikov
Date: Wed, 11 Jan 2023 11:00:29 +0200
Subject: [PATCH 1/7] feat(grid): sw-5987 add card view to grid
---
.../body/ui-grid-row-card-view.directive.ts | 18 +++
.../components/ui-grid/src/public_api.ts | 1 +
.../ui-grid/src/ui-grid.component.html | 90 +++++++++--
.../ui-grid/src/ui-grid.component.scss | 28 ++++
.../ui-grid/src/ui-grid.component.spec.ts | 149 ++++++++++++++++++
.../ui-grid/src/ui-grid.component.ts | 18 +++
.../components/ui-grid/src/ui-grid.module.ts | 3 +
.../pages/grid/component/grid.component.html | 15 ++
.../pages/grid/component/grid.component.scss | 9 ++
.../src/app/pages/grid/grid.models.ts | 1 +
.../src/app/pages/grid/grid.page.ts | 2 +
11 files changed, 320 insertions(+), 14 deletions(-)
create mode 100644 projects/angular/components/ui-grid/src/body/ui-grid-row-card-view.directive.ts
diff --git a/projects/angular/components/ui-grid/src/body/ui-grid-row-card-view.directive.ts b/projects/angular/components/ui-grid/src/body/ui-grid-row-card-view.directive.ts
new file mode 100644
index 000000000..75efa9ad6
--- /dev/null
+++ b/projects/angular/components/ui-grid/src/body/ui-grid-row-card-view.directive.ts
@@ -0,0 +1,18 @@
+import {
+ ContentChild,
+ Directive, TemplateRef,
+} from '@angular/core';
+
+export interface IGridRowCardViewContext {
+ index: number;
+ last: boolean;
+ data: any;
+}
+
+@Directive({ selector: '[uiGridRowCardView], ui-grid-row-card-view' })
+export class UiGridRowCardViewDirective {
+ @ContentChild(TemplateRef, {
+ static: true,
+ })
+ html?: TemplateRef;
+}
diff --git a/projects/angular/components/ui-grid/src/public_api.ts b/projects/angular/components/ui-grid/src/public_api.ts
index 4467b3987..1ff26f8b4 100644
--- a/projects/angular/components/ui-grid/src/public_api.ts
+++ b/projects/angular/components/ui-grid/src/public_api.ts
@@ -15,6 +15,7 @@ export { UiGridColumnDirective } from './body/ui-grid-column.directive';
export { UiGridExpandedRowDirective } from './body/ui-grid-expanded-row.directive';
export { UiGridRowActionDirective } from './body/ui-grid-row-action.directive';
export { UiGridRowConfigDirective } from './body/ui-grid-row-config.directive';
+export { UiGridRowCardViewDirective } from './body/ui-grid-row-card-view.directive';
export { UiGridLoadingDirective } from './body/ui-grid-loading.directive';
export { UiGridNoContentDirective } from './body/ui-grid-no-content.directive';
export { UiGridSearchComponent } from './components/ui-grid-search/ui-grid-search.component';
diff --git a/projects/angular/components/ui-grid/src/ui-grid.component.html b/projects/angular/components/ui-grid/src/ui-grid.component.html
index 18ec0f89d..20736da35 100644
--- a/projects/angular/components/ui-grid/src/ui-grid.component.html
+++ b/projects/angular/components/ui-grid/src/ui-grid.component.html
@@ -232,31 +232,64 @@
[itemSize]="rowSize"
uiVirtualScrollViewportResize
class="ui-grid-viewport">
-
+
+
+
+
+
+
+
+
-
+
+
-
+
+
+
+
+
+
+
+
-
+
+
@@ -401,6 +434,35 @@
[matTooltipDisabled]="resizeManager.isResizing">{{ dataManager.getProperty(row, property) }}
+
+
+
+
+
{{column.directive.title}}
+
+ {{ column.directive.title ?? column.directive.property }}:
+
+
+
+
+
+
+
diff --git a/projects/angular/components/ui-grid/src/ui-grid.component.scss b/projects/angular/components/ui-grid/src/ui-grid.component.scss
index cf6645355..c07fd2cce 100644
--- a/projects/angular/components/ui-grid/src/ui-grid.component.scss
+++ b/projects/angular/components/ui-grid/src/ui-grid.component.scss
@@ -515,6 +515,34 @@ ui-grid {
.ui-grid-header-cell-sortable {
cursor: pointer;
}
+
+ .ui-grid-cards-container {
+ margin: 16px;
+ display: flex;
+ flex-direction: row;
+ flex-wrap: wrap;
+
+ @supports (display: grid) {
+ display: grid;
+ grid-column-gap: 12px;
+ grid-row-gap: 16px;
+ grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
+ }
+ }
+
+ .ui-grid-card-default {
+ border-radius: 5px;
+ background: #ffffff;
+ border: 1px solid #cfd8dd;
+ color: #273139;
+ padding: 16px;
+ }
+
+ .ui-grid-card-default-cell-content {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ }
}
}
}
diff --git a/projects/angular/components/ui-grid/src/ui-grid.component.spec.ts b/projects/angular/components/ui-grid/src/ui-grid.component.spec.ts
index 870c42ab1..75ee56dba 100644
--- a/projects/angular/components/ui-grid/src/ui-grid.component.spec.ts
+++ b/projects/angular/components/ui-grid/src/ui-grid.component.spec.ts
@@ -4178,4 +4178,153 @@ describe('Component: UiGrid', () => {
expect(expandedRows.length).toBe(fixture.componentInstance.expandedEntries.length);
});
});
+
+ describe('Scenatio: card view', () => {
+
+ describe('Behavior: default card view', () => {
+
+ @Component({
+ template: `
+
+
+
+
+
+
+
+
+ `,
+ })
+ class TextFixtureGridCardViewComponent {
+ @ViewChild(UiGridComponent, {
+ static: true,
+ })
+ grid!: UiGridComponent;
+
+ data: ITestEntity[] = [];
+ }
+
+ let fixture: ComponentFixture;
+ let component: TextFixtureGridCardViewComponent;
+ let data: ITestEntity[];
+
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ imports: [
+ UiGridModule,
+ NoopAnimationsModule,
+ ],
+ declarations: [TextFixtureGridCardViewComponent],
+ });
+
+ fixture = TestBed.createComponent(TextFixtureGridCardViewComponent);
+ component = fixture.componentInstance;
+ data = generateListFactory(generateEntity)(6);
+ component.data = data;
+ fixture.detectChanges();
+ });
+
+ afterEach(() => {
+ fixture.destroy();
+ });
+
+ it('should render default card', () => {
+
+ const cardContainer = fixture.debugElement.query(By.css('.ui-grid-card-container'));
+ expect(cardContainer).toBeDefined();
+
+ });
+
+ it('should render properties defined in the column section', () => {
+
+ const cells = fixture.debugElement.queryAll(By.css('.ui-grid-cards-container .ui-grid-card-default-cell-content'));
+
+ expect((cells[0].nativeElement as HTMLElement).innerHTML).toContain('Number Header');
+ expect((cells[1].nativeElement as HTMLElement).innerHTML).toContain('String Header');
+
+ });
+
+ });
+
+ describe('Behavior: card view with a template', () => {
+ @Component({
+ template: `
+
+
+
+
+
{{entry.myNumber}}
+
{{entry.myBool}}
+
+
+
+
+ `,
+ })
+ class TextFixtureGridCardViewComponent {
+ @ViewChild(UiGridComponent, {
+ static: true,
+ })
+ grid!: UiGridComponent;
+
+ data: ITestEntity[] = [];
+ }
+
+ let fixture: ComponentFixture;
+ let component: TextFixtureGridCardViewComponent;
+ let data: ITestEntity[];
+
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ imports: [
+ UiGridModule,
+ NoopAnimationsModule,
+ ],
+ declarations: [TextFixtureGridCardViewComponent],
+ });
+
+ fixture = TestBed.createComponent(TextFixtureGridCardViewComponent);
+ component = fixture.componentInstance;
+ data = generateListFactory(generateEntity)(6);
+ component.data = data;
+ fixture.detectChanges();
+ });
+
+ afterEach(() => {
+ fixture.destroy();
+ });
+
+ it('should render provided card template', () => {
+
+ const cardContainer = fixture.debugElement.query(By.css('.expanded-row'));
+
+ console.log(cardContainer);
+ expect(cardContainer).toBeDefined();
+ expect(cardContainer.nativeElement.querySelector('[data-property="myNumber"]')).toBeDefined();
+ expect(cardContainer.nativeElement.querySelector('[data-property="myBool"]')).toBeDefined();
+
+ });
+
+ it('should not render any default card view', () => {
+ const cardContainer = fixture.debugElement.query(By.css('.ui-grid-card-container'));
+ expect(cardContainer).toBeNull();
+ });
+ });
+
+ });
+
});
diff --git a/projects/angular/components/ui-grid/src/ui-grid.component.ts b/projects/angular/components/ui-grid/src/ui-grid.component.ts
index 8d454580b..2f046dc72 100644
--- a/projects/angular/components/ui-grid/src/ui-grid.component.ts
+++ b/projects/angular/components/ui-grid/src/ui-grid.component.ts
@@ -66,6 +66,7 @@ import { UiGridLoadingDirective } from './body/ui-grid-loading.directive';
import { UiGridNoContentDirective } from './body/ui-grid-no-content.directive';
import { UiGridRowActionDirective } from './body/ui-grid-row-action.directive';
import { UiGridRowConfigDirective } from './body/ui-grid-row-config.directive';
+import { UiGridRowCardViewDirective } from './body/ui-grid-row-card-view.directive';
import { UiGridSearchFilterDirective } from './filters/ui-grid-search-filter.directive';
import { UiGridFooterDirective } from './footer/ui-grid-footer.directive';
import { UiGridHeaderDirective } from './header/ui-grid-header.directive';
@@ -375,6 +376,13 @@ export class UiGridComponent extends ResizableGrid
this.filterManager.updateCustomFilters(customValue);
}
+ /**
+ * Configure if Card view should be used
+ *
+ */
+ @Input()
+ useCardView = false;
+
/**
* Emits an event with the sort model when a column sort changes.
*
@@ -496,6 +504,16 @@ export class UiGridComponent extends ResizableGrid
static: true,
})
loadingState?: UiGridLoadingDirective;
+
+ /**
+ * Custom card view template reference.
+ *
+ * @ignore
+ */
+ @ContentChild(UiGridRowCardViewDirective, {
+ static: true,
+ })
+ cardTemplate?: UiGridRowCardViewDirective;
/**
* Reference to the grid action buttons container
*
diff --git a/projects/angular/components/ui-grid/src/ui-grid.module.ts b/projects/angular/components/ui-grid/src/ui-grid.module.ts
index ba4ad8827..9497c30ce 100644
--- a/projects/angular/components/ui-grid/src/ui-grid.module.ts
+++ b/projects/angular/components/ui-grid/src/ui-grid.module.ts
@@ -21,6 +21,7 @@ import { UiGridLoadingDirective } from './body/ui-grid-loading.directive';
import { UiGridNoContentDirective } from './body/ui-grid-no-content.directive';
import { UiGridRowActionDirective } from './body/ui-grid-row-action.directive';
import { UiGridRowConfigDirective } from './body/ui-grid-row-config.directive';
+import { UiGridRowCardViewDirective } from './body/ui-grid-row-card-view.directive';
import { UiGridCustomPaginatorModule } from './components/ui-grid-custom-paginator/ui-grid-custom-paginator.module';
import { UiGridSearchModule } from './components/ui-grid-search/ui-grid-search.module';
import { UiGridToggleColumnsModule } from './components/ui-grid-toggle-columns/ui-grid-toggle-columns.module';
@@ -65,6 +66,7 @@ import { UiGridComponent } from './ui-grid.component';
UiGridExpandedRowDirective,
UiGridNoContentDirective,
UiGridLoadingDirective,
+ UiGridRowCardViewDirective,
],
exports: [
UiGridComponent,
@@ -79,6 +81,7 @@ import { UiGridComponent } from './ui-grid.component';
UiGridExpandedRowDirective,
UiGridNoContentDirective,
UiGridLoadingDirective,
+ UiGridRowCardViewDirective,
],
})
export class UiGridModule { }
diff --git a/projects/playground/src/app/pages/grid/component/grid.component.html b/projects/playground/src/app/pages/grid/component/grid.component.html
index eff58d178..25d3e1e8e 100644
--- a/projects/playground/src/app/pages/grid/component/grid.component.html
+++ b/projects/playground/src/app/pages/grid/component/grid.component.html
@@ -13,6 +13,7 @@
[showPaintTime]="inputs.showPaintTime"
[showHeaderRow]="inputs.showHeaderRow"
[expandedEntries]="editedEntity"
+ [useCardView]="inputs.useCardView"
[expandMode]="'preserve'"
[customFilterValue]="inputs.customFilter ? [{property: 'parity', method: 'eq', value: 'odd'}] : []">
@@ -106,4 +107,18 @@ Expanded row with ID: {{ entry.id }}
+
+
+
+
+
{{data.name}}
+
parity: {{data.parity}}
+
+
+
diff --git a/projects/playground/src/app/pages/grid/component/grid.component.scss b/projects/playground/src/app/pages/grid/component/grid.component.scss
index 056b92dbd..2bc27251a 100644
--- a/projects/playground/src/app/pages/grid/component/grid.component.scss
+++ b/projects/playground/src/app/pages/grid/component/grid.component.scss
@@ -4,3 +4,12 @@
justify-content: center;
align-items: center;
}
+
+.card {
+ background: #ffffff;
+ border: 1px solid #cfd8dd;
+ color: #273139;
+ padding: 16px;
+ text-align: center;
+ border-radius: 5px;
+}
diff --git a/projects/playground/src/app/pages/grid/grid.models.ts b/projects/playground/src/app/pages/grid/grid.models.ts
index ad4ccf8cd..43c7f3ea9 100644
--- a/projects/playground/src/app/pages/grid/grid.models.ts
+++ b/projects/playground/src/app/pages/grid/grid.models.ts
@@ -28,4 +28,5 @@ export interface IInputs {
showPaintTime: boolean;
showHeaderRow: boolean;
customFilter: boolean;
+ useCardView: boolean;
}
diff --git a/projects/playground/src/app/pages/grid/grid.page.ts b/projects/playground/src/app/pages/grid/grid.page.ts
index 7f3e2251f..c3d0faf3a 100644
--- a/projects/playground/src/app/pages/grid/grid.page.ts
+++ b/projects/playground/src/app/pages/grid/grid.page.ts
@@ -53,6 +53,7 @@ export class GridPageComponent implements AfterViewInit {
'showPaintTime',
'showHeaderRow',
'customFilter',
+ 'useCardView',
];
buttonKeys = [
@@ -103,6 +104,7 @@ export class GridPageComponent implements AfterViewInit {
showPaintTime: [false],
showHeaderRow: [true],
customFilter: [false],
+ useCardView: [true],
}),
header: this._fb.group({
searchable: [true],
From d1c98dd072d7ac097323ac7f2ab9930df44a1cf5 Mon Sep 17 00:00:00 2001
From: Denys Korobeinikov
Date: Thu, 12 Jan 2023 13:55:06 +0200
Subject: [PATCH 2/7] feat(grid): make card accessible
---
.../ui-grid/src/ui-grid.component.html | 39 +++++++++++++++----
.../pages/grid/component/grid.component.html | 11 ++++++
2 files changed, 43 insertions(+), 7 deletions(-)
diff --git a/projects/angular/components/ui-grid/src/ui-grid.component.html b/projects/angular/components/ui-grid/src/ui-grid.component.html
index 20736da35..a59a8f3f4 100644
--- a/projects/angular/components/ui-grid/src/ui-grid.component.html
+++ b/projects/angular/components/ui-grid/src/ui-grid.component.html
@@ -238,7 +238,7 @@
let last = last;
let index = index;
trackBy: dataManager.hashTrack">
-
-
+
+
@@ -434,6 +435,30 @@
[matTooltipDisabled]="resizeManager.isResizing">{{ dataManager.getProperty(row, property) }}
+
+
+
+
+
+
+
+
diff --git a/projects/playground/src/app/pages/grid/component/grid.component.html b/projects/playground/src/app/pages/grid/component/grid.component.html
index 25d3e1e8e..6e87e5852 100644
--- a/projects/playground/src/app/pages/grid/component/grid.component.html
+++ b/projects/playground/src/app/pages/grid/component/grid.component.html
@@ -118,7 +118,18 @@ Expanded row with ID: {{ entry.id }}
{{data.name}}
parity: {{data.parity}}
+
+
+
+
+
+
+
From 07ae4cadae211efcb7a796549a80a10de03ced17 Mon Sep 17 00:00:00 2001
From: Denys Korobeinikov
Date: Thu, 2 Mar 2023 10:43:28 +0200
Subject: [PATCH 3/7] feat(grid): disable cards when loading state
---
projects/angular/components/ui-grid/src/_ui-grid.theme.scss | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/projects/angular/components/ui-grid/src/_ui-grid.theme.scss b/projects/angular/components/ui-grid/src/_ui-grid.theme.scss
index 8787b1a6d..a6c50f4cc 100644
--- a/projects/angular/components/ui-grid/src/_ui-grid.theme.scss
+++ b/projects/angular/components/ui-grid/src/_ui-grid.theme.scss
@@ -52,7 +52,8 @@ $ui-grid-opacity-transition: opacity $ui-grid-default-transition;
}
&.ui-grid-state-loading {
- .ui-grid-row {
+ .ui-grid-row,
+ .ui-grid-card-wrapper {
pointer-events: none;
opacity: 0.5;
}
From 2a323be200b54321c404e2eef11218611935d77a Mon Sep 17 00:00:00 2001
From: Denys Korobeinikov
Date: Thu, 2 Mar 2023 10:57:21 +0200
Subject: [PATCH 4/7] feat(grid): add opacity transition to card wrapper
---
projects/angular/components/ui-grid/src/_ui-grid.theme.scss | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/projects/angular/components/ui-grid/src/_ui-grid.theme.scss b/projects/angular/components/ui-grid/src/_ui-grid.theme.scss
index a6c50f4cc..33eeec252 100644
--- a/projects/angular/components/ui-grid/src/_ui-grid.theme.scss
+++ b/projects/angular/components/ui-grid/src/_ui-grid.theme.scss
@@ -151,6 +151,10 @@ $ui-grid-opacity-transition: opacity $ui-grid-default-transition;
border-bottom-color: $ui-grid-border-color;
transition: $ui-grid-opacity-transition;
}
+
+ &-card-wrapper {
+ transition: $ui-grid-opacity-transition;
+ }
}
.ui-grid-row {
From df0b3cc01e7b10bc51e0d89bcb6c155f659cef84 Mon Sep 17 00:00:00 2001
From: Denys Korobeinikov
Date: Thu, 2 Mar 2023 11:01:29 +0200
Subject: [PATCH 5/7] feat(grid): make columns non-resizable for card view
---
projects/angular/components/ui-grid/src/ui-grid.component.html | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/projects/angular/components/ui-grid/src/ui-grid.component.html b/projects/angular/components/ui-grid/src/ui-grid.component.html
index a59a8f3f4..7d6a05547 100644
--- a/projects/angular/components/ui-grid/src/ui-grid.component.html
+++ b/projects/angular/components/ui-grid/src/ui-grid.component.html
@@ -183,7 +183,7 @@
-
@@ -466,7 +466,6 @@
Date: Thu, 2 Mar 2023 11:01:55 +0200
Subject: [PATCH 6/7] feat(grid): make card view directive generic
---
.../ui-grid/src/body/ui-grid-row-card-view.directive.ts | 8 ++++----
.../angular/components/ui-grid/src/ui-grid.component.ts | 2 +-
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/projects/angular/components/ui-grid/src/body/ui-grid-row-card-view.directive.ts b/projects/angular/components/ui-grid/src/body/ui-grid-row-card-view.directive.ts
index 75efa9ad6..05f51ffa3 100644
--- a/projects/angular/components/ui-grid/src/body/ui-grid-row-card-view.directive.ts
+++ b/projects/angular/components/ui-grid/src/body/ui-grid-row-card-view.directive.ts
@@ -3,16 +3,16 @@ import {
Directive, TemplateRef,
} from '@angular/core';
-export interface IGridRowCardViewContext {
+export interface IGridRowCardViewContext
{
index: number;
last: boolean;
- data: any;
+ data: T;
}
@Directive({ selector: '[uiGridRowCardView], ui-grid-row-card-view' })
-export class UiGridRowCardViewDirective {
+export class UiGridRowCardViewDirective {
@ContentChild(TemplateRef, {
static: true,
})
- html?: TemplateRef;
+ html?: TemplateRef>;
}
diff --git a/projects/angular/components/ui-grid/src/ui-grid.component.ts b/projects/angular/components/ui-grid/src/ui-grid.component.ts
index 2f046dc72..e396c7673 100644
--- a/projects/angular/components/ui-grid/src/ui-grid.component.ts
+++ b/projects/angular/components/ui-grid/src/ui-grid.component.ts
@@ -513,7 +513,7 @@ export class UiGridComponent extends ResizableGrid
@ContentChild(UiGridRowCardViewDirective, {
static: true,
})
- cardTemplate?: UiGridRowCardViewDirective;
+ cardTemplate?: UiGridRowCardViewDirective;
/**
* Reference to the grid action buttons container
*
From 0f9588d1efeec7ca58b49dfa4e91efc72c56eabf Mon Sep 17 00:00:00 2001
From: Alexandru Georoceanu
Date: Thu, 2 Mar 2023 11:45:25 +0200
Subject: [PATCH 7/7] chore: bump to v14.5.0
---
CHANGELOG.md | 3 +++
package-lock.json | 4 ++--
package.json | 2 +-
projects/angular/package.json | 2 +-
4 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 91a9e1c0d..803a844bb 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,6 @@
+# v14.5.0 (2023-03-02)
+* **grid** add card view support
+
# v14.4.1 (2023-02-15)
* **dateformat** use luxon for absolute time if enabled
diff --git a/package-lock.json b/package-lock.json
index aa766d831..6c79bda37 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "angular-components",
- "version": "14.4.1",
+ "version": "14.5.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "angular-components",
- "version": "14.4.1",
+ "version": "14.5.0",
"license": "MIT",
"dependencies": {
"@angular/animations": "14.2.12",
diff --git a/package.json b/package.json
index fa5eb094c..da07e1fa5 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "angular-components",
- "version": "14.4.1",
+ "version": "14.5.0",
"author": {
"name": "UiPath Inc",
"url": "https://uipath.com"
diff --git a/projects/angular/package.json b/projects/angular/package.json
index 32012fbd4..c6af97ce6 100644
--- a/projects/angular/package.json
+++ b/projects/angular/package.json
@@ -1,6 +1,6 @@
{
"name": "@uipath/angular",
- "version": "14.4.1",
+ "version": "14.5.0",
"license": "MIT",
"author": {
"name": "UiPath Inc",