From ea6c063986497a0208f47cc0a5d9dabdc9f4bba2 Mon Sep 17 00:00:00 2001 From: ci Date: Tue, 31 Jan 2023 21:45:07 +0000 Subject: [PATCH] release(workspace): v9.21.0 release feat: added dbx-content-pit feat: dbx-table (#23) * checkpoint: outlined @dbx-web/table * checkpoint: dbx-table * checkpoint: dbx-table * checkpoint: dbx-table * checkpoint: dbx-table * checkpoint: dbx-table refactor: updated accumulatorFlattenPageListLoadingState() - fixed issue where accumulatorFlattenPageListLoadingState() would return an empty loading state instead of all the current values fix: fixed enableMultiTabIndexedDbPersistence usage - fixed issue where trying to use both enableMultiTabIndexedDbPersistence and enableMultiTabIndexedDbPersistence at the same time - enableMultiTabIndexedDbPersistence is now the default, with enableIndexedDbPersistence being used if enableMultiTabIndexedDbPersistence is false --- CHANGELOG.md | 15 ++ apps/demo-api/CHANGELOG.md | 4 + apps/demo-e2e/CHANGELOG.md | 4 + apps/demo/CHANGELOG.md | 10 + .../table.item.action.example.component.ts | 17 ++ .../component/table.item.action.example.scss | 7 + .../table.item.cell.example.component.ts | 28 +++ .../table.item.header.example.component.ts | 19 ++ .../modules/extension/component/table.item.ts | 5 + .../extension/container/table.component.html | 16 ++ .../extension/container/table.component.ts | 117 ++++++++++++ .../modules/extension/doc.extension.module.ts | 11 ++ .../modules/extension/doc.extension.router.ts | 10 +- .../doc/modules/extension/doc.extension.ts | 6 + .../layout/container/content.component.html | 24 +++ components/demo-components/CHANGELOG.md | 4 + components/demo-components/package.json | 2 +- .../development/setup.widget.component.html | 4 + .../development/setup.widget.component.ts | 10 + components/demo-firebase/CHANGELOG.md | 4 + components/demo-firebase/package.json | 2 +- package.json | 2 +- packages/browser/CHANGELOG.md | 4 + packages/browser/package.json | 2 +- packages/date/CHANGELOG.md | 9 + packages/date/package.json | 2 +- packages/date/src/lib/date/date.block.ts | 2 +- packages/date/src/lib/date/date.range.spec.ts | 37 +++- packages/date/src/lib/date/date.range.ts | 62 +++++- packages/dbx-analytics/CHANGELOG.md | 4 + packages/dbx-analytics/package.json | 2 +- packages/dbx-core/CHANGELOG.md | 9 + packages/dbx-core/package.json | 2 +- .../dbx-core/src/lib/injection/injection.ts | 4 +- packages/dbx-firebase/CHANGELOG.md | 9 + packages/dbx-firebase/package.json | 2 +- .../src/lib/firebase/firebase.module.ts | 6 +- .../dbx-firebase/src/lib/firebase/options.ts | 10 +- .../store/store.collection.list.directive.ts | 15 +- packages/dbx-form/CHANGELOG.md | 9 + packages/dbx-form/calendar/CHANGELOG.md | 9 + packages/dbx-form/calendar/package.json | 2 +- ...ndar.schedule.selection.range.component.ts | 1 + packages/dbx-form/mapbox/CHANGELOG.md | 4 + packages/dbx-form/mapbox/package.json | 2 +- packages/dbx-form/package.json | 2 +- packages/dbx-web/CHANGELOG.md | 10 + packages/dbx-web/calendar/CHANGELOG.md | 9 + packages/dbx-web/calendar/package.json | 2 +- packages/dbx-web/calendar/tsconfig.spec.json | 1 - packages/dbx-web/mapbox/CHANGELOG.md | 9 + packages/dbx-web/mapbox/package.json | 2 +- packages/dbx-web/mapbox/tsconfig.lib.json | 2 +- packages/dbx-web/mapbox/tsconfig.spec.json | 1 - packages/dbx-web/package.json | 6 +- packages/dbx-web/project.json | 4 + .../dbx-web/src/lib/extension/_extension.scss | 19 ++ .../src/lib/extension/table/_table.scss | 60 ++++++ .../src/lib/layout/content/_content.scss | 14 ++ .../layout/content/content.layout.module.ts | 16 +- .../layout/content/content.pit.directive.ts | 12 ++ .../dbx-web/src/lib/layout/content/index.ts | 1 + .../src/lib/layout/list/list.wrapper.ts | 3 +- .../dbx-web/src/lib/layout/style/_style.scss | 4 + packages/dbx-web/src/lib/style/_config.scss | 10 +- packages/dbx-web/table/.eslintrc.json | 4 + packages/dbx-web/table/CHANGELOG.md | 10 + packages/dbx-web/table/README.md | 6 + packages/dbx-web/table/jest.config.ts | 9 + packages/dbx-web/table/ng-package.json | 7 + packages/dbx-web/table/package.json | 11 ++ packages/dbx-web/table/project.json | 40 ++++ packages/dbx-web/table/src/index.ts | 1 + .../date.table.column.header.component.ts | 46 +++++ .../daterange.table.cell.input.component.ts | 179 ++++++++++++++++++ packages/dbx-web/table/src/lib/date/index.ts | 3 + .../table/src/lib/date/table.date.module.ts | 35 ++++ packages/dbx-web/table/src/lib/index.ts | 17 ++ .../src/lib/table.cell.action.component.ts | 19 ++ .../src/lib/table.cell.input.component.ts | 23 +++ .../lib/table.cell.summaryend.component.ts | 19 ++ .../lib/table.cell.summarystart.component.ts | 23 +++ .../table/src/lib/table.column.directive.ts | 26 +++ .../src/lib/table.column.footer.component.ts | 25 +++ .../src/lib/table.column.header.component.ts | 25 +++ .../table/src/lib/table.component.html | 52 +++++ .../dbx-web/table/src/lib/table.component.ts | 62 ++++++ .../dbx-web/table/src/lib/table.directive.ts | 34 ++++ .../src/lib/table.item.action.component.ts | 29 +++ .../src/lib/table.item.cell.component.ts | 33 ++++ .../table/src/lib/table.item.directive.ts | 26 +++ .../src/lib/table.item.header.component.ts | 21 ++ .../dbx-web/table/src/lib/table.module.ts | 45 +++++ packages/dbx-web/table/src/lib/table.store.ts | 108 +++++++++++ packages/dbx-web/table/src/lib/table.ts | 103 ++++++++++ packages/dbx-web/table/tsconfig.json | 31 +++ packages/dbx-web/table/tsconfig.lib.json | 12 ++ packages/dbx-web/table/tsconfig.lib.prod.json | 9 + packages/dbx-web/table/tsconfig.spec.json | 9 + packages/dbx-web/tsconfig.lib.json | 2 +- packages/dbx-web/tsconfig.lib.prod.json | 2 +- packages/dbx-web/tsconfig.spec.json | 2 +- packages/firebase-server/CHANGELOG.md | 4 + packages/firebase-server/mailgun/CHANGELOG.md | 4 + packages/firebase-server/mailgun/package.json | 2 +- packages/firebase-server/package.json | 2 +- packages/firebase-server/test/CHANGELOG.md | 4 + packages/firebase-server/test/package.json | 2 +- packages/firebase/CHANGELOG.md | 4 + packages/firebase/package.json | 2 +- packages/firebase/test/CHANGELOG.md | 4 + packages/firebase/test/package.json | 2 +- packages/model/CHANGELOG.md | 4 + packages/model/package.json | 2 +- packages/nestjs/CHANGELOG.md | 4 + packages/nestjs/mailgun/CHANGELOG.md | 4 + packages/nestjs/mailgun/package.json | 2 +- packages/nestjs/package.json | 2 +- packages/nestjs/stripe/CHANGELOG.md | 4 + packages/nestjs/stripe/package.json | 2 +- packages/rxjs/CHANGELOG.md | 9 + packages/rxjs/package.json | 2 +- .../iteration.accumulator.rxjs.spec.ts | 26 ++- .../iterator/iteration.accumulator.rxjs.ts | 2 + .../rxjs/src/lib/loading/loading.state.ts | 12 +- packages/util/CHANGELOG.md | 4 + packages/util/fetch/CHANGELOG.md | 4 + packages/util/fetch/package.json | 2 +- packages/util/package.json | 2 +- packages/util/test/CHANGELOG.md | 4 + packages/util/test/package.json | 2 +- tsconfig.base.json | 1 + workspace.json | 1 + 133 files changed, 1886 insertions(+), 63 deletions(-) create mode 100644 apps/demo/src/app/modules/doc/modules/extension/component/table.item.action.example.component.ts create mode 100644 apps/demo/src/app/modules/doc/modules/extension/component/table.item.action.example.scss create mode 100644 apps/demo/src/app/modules/doc/modules/extension/component/table.item.cell.example.component.ts create mode 100644 apps/demo/src/app/modules/doc/modules/extension/component/table.item.header.example.component.ts create mode 100644 apps/demo/src/app/modules/doc/modules/extension/component/table.item.ts create mode 100644 apps/demo/src/app/modules/doc/modules/extension/container/table.component.html create mode 100644 apps/demo/src/app/modules/doc/modules/extension/container/table.component.ts create mode 100644 packages/dbx-web/src/lib/extension/table/_table.scss create mode 100644 packages/dbx-web/src/lib/layout/content/content.pit.directive.ts create mode 100644 packages/dbx-web/table/.eslintrc.json create mode 100644 packages/dbx-web/table/CHANGELOG.md create mode 100644 packages/dbx-web/table/README.md create mode 100644 packages/dbx-web/table/jest.config.ts create mode 100644 packages/dbx-web/table/ng-package.json create mode 100644 packages/dbx-web/table/package.json create mode 100644 packages/dbx-web/table/project.json create mode 100644 packages/dbx-web/table/src/index.ts create mode 100644 packages/dbx-web/table/src/lib/date/date.table.column.header.component.ts create mode 100644 packages/dbx-web/table/src/lib/date/daterange.table.cell.input.component.ts create mode 100644 packages/dbx-web/table/src/lib/date/index.ts create mode 100644 packages/dbx-web/table/src/lib/date/table.date.module.ts create mode 100644 packages/dbx-web/table/src/lib/index.ts create mode 100644 packages/dbx-web/table/src/lib/table.cell.action.component.ts create mode 100644 packages/dbx-web/table/src/lib/table.cell.input.component.ts create mode 100644 packages/dbx-web/table/src/lib/table.cell.summaryend.component.ts create mode 100644 packages/dbx-web/table/src/lib/table.cell.summarystart.component.ts create mode 100644 packages/dbx-web/table/src/lib/table.column.directive.ts create mode 100644 packages/dbx-web/table/src/lib/table.column.footer.component.ts create mode 100644 packages/dbx-web/table/src/lib/table.column.header.component.ts create mode 100644 packages/dbx-web/table/src/lib/table.component.html create mode 100644 packages/dbx-web/table/src/lib/table.component.ts create mode 100644 packages/dbx-web/table/src/lib/table.directive.ts create mode 100644 packages/dbx-web/table/src/lib/table.item.action.component.ts create mode 100644 packages/dbx-web/table/src/lib/table.item.cell.component.ts create mode 100644 packages/dbx-web/table/src/lib/table.item.directive.ts create mode 100644 packages/dbx-web/table/src/lib/table.item.header.component.ts create mode 100644 packages/dbx-web/table/src/lib/table.module.ts create mode 100644 packages/dbx-web/table/src/lib/table.store.ts create mode 100644 packages/dbx-web/table/src/lib/table.ts create mode 100644 packages/dbx-web/table/tsconfig.json create mode 100644 packages/dbx-web/table/tsconfig.lib.json create mode 100644 packages/dbx-web/table/tsconfig.lib.prod.json create mode 100644 packages/dbx-web/table/tsconfig.spec.json diff --git a/CHANGELOG.md b/CHANGELOG.md index 659980626..125217972 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,21 @@ This file was generated using [@jscutlery/semver](https://github.com/jscutlery/semver). +# [9.21.0](https://github.com/dereekb/dbx-components/compare/v9.20.20-dev...v9.21.0) (2023-01-31) + + +### Bug Fixes + +* fixed enableMultiTabIndexedDbPersistence usage ([2c41552](https://github.com/dereekb/dbx-components/commit/2c41552c6849cd7cae2405cd456d92bca265a5d3)) + + +### Features + +* added dbx-content-pit ([cbce68a](https://github.com/dereekb/dbx-components/commit/cbce68ad73dc896acc34232e3375698133e99241)) +* dbx-table ([#23](https://github.com/dereekb/dbx-components/issues/23)) ([4661508](https://github.com/dereekb/dbx-components/commit/466150895b5bdc6e9e5289ef38ef5dd3e0ae67f9)) + + + ## [9.20.20](https://github.com/dereekb/dbx-components/compare/v9.20.19-dev...v9.20.20) (2023-01-23) diff --git a/apps/demo-api/CHANGELOG.md b/apps/demo-api/CHANGELOG.md index 94a780d05..39c4617eb 100644 --- a/apps/demo-api/CHANGELOG.md +++ b/apps/demo-api/CHANGELOG.md @@ -2,6 +2,10 @@ This file was generated using [@jscutlery/semver](https://github.com/jscutlery/semver). +# [9.21.0](https://github.com/dereekb/dbx-components/compare/v9.20.20-dev...v9.21.0) (2023-01-31) + + + ## [9.20.20](https://github.com/dereekb/dbx-components/compare/v9.20.19-dev...v9.20.20) (2023-01-23) diff --git a/apps/demo-e2e/CHANGELOG.md b/apps/demo-e2e/CHANGELOG.md index 8e80886c1..c6c8a6fc8 100644 --- a/apps/demo-e2e/CHANGELOG.md +++ b/apps/demo-e2e/CHANGELOG.md @@ -2,6 +2,10 @@ This file was generated using [@jscutlery/semver](https://github.com/jscutlery/semver). +# [9.21.0](https://github.com/dereekb/dbx-components/compare/v9.20.20-dev...v9.21.0) (2023-01-31) + + + ## [9.20.20](https://github.com/dereekb/dbx-components/compare/v9.20.19-dev...v9.20.20) (2023-01-23) diff --git a/apps/demo/CHANGELOG.md b/apps/demo/CHANGELOG.md index 56e968ffa..f0ed3b62f 100644 --- a/apps/demo/CHANGELOG.md +++ b/apps/demo/CHANGELOG.md @@ -2,6 +2,16 @@ This file was generated using [@jscutlery/semver](https://github.com/jscutlery/semver). +# [9.21.0](https://github.com/dereekb/dbx-components/compare/v9.20.20-dev...v9.21.0) (2023-01-31) + + +### Features + +* added dbx-content-pit ([cbce68a](https://github.com/dereekb/dbx-components/commit/cbce68ad73dc896acc34232e3375698133e99241)) +* dbx-table ([#23](https://github.com/dereekb/dbx-components/issues/23)) ([4661508](https://github.com/dereekb/dbx-components/commit/466150895b5bdc6e9e5289ef38ef5dd3e0ae67f9)) + + + ## [9.20.20](https://github.com/dereekb/dbx-components/compare/v9.20.19-dev...v9.20.20) (2023-01-23) diff --git a/apps/demo/src/app/modules/doc/modules/extension/component/table.item.action.example.component.ts b/apps/demo/src/app/modules/doc/modules/extension/component/table.item.action.example.component.ts new file mode 100644 index 000000000..4e7eb99fe --- /dev/null +++ b/apps/demo/src/app/modules/doc/modules/extension/component/table.item.action.example.component.ts @@ -0,0 +1,17 @@ +import { filterMaybe } from '@dereekb/rxjs'; +import { ChangeDetectionStrategy, Component, OnInit, OnDestroy, Input } from '@angular/core'; +import { AbstractDbxInjectionDirective } from '@dereekb/dbx-core'; +import { map, distinctUntilChanged, BehaviorSubject, switchMap } from 'rxjs'; +import { Maybe } from '@dereekb/util'; + +@Component({ + template: ` +
+ + + +
+ `, + styleUrls: ['./table.item.action.example.scss'] +}) +export class DocExtensionTableItemActionExampleComponent {} diff --git a/apps/demo/src/app/modules/doc/modules/extension/component/table.item.action.example.scss b/apps/demo/src/app/modules/doc/modules/extension/component/table.item.action.example.scss new file mode 100644 index 000000000..1eacf7197 --- /dev/null +++ b/apps/demo/src/app/modules/doc/modules/extension/component/table.item.action.example.scss @@ -0,0 +1,7 @@ +.doc-example-table-action-cell { + min-width: 110px; + display: flex; + align-items: center; + justify-content: center; + padding: 4px; +} diff --git a/apps/demo/src/app/modules/doc/modules/extension/component/table.item.cell.example.component.ts b/apps/demo/src/app/modules/doc/modules/extension/component/table.item.cell.example.component.ts new file mode 100644 index 000000000..b6e70cd38 --- /dev/null +++ b/apps/demo/src/app/modules/doc/modules/extension/component/table.item.cell.example.component.ts @@ -0,0 +1,28 @@ +import { filterMaybe } from '@dereekb/rxjs'; +import { ChangeDetectionStrategy, Component, OnInit, OnDestroy, Input } from '@angular/core'; +import { AbstractDbxInjectionDirective } from '@dereekb/dbx-core'; +import { map, distinctUntilChanged, BehaviorSubject, switchMap } from 'rxjs'; +import { Maybe } from '@dereekb/util'; +import { DbxTableColumn } from '@dereekb/dbx-web/table'; +import { ExampleTableData } from './table.item'; + +@Component({ + template: ` +
+
{{ name }}
+
{{ columnName }}
+
+ ` +}) +export class DocExtensionTableItemCellExampleComponent { + item!: ExampleTableData; + column!: DbxTableColumn; + + get name() { + return this.item.name; + } + + get columnName() { + return this.column.columnName; + } +} diff --git a/apps/demo/src/app/modules/doc/modules/extension/component/table.item.header.example.component.ts b/apps/demo/src/app/modules/doc/modules/extension/component/table.item.header.example.component.ts new file mode 100644 index 000000000..dfe9a1bfd --- /dev/null +++ b/apps/demo/src/app/modules/doc/modules/extension/component/table.item.header.example.component.ts @@ -0,0 +1,19 @@ +import { filterMaybe } from '@dereekb/rxjs'; +import { ChangeDetectionStrategy, Component, OnInit, OnDestroy, Input } from '@angular/core'; +import { AbstractDbxInjectionDirective } from '@dereekb/dbx-core'; +import { map, distinctUntilChanged, BehaviorSubject, switchMap } from 'rxjs'; +import { Maybe } from '@dereekb/util'; +import { ExampleTableData } from './table.item'; + +@Component({ + template: ` +
{{ name }}
+ ` +}) +export class DocExtensionTableItemHeaderExampleComponent { + item!: ExampleTableData; + + get name() { + return this.item.name; + } +} diff --git a/apps/demo/src/app/modules/doc/modules/extension/component/table.item.ts b/apps/demo/src/app/modules/doc/modules/extension/component/table.item.ts new file mode 100644 index 000000000..90a722dce --- /dev/null +++ b/apps/demo/src/app/modules/doc/modules/extension/component/table.item.ts @@ -0,0 +1,5 @@ +import { ModelKeyRef } from '@dereekb/util'; + +export interface ExampleTableData extends ModelKeyRef { + name: string; +} diff --git a/apps/demo/src/app/modules/doc/modules/extension/container/table.component.html b/apps/demo/src/app/modules/doc/modules/extension/container/table.component.html new file mode 100644 index 000000000..87082e034 --- /dev/null +++ b/apps/demo/src/app/modules/doc/modules/extension/container/table.component.html @@ -0,0 +1,16 @@ + + + + + +

Context Loading

+

While the context is loading the table shows a spinning loader.

+ +

Data Loading

+

This example shows how loading the data is handled. The delegate also provides a loadMore() functionality, allowing more items to load as the table is scrolled.

+ +

+ +
+
+
diff --git a/apps/demo/src/app/modules/doc/modules/extension/container/table.component.ts b/apps/demo/src/app/modules/doc/modules/extension/container/table.component.ts new file mode 100644 index 000000000..7c485590f --- /dev/null +++ b/apps/demo/src/app/modules/doc/modules/extension/container/table.component.ts @@ -0,0 +1,117 @@ +import { DocExtensionTableItemCellExampleComponent } from './../component/table.item.cell.example.component'; +import { startOfDay } from 'date-fns/esm'; +import { Component, OnDestroy } from '@angular/core'; +import { DateRangeDayDistanceInput, expandDaysForDateRange, dateRange, formatToISO8601DayString, DateRangeType } from '@dereekb/date'; +import { DbxInjectionComponentConfig } from '@dereekb/dbx-core'; +import { DbxWidgetDataPair } from '@dereekb/dbx-web'; +import { DbxTableColumn, DbxTableContextData, DbxTableContextDataDelegate, dbxTableDateHeaderInjectionFactory, dbxTableDateRangeDayDistanceInputCellInput, DbxTableViewDelegate } from '@dereekb/dbx-web/table'; +import { beginLoading, beginLoadingPage, ListLoadingState, PageListLoadingState, successPageResult, successResult } from '@dereekb/rxjs'; +import { Maybe, ModelKeyRef, range } from '@dereekb/util'; +import { delay, map, Observable, of, startWith, BehaviorSubject, skip, shareReplay, distinctUntilChanged, switchMap } from 'rxjs'; +import { DocExtensionTableItemActionExampleComponent } from '../component/table.item.action.example.component'; +import { DocExtensionTableItemHeaderExampleComponent } from '../component/table.item.header.example.component'; +import { ExampleTableData } from '../component/table.item'; + +@Component({ + templateUrl: './table.component.html' +}) +export class DocExtensionTableComponent implements OnDestroy { + readonly exampleInput: DateRangeDayDistanceInput = { + date: startOfDay(new Date()), + distance: 6 + }; + + readonly exampleTableData: ExampleTableData[] = range(0, 15).map((x) => ({ name: `Example ${x}`, key: String(x) })); + readonly exampleTableDataItems = new BehaviorSubject(this.exampleTableData); + + readonly isLoading$ = this.exampleTableDataItems.pipe( + skip(1), + map((x) => false), + startWith(true), + distinctUntilChanged(), + shareReplay(1) + ); + + readonly exampleViewDelegate: DbxTableViewDelegate = { + inputHeader: dbxTableDateRangeDayDistanceInputCellInput(), + columnHeader: dbxTableDateHeaderInjectionFactory(), + itemHeader: function (item: ExampleTableData) { + return { + componentClass: DocExtensionTableItemHeaderExampleComponent, + init: (x) => { + x.item = item; + } + }; + }, + itemCell: function (column: DbxTableColumn, item: ExampleTableData) { + return { + componentClass: DocExtensionTableItemCellExampleComponent, + init: (x) => { + x.item = item; + x.column = column; + } + }; + }, + itemAction: function (item: ExampleTableData) { + return { + componentClass: DocExtensionTableItemActionExampleComponent + }; + } + }; + + readonly exampleDataDelegate: DbxTableContextDataDelegate = { + loadData: (input) => { + const allDays = expandDaysForDateRange(dateRange({ ...input })); + const columns: DbxTableColumn[] = allDays.map((x) => ({ columnName: formatToISO8601DayString(x), meta: x })); + const items: ExampleTableData[] = [...this.exampleTableData]; + const items$: Observable> = of(successPageResult(0, items)); + + const result: DbxTableContextData = { + input, + columns, + items$ + }; + + return of(successResult(result)); // .pipe(delay(1000), startWith(beginLoadingPage(0))); + } + }; + + readonly exampleLoadingContextDelegate: DbxTableContextDataDelegate = { + loadData: (input) => { + return of(beginLoadingPage>(0)); + } + }; + + readonly exampleLoadingDataDelegate: DbxTableContextDataDelegate = { + loadData: (input) => { + const allDays = expandDaysForDateRange(dateRange({ ...input })); + const columns: DbxTableColumn[] = allDays.map((x) => ({ columnName: formatToISO8601DayString(x), meta: x })); + const items$: Observable> = this.exampleTableDataItems + .pipe( + skip(1), + switchMap((x) => of(successPageResult(0, x)).pipe(delay(1000), startWith(beginLoadingPage(0)))) + ) + .pipe(startWith(beginLoadingPage(0))); + + const result: DbxTableContextData = { + input, + columns, + items$, + loadMore: () => this.loadMoreItems() + }; + + return of(successResult(result)); + } + }; + + loadMoreItems() { + const currentItems = this.exampleTableDataItems.value; + const itemsCount = currentItems.length; + const newItems = range(itemsCount + 1, itemsCount + 15).map((x) => ({ name: `Example ${x}`, key: String(x) })); + this.exampleTableDataItems.next([...currentItems, ...newItems]); + } + + ngOnDestroy(): void { + this.exampleTableDataItems.complete(); + } +} diff --git a/apps/demo/src/app/modules/doc/modules/extension/doc.extension.module.ts b/apps/demo/src/app/modules/doc/modules/extension/doc.extension.module.ts index be279ac9f..db896d907 100644 --- a/apps/demo/src/app/modules/doc/modules/extension/doc.extension.module.ts +++ b/apps/demo/src/app/modules/doc/modules/extension/doc.extension.module.ts @@ -13,6 +13,7 @@ import { DocFormComponentsModule } from '../form/doc.form.module'; import { DocExtensionMapboxComponent } from './container/mapbox.component'; import { DbxFormMapboxModule } from '@dereekb/dbx-form/mapbox'; import { DbxMapboxModule } from '@dereekb/dbx-web/mapbox'; +import { DbxTableDateModule, DbxTableModule } from '@dereekb/dbx-web/table'; import { NgxMapboxGLModule } from 'ngx-mapbox-gl'; import { DocExtensionMapboxContentExampleComponent } from './component/mapbox.content.example.component'; import { DocExtensionMapboxMarkersExampleComponent } from './component/mapbox.markers.example.component'; @@ -20,6 +21,10 @@ import { DbxCalendarRootModule } from '@dereekb/dbx-web/calendar'; import { DocExtensionCalendarScheduleSelectionComponent } from './component/selection.calendar.component'; import { DbxFormCalendarModule, DbxFormDateScheduleRangeFieldModule } from '@dereekb/dbx-form/calendar'; import { DocExtensionCalendarScheduleSelectionWithFilterComponent } from './component/selection.filter.calendar.component'; +import { DocExtensionTableComponent } from './container/table.component'; +import { DocExtensionTableItemActionExampleComponent } from './component/table.item.action.example.component'; +import { DocExtensionTableItemCellExampleComponent } from './component/table.item.cell.example.component'; +import { DocExtensionTableItemHeaderExampleComponent } from './component/table.item.header.example.component'; @NgModule({ imports: [ @@ -32,6 +37,8 @@ import { DocExtensionCalendarScheduleSelectionWithFilterComponent } from './comp DbxMapboxModule, NgxMapboxGLModule, DbxFormMapboxModule, + DbxTableModule, + DbxTableDateModule, UIRouterModule.forChild({ states: STATES }) @@ -44,10 +51,14 @@ import { DocExtensionCalendarScheduleSelectionWithFilterComponent } from './comp DocExtensionMapboxMarkersExampleComponent, DocExtensionCalendarScheduleSelectionComponent, DocExtensionCalendarScheduleSelectionWithFilterComponent, + DocExtensionTableItemHeaderExampleComponent, + DocExtensionTableItemCellExampleComponent, + DocExtensionTableItemActionExampleComponent, // container DocExtensionLayoutComponent, DocExtensionHomeComponent, DocExtensionCalendarComponent, + DocExtensionTableComponent, DocExtensionWidgetComponent, DocExtensionMapboxComponent ] diff --git a/apps/demo/src/app/modules/doc/modules/extension/doc.extension.router.ts b/apps/demo/src/app/modules/doc/modules/extension/doc.extension.router.ts index fdccf9aaa..adb50747c 100644 --- a/apps/demo/src/app/modules/doc/modules/extension/doc.extension.router.ts +++ b/apps/demo/src/app/modules/doc/modules/extension/doc.extension.router.ts @@ -4,6 +4,7 @@ import { DocExtensionCalendarComponent } from './container/calendar.component'; import { DocExtensionHomeComponent } from './container/home.component'; import { DocExtensionWidgetComponent } from './container/widget.component'; import { DocExtensionMapboxComponent } from './container/mapbox.component'; +import { DocExtensionTableComponent } from './container/table.component'; export const layoutState: Ng2StateDeclaration = { url: '/extension', @@ -36,11 +37,18 @@ export const docExtensionMapboxState: Ng2StateDeclaration = { component: DocExtensionMapboxComponent }; +export const docExtensionTableState: Ng2StateDeclaration = { + url: '/table', + name: 'doc.extension.table', + component: DocExtensionTableComponent +}; + export const STATES: Ng2StateDeclaration[] = [ // layoutState, homeState, docExtensionCalendarState, docExtensionWidgetState, - docExtensionMapboxState + docExtensionMapboxState, + docExtensionTableState ]; diff --git a/apps/demo/src/app/modules/doc/modules/extension/doc.extension.ts b/apps/demo/src/app/modules/doc/modules/extension/doc.extension.ts index 121b94543..127b6028e 100644 --- a/apps/demo/src/app/modules/doc/modules/extension/doc.extension.ts +++ b/apps/demo/src/app/modules/doc/modules/extension/doc.extension.ts @@ -16,6 +16,12 @@ export const DOC_EXTENSION_ROUTES = [ title: 'Mapbox', detail: 'mapbox extension', ref: 'doc.extension.mapbox' + }, + { + icon: 'table_view', + title: 'Table', + detail: 'table extension', + ref: 'doc.extension.table' } ]; diff --git a/apps/demo/src/app/modules/doc/modules/layout/container/content.component.html b/apps/demo/src/app/modules/doc/modules/layout/container/content.component.html index 87535530f..59585fde1 100644 --- a/apps/demo/src/app/modules/doc/modules/layout/container/content.component.html +++ b/apps/demo/src/app/modules/doc/modules/layout/container/content.component.html @@ -60,6 +60,30 @@

Growth can be customized.

This content is in a box that is not elevated.

+ + +

This content is in pit.

+
+

Examples

+

Example of a dbx-content-pit with dbx-label-block and content.

+
+ + +
100
+
+
+ + +
100
+
+
+ + +
100
+
+
+
+
diff --git a/components/demo-components/CHANGELOG.md b/components/demo-components/CHANGELOG.md index 164d587db..0cf3236cb 100644 --- a/components/demo-components/CHANGELOG.md +++ b/components/demo-components/CHANGELOG.md @@ -2,6 +2,10 @@ This file was generated using [@jscutlery/semver](https://github.com/jscutlery/semver). +# [9.21.0](https://github.com/dereekb/dbx-components/compare/v9.20.20-dev...v9.21.0) (2023-01-31) + + + ## [9.20.20](https://github.com/dereekb/dbx-components/compare/v9.20.19-dev...v9.20.20) (2023-01-23) diff --git a/components/demo-components/package.json b/components/demo-components/package.json index 87d178e63..720d23af8 100644 --- a/components/demo-components/package.json +++ b/components/demo-components/package.json @@ -1,6 +1,6 @@ { "name": "@dereekb/demo-components", - "version": "9.20.20", + "version": "9.21.0", "peerDependencies": { "@angular/common": "^14.0.0", "@angular/core": "^14.0.0" diff --git a/components/demo-components/src/lib/modules/development/setup.widget.component.html b/components/demo-components/src/lib/modules/development/setup.widget.component.html index f51e98610..91b342e61 100644 --- a/components/demo-components/src/lib/modules/development/setup.widget.component.html +++ b/components/demo-components/src/lib/modules/development/setup.widget.component.html @@ -3,4 +3,8 @@ + + + + diff --git a/components/demo-components/src/lib/modules/development/setup.widget.component.ts b/components/demo-components/src/lib/modules/development/setup.widget.component.ts index dc89ec741..fda917391 100644 --- a/components/demo-components/src/lib/modules/development/setup.widget.component.ts +++ b/components/demo-components/src/lib/modules/development/setup.widget.component.ts @@ -24,4 +24,14 @@ export class DemoSetupDevelopmentWidgetComponent implements OnInit { readonly handleCreateGuestbook: HandleActionWithContext = (value, context) => { context.startWorkingWithLoadingStateObservable(this.guestbookDocumentStore.createGuestbook({ name: `My New Guestbook ${randomNumber(999)}`, published: true })); }; + + readonly handleCreateTwentyGuestbooks: HandleActionWithContext = (value, context) => { + context.startWorking(); + + for (let i = 0; i < 20; i += 1) { + this.guestbookDocumentStore.createGuestbook({ name: `My New Guestbook ${randomNumber(999)}`, published: true }).subscribe(); + } + + context.success(); + }; } diff --git a/components/demo-firebase/CHANGELOG.md b/components/demo-firebase/CHANGELOG.md index ada53dd3a..4b20b2d61 100644 --- a/components/demo-firebase/CHANGELOG.md +++ b/components/demo-firebase/CHANGELOG.md @@ -2,6 +2,10 @@ This file was generated using [@jscutlery/semver](https://github.com/jscutlery/semver). +# [9.21.0](https://github.com/dereekb/dbx-components/compare/v9.20.20-dev...v9.21.0) (2023-01-31) + + + ## [9.20.20](https://github.com/dereekb/dbx-components/compare/v9.20.19-dev...v9.20.20) (2023-01-23) diff --git a/components/demo-firebase/package.json b/components/demo-firebase/package.json index 9e3d753f6..5a4edff26 100644 --- a/components/demo-firebase/package.json +++ b/components/demo-firebase/package.json @@ -1,5 +1,5 @@ { "name": "@dereekb/demo-firebase", - "version": "9.20.20", + "version": "9.21.0", "type": "commonjs" } diff --git a/package.json b/package.json index f5016fa1a..dd43bc87e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@dereekb/dbx-components", - "version": "9.20.20", + "version": "9.21.0", "license": "MIT", "scripts": { "postinstall": "ngcc --properties es2020 browser module main && echo >> .env.local", diff --git a/packages/browser/CHANGELOG.md b/packages/browser/CHANGELOG.md index 198f3b20d..cfb5ae66e 100644 --- a/packages/browser/CHANGELOG.md +++ b/packages/browser/CHANGELOG.md @@ -2,6 +2,10 @@ This file was generated using [@jscutlery/semver](https://github.com/jscutlery/semver). +# [9.21.0](https://github.com/dereekb/dbx-components/compare/v9.20.20-dev...v9.21.0) (2023-01-31) + + + ## [9.20.20](https://github.com/dereekb/dbx-components/compare/v9.20.19-dev...v9.20.20) (2023-01-23) diff --git a/packages/browser/package.json b/packages/browser/package.json index 1a01f1288..4067991d5 100644 --- a/packages/browser/package.json +++ b/packages/browser/package.json @@ -1,5 +1,5 @@ { "name": "@dereekb/browser", - "version": "9.20.20", + "version": "9.21.0", "type": "commonjs" } diff --git a/packages/date/CHANGELOG.md b/packages/date/CHANGELOG.md index 75aac3f76..decbaf8a6 100644 --- a/packages/date/CHANGELOG.md +++ b/packages/date/CHANGELOG.md @@ -2,6 +2,15 @@ This file was generated using [@jscutlery/semver](https://github.com/jscutlery/semver). +# [9.21.0](https://github.com/dereekb/dbx-components/compare/v9.20.20-dev...v9.21.0) (2023-01-31) + + +### Features + +* dbx-table ([#23](https://github.com/dereekb/dbx-components/issues/23)) ([4661508](https://github.com/dereekb/dbx-components/commit/466150895b5bdc6e9e5289ef38ef5dd3e0ae67f9)) + + + ## [9.20.20](https://github.com/dereekb/dbx-components/compare/v9.20.19-dev...v9.20.20) (2023-01-23) diff --git a/packages/date/package.json b/packages/date/package.json index ca289967b..cdcc0e4a5 100644 --- a/packages/date/package.json +++ b/packages/date/package.json @@ -1,5 +1,5 @@ { "name": "@dereekb/date", - "version": "9.20.20", + "version": "9.21.0", "type": "commonjs" } diff --git a/packages/date/src/lib/date/date.block.ts b/packages/date/src/lib/date/date.block.ts index ecdc22abf..a715d3043 100644 --- a/packages/date/src/lib/date/date.block.ts +++ b/packages/date/src/lib/date/date.block.ts @@ -254,7 +254,7 @@ export function dateBlockTiming(durationInput: DateDurationSpan, inputRange: Dat } else { inputDate = startsAt; // TODO: May not be needed? numberOfBlockedDays = inputRange.distance - 1; - range = dateRange({ date: inputDate, distance: inputRange.distance }, true); + range = dateRange({ type: DateRangeType.DAY, date: inputDate, distance: inputRange.distance }, true); } if (inputDate != null) { diff --git a/packages/date/src/lib/date/date.range.spec.ts b/packages/date/src/lib/date/date.range.spec.ts index 5d63b4c0d..5985f491a 100644 --- a/packages/date/src/lib/date/date.range.spec.ts +++ b/packages/date/src/lib/date/date.range.spec.ts @@ -1,5 +1,38 @@ -import { addDays, addHours } from 'date-fns'; -import { dateRangeOverlapsDateRangeFunction, isDateInDateRangeFunction, isDateRangeInDateRangeFunction } from './date.range'; +import { startOfDay, addDays, addHours } from 'date-fns'; +import { dateRange, dateRangeOverlapsDateRangeFunction, DateRangeType, expandDaysForDateRangeFunction, isDateInDateRangeFunction, isDateRangeInDateRangeFunction } from './date.range'; + +describe('expandDaysForDateRangeFunction()', () => { + describe('function', () => { + const expandFn = expandDaysForDateRangeFunction({}); + + it('should expand the range to an array of days', () => { + const days = 3; + const start = startOfDay(new Date()); + const end = addDays(start, days - 1); + + const result = expandFn({ start, end }); + expect(result.length).toBe(days); + + expect(result[0]).toBeSameSecondAs(start); + expect(result[1]).toBeSameSecondAs(addDays(start, 1)); + expect(result[2]).toBeSameSecondAs(addDays(addDays(start, 1), 1)); + expect(result[2]).toBeSameSecondAs(end); + }); + + it('should expand the dateRange', () => { + const distance = 3; + const { start, end } = dateRange({ date: new Date(), distance, type: DateRangeType.DAYS_RANGE }); + + const result = expandFn({ start, end }); + expect(result.length).toBe(distance + 1); + + expect(result[0]).toBeSameSecondAs(start); + expect(result[1]).toBeSameSecondAs(addDays(start, 1)); + expect(result[2]).toBeSameSecondAs(addDays(addDays(start, 1), 1)); + expect(result[3]).toBeSameSecondAs(addDays(addDays(addDays(start, 1), 1), 1)); + }); + }); +}); describe('isDateInDateRangeFunction()', () => { describe('function', () => { diff --git a/packages/date/src/lib/date/date.range.ts b/packages/date/src/lib/date/date.range.ts index 13865f931..1c9b27119 100644 --- a/packages/date/src/lib/date/date.range.ts +++ b/packages/date/src/lib/date/date.range.ts @@ -1,7 +1,7 @@ -import { Building, Maybe } from '@dereekb/util'; +import { Building, FactoryWithRequiredInput, Maybe } from '@dereekb/util'; import { Expose, Type } from 'class-transformer'; import { IsEnum, IsOptional, IsDate, IsNumber } from 'class-validator'; -import { addDays, addHours, endOfDay, endOfMonth, endOfWeek, isDate, isPast, startOfDay, startOfMinute, startOfMonth, startOfWeek } from 'date-fns'; +import { addDays, addHours, differenceInDays, endOfDay, endOfMonth, endOfWeek, isAfter, isBefore, isDate, isPast, startOfDay, startOfMinute, startOfMonth, startOfWeek } from 'date-fns'; import { isSameDate } from './date'; /** @@ -190,7 +190,7 @@ export type DateRangeInput = (DateRangeTypedInput | DateRangeDistanceInput) & { * @param roundToMinute * @returns */ -export function dateRange({ type = DateRangeType.DAY, date = new Date(), distance, roundToMinute: inputRoundToMinute = false }: DateRangeInput, roundToMinute = inputRoundToMinute): DateRange { +export function dateRange({ type = DateRangeType.DAYS_RANGE, date = new Date(), distance, roundToMinute: inputRoundToMinute = false }: DateRangeInput, roundToMinute = inputRoundToMinute): DateRange { let start: Date; let end: Date; @@ -269,6 +269,62 @@ export function dateRange({ type = DateRangeType.DAY, date = new Date(), distanc }; } +export interface ExpandDaysForDateRangeConfig { + /** + * (Optiona) Max expansion size for expanding a date range. + * + * If the expected expansion is larger than this size, an exception is thrown. + * + * If 0 or false, there is no max size. + * + * Defaults to 1500 days. + */ + maxExpansionSize?: number | 0 | false; +} + +export const DEFAULT_EXPAND_DAYS_FOR_DATE_RANGE_MAX_EXPANSION_SIZE = 1500; + +export type ExpandDaysForDateRangeFunction = FactoryWithRequiredInput; + +/** + * Expands the input range into dates. + * + * @param param0 + */ +export function expandDaysForDateRangeFunction(config: ExpandDaysForDateRangeConfig = {}): ExpandDaysForDateRangeFunction { + const { maxExpansionSize: inputMaxExpansionSize = DEFAULT_EXPAND_DAYS_FOR_DATE_RANGE_MAX_EXPANSION_SIZE } = config; + const maxExpansionSize = inputMaxExpansionSize ? inputMaxExpansionSize : Number.MAX_SAFE_INTEGER; + + return ({ start, end }: DateRange) => { + // check the expansion isn't too large + const distance = Math.abs(differenceInDays(start, end)); + + if (distance > maxExpansionSize) { + throw new Error(`Attempted to expand days past the max expansion size of "${distance}"`); + } + + const dates: Date[] = []; + let current = start; + + while (!isAfter(current, end)) { + dates.push(current); + current = addDays(current, 1); + } + + return dates; + }; +} + +/** + * Expands the input range to the days. + * + * @param range + * @returns + */ +export function expandDaysForDateRange(range: DateRange): Date[] { + return expandDaysForDateRangeFunction({})(range); +} + /** * Returns the DateRangeState from the input DateRange. * diff --git a/packages/dbx-analytics/CHANGELOG.md b/packages/dbx-analytics/CHANGELOG.md index 7be2448b7..b73349c92 100644 --- a/packages/dbx-analytics/CHANGELOG.md +++ b/packages/dbx-analytics/CHANGELOG.md @@ -2,6 +2,10 @@ This file was generated using [@jscutlery/semver](https://github.com/jscutlery/semver). +# [9.21.0](https://github.com/dereekb/dbx-components/compare/v9.20.20-dev...v9.21.0) (2023-01-31) + + + ## [9.20.20](https://github.com/dereekb/dbx-components/compare/v9.20.19-dev...v9.20.20) (2023-01-23) diff --git a/packages/dbx-analytics/package.json b/packages/dbx-analytics/package.json index 83c09cf33..207343d8e 100644 --- a/packages/dbx-analytics/package.json +++ b/packages/dbx-analytics/package.json @@ -1,6 +1,6 @@ { "name": "@dereekb/dbx-analytics", - "version": "9.20.20", + "version": "9.21.0", "peerDependencies": { "@angular/common": "^14.0.0", "@angular/core": "^14.0.0" diff --git a/packages/dbx-core/CHANGELOG.md b/packages/dbx-core/CHANGELOG.md index b7d14bddf..cf05d878e 100644 --- a/packages/dbx-core/CHANGELOG.md +++ b/packages/dbx-core/CHANGELOG.md @@ -2,6 +2,15 @@ This file was generated using [@jscutlery/semver](https://github.com/jscutlery/semver). +# [9.21.0](https://github.com/dereekb/dbx-components/compare/v9.20.20-dev...v9.21.0) (2023-01-31) + + +### Features + +* dbx-table ([#23](https://github.com/dereekb/dbx-components/issues/23)) ([4661508](https://github.com/dereekb/dbx-components/commit/466150895b5bdc6e9e5289ef38ef5dd3e0ae67f9)) + + + ## [9.20.20](https://github.com/dereekb/dbx-components/compare/v9.20.19-dev...v9.20.20) (2023-01-23) diff --git a/packages/dbx-core/package.json b/packages/dbx-core/package.json index 62711e0ad..fbe894e88 100644 --- a/packages/dbx-core/package.json +++ b/packages/dbx-core/package.json @@ -1,6 +1,6 @@ { "name": "@dereekb/dbx-core", - "version": "9.20.20", + "version": "9.21.0", "peerDependencies": { "@angular/common": "^14.0.0", "@angular/core": "^14.0.0", diff --git a/packages/dbx-core/src/lib/injection/injection.ts b/packages/dbx-core/src/lib/injection/injection.ts index b2a5a6e2d..f58e698cc 100644 --- a/packages/dbx-core/src/lib/injection/injection.ts +++ b/packages/dbx-core/src/lib/injection/injection.ts @@ -1,5 +1,5 @@ import { InjectionToken, Injector, NgModuleRef, StaticProvider, TemplateRef, Type, ViewRef } from '@angular/core'; -import { filterMaybeValues, Maybe, mergeArrays, mergeObjects } from '@dereekb/util'; +import { FactoryWithRequiredInput, filterMaybeValues, Maybe, mergeArrays, mergeObjects } from '@dereekb/util'; export const DBX_INJECTION_COMPONENT_DATA = new InjectionToken('DbxInjectionComponentConfigData'); @@ -30,6 +30,8 @@ export interface DbxInjectionComponentConfig { data?: unknown; } +export type DbxInjectionComponentConfigFactory = FactoryWithRequiredInput, I>; + export interface DbxInjectionTemplateConfig { /** * Template ref to display. diff --git a/packages/dbx-firebase/CHANGELOG.md b/packages/dbx-firebase/CHANGELOG.md index faa2dafd6..7209b8126 100644 --- a/packages/dbx-firebase/CHANGELOG.md +++ b/packages/dbx-firebase/CHANGELOG.md @@ -2,6 +2,15 @@ This file was generated using [@jscutlery/semver](https://github.com/jscutlery/semver). +# [9.21.0](https://github.com/dereekb/dbx-components/compare/v9.20.20-dev...v9.21.0) (2023-01-31) + + +### Bug Fixes + +* fixed enableMultiTabIndexedDbPersistence usage ([2c41552](https://github.com/dereekb/dbx-components/commit/2c41552c6849cd7cae2405cd456d92bca265a5d3)) + + + ## [9.20.20](https://github.com/dereekb/dbx-components/compare/v9.20.19-dev...v9.20.20) (2023-01-23) diff --git a/packages/dbx-firebase/package.json b/packages/dbx-firebase/package.json index e2a4c9c6b..fbd0cc227 100644 --- a/packages/dbx-firebase/package.json +++ b/packages/dbx-firebase/package.json @@ -1,6 +1,6 @@ { "name": "@dereekb/dbx-firebase", - "version": "9.20.20", + "version": "9.21.0", "peerDependencies": { "@angular/common": "^14.0.0", "@angular/core": "^14.0.0" diff --git a/packages/dbx-firebase/src/lib/firebase/firebase.module.ts b/packages/dbx-firebase/src/lib/firebase/firebase.module.ts index 59bd2f35a..0c9b98fb1 100644 --- a/packages/dbx-firebase/src/lib/firebase/firebase.module.ts +++ b/packages/dbx-firebase/src/lib/firebase/firebase.module.ts @@ -30,12 +30,10 @@ import { DbxFirebaseAppCheckHttpInterceptor } from '../auth/appcheck/appcheck.in connectFirestoreEmulator(firestore, emulators.firestore.host, emulators.firestore.port, {}); } - if (firebaseOptions.enableIndexedDbPersistence !== false) { - enableIndexedDbPersistence(firestore); - } - if (firebaseOptions.enableMultiTabIndexedDbPersistence !== false) { enableMultiTabIndexedDbPersistence(firestore); + } else if (firebaseOptions.enableIndexedDbPersistence !== false) { + enableIndexedDbPersistence(firestore); } return firestore; diff --git a/packages/dbx-firebase/src/lib/firebase/options.ts b/packages/dbx-firebase/src/lib/firebase/options.ts index 35036d399..cdab149f9 100644 --- a/packages/dbx-firebase/src/lib/firebase/options.ts +++ b/packages/dbx-firebase/src/lib/firebase/options.ts @@ -17,15 +17,15 @@ export interface DbxFirebaseOptions extends FirebaseOptions, Pick { +export class DbxFirebaseCollectionListDirective extends AbstractSubscriptionDirective implements OnInit { constructor(readonly dbxFirebaseCollectionStoreDirective: DbxFirebaseCollectionStoreDirective, @Host() readonly dbxListViewWrapper: DbxListViewWrapper) { - this.dbxListViewWrapper.state$ = this.dbxFirebaseCollectionStoreDirective.pageLoadingState$; + super(); + this.dbxListViewWrapper.state$ = this.dbxFirebaseCollectionStoreDirective.pageLoadingState$.pipe(tapLog('xxx')); + } + + ngOnInit(): void { + this.sub = this.dbxListViewWrapper.loadMore?.subscribe(() => { + this.dbxFirebaseCollectionStoreDirective.next(); + }); } } diff --git a/packages/dbx-form/CHANGELOG.md b/packages/dbx-form/CHANGELOG.md index 173c7dcde..d1b75300c 100644 --- a/packages/dbx-form/CHANGELOG.md +++ b/packages/dbx-form/CHANGELOG.md @@ -2,6 +2,15 @@ This file was generated using [@jscutlery/semver](https://github.com/jscutlery/semver). +# [9.21.0](https://github.com/dereekb/dbx-components/compare/v9.20.20-dev...v9.21.0) (2023-01-31) + + +### Features + +* dbx-table ([#23](https://github.com/dereekb/dbx-components/issues/23)) ([4661508](https://github.com/dereekb/dbx-components/commit/466150895b5bdc6e9e5289ef38ef5dd3e0ae67f9)) + + + ## [9.20.20](https://github.com/dereekb/dbx-components/compare/v9.20.19-dev...v9.20.20) (2023-01-23) diff --git a/packages/dbx-form/calendar/CHANGELOG.md b/packages/dbx-form/calendar/CHANGELOG.md index a44c95ccc..8ea58974b 100644 --- a/packages/dbx-form/calendar/CHANGELOG.md +++ b/packages/dbx-form/calendar/CHANGELOG.md @@ -2,6 +2,15 @@ This file was generated using [@jscutlery/semver](https://github.com/jscutlery/semver). +# [9.21.0](https://github.com/dereekb/dbx-components/compare/v9.20.20-dev...v9.21.0) (2023-01-31) + + +### Features + +* dbx-table ([#23](https://github.com/dereekb/dbx-components/issues/23)) ([4661508](https://github.com/dereekb/dbx-components/commit/466150895b5bdc6e9e5289ef38ef5dd3e0ae67f9)) + + + ## [9.20.20](https://github.com/dereekb/dbx-components/compare/v9.20.19-dev...v9.20.20) (2023-01-23) diff --git a/packages/dbx-form/calendar/package.json b/packages/dbx-form/calendar/package.json index db2460b1e..8eab41271 100644 --- a/packages/dbx-form/calendar/package.json +++ b/packages/dbx-form/calendar/package.json @@ -1,6 +1,6 @@ { "name": "@dereekb/dbx-form/calendar", - "version": "9.20.20", + "version": "9.21.0", "peerDependencies": { "@angular/common": "^14.2.0", "@angular/core": "^14.2.0" diff --git a/packages/dbx-form/calendar/src/lib/calendar.schedule.selection.range.component.ts b/packages/dbx-form/calendar/src/lib/calendar.schedule.selection.range.component.ts index cf3efed16..c22e0368f 100644 --- a/packages/dbx-form/calendar/src/lib/calendar.schedule.selection.range.component.ts +++ b/packages/dbx-form/calendar/src/lib/calendar.schedule.selection.range.component.ts @@ -92,6 +92,7 @@ export class DbxScheduleSelectionCalendarDateRangeComponent implements OnDestroy } ngOnDestroy(): void { + this._pickerOpened.complete(); this._syncSub.destroy(); this._valueSub.destroy(); } diff --git a/packages/dbx-form/mapbox/CHANGELOG.md b/packages/dbx-form/mapbox/CHANGELOG.md index d2cde23da..e6e71edda 100644 --- a/packages/dbx-form/mapbox/CHANGELOG.md +++ b/packages/dbx-form/mapbox/CHANGELOG.md @@ -2,6 +2,10 @@ This file was generated using [@jscutlery/semver](https://github.com/jscutlery/semver). +# [9.21.0](https://github.com/dereekb/dbx-components/compare/v9.20.20-dev...v9.21.0) (2023-01-31) + + + ## [9.20.20](https://github.com/dereekb/dbx-components/compare/v9.20.19-dev...v9.20.20) (2023-01-23) diff --git a/packages/dbx-form/mapbox/package.json b/packages/dbx-form/mapbox/package.json index 046a7a457..e16113a4a 100644 --- a/packages/dbx-form/mapbox/package.json +++ b/packages/dbx-form/mapbox/package.json @@ -1,6 +1,6 @@ { "name": "@dereekb/dbx-form/mapbox", - "version": "9.20.20", + "version": "9.21.0", "peerDependencies": { "@angular/common": "^14.1.0", "@angular/core": "^14.1.0" diff --git a/packages/dbx-form/package.json b/packages/dbx-form/package.json index 4df95431f..c19644875 100644 --- a/packages/dbx-form/package.json +++ b/packages/dbx-form/package.json @@ -1,6 +1,6 @@ { "name": "@dereekb/dbx-form", - "version": "9.20.20", + "version": "9.21.0", "peerDependencies": { "@angular/common": "^14.0.0", "@angular/core": "^14.0.0", diff --git a/packages/dbx-web/CHANGELOG.md b/packages/dbx-web/CHANGELOG.md index 7957595a2..b7e3b6bf3 100644 --- a/packages/dbx-web/CHANGELOG.md +++ b/packages/dbx-web/CHANGELOG.md @@ -2,6 +2,16 @@ This file was generated using [@jscutlery/semver](https://github.com/jscutlery/semver). +# [9.21.0](https://github.com/dereekb/dbx-components/compare/v9.20.20-dev...v9.21.0) (2023-01-31) + + +### Features + +* added dbx-content-pit ([cbce68a](https://github.com/dereekb/dbx-components/commit/cbce68ad73dc896acc34232e3375698133e99241)) +* dbx-table ([#23](https://github.com/dereekb/dbx-components/issues/23)) ([4661508](https://github.com/dereekb/dbx-components/commit/466150895b5bdc6e9e5289ef38ef5dd3e0ae67f9)) + + + ## [9.20.20](https://github.com/dereekb/dbx-components/compare/v9.20.19-dev...v9.20.20) (2023-01-23) diff --git a/packages/dbx-web/calendar/CHANGELOG.md b/packages/dbx-web/calendar/CHANGELOG.md index 5b0f3e0e2..df5a77a6f 100644 --- a/packages/dbx-web/calendar/CHANGELOG.md +++ b/packages/dbx-web/calendar/CHANGELOG.md @@ -2,6 +2,15 @@ This file was generated using [@jscutlery/semver](https://github.com/jscutlery/semver). +# [9.21.0](https://github.com/dereekb/dbx-components/compare/v9.20.20-dev...v9.21.0) (2023-01-31) + + +### Features + +* dbx-table ([#23](https://github.com/dereekb/dbx-components/issues/23)) ([4661508](https://github.com/dereekb/dbx-components/commit/466150895b5bdc6e9e5289ef38ef5dd3e0ae67f9)) + + + ## [9.20.20](https://github.com/dereekb/dbx-components/compare/v9.20.19-dev...v9.20.20) (2023-01-23) diff --git a/packages/dbx-web/calendar/package.json b/packages/dbx-web/calendar/package.json index f3e54dfeb..30151a9bc 100644 --- a/packages/dbx-web/calendar/package.json +++ b/packages/dbx-web/calendar/package.json @@ -1,6 +1,6 @@ { "name": "@dereekb/dbx-web/calendar", - "version": "9.20.20", + "version": "9.21.0", "peerDependencies": { "@angular/common": "^14.2.0", "@angular/core": "^14.2.0" diff --git a/packages/dbx-web/calendar/tsconfig.spec.json b/packages/dbx-web/calendar/tsconfig.spec.json index 7aa46d88c..99ef89807 100644 --- a/packages/dbx-web/calendar/tsconfig.spec.json +++ b/packages/dbx-web/calendar/tsconfig.spec.json @@ -5,6 +5,5 @@ "module": "commonjs", "types": ["jest", "node"] }, - "files": ["src/test-setup.ts"], "include": ["jest.config.ts", "**/*.test.ts", "**/*.spec.ts", "**/*.d.ts"] } diff --git a/packages/dbx-web/mapbox/CHANGELOG.md b/packages/dbx-web/mapbox/CHANGELOG.md index 3ee0908e8..08a58992f 100644 --- a/packages/dbx-web/mapbox/CHANGELOG.md +++ b/packages/dbx-web/mapbox/CHANGELOG.md @@ -2,6 +2,15 @@ This file was generated using [@jscutlery/semver](https://github.com/jscutlery/semver). +# [9.21.0](https://github.com/dereekb/dbx-components/compare/v9.20.20-dev...v9.21.0) (2023-01-31) + + +### Features + +* dbx-table ([#23](https://github.com/dereekb/dbx-components/issues/23)) ([4661508](https://github.com/dereekb/dbx-components/commit/466150895b5bdc6e9e5289ef38ef5dd3e0ae67f9)) + + + ## [9.20.20](https://github.com/dereekb/dbx-components/compare/v9.20.19-dev...v9.20.20) (2023-01-23) diff --git a/packages/dbx-web/mapbox/package.json b/packages/dbx-web/mapbox/package.json index d428ef2f0..6cf1057fe 100644 --- a/packages/dbx-web/mapbox/package.json +++ b/packages/dbx-web/mapbox/package.json @@ -1,6 +1,6 @@ { "name": "@dereekb/dbx-web/mapbox", - "version": "9.20.20", + "version": "9.21.0", "peerDependencies": { "@angular/common": "^14.1.0", "@angular/core": "^14.1.0" diff --git a/packages/dbx-web/mapbox/tsconfig.lib.json b/packages/dbx-web/mapbox/tsconfig.lib.json index 814ca7c78..a17e7cae7 100644 --- a/packages/dbx-web/mapbox/tsconfig.lib.json +++ b/packages/dbx-web/mapbox/tsconfig.lib.json @@ -7,6 +7,6 @@ "inlineSources": true, "types": [] }, - "exclude": ["src/test-setup.ts", "**/*.spec.ts", "jest.config.ts", "**/*.test.ts"], + "exclude": ["**/*.spec.ts", "jest.config.ts", "**/*.test.ts"], "include": ["**/*.ts"] } diff --git a/packages/dbx-web/mapbox/tsconfig.spec.json b/packages/dbx-web/mapbox/tsconfig.spec.json index 7aa46d88c..99ef89807 100644 --- a/packages/dbx-web/mapbox/tsconfig.spec.json +++ b/packages/dbx-web/mapbox/tsconfig.spec.json @@ -5,6 +5,5 @@ "module": "commonjs", "types": ["jest", "node"] }, - "files": ["src/test-setup.ts"], "include": ["jest.config.ts", "**/*.test.ts", "**/*.spec.ts", "**/*.d.ts"] } diff --git a/packages/dbx-web/package.json b/packages/dbx-web/package.json index ff23ca6ba..021ad20d3 100644 --- a/packages/dbx-web/package.json +++ b/packages/dbx-web/package.json @@ -1,6 +1,6 @@ { "name": "@dereekb/dbx-web", - "version": "9.20.20", + "version": "9.21.0", "peerDependencies": { "@angular/common": "^14.0.0", "@angular/core": "^14.0.0", @@ -14,6 +14,8 @@ ".": { "sass": "./_index.scss" }, - "./mapbox": {} + "./mapbox": {}, + "./calendar": {}, + "./table": {} } } diff --git a/packages/dbx-web/project.json b/packages/dbx-web/project.json index 27c16a599..085c9dbf4 100644 --- a/packages/dbx-web/project.json +++ b/packages/dbx-web/project.json @@ -33,6 +33,10 @@ { "description": "build dbx-web/calendar", "command": "npx nx run dbx-web-calendar:build-base:production" + }, + { + "description": "build dbx-web/table", + "command": "npx nx run dbx-web-table:build-base:production" } ], "parallel": false, diff --git a/packages/dbx-web/src/lib/extension/_extension.scss b/packages/dbx-web/src/lib/extension/_extension.scss index 2bfda3b5c..0bc9706ca 100644 --- a/packages/dbx-web/src/lib/extension/_extension.scss +++ b/packages/dbx-web/src/lib/extension/_extension.scss @@ -1,38 +1,57 @@ @use '../style/config'; @use './calendar/calendar'; +@use './table/table'; @mixin all-extension-core($theme-config) { $calendar-enabled: 1; + $table-enabled: 1; @if ($theme-config != null) { $calendar-enabled: config.get-dbx-extension-calendar-enabled($theme-config); + $table-enabled: config.get-dbx-extension-table-enabled($theme-config); } @if ($calendar-enabled == 1) { @include calendar.core(); } + + @if ($table-enabled == 1) { + @include table.core(); + } } @mixin all-extension-typography($typography-config, $theme-config) { $calendar-enabled: 1; + $table-enabled: 1; @if ($theme-config != null) { $calendar-enabled: config.get-dbx-extension-calendar-enabled($theme-config); + $table-enabled: config.get-dbx-extension-table-enabled($theme-config); } @if ($calendar-enabled == 1) { @include calendar.typography($typography-config); } + + @if ($table-enabled == 1) { + @include table.typography($typography-config); + } } @mixin all-extension-theme($theme-config) { $calendar-enabled: 1; + $table-enabled: 1; @if ($theme-config != null) { $calendar-enabled: config.get-dbx-extension-calendar-enabled($theme-config); + $table-enabled: config.get-dbx-extension-table-enabled($theme-config); } @if ($calendar-enabled == 1) { @include calendar.theme($theme-config); } + + @if ($table-enabled == 1) { + @include table.theme($theme-config); + } } diff --git a/packages/dbx-web/src/lib/extension/table/_table.scss b/packages/dbx-web/src/lib/extension/table/_table.scss new file mode 100644 index 000000000..a7687d60f --- /dev/null +++ b/packages/dbx-web/src/lib/extension/table/_table.scss @@ -0,0 +1,60 @@ +@use 'sass:map'; +@use '../../style/theming'; + +// MARK: Variables + +// MARK: Mixin +@mixin core() { + .dbx-table-view { + height: 600px; + overflow: auto; + + .dbx-table-view-table { + width: 100%; + } + } + + .dbx-table-view-loading { + } + + // MARK: Date + .dbx-table-date-range-distance-input-cell { + min-width: 140px; + + .dbx-table-date-range-distance-input { + height: 0px; + overflow: hidden; + } + } + + .dbx-table-date-column-header { + min-width: 80px; + text-align: center; + + .dbx-table-date-column-header-left { + margin-right: 4px; + font-weight: 800; + } + } +} + +@mixin color($theme-config) { +} + +@mixin typography($typography-config) { +} + +@mixin theme($theme-config) { + @include theming.private-check-duplicate-theme-styles($theme-config, 'dbx-table') { + $color: theming.get-color-config($theme-config); + $typography: theming.get-typography-config($theme-config); + + @if $color !=null { + @include color($theme-config); + } + + @if $typography !=null { + @include typography($typography); + } + } +} diff --git a/packages/dbx-web/src/lib/layout/content/_content.scss b/packages/dbx-web/src/lib/layout/content/_content.scss index 40b3a3fe0..43ad9e9de 100644 --- a/packages/dbx-web/src/lib/layout/content/_content.scss +++ b/packages/dbx-web/src/lib/layout/content/_content.scss @@ -13,6 +13,8 @@ $max-small-content-container-width: calc($content-max-width / 3); $max-medium-content-container-width: calc($content-max-width / 2); $max-content-container-width: $content-max-width; +$pit-padding: theming.$padding-4; + $content-container-padding: theming.$padding-4; $content-container-padding-small-screen: theming.$padding-2; @@ -41,6 +43,14 @@ $scroll-content-bottom-padding: 42px; } } + .dbx-content-pit { + padding: $pit-padding; + } + + .dbx-content-pit > .dbx-label-block > .dbx-label { + opacity: 0.66; // increase opacity slightly to make it easier to read against background + } + .dbx-content-end { margin-bottom: $content-end-margin; } @@ -142,6 +152,10 @@ $scroll-content-bottom-padding: 42px; background: $content-background; } + .dbx-content-pit { + background: $content-border-background; + } + .dbx-content-border { // border-radius: 6px; border: 3px dashed $content-border-background; diff --git a/packages/dbx-web/src/lib/layout/content/content.layout.module.ts b/packages/dbx-web/src/lib/layout/content/content.layout.module.ts index 07a5ec543..b5db1cd11 100644 --- a/packages/dbx-web/src/lib/layout/content/content.layout.module.ts +++ b/packages/dbx-web/src/lib/layout/content/content.layout.module.ts @@ -6,13 +6,25 @@ import { DbxContentBorderDirective } from './content.border.directive'; import { DbxContentContainerDirective } from './content.container.directive'; import { DbxContentBoxDirective } from './content.box.directive'; import { DbxContentPageDirective } from './content.page.directive'; +import { DbxContentPitDirective } from './content.pit.directive'; + +const declarations = [ + // + DbxContentDirective, + DbxContentContainerDirective, + DbxContentBorderDirective, + DbxContentElevateDirective, + DbxContentBoxDirective, + DbxContentPageDirective, + DbxContentPitDirective +]; /** * Module for container-type components. */ @NgModule({ imports: [CommonModule], - declarations: [DbxContentDirective, DbxContentContainerDirective, DbxContentBorderDirective, DbxContentElevateDirective, DbxContentBoxDirective, DbxContentPageDirective], - exports: [DbxContentDirective, DbxContentContainerDirective, DbxContentBorderDirective, DbxContentElevateDirective, DbxContentBoxDirective, DbxContentPageDirective] + declarations, + exports: declarations }) export class DbxContentLayoutModule {} diff --git a/packages/dbx-web/src/lib/layout/content/content.pit.directive.ts b/packages/dbx-web/src/lib/layout/content/content.pit.directive.ts new file mode 100644 index 000000000..211600b07 --- /dev/null +++ b/packages/dbx-web/src/lib/layout/content/content.pit.directive.ts @@ -0,0 +1,12 @@ +import { Component, Directive, Input } from '@angular/core'; + +/** + * Component used to wrap content in a pit with a label. + */ +@Directive({ + selector: 'dbx-content-pit, [dbxContentPit]', + host: { + class: 'd-block dbx-content-pit' + } +}) +export class DbxContentPitDirective {} diff --git a/packages/dbx-web/src/lib/layout/content/index.ts b/packages/dbx-web/src/lib/layout/content/index.ts index ed8cfc630..498a1ca6e 100644 --- a/packages/dbx-web/src/lib/layout/content/index.ts +++ b/packages/dbx-web/src/lib/layout/content/index.ts @@ -5,3 +5,4 @@ export * from './content.container.directive'; export * from './content.elevate.directive'; export * from './content.layout.module'; export * from './content.page.directive'; +export * from './content.pit.directive'; diff --git a/packages/dbx-web/src/lib/layout/list/list.wrapper.ts b/packages/dbx-web/src/lib/layout/list/list.wrapper.ts index d16353222..23b49d36c 100644 --- a/packages/dbx-web/src/lib/layout/list/list.wrapper.ts +++ b/packages/dbx-web/src/lib/layout/list/list.wrapper.ts @@ -1,6 +1,6 @@ import { Observable } from 'rxjs'; import { ListLoadingState } from '@dereekb/rxjs'; -import { forwardRef, Provider, Type } from '@angular/core'; +import { EventEmitter, forwardRef, Provider, Type } from '@angular/core'; import { Maybe } from '@dereekb/util'; /** @@ -8,6 +8,7 @@ import { Maybe } from '@dereekb/util'; */ export abstract class DbxListViewWrapper = ListLoadingState> { state$?: Maybe>; + readonly loadMore?: EventEmitter; } export function provideDbxListViewWrapper(sourceType: Type): Provider[] { diff --git a/packages/dbx-web/src/lib/layout/style/_style.scss b/packages/dbx-web/src/lib/layout/style/_style.scss index 7755ae8aa..16d7dbba0 100644 --- a/packages/dbx-web/src/lib/layout/style/_style.scss +++ b/packages/dbx-web/src/lib/layout/style/_style.scss @@ -21,6 +21,10 @@ padding: 0 !important; } + .dbx-hide { + display: none !important; + } + @each $i, $padding in theming.$padding-map { .pad-#{$i}, .padding-#{$i} { diff --git a/packages/dbx-web/src/lib/style/_config.scss b/packages/dbx-web/src/lib/style/_config.scss index 19f06776f..a5453b40b 100644 --- a/packages/dbx-web/src/lib/style/_config.scss +++ b/packages/dbx-web/src/lib/style/_config.scss @@ -151,8 +151,10 @@ // extension @function define-dbx-extension-config($input-dbx-theme-extension-config: null) { $dbx-extension-config: ( - // calendar - 'calendar': 1 // enabled by default + // calendar enabled by default + 'calendar': 1, + // table enabled by default + 'table': 1 ); @if ($input-dbx-theme-extension-config != null) { @@ -173,3 +175,7 @@ @function get-dbx-extension-calendar-enabled($theme-config) { @return get-dbx-extension-config-var($theme-config, 'calendar'); } + +@function get-dbx-extension-table-enabled($theme-config) { + @return get-dbx-extension-config-var($theme-config, 'table'); +} diff --git a/packages/dbx-web/table/.eslintrc.json b/packages/dbx-web/table/.eslintrc.json new file mode 100644 index 000000000..173a30f54 --- /dev/null +++ b/packages/dbx-web/table/.eslintrc.json @@ -0,0 +1,4 @@ +{ + "extends": ["../../../.eslintrc.angular.json"], + "ignorePatterns": ["!**/*"] +} diff --git a/packages/dbx-web/table/CHANGELOG.md b/packages/dbx-web/table/CHANGELOG.md new file mode 100644 index 000000000..217d7d03d --- /dev/null +++ b/packages/dbx-web/table/CHANGELOG.md @@ -0,0 +1,10 @@ +# Changelog + +This file was generated using [@jscutlery/semver](https://github.com/jscutlery/semver). + +# [9.21.0](https://github.com/dereekb/dbx-components/compare/v9.20.20-dev...v9.21.0) (2023-01-31) + + +### Features + +* dbx-table ([#23](https://github.com/dereekb/dbx-components/issues/23)) ([4661508](https://github.com/dereekb/dbx-components/commit/466150895b5bdc6e9e5289ef38ef5dd3e0ae67f9)) diff --git a/packages/dbx-web/table/README.md b/packages/dbx-web/table/README.md new file mode 100644 index 000000000..f45702e92 --- /dev/null +++ b/packages/dbx-web/table/README.md @@ -0,0 +1,6 @@ +@dereekb/dbx-web/table +======= + +The sources for this package are in the main [@dereekb/dbx-components](https://github.com/dereekb/dbx-components) repo. Please file issues and pull requests against that repo. + +License: MIT diff --git a/packages/dbx-web/table/jest.config.ts b/packages/dbx-web/table/jest.config.ts new file mode 100644 index 000000000..165303fdc --- /dev/null +++ b/packages/dbx-web/table/jest.config.ts @@ -0,0 +1,9 @@ +/* eslint-disable */ +(global as any).appTestType = 'angular'; +(global as any).testFolderRootPath = '/../../..'; + +module.exports = { + displayName: 'dbx-web-table', + preset: '../../../jest.preset.ts', + coverageDirectory: '../../../../coverage/packages/dbx-web/table' +}; diff --git a/packages/dbx-web/table/ng-package.json b/packages/dbx-web/table/ng-package.json new file mode 100644 index 000000000..9563c8fb8 --- /dev/null +++ b/packages/dbx-web/table/ng-package.json @@ -0,0 +1,7 @@ +{ + "$schema": "../../../node_modules/ng-packagr/ng-package.schema.json", + "dest": "../../../dist/packages/dbx-web/table", + "lib": { + "entryFile": "src/index.ts" + } +} diff --git a/packages/dbx-web/table/package.json b/packages/dbx-web/table/package.json new file mode 100644 index 000000000..07d1dc456 --- /dev/null +++ b/packages/dbx-web/table/package.json @@ -0,0 +1,11 @@ +{ + "name": "@dereekb/dbx-web/table", + "version": "9.21.0", + "peerDependencies": { + "@angular/common": "^14.2.0", + "@angular/core": "^14.2.0" + }, + "dependencies": { + "tslib": "^2.3.0" + } +} diff --git a/packages/dbx-web/table/project.json b/packages/dbx-web/table/project.json new file mode 100644 index 000000000..810debe18 --- /dev/null +++ b/packages/dbx-web/table/project.json @@ -0,0 +1,40 @@ +{ + "name": "dbx-web-table", + "$schema": "../../../node_modules/nx/schemas/project-schema.json", + "projectType": "library", + "sourceRoot": "packages/dbx-web/table/src", + "prefix": "dereekb", + "targets": { + "build-base": { + "executor": "@nrwl/angular:package", + "outputs": ["dist/packages/dbx-web/table"], + "options": { + "project": "packages/dbx-web/table/ng-package.json" + }, + "configurations": { + "production": { + "tsConfig": "packages/dbx-web/table/tsconfig.lib.prod.json" + }, + "development": { + "tsConfig": "packages/dbx-web/table/tsconfig.lib.json" + } + }, + "defaultConfiguration": "production" + }, + "test": { + "executor": "@nrwl/jest:jest", + "outputs": ["coverage/packages/dbx-web/table"], + "options": { + "jestConfig": "packages/dbx-web/table/jest.config.ts", + "passWithNoTests": true + } + }, + "lint": { + "executor": "@nrwl/linter:eslint", + "options": { + "lintFilePatterns": ["packages/dbx-web/table/**/*.ts", "packages/dbx-web/table/**/*.html"] + } + } + }, + "tags": [] +} diff --git a/packages/dbx-web/table/src/index.ts b/packages/dbx-web/table/src/index.ts new file mode 100644 index 000000000..f41a696fd --- /dev/null +++ b/packages/dbx-web/table/src/index.ts @@ -0,0 +1 @@ +export * from './lib'; diff --git a/packages/dbx-web/table/src/lib/date/date.table.column.header.component.ts b/packages/dbx-web/table/src/lib/date/date.table.column.header.component.ts new file mode 100644 index 000000000..f005ba168 --- /dev/null +++ b/packages/dbx-web/table/src/lib/date/date.table.column.header.component.ts @@ -0,0 +1,46 @@ +import { ChangeDetectionStrategy, Component } from '@angular/core'; +import { DbxInjectionComponentConfig, DbxInjectionComponentConfigFactory } from '@dereekb/dbx-core'; +import { Maybe } from '@dereekb/util'; +import { DbxTableColumn } from '../table'; + +/** + * A table header component used for rendering date values on the header. + */ +@Component({ + template: ` +
+ {{ date | date: left }} + {{ date | date: right }} +
+ `, + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class DbxTableDateHeaderComponent { + left: string = 'E'; + right: string = 'MMM d'; + + private _date: Maybe; + + constructor() {} + + get date() { + return this._date; + } + + set date(date: Maybe) { + this._date = date; + } +} + +export function dbxTableDateHeaderInjectionFactory(): DbxInjectionComponentConfigFactory, DbxTableDateHeaderComponent> { + return (column: DbxTableColumn) => { + const config: DbxInjectionComponentConfig = { + componentClass: DbxTableDateHeaderComponent, + init: (x) => { + x.date = column.meta; + } + }; + + return config; + }; +} diff --git a/packages/dbx-web/table/src/lib/date/daterange.table.cell.input.component.ts b/packages/dbx-web/table/src/lib/date/daterange.table.cell.input.component.ts new file mode 100644 index 000000000..000c53d00 --- /dev/null +++ b/packages/dbx-web/table/src/lib/date/daterange.table.cell.input.component.ts @@ -0,0 +1,179 @@ +import { ChangeDetectionStrategy, Component, Injectable, OnDestroy, OnInit } from '@angular/core'; +import { DateBlock, DateDurationSpan, DateRangeDayDistanceInput, isSameDateDay } from '@dereekb/date'; +import { DbxTableStore } from '../table.store'; +import { MatDateRangeSelectionStrategy, DateRange, MAT_DATE_RANGE_SELECTION_STRATEGY } from '@angular/material/datepicker'; +import { DateAdapter } from '@angular/material/core'; +import { Days, Maybe } from '@dereekb/util'; +import { FormGroup, FormControl } from '@angular/forms'; +import { SubscriptionObject } from '@dereekb/rxjs'; +import { addDays, format as formatDate } from 'date-fns'; +import { BehaviorSubject, distinctUntilChanged, filter, map, Observable, of, startWith, switchMap, throttleTime, combineLatest } from 'rxjs'; +import { DbxInjectionComponentConfig, DbxInjectionComponentConfigFactory } from '@dereekb/dbx-core'; + +@Injectable() +export class DbxTableDateRangeDayDistanceInputCellInputRangeSelectionStrategy implements MatDateRangeSelectionStrategy { + constructor(private _dateAdapter: DateAdapter, private dbxTableDateRangeDayDistanceInputCellInputComponent: DbxTableDateRangeDayDistanceInputCellInputComponent) {} + + selectionFinished(date: D | null): DateRange { + return this._createFiveDayRange(date); + } + + createPreview(activeDate: D | null): DateRange { + return this._createFiveDayRange(activeDate); + } + + private _createFiveDayRange(date: D | null): DateRange { + if (date) { + const start = date; + const end = this._dateAdapter.addCalendarDays(date, this.dbxTableDateRangeDayDistanceInputCellInputComponent.daysDistance); + return new DateRange(start, end); + } + + return new DateRange(null, null); + } +} + +export interface DbxTableDateRangeDayDistanceInputCellInputComponentConfig { + /** + * Button format for the dates + */ + buttonFormat?: string; + /** + * Distance from the start to span. + */ + daysDistance: Days; + minDate?: Maybe; + maxDate?: Maybe; +} + +export const DEFAULT_DBX_TABLE_DATE_RANGE_DAY_DISTIANCE_INPUT_CELL_COMPONENT_CONFIG = { daysDistance: 6 }; + +export const DEFAULT_DBX_TABLE_DATE_RANGE_DAY_BUTTON_FORMAT = 'MMM dd'; + +/** + * Cell input for a DateRangeDayDistanceInput value. + */ +@Component({ + template: ` +
+ + + + + + +
+ `, + providers: [ + { + provide: MAT_DATE_RANGE_SELECTION_STRATEGY, + useClass: DbxTableDateRangeDayDistanceInputCellInputRangeSelectionStrategy + } + ], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class DbxTableDateRangeDayDistanceInputCellInputComponent implements OnInit, OnDestroy { + private _syncSub = new SubscriptionObject(); + private _valueSub = new SubscriptionObject(); + + private _pickerOpened = new BehaviorSubject(false); + private _config = new BehaviorSubject(DEFAULT_DBX_TABLE_DATE_RANGE_DAY_DISTIANCE_INPUT_CELL_COMPONENT_CONFIG); + + readonly range = new FormGroup({ + start: new FormControl>(null), + end: new FormControl>(null) + }); + + readonly pickerOpened$ = this._pickerOpened.asObservable(); + + readonly minDate$ = this._config.pipe(map((x) => x.minDate)); + readonly maxDate$ = this._config.pipe(map((x) => x.maxDate)); + + readonly buttonFormat$ = this._config.pipe(map((x) => x.buttonFormat ?? DEFAULT_DBX_TABLE_DATE_RANGE_DAY_BUTTON_FORMAT)); + + readonly dateRangeString$ = combineLatest([this.buttonFormat$, this.range.valueChanges]).pipe( + map(([buttonFormat, { start, end }]) => { + if (start && end) { + return `${formatDate(start, buttonFormat)} - ${formatDate(end, buttonFormat)}`; + } else { + return `Select Date`; + } + }) + ); + + constructor(readonly tableStore: DbxTableStore) {} + + ngOnInit(): void { + this._syncSub.subscription = this.tableStore.input$.subscribe((x) => { + const start = x?.date ?? null; + const end = start ? addDays(start, this.daysDistance) : undefined; + + this.range.setValue({ + start, + end + }); + }); + + this._valueSub.subscription = this._pickerOpened + .pipe( + distinctUntilChanged(), + switchMap((opened) => { + let obs: Observable<{ start?: Maybe }>; + + if (opened) { + obs = of({}); + } else { + obs = this.range.valueChanges.pipe(startWith(this.range.value)); + } + + return obs; + }), + filter((x) => Boolean(x.start)), + distinctUntilChanged((a, b) => isSameDateDay(a.start, b.start)), + throttleTime(100, undefined, { trailing: true }) + ) + .subscribe((x) => { + if (x.start) { + this.tableStore.setInput({ date: x.start, distance: this.daysDistance }); + } + }); + } + + ngOnDestroy(): void { + this._pickerOpened.complete(); + this._config.complete(); + this._syncSub.destroy(); + this._valueSub.destroy(); + } + + get daysDistance() { + return this._config.value.daysDistance; + } + + get config() { + return this._config.value; + } + + set config(config: Maybe) { + this._config.next(config || DEFAULT_DBX_TABLE_DATE_RANGE_DAY_DISTIANCE_INPUT_CELL_COMPONENT_CONFIG); + } + + pickerOpened() { + this._pickerOpened.next(true); + } + + pickerClosed() { + this._pickerOpened.next(false); + } +} + +export function dbxTableDateRangeDayDistanceInputCellInput(componentConfig?: DbxTableDateRangeDayDistanceInputCellInputComponentConfig): DbxInjectionComponentConfig { + const config: DbxInjectionComponentConfig = { + componentClass: DbxTableDateRangeDayDistanceInputCellInputComponent, + init: (x) => { + x.config = componentConfig; + } + }; + + return config; +} diff --git a/packages/dbx-web/table/src/lib/date/index.ts b/packages/dbx-web/table/src/lib/date/index.ts new file mode 100644 index 000000000..bcdbc10e1 --- /dev/null +++ b/packages/dbx-web/table/src/lib/date/index.ts @@ -0,0 +1,3 @@ +export * from './date.table.column.header.component'; +export * from './daterange.table.cell.input.component'; +export * from './table.date.module'; diff --git a/packages/dbx-web/table/src/lib/date/table.date.module.ts b/packages/dbx-web/table/src/lib/date/table.date.module.ts new file mode 100644 index 000000000..38dd4309c --- /dev/null +++ b/packages/dbx-web/table/src/lib/date/table.date.module.ts @@ -0,0 +1,35 @@ +import { MatIconModule } from '@angular/material/icon'; +import { MatButtonModule } from '@angular/material/button'; +import { DbxLoadingModule } from '@dereekb/dbx-web'; +import { MatTableModule } from '@angular/material/table'; +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { DbxInjectionComponentModule } from '@dereekb/dbx-core'; +import { DbxTableDateHeaderComponent } from './date.table.column.header.component'; +import { DbxTableDateRangeDayDistanceInputCellInputComponent } from './daterange.table.cell.input.component'; +import { MatDatepickerModule } from '@angular/material/datepicker'; +import { FormsModule, ReactiveFormsModule } from '@angular/forms'; + +const declarations = [ + // + DbxTableDateHeaderComponent, + DbxTableDateRangeDayDistanceInputCellInputComponent +]; + +@NgModule({ + imports: [ + // + CommonModule, + DbxLoadingModule, + DbxInjectionComponentModule, + FormsModule, + ReactiveFormsModule, + MatIconModule, + MatDatepickerModule, + MatButtonModule, + MatTableModule + ], + declarations, + exports: declarations +}) +export class DbxTableDateModule {} diff --git a/packages/dbx-web/table/src/lib/index.ts b/packages/dbx-web/table/src/lib/index.ts new file mode 100644 index 000000000..15ba81df7 --- /dev/null +++ b/packages/dbx-web/table/src/lib/index.ts @@ -0,0 +1,17 @@ +export * from './date'; +export * from './table.cell.action.component'; +export * from './table.cell.input.component'; +export * from './table.cell.summaryend.component'; +export * from './table.cell.summarystart.component'; +export * from './table.column.directive'; +export * from './table.column.header.component'; +export * from './table.column.footer.component'; +export * from './table.component'; +export * from './table.directive'; +export * from './table.item.action.component'; +export * from './table.item.cell.component'; +export * from './table.item.directive'; +export * from './table.item.header.component'; +export * from './table.module'; +export * from './table.store'; +export * from './table'; diff --git a/packages/dbx-web/table/src/lib/table.cell.action.component.ts b/packages/dbx-web/table/src/lib/table.cell.action.component.ts new file mode 100644 index 000000000..198b44b4b --- /dev/null +++ b/packages/dbx-web/table/src/lib/table.cell.action.component.ts @@ -0,0 +1,19 @@ +import { ChangeDetectionStrategy, Component } from '@angular/core'; +import { map, distinctUntilChanged } from 'rxjs'; +import { DbxTableStore } from './table.store'; + +@Component({ + selector: 'dbx-table-action-cell', + template: ` + + `, + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class DbxTableActionCellComponent { + readonly config$ = this.tableStore.viewDelegate$.pipe( + map((x) => x.summaryRowEnd), + distinctUntilChanged() + ); + + constructor(readonly tableStore: DbxTableStore) {} +} diff --git a/packages/dbx-web/table/src/lib/table.cell.input.component.ts b/packages/dbx-web/table/src/lib/table.cell.input.component.ts new file mode 100644 index 000000000..b66bcc76a --- /dev/null +++ b/packages/dbx-web/table/src/lib/table.cell.input.component.ts @@ -0,0 +1,23 @@ +import { ChangeDetectionStrategy, Component } from '@angular/core'; +import { AbstractDbxInjectionDirective } from '@dereekb/dbx-core'; +import { map, distinctUntilChanged } from 'rxjs'; +import { DbxTableStore } from './table.store'; + +/** + * A table header component used for injecting the input picker view. + */ +@Component({ + selector: 'dbx-table-input-cell', + template: ` + + `, + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class DbxTableInputCellComponent { + readonly config$ = this.tableStore.viewDelegate$.pipe( + map((x) => x.inputHeader), + distinctUntilChanged() + ); + + constructor(readonly tableStore: DbxTableStore) {} +} diff --git a/packages/dbx-web/table/src/lib/table.cell.summaryend.component.ts b/packages/dbx-web/table/src/lib/table.cell.summaryend.component.ts new file mode 100644 index 000000000..b4f9e3763 --- /dev/null +++ b/packages/dbx-web/table/src/lib/table.cell.summaryend.component.ts @@ -0,0 +1,19 @@ +import { ChangeDetectionStrategy, Component } from '@angular/core'; +import { map, distinctUntilChanged } from 'rxjs'; +import { DbxTableStore } from './table.store'; + +@Component({ + selector: 'dbx-table-summary-end-cell', + template: ` + + `, + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class DbxTableSummaryEndCellComponent { + readonly config$ = this.tableStore.viewDelegate$.pipe( + map((x) => x.summaryRowEnd), + distinctUntilChanged() + ); + + constructor(readonly tableStore: DbxTableStore) {} +} diff --git a/packages/dbx-web/table/src/lib/table.cell.summarystart.component.ts b/packages/dbx-web/table/src/lib/table.cell.summarystart.component.ts new file mode 100644 index 000000000..e10020407 --- /dev/null +++ b/packages/dbx-web/table/src/lib/table.cell.summarystart.component.ts @@ -0,0 +1,23 @@ +import { ChangeDetectionStrategy, Component } from '@angular/core'; +import { AbstractDbxInjectionDirective } from '@dereekb/dbx-core'; +import { map, distinctUntilChanged } from 'rxjs'; +import { DbxTableStore } from './table.store'; + +/** + * A table header component used for injecting the input picker view. + */ +@Component({ + selector: 'dbx-table-summary-start-cell', + template: ` + + `, + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class DbxTableSummaryStartCellComponent { + readonly config$ = this.tableStore.viewDelegate$.pipe( + map((x) => x.summaryRowHeader), + distinctUntilChanged() + ); + + constructor(readonly tableStore: DbxTableStore) {} +} diff --git a/packages/dbx-web/table/src/lib/table.column.directive.ts b/packages/dbx-web/table/src/lib/table.column.directive.ts new file mode 100644 index 000000000..4b857906b --- /dev/null +++ b/packages/dbx-web/table/src/lib/table.column.directive.ts @@ -0,0 +1,26 @@ +import { filterMaybe } from '@dereekb/rxjs'; +import { ChangeDetectionStrategy, Component, OnInit, OnDestroy, Input, Directive } from '@angular/core'; +import { map, distinctUntilChanged, BehaviorSubject, switchMap } from 'rxjs'; +import { DbxTableStore } from './table.store'; +import { Maybe } from '@dereekb/util'; +import { DbxTableColumn } from './table'; + +/** + * Abstract directive that has a column input. + */ +@Directive() +export class AbstractDbxTableColumnDirective implements OnDestroy { + private readonly _column = new BehaviorSubject>>(undefined); + readonly column$ = this._column.pipe(filterMaybe(), distinctUntilChanged()); + + constructor(readonly tableStore: DbxTableStore) {} + + @Input() + set column(column: Maybe>) { + this._column.next(column); + } + + ngOnDestroy(): void { + this._column.complete(); + } +} diff --git a/packages/dbx-web/table/src/lib/table.column.footer.component.ts b/packages/dbx-web/table/src/lib/table.column.footer.component.ts new file mode 100644 index 000000000..5eb876c0e --- /dev/null +++ b/packages/dbx-web/table/src/lib/table.column.footer.component.ts @@ -0,0 +1,25 @@ +import { ChangeDetectionStrategy, Component, OnDestroy } from '@angular/core'; +import { map, distinctUntilChanged, switchMap, of } from 'rxjs'; +import { AbstractDbxTableColumnDirective } from './table.column.directive'; + +@Component({ + selector: 'dbx-table-column-footer', + template: ` + + `, + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class DbxTableColumnFooterComponent extends AbstractDbxTableColumnDirective implements OnDestroy { + readonly config$ = this.tableStore.viewDelegate$.pipe( + switchMap((viewDelegate) => { + const columnFooter = viewDelegate.columnFooter; + + if (columnFooter) { + return this.column$.pipe(map((x) => columnFooter(x))); + } else { + return of(undefined); + } + }), + distinctUntilChanged() + ); +} diff --git a/packages/dbx-web/table/src/lib/table.column.header.component.ts b/packages/dbx-web/table/src/lib/table.column.header.component.ts new file mode 100644 index 000000000..0e4271210 --- /dev/null +++ b/packages/dbx-web/table/src/lib/table.column.header.component.ts @@ -0,0 +1,25 @@ +import { ChangeDetectionStrategy, Component, OnDestroy } from '@angular/core'; +import { map, distinctUntilChanged, switchMap, of } from 'rxjs'; +import { AbstractDbxTableColumnDirective } from './table.column.directive'; + +@Component({ + selector: 'dbx-table-column-header', + template: ` + + `, + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class DbxTableColumnHeaderComponent extends AbstractDbxTableColumnDirective implements OnDestroy { + readonly config$ = this.tableStore.viewDelegate$.pipe( + switchMap((viewDelegate) => { + const columnHeader = viewDelegate.columnHeader; + + if (columnHeader) { + return this.column$.pipe(map((x) => columnHeader(x))); + } else { + return of(undefined); + } + }), + distinctUntilChanged() + ); +} diff --git a/packages/dbx-web/table/src/lib/table.component.html b/packages/dbx-web/table/src/lib/table.component.html new file mode 100644 index 000000000..812873499 --- /dev/null +++ b/packages/dbx-web/table/src/lib/table.component.html @@ -0,0 +1,52 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + +
+
+
diff --git a/packages/dbx-web/table/src/lib/table.component.ts b/packages/dbx-web/table/src/lib/table.component.ts new file mode 100644 index 000000000..ca5af9556 --- /dev/null +++ b/packages/dbx-web/table/src/lib/table.component.ts @@ -0,0 +1,62 @@ +import { shareReplay } from 'rxjs/operators'; +import { ChangeDetectionStrategy, Component, OnDestroy, TrackByFunction } from '@angular/core'; +import { DbxTableStore } from './table.store'; +import { loadingStateContext, tapLog } from '@dereekb/rxjs'; +import { map, Observable } from 'rxjs'; +import { DbxValueListItemConfig } from '@dereekb/dbx-web'; + +export const DBX_TABLE_ITEMS_COLUMN_NAME = '_items'; +export const DBX_TABLE_ACTIONS_COLUMN_NAME = '_actions'; + +/** + * A table with fixed content + */ +@Component({ + selector: 'dbx-table-view', + templateUrl: './table.component.html', + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class DbxTableViewComponent implements OnDestroy { + readonly DEFAULT_TRACK_BY_FUNCTION: TrackByFunction = (index) => { + return index; + }; + + scrollDistance = 0.5; + throttleScroll = 50; + + readonly itemsColumnName = DBX_TABLE_ITEMS_COLUMN_NAME; + readonly actionsColumnName = DBX_TABLE_ACTIONS_COLUMN_NAME; + + readonly innerColumns$ = this.tableStore.columns$; + readonly innerColumnNames$ = this.innerColumns$.pipe( + map((x) => x.map((y) => y.columnName)), + shareReplay(1) + ); + + readonly elements$ = this.tableStore.items$; + + readonly displayedColumns$ = this.innerColumnNames$.pipe( + map((columnNames) => { + return [this.itemsColumnName, ...columnNames, this.actionsColumnName]; + }), + shareReplay(1) + ); + + readonly trackByFunction$: Observable> = this.tableStore.viewDelegate$.pipe( + map((x) => x.trackBy ?? this.DEFAULT_TRACK_BY_FUNCTION), + shareReplay(1) + ); + + readonly context = loadingStateContext({ obs: this.tableStore.dataState$ }); + readonly dataLoadingContext = loadingStateContext({ obs: this.tableStore.itemsState$ }); + + constructor(readonly tableStore: DbxTableStore) {} + + ngOnDestroy(): void { + this.context.destroy(); + } + + onScrollDown(): void { + this.tableStore.loadMore(); + } +} diff --git a/packages/dbx-web/table/src/lib/table.directive.ts b/packages/dbx-web/table/src/lib/table.directive.ts new file mode 100644 index 000000000..3274c61c7 --- /dev/null +++ b/packages/dbx-web/table/src/lib/table.directive.ts @@ -0,0 +1,34 @@ +import { filterMaybe } from '@dereekb/rxjs'; +import { ChangeDetectionStrategy, Component, OnInit, OnDestroy, Input, Directive } from '@angular/core'; +import { AbstractDbxInjectionDirective } from '@dereekb/dbx-core'; +import { map, distinctUntilChanged, BehaviorSubject, switchMap } from 'rxjs'; +import { DbxTableStore } from './table.store'; +import { Maybe } from '@dereekb/util'; +import { AbstractDbxTableElementDirective } from './table.item.directive'; +import { DbxTableContextDataDelegate, DbxTableViewDelegate } from './table'; + +/** + * Directive for providing and configuring a DbxTableStore + */ +@Directive({ + selector: '[dbxTable]', + providers: [DbxTableStore] +}) +export class DbxTableDirective { + constructor(readonly tableStore: DbxTableStore) {} + + @Input() + set dbxTableInput(input: Maybe) { + this.tableStore.setInput(input); + } + + @Input() + set dbxTableViewDelegate(dbxTableViewDelegate: Maybe>) { + this.tableStore.setViewDelegate(dbxTableViewDelegate); + } + + @Input() + set dbxTableDataDelegate(dbxTableDataDelegate: Maybe>) { + this.tableStore.setDataDelegate(dbxTableDataDelegate); + } +} diff --git a/packages/dbx-web/table/src/lib/table.item.action.component.ts b/packages/dbx-web/table/src/lib/table.item.action.component.ts new file mode 100644 index 000000000..3b9b515c6 --- /dev/null +++ b/packages/dbx-web/table/src/lib/table.item.action.component.ts @@ -0,0 +1,29 @@ +import { filterMaybe } from '@dereekb/rxjs'; +import { ChangeDetectionStrategy, Component, OnInit, OnDestroy, Input } from '@angular/core'; +import { AbstractDbxInjectionDirective } from '@dereekb/dbx-core'; +import { map, distinctUntilChanged, BehaviorSubject, switchMap, of } from 'rxjs'; +import { DbxTableStore } from './table.store'; +import { Maybe } from '@dereekb/util'; +import { AbstractDbxTableElementDirective } from './table.item.directive'; + +@Component({ + selector: 'dbx-table-item-action', + template: ` + + `, + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class DbxTableItemActionComponent extends AbstractDbxTableElementDirective { + readonly config$ = this.tableStore.viewDelegate$.pipe( + switchMap((viewDelegate) => { + const itemAction = viewDelegate.itemAction; + + if (itemAction) { + return this.element$.pipe(map((x) => itemAction(x))); + } else { + return of(undefined); + } + }), + distinctUntilChanged() + ); +} diff --git a/packages/dbx-web/table/src/lib/table.item.cell.component.ts b/packages/dbx-web/table/src/lib/table.item.cell.component.ts new file mode 100644 index 000000000..ff097580b --- /dev/null +++ b/packages/dbx-web/table/src/lib/table.item.cell.component.ts @@ -0,0 +1,33 @@ +import { filterMaybe } from '@dereekb/rxjs'; +import { ChangeDetectionStrategy, Component, Input } from '@angular/core'; +import { map, distinctUntilChanged, BehaviorSubject, switchMap, combineLatest } from 'rxjs'; +import { Maybe } from '@dereekb/util'; +import { AbstractDbxTableElementDirective } from './table.item.directive'; +import { DbxTableColumn } from './table'; + +@Component({ + selector: 'dbx-table-item-cell', + template: ` + + `, + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class DbxTableItemCellComponent extends AbstractDbxTableElementDirective { + private readonly _column = new BehaviorSubject>>(undefined); + readonly column$ = this._column.pipe(filterMaybe(), distinctUntilChanged()); + + readonly config$ = this.tableStore.viewDelegate$.pipe( + switchMap((viewDelegate) => combineLatest([this.column$, this.element$]).pipe(map(([column, element]) => viewDelegate.itemCell(column, element)))), + distinctUntilChanged() + ); + + @Input() + set column(column: Maybe>) { + this._column.next(column); + } + + override ngOnDestroy(): void { + super.ngOnDestroy(); + this._column.complete(); + } +} diff --git a/packages/dbx-web/table/src/lib/table.item.directive.ts b/packages/dbx-web/table/src/lib/table.item.directive.ts new file mode 100644 index 000000000..1d7c67327 --- /dev/null +++ b/packages/dbx-web/table/src/lib/table.item.directive.ts @@ -0,0 +1,26 @@ +import { filterMaybe } from '@dereekb/rxjs'; +import { ChangeDetectionStrategy, Component, OnInit, OnDestroy, Input, Directive } from '@angular/core'; +import { AbstractDbxInjectionDirective } from '@dereekb/dbx-core'; +import { map, distinctUntilChanged, BehaviorSubject, switchMap } from 'rxjs'; +import { DbxTableStore } from './table.store'; +import { Maybe } from '@dereekb/util'; + +/** + * Abstract directive that has an element input. + */ +@Directive() +export abstract class AbstractDbxTableElementDirective implements OnDestroy { + private readonly _element = new BehaviorSubject>(undefined); + readonly element$ = this._element.pipe(filterMaybe(), distinctUntilChanged()); + + constructor(readonly tableStore: DbxTableStore) {} + + @Input() + set element(element: Maybe) { + this._element.next(element); + } + + ngOnDestroy(): void { + this._element.complete(); + } +} diff --git a/packages/dbx-web/table/src/lib/table.item.header.component.ts b/packages/dbx-web/table/src/lib/table.item.header.component.ts new file mode 100644 index 000000000..cad98bca6 --- /dev/null +++ b/packages/dbx-web/table/src/lib/table.item.header.component.ts @@ -0,0 +1,21 @@ +import { filterMaybe } from '@dereekb/rxjs'; +import { ChangeDetectionStrategy, Component, OnInit, OnDestroy, Input } from '@angular/core'; +import { AbstractDbxInjectionDirective } from '@dereekb/dbx-core'; +import { map, distinctUntilChanged, BehaviorSubject, switchMap } from 'rxjs'; +import { DbxTableStore } from './table.store'; +import { Maybe } from '@dereekb/util'; +import { AbstractDbxTableElementDirective } from './table.item.directive'; + +@Component({ + selector: 'dbx-table-item-header', + template: ` + + `, + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class DbxTableItemHeaderComponent extends AbstractDbxTableElementDirective { + readonly config$ = this.tableStore.viewDelegate$.pipe( + switchMap((viewDelegate) => this.element$.pipe(map((x) => viewDelegate.itemHeader(x)))), + distinctUntilChanged() + ); +} diff --git a/packages/dbx-web/table/src/lib/table.module.ts b/packages/dbx-web/table/src/lib/table.module.ts new file mode 100644 index 000000000..f53a137ef --- /dev/null +++ b/packages/dbx-web/table/src/lib/table.module.ts @@ -0,0 +1,45 @@ +import { InfiniteScrollModule } from 'ngx-infinite-scroll'; +import { DbxLoadingModule } from '@dereekb/dbx-web'; +import { MatTableModule } from '@angular/material/table'; +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { DbxTableItemHeaderComponent } from './table.item.header.component'; +import { DbxTableViewComponent } from './table.component'; +import { DbxTableInputCellComponent } from './table.cell.input.component'; +import { DbxTableSummaryEndCellComponent } from './table.cell.summaryend.component'; +import { DbxTableSummaryStartCellComponent } from './table.cell.summarystart.component'; +import { DbxTableItemActionComponent } from './table.item.action.component'; +import { DbxTableActionCellComponent } from './table.cell.action.component'; +import { DbxTableItemCellComponent } from './table.item.cell.component'; +import { DbxInjectionComponentModule } from '@dereekb/dbx-core'; +import { DbxTableColumnHeaderComponent } from './table.column.header.component'; +import { DbxTableDirective } from './table.directive'; +import { DbxTableColumnFooterComponent } from './table.column.footer.component'; + +const exports = [DbxTableDirective, DbxTableViewComponent]; +const internalDeclarations = [ + // + DbxTableColumnHeaderComponent, + DbxTableColumnFooterComponent, + DbxTableInputCellComponent, + DbxTableActionCellComponent, + DbxTableItemCellComponent, + DbxTableItemHeaderComponent, + DbxTableItemActionComponent, + DbxTableSummaryStartCellComponent, + DbxTableSummaryEndCellComponent +]; + +@NgModule({ + imports: [ + // + CommonModule, + DbxLoadingModule, + DbxInjectionComponentModule, + MatTableModule, + InfiniteScrollModule + ], + declarations: [...exports, ...internalDeclarations], + exports +}) +export class DbxTableModule {} diff --git a/packages/dbx-web/table/src/lib/table.store.ts b/packages/dbx-web/table/src/lib/table.store.ts new file mode 100644 index 000000000..59b1c6a5f --- /dev/null +++ b/packages/dbx-web/table/src/lib/table.store.ts @@ -0,0 +1,108 @@ +import { Injectable } from '@angular/core'; +import { beginLoading, filterMaybe, LoadingState, PageListLoadingState, PageLoadingState, tapOnLoadingStateSuccess, valueFromLoadingState, tapLog } from '@dereekb/rxjs'; +import { Maybe } from '@dereekb/util'; +import { ComponentStore } from '@ngrx/component-store'; +import { Observable, distinctUntilChanged, first, map, shareReplay, switchMap, tap, combineLatest, of, EMPTY } from 'rxjs'; +import { DbxTableColumn, DbxTableContextData, DbxTableContextDataDelegate, DbxTableViewDelegate } from './table'; + +export interface DbxTableStoreState { + /** + * Contextual input that is passed to the data delegate. + */ + readonly input: Maybe; + /** + * Delegate used for retrieving info given the selection. + */ + readonly dataDelegate: Maybe>; + /** + * Delegate used for retrieving view configurations. + */ + readonly viewDelegate: Maybe>; +} + +@Injectable() +export class DbxTableStore extends ComponentStore> { + constructor() { + super({ + input: null, + dataDelegate: null, + viewDelegate: null + }); + } + + // MARK: Effects + readonly loadMore = this.effect((input: Observable) => { + return input.pipe( + switchMap(() => + this.data$.pipe( + first(), + tap((x) => { + if (x.loadMore) { + x.loadMore(); + } + }) + ) + ) + ); + }); + + // MARK: Accessors + readonly input$ = this.state$.pipe( + map((x) => x.input), + distinctUntilChanged(), + shareReplay(1) + ); + + readonly dataDelegate$ = this.state$.pipe( + map((x) => x.dataDelegate), + distinctUntilChanged(), + shareReplay(1) + ); + + readonly currentViewDelegate$ = this.state$.pipe( + map((x) => x.viewDelegate), + distinctUntilChanged(), + shareReplay(1) + ); + + readonly viewDelegate$ = this.currentViewDelegate$.pipe(filterMaybe()); + + readonly dataState$: Observable>> = combineLatest([this.input$, this.dataDelegate$]).pipe( + switchMap(([input, dataDelegate]) => { + let obs: Observable>>; + + if (input && dataDelegate) { + obs = dataDelegate.loadData(input); + } else { + obs = of(beginLoading>()); + } + + return obs; + }), + shareReplay(1) + ); + + readonly data$: Observable> = this.dataState$.pipe( + // + valueFromLoadingState(), + distinctUntilChanged(), + shareReplay(1) + ); + + readonly columns$: Observable[]> = this.data$.pipe( + map((x) => x.columns), + shareReplay(1) + ); + + readonly itemsState$: Observable> = this.data$.pipe( + switchMap((x) => x.items$), + shareReplay(1) + ); + + readonly items$: Observable = this.itemsState$.pipe(valueFromLoadingState(), shareReplay(1)); + + // MARK: State Changes + readonly setInput = this.updater((state, input: Maybe) => ({ ...state, input })); + readonly setDataDelegate = this.updater((state, dataDelegate: Maybe>) => ({ ...state, dataDelegate })); + readonly setViewDelegate = this.updater((state, viewDelegate: Maybe>) => ({ ...state, viewDelegate })); +} diff --git a/packages/dbx-web/table/src/lib/table.ts b/packages/dbx-web/table/src/lib/table.ts new file mode 100644 index 000000000..3da7782ba --- /dev/null +++ b/packages/dbx-web/table/src/lib/table.ts @@ -0,0 +1,103 @@ +import { Observable } from 'rxjs'; +import { LoadingState, PageListLoadingState } from '@dereekb/rxjs'; +import { ClassType, Maybe } from '@dereekb/util'; +import { DbxInjectionComponentConfig } from '@dereekb/dbx-core'; +import { TrackByFunction } from '@angular/core'; + +/** + * Delegate used for retrieving data for a table. + */ +export interface DbxTableContextDataDelegate { + /** + * Loads data given the input. + * + * @param input + */ + loadData(input: I): Observable>>; +} + +export interface DbxTableContextData { + /** + * Original context input + */ + readonly input: I; + /** + * All columns in this data context. + */ + readonly columns: DbxTableColumn[]; + /** + * All currently loaded items. + */ + readonly items$: Observable>; + /** + * Loads more items, if applicable. + */ + loadMore?(): void; +} + +export interface DbxTableColumn { + /** + * Unique column name + */ + readonly columnName: string; + /** + * Column metadata + */ + readonly meta: C; +} + +/** + * Delegate used for generating view configurations given the input. + */ +export interface DbxTableViewDelegate { + /** + * Track by + */ + readonly trackBy?: TrackByFunction; + /** + * Input picker view configuration + */ + readonly inputHeader?: Maybe>; + /** + * Action header view configuration + */ + readonly actionHeader?: Maybe>; + /** + * Summary row header view configuration + */ + readonly summaryRowHeader?: Maybe>; + /** + * Summary row end view configuration + */ + readonly summaryRowEnd?: Maybe>; + /** + * Column header view configuration for a specific column. + * + * @param item + */ + columnHeader?(column: DbxTableColumn): Maybe>; + /** + * Column footer view configuration for a specific column. + * + * @param item + */ + columnFooter?(column: DbxTableColumn): Maybe>; + /** + * Item header view configuration for a specific item. + * + * @param item + */ + itemHeader(item: T): Maybe>; + /** + * Item cell view configuration for a specific item and column. + * + * @param item + */ + itemCell(column: DbxTableColumn, item: T): Maybe>; + /** + * Item action view configuration for a specific item. + * + * @param item + */ + itemAction?(item: T): Maybe>; +} diff --git a/packages/dbx-web/table/tsconfig.json b/packages/dbx-web/table/tsconfig.json new file mode 100644 index 000000000..99e21401e --- /dev/null +++ b/packages/dbx-web/table/tsconfig.json @@ -0,0 +1,31 @@ +{ + "extends": "../../../tsconfig.base.json", + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.lib.prod.json" + }, + { + "path": "./tsconfig.spec.json" + } + ], + "compilerOptions": { + "target": "es2020", + "forceConsistentCasingInFileNames": true, + "strict": true, + "noImplicitOverride": true, + "noPropertyAccessFromIndexSignature": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true + }, + "angularCompilerOptions": { + "enableI18nLegacyMessageIdFormat": false, + "strictInjectionParameters": true, + "strictInputAccessModifiers": true, + "strictTemplates": true + } +} diff --git a/packages/dbx-web/table/tsconfig.lib.json b/packages/dbx-web/table/tsconfig.lib.json new file mode 100644 index 000000000..a17e7cae7 --- /dev/null +++ b/packages/dbx-web/table/tsconfig.lib.json @@ -0,0 +1,12 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../../dist/out-tsc", + "declaration": true, + "declarationMap": true, + "inlineSources": true, + "types": [] + }, + "exclude": ["**/*.spec.ts", "jest.config.ts", "**/*.test.ts"], + "include": ["**/*.ts"] +} diff --git a/packages/dbx-web/table/tsconfig.lib.prod.json b/packages/dbx-web/table/tsconfig.lib.prod.json new file mode 100644 index 000000000..2a2faa884 --- /dev/null +++ b/packages/dbx-web/table/tsconfig.lib.prod.json @@ -0,0 +1,9 @@ +{ + "extends": "./tsconfig.lib.json", + "compilerOptions": { + "declarationMap": false + }, + "angularCompilerOptions": { + "compilationMode": "partial" + } +} diff --git a/packages/dbx-web/table/tsconfig.spec.json b/packages/dbx-web/table/tsconfig.spec.json new file mode 100644 index 000000000..99ef89807 --- /dev/null +++ b/packages/dbx-web/table/tsconfig.spec.json @@ -0,0 +1,9 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"] + }, + "include": ["jest.config.ts", "**/*.test.ts", "**/*.spec.ts", "**/*.d.ts"] +} diff --git a/packages/dbx-web/tsconfig.lib.json b/packages/dbx-web/tsconfig.lib.json index 9efbf1ef9..d3afad591 100644 --- a/packages/dbx-web/tsconfig.lib.json +++ b/packages/dbx-web/tsconfig.lib.json @@ -7,6 +7,6 @@ "inlineSources": true, "types": [] }, - "exclude": ["mapbox/**", "calendar/**", "**/*.spec.ts", "**/*.test.ts", "jest.config.ts"], + "exclude": ["mapbox/**", "calendar/**", "table/**", "**/*.spec.ts", "**/*.test.ts", "jest.config.ts"], "include": ["**/*.ts"] } diff --git a/packages/dbx-web/tsconfig.lib.prod.json b/packages/dbx-web/tsconfig.lib.prod.json index f855629cc..b57502814 100644 --- a/packages/dbx-web/tsconfig.lib.prod.json +++ b/packages/dbx-web/tsconfig.lib.prod.json @@ -6,5 +6,5 @@ "angularCompilerOptions": { "compilationMode": "partial" }, - "exclude": ["mapbox/**", "calendar/**", "jest.config.ts"] + "exclude": ["mapbox/**", "calendar/**", "table/**", "jest.config.ts"] } diff --git a/packages/dbx-web/tsconfig.spec.json b/packages/dbx-web/tsconfig.spec.json index c82fafc8f..74c1c9bb2 100644 --- a/packages/dbx-web/tsconfig.spec.json +++ b/packages/dbx-web/tsconfig.spec.json @@ -6,5 +6,5 @@ "types": ["jest", "node"] }, "include": ["**/*.spec.ts", "**/*.d.ts", "../../jest.setup.typings.ts", "jest.config.ts"], - "exclude": ["mapbox/**", "calendar/**"] + "exclude": ["mapbox/**", "calendar/**", "table/**"] } diff --git a/packages/firebase-server/CHANGELOG.md b/packages/firebase-server/CHANGELOG.md index e307aa49d..0355ad3af 100644 --- a/packages/firebase-server/CHANGELOG.md +++ b/packages/firebase-server/CHANGELOG.md @@ -2,6 +2,10 @@ This file was generated using [@jscutlery/semver](https://github.com/jscutlery/semver). +# [9.21.0](https://github.com/dereekb/dbx-components/compare/v9.20.20-dev...v9.21.0) (2023-01-31) + + + ## [9.20.20](https://github.com/dereekb/dbx-components/compare/v9.20.19-dev...v9.20.20) (2023-01-23) diff --git a/packages/firebase-server/mailgun/CHANGELOG.md b/packages/firebase-server/mailgun/CHANGELOG.md index a6f1ad297..24d507fe2 100644 --- a/packages/firebase-server/mailgun/CHANGELOG.md +++ b/packages/firebase-server/mailgun/CHANGELOG.md @@ -2,6 +2,10 @@ This file was generated using [@jscutlery/semver](https://github.com/jscutlery/semver). +# [9.21.0](https://github.com/dereekb/dbx-components/compare/v9.20.20-dev...v9.21.0) (2023-01-31) + + + ## [9.20.20](https://github.com/dereekb/dbx-components/compare/v9.20.19-dev...v9.20.20) (2023-01-23) diff --git a/packages/firebase-server/mailgun/package.json b/packages/firebase-server/mailgun/package.json index 68a199f8e..d647ba702 100644 --- a/packages/firebase-server/mailgun/package.json +++ b/packages/firebase-server/mailgun/package.json @@ -1,5 +1,5 @@ { "name": "@dereekb/firebase-server/mailgun", - "version": "9.20.20", + "version": "9.21.0", "type": "commonjs" } diff --git a/packages/firebase-server/package.json b/packages/firebase-server/package.json index 3b2442fdd..f6d2a058d 100644 --- a/packages/firebase-server/package.json +++ b/packages/firebase-server/package.json @@ -1,6 +1,6 @@ { "name": "@dereekb/firebase-server", - "version": "9.20.20", + "version": "9.21.0", "devDependencies": { "firebase-functions-test": "2.0.2" }, diff --git a/packages/firebase-server/test/CHANGELOG.md b/packages/firebase-server/test/CHANGELOG.md index 8c6846f5e..2adf446da 100644 --- a/packages/firebase-server/test/CHANGELOG.md +++ b/packages/firebase-server/test/CHANGELOG.md @@ -2,6 +2,10 @@ This file was generated using [@jscutlery/semver](https://github.com/jscutlery/semver). +# [9.21.0](https://github.com/dereekb/dbx-components/compare/v9.20.20-dev...v9.21.0) (2023-01-31) + + + ## [9.20.20](https://github.com/dereekb/dbx-components/compare/v9.20.19-dev...v9.20.20) (2023-01-23) diff --git a/packages/firebase-server/test/package.json b/packages/firebase-server/test/package.json index 8daf9a53f..a18528f15 100644 --- a/packages/firebase-server/test/package.json +++ b/packages/firebase-server/test/package.json @@ -1,5 +1,5 @@ { "name": "@dereekb/firebase-server/test", - "version": "9.20.20", + "version": "9.21.0", "type": "commonjs" } diff --git a/packages/firebase/CHANGELOG.md b/packages/firebase/CHANGELOG.md index dbdf03f58..817749428 100644 --- a/packages/firebase/CHANGELOG.md +++ b/packages/firebase/CHANGELOG.md @@ -2,6 +2,10 @@ This file was generated using [@jscutlery/semver](https://github.com/jscutlery/semver). +# [9.21.0](https://github.com/dereekb/dbx-components/compare/v9.20.20-dev...v9.21.0) (2023-01-31) + + + ## [9.20.20](https://github.com/dereekb/dbx-components/compare/v9.20.19-dev...v9.20.20) (2023-01-23) diff --git a/packages/firebase/package.json b/packages/firebase/package.json index c05bfbb03..0f1ee3e30 100644 --- a/packages/firebase/package.json +++ b/packages/firebase/package.json @@ -1,6 +1,6 @@ { "name": "@dereekb/firebase", - "version": "9.20.20", + "version": "9.21.0", "devDependencies": { "@firebase/rules-unit-testing": "^2.0.0" }, diff --git a/packages/firebase/test/CHANGELOG.md b/packages/firebase/test/CHANGELOG.md index 4a9f0af5a..794c1bd75 100644 --- a/packages/firebase/test/CHANGELOG.md +++ b/packages/firebase/test/CHANGELOG.md @@ -2,6 +2,10 @@ This file was generated using [@jscutlery/semver](https://github.com/jscutlery/semver). +# [9.21.0](https://github.com/dereekb/dbx-components/compare/v9.20.20-dev...v9.21.0) (2023-01-31) + + + ## [9.20.20](https://github.com/dereekb/dbx-components/compare/v9.20.19-dev...v9.20.20) (2023-01-23) diff --git a/packages/firebase/test/package.json b/packages/firebase/test/package.json index 12b7c354a..eac1bf7a3 100644 --- a/packages/firebase/test/package.json +++ b/packages/firebase/test/package.json @@ -1,5 +1,5 @@ { "name": "@dereekb/firebase/test", - "version": "9.20.20", + "version": "9.21.0", "type": "commonjs" } diff --git a/packages/model/CHANGELOG.md b/packages/model/CHANGELOG.md index e101fcb45..3b5f7d1cc 100644 --- a/packages/model/CHANGELOG.md +++ b/packages/model/CHANGELOG.md @@ -2,6 +2,10 @@ This file was generated using [@jscutlery/semver](https://github.com/jscutlery/semver). +# [9.21.0](https://github.com/dereekb/dbx-components/compare/v9.20.20-dev...v9.21.0) (2023-01-31) + + + ## [9.20.20](https://github.com/dereekb/dbx-components/compare/v9.20.19-dev...v9.20.20) (2023-01-23) diff --git a/packages/model/package.json b/packages/model/package.json index ecd641dfa..83aae2d55 100644 --- a/packages/model/package.json +++ b/packages/model/package.json @@ -1,5 +1,5 @@ { "name": "@dereekb/model", - "version": "9.20.20", + "version": "9.21.0", "type": "commonjs" } diff --git a/packages/nestjs/CHANGELOG.md b/packages/nestjs/CHANGELOG.md index 15850b4ab..890fe548e 100644 --- a/packages/nestjs/CHANGELOG.md +++ b/packages/nestjs/CHANGELOG.md @@ -2,6 +2,10 @@ This file was generated using [@jscutlery/semver](https://github.com/jscutlery/semver). +# [9.21.0](https://github.com/dereekb/dbx-components/compare/v9.20.20-dev...v9.21.0) (2023-01-31) + + + ## [9.20.20](https://github.com/dereekb/dbx-components/compare/v9.20.19-dev...v9.20.20) (2023-01-23) diff --git a/packages/nestjs/mailgun/CHANGELOG.md b/packages/nestjs/mailgun/CHANGELOG.md index 23d14e82c..8a4ce700f 100644 --- a/packages/nestjs/mailgun/CHANGELOG.md +++ b/packages/nestjs/mailgun/CHANGELOG.md @@ -2,6 +2,10 @@ This file was generated using [@jscutlery/semver](https://github.com/jscutlery/semver). +# [9.21.0](https://github.com/dereekb/dbx-components/compare/v9.20.20-dev...v9.21.0) (2023-01-31) + + + ## [9.20.20](https://github.com/dereekb/dbx-components/compare/v9.20.19-dev...v9.20.20) (2023-01-23) diff --git a/packages/nestjs/mailgun/package.json b/packages/nestjs/mailgun/package.json index a21b676ab..a3b6ea2f2 100644 --- a/packages/nestjs/mailgun/package.json +++ b/packages/nestjs/mailgun/package.json @@ -1,5 +1,5 @@ { "name": "@dereekb/nestjs/mailgun", - "version": "9.20.20", + "version": "9.21.0", "type": "commonjs" } diff --git a/packages/nestjs/package.json b/packages/nestjs/package.json index 3af56e117..38181c31a 100644 --- a/packages/nestjs/package.json +++ b/packages/nestjs/package.json @@ -1,6 +1,6 @@ { "name": "@dereekb/nestjs", - "version": "9.20.20", + "version": "9.21.0", "type": "commonjs", "exports": { ".": { diff --git a/packages/nestjs/stripe/CHANGELOG.md b/packages/nestjs/stripe/CHANGELOG.md index 25a271510..f646324e3 100644 --- a/packages/nestjs/stripe/CHANGELOG.md +++ b/packages/nestjs/stripe/CHANGELOG.md @@ -2,6 +2,10 @@ This file was generated using [@jscutlery/semver](https://github.com/jscutlery/semver). +# [9.21.0](https://github.com/dereekb/dbx-components/compare/v9.20.20-dev...v9.21.0) (2023-01-31) + + + ## [9.20.20](https://github.com/dereekb/dbx-components/compare/v9.20.19-dev...v9.20.20) (2023-01-23) diff --git a/packages/nestjs/stripe/package.json b/packages/nestjs/stripe/package.json index 80029c9fe..f740159e9 100644 --- a/packages/nestjs/stripe/package.json +++ b/packages/nestjs/stripe/package.json @@ -1,5 +1,5 @@ { "name": "@dereekb/nestjs/stripe", - "version": "9.20.20", + "version": "9.21.0", "type": "commonjs" } diff --git a/packages/rxjs/CHANGELOG.md b/packages/rxjs/CHANGELOG.md index 7787e2121..89bd0146f 100644 --- a/packages/rxjs/CHANGELOG.md +++ b/packages/rxjs/CHANGELOG.md @@ -2,6 +2,15 @@ This file was generated using [@jscutlery/semver](https://github.com/jscutlery/semver). +# [9.21.0](https://github.com/dereekb/dbx-components/compare/v9.20.20-dev...v9.21.0) (2023-01-31) + + +### Features + +* dbx-table ([#23](https://github.com/dereekb/dbx-components/issues/23)) ([4661508](https://github.com/dereekb/dbx-components/commit/466150895b5bdc6e9e5289ef38ef5dd3e0ae67f9)) + + + ## [9.20.20](https://github.com/dereekb/dbx-components/compare/v9.20.19-dev...v9.20.20) (2023-01-23) diff --git a/packages/rxjs/package.json b/packages/rxjs/package.json index 6ee17b760..efb098d38 100644 --- a/packages/rxjs/package.json +++ b/packages/rxjs/package.json @@ -1,5 +1,5 @@ { "name": "@dereekb/rxjs", - "version": "9.20.20", + "version": "9.21.0", "type": "commonjs" } diff --git a/packages/rxjs/src/lib/iterator/iteration.accumulator.rxjs.spec.ts b/packages/rxjs/src/lib/iterator/iteration.accumulator.rxjs.spec.ts index c5937cf25..c41bb822c 100644 --- a/packages/rxjs/src/lib/iterator/iteration.accumulator.rxjs.spec.ts +++ b/packages/rxjs/src/lib/iterator/iteration.accumulator.rxjs.spec.ts @@ -2,7 +2,7 @@ import { ItemPageIterator, ItemPageIterationInstance } from './iterator.page'; import { TestPageIteratorFilter, TEST_PAGE_ARRAY_ITERATOR_DELEGATE, TEST_PAGE_ARRAY_ITERATOR_PAGE_SIZE } from './iterator.page.spec'; import { iteratorNextPageUntilPage } from './iteration.next'; import { accumulatorFlattenPageListLoadingState, flattenAccumulatorResultItemArray } from './iteration.accumulator.rxjs'; -import { filter, first } from 'rxjs'; +import { filter, first, skip } from 'rxjs'; import { itemAccumulator, ItemAccumulatorInstance } from './iteration.accumulator'; import { PageItemIteration } from './iteration'; import { loadingStateHasFinishedLoading } from '../loading'; @@ -110,5 +110,29 @@ describe('iteration.rxjs', () => { }); }); }); + + it(`should return all the values when loading.`, (done) => { + iteratorNextPageUntilPage(iteration, 1).then(() => { + const obs = accumulatorFlattenPageListLoadingState(accumulator); + + obs + .pipe( + //skip the first emission, which is the first page + skip(1) + ) + .subscribe((state) => { + if (!loadingStateHasFinishedLoading(state)) { + expect(state.value).toBeDefined(); + expect(Array.isArray(state.value)).toBe(true); + } else { + expect(state.value).toBeDefined(); + expect(Array.isArray(state.value)).toBe(true); + done(); + } + }); + + iteration.next(); + }); + }); }); }); diff --git a/packages/rxjs/src/lib/iterator/iteration.accumulator.rxjs.ts b/packages/rxjs/src/lib/iterator/iteration.accumulator.rxjs.ts index 5cac372c0..0dfb8b41a 100644 --- a/packages/rxjs/src/lib/iterator/iteration.accumulator.rxjs.ts +++ b/packages/rxjs/src/lib/iterator/iteration.accumulator.rxjs.ts @@ -42,6 +42,7 @@ export function accumulatorFlattenPageListLoadingState(accumulat map( ([state, values]) => mapLoadingStateResults(state, { + alwaysMapValue: true, mapValue: () => values }) as PageListLoadingState ), @@ -57,6 +58,7 @@ export function accumulatorCurrentPageListLoadingState(accumulat map( ([state, values]) => mapLoadingStateResults(state, { + alwaysMapValue: true, mapValue: () => values }) as PageListLoadingState ), diff --git a/packages/rxjs/src/lib/loading/loading.state.ts b/packages/rxjs/src/lib/loading/loading.state.ts index 84312abb5..f5d953868 100644 --- a/packages/rxjs/src/lib/loading/loading.state.ts +++ b/packages/rxjs/src/lib/loading/loading.state.ts @@ -122,10 +122,15 @@ export function idleLoadingState(): LoadingState { export function beginLoading(): LoadingState; export function beginLoading(state?: Partial>): PageLoadingState; +export function beginLoading(state?: Partial>): LoadingState; export function beginLoading(state?: Partial>): LoadingState { return state ? { ...state, loading: true } : { loading: true }; } +export function beginLoadingPage(page: PageNumber, state?: Partial>): PageLoadingState { + return state ? { page, ...state, loading: true } : { page, loading: true }; +} + export function successResult(value: T): LoadingStateWithValue { return { value, loading: false }; } @@ -339,6 +344,7 @@ export type MapLoadingStateFn = LoadingState, export type MapLoadingStateValuesFn = LoadingState> = (input: A, state: L) => B; export interface MapLoadingStateResultsConfiguration = LoadingState, O extends LoadingState = LoadingState> { + alwaysMapValue?: boolean; mapValue?: MapLoadingStateValuesFn; mapState?: MapLoadingStateFn; } @@ -347,12 +353,12 @@ export function mapLoadingStateResults = Loading export function mapLoadingStateResults = PageLoadingState, O extends PageLoadingState = PageLoadingState>(input: L, config: MapLoadingStateResultsConfiguration): O; export function mapLoadingStateResults> = Partial>, O extends Partial> = Partial>>(input: L, config: MapLoadingStateResultsConfiguration): O; export function mapLoadingStateResults> = Partial>, O extends Partial> = Partial>>(input: L, config: MapLoadingStateResultsConfiguration): O { - const { mapValue, mapState } = config; + const { mapValue, mapState, alwaysMapValue = false } = config; const inputValue = input?.value; let value: B; - if (inputValue != null && mapValue) { - value = mapValue(inputValue, input); + if ((inputValue != null || alwaysMapValue) && mapValue) { + value = mapValue(inputValue as A, input); } else { value = inputValue as unknown as B; } diff --git a/packages/util/CHANGELOG.md b/packages/util/CHANGELOG.md index 685342984..495ea1e30 100644 --- a/packages/util/CHANGELOG.md +++ b/packages/util/CHANGELOG.md @@ -2,6 +2,10 @@ This file was generated using [@jscutlery/semver](https://github.com/jscutlery/semver). +# [9.21.0](https://github.com/dereekb/dbx-components/compare/v9.20.20-dev...v9.21.0) (2023-01-31) + + + ## [9.20.20](https://github.com/dereekb/dbx-components/compare/v9.20.19-dev...v9.20.20) (2023-01-23) diff --git a/packages/util/fetch/CHANGELOG.md b/packages/util/fetch/CHANGELOG.md index 5b1159b2c..9e5b512d6 100644 --- a/packages/util/fetch/CHANGELOG.md +++ b/packages/util/fetch/CHANGELOG.md @@ -2,6 +2,10 @@ This file was generated using [@jscutlery/semver](https://github.com/jscutlery/semver). +# [9.21.0](https://github.com/dereekb/dbx-components/compare/v9.20.20-dev...v9.21.0) (2023-01-31) + + + ## [9.20.20](https://github.com/dereekb/dbx-components/compare/v9.20.19-dev...v9.20.20) (2023-01-23) diff --git a/packages/util/fetch/package.json b/packages/util/fetch/package.json index ba947d617..2ee3f205e 100644 --- a/packages/util/fetch/package.json +++ b/packages/util/fetch/package.json @@ -1,4 +1,4 @@ { "name": "@dereekb/util/fetch", - "version": "9.20.20" + "version": "9.21.0" } diff --git a/packages/util/package.json b/packages/util/package.json index 7e16d851a..7cbf34794 100644 --- a/packages/util/package.json +++ b/packages/util/package.json @@ -1,6 +1,6 @@ { "name": "@dereekb/util", - "version": "9.20.20", + "version": "9.21.0", "type": "commonjs", "exports": { ".": { diff --git a/packages/util/test/CHANGELOG.md b/packages/util/test/CHANGELOG.md index 3d69d0033..0bae0f902 100644 --- a/packages/util/test/CHANGELOG.md +++ b/packages/util/test/CHANGELOG.md @@ -2,6 +2,10 @@ This file was generated using [@jscutlery/semver](https://github.com/jscutlery/semver). +# [9.21.0](https://github.com/dereekb/dbx-components/compare/v9.20.20-dev...v9.21.0) (2023-01-31) + + + ## [9.20.20](https://github.com/dereekb/dbx-components/compare/v9.20.19-dev...v9.20.20) (2023-01-23) diff --git a/packages/util/test/package.json b/packages/util/test/package.json index e6fd23d75..86148c002 100644 --- a/packages/util/test/package.json +++ b/packages/util/test/package.json @@ -1,5 +1,5 @@ { "name": "@dereekb/util/test", - "version": "9.20.20", + "version": "9.21.0", "type": "commonjs" } diff --git a/tsconfig.base.json b/tsconfig.base.json index 2304a37f8..19f446706 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -30,6 +30,7 @@ "@dereekb/dbx-web": ["packages/dbx-web/src/index.ts"], "@dereekb/dbx-web/calendar": ["packages/dbx-web/calendar/src/index.ts"], "@dereekb/dbx-web/mapbox": ["packages/dbx-web/mapbox/src/index.ts"], + "@dereekb/dbx-web/table": ["packages/dbx-web/table/src/index.ts"], "@dereekb/demo-components": ["components/demo-components/src/index.ts"], "@dereekb/demo-firebase": ["components/demo-firebase/src/index.ts"], "@dereekb/firebase": ["packages/firebase/src/index.ts"], diff --git a/workspace.json b/workspace.json index 3c8ee2fb6..019ff4835 100644 --- a/workspace.json +++ b/workspace.json @@ -12,6 +12,7 @@ "dbx-web": "packages/dbx-web", "dbx-web-calendar": "packages/dbx-web/calendar", "dbx-web-mapbox": "packages/dbx-web/mapbox", + "dbx-web-table": "packages/dbx-web/table", "demo": "apps/demo", "demo-api": "apps/demo-api", "demo-components": "components/demo-components",