+
+
+
+
+
{{ 'PAC.KEY_WORDS.Dimensions' | translate: {Default: 'Dimensions'} }}
+
-
{{ 'PAC.KEY_WORDS.Dimensions' | translate: {Default: 'Dimensions'} }}
-
-
-
-
+ [cdkDropListEnterPredicate]="dropRowPredicate">
+
+
+
-
-
-
- {{'FORMLY.CHART.' + group.label | translate: {Default: group.label} }}
-
-
-
-
-
+
{{ 'PAC.KEY_WORDS.Measures' | translate: {Default: 'Measures'} }}
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+ {{'FORMLY.CHART.' + group.label | translate: {Default: group.label} }}
-
-
-
+
+
+
{{ 'FORMLY.CHART.' + chart.label | translate: {Default: chart.label} }}
+
+
+
+
+
+
+
+
+
-
- Table
- Chart
-
+
+
+
+
+
+ Visual
+ Options
+
-
-
-
-
+
+ Table
+ Chart
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ 'Story.Explorer.AddDimensions' | translate: { Default: 'Add dimensions' } }}
+
+
+
+
+
+
+ {{property.caption}}
+
+
+
-
\ No newline at end of file
+
+
+
+
+
+
+
+
+
diff --git a/libs/story-angular/src/lib/explorer/explorer.component.scss b/libs/story-angular/src/lib/explorer/explorer.component.scss
index e5a58fcf8..8b39d2842 100644
--- a/libs/story-angular/src/lib/explorer/explorer.component.scss
+++ b/libs/story-angular/src/lib/explorer/explorer.component.scss
@@ -7,4 +7,8 @@
}
.ngm-story-explorer__chart.selected {
@apply ring-violet-500;
-}
\ No newline at end of file
+}
+
+.cdk-drag-placeholder {
+ opacity: 0;
+}
diff --git a/libs/story-angular/src/lib/explorer/explorer.component.ts b/libs/story-angular/src/lib/explorer/explorer.component.ts
index 055f7017e..bae93769c 100644
--- a/libs/story-angular/src/lib/explorer/explorer.component.ts
+++ b/libs/story-angular/src/lib/explorer/explorer.component.ts
@@ -1,6 +1,6 @@
-import { CdkDrag, CdkDragDrop, DragDropModule } from '@angular/cdk/drag-drop'
+import { CdkDrag, CdkDragDrop, DragDropModule, moveItemInArray } from '@angular/cdk/drag-drop'
import { CommonModule } from '@angular/common'
-import { Component, EventEmitter, Input, Output, computed, effect, inject, signal } from '@angular/core'
+import { Component, ElementRef, EventEmitter, Input, Output, TemplateRef, ViewChild, computed, effect, inject, signal } from '@angular/core'
import { toObservable, toSignal } from '@angular/core/rxjs-interop'
import { FormsModule, ReactiveFormsModule } from '@angular/forms'
import { MatButtonModule } from '@angular/material/button'
@@ -25,9 +25,11 @@ import {
DataSettings,
Dimension,
DisplayBehaviour,
+ FilterSelectionType,
ISlicer,
assignDeepOmitBlank,
cloneDeep,
+ compact,
getEntityDimensions,
getEntityMeasures,
nonNullable,
@@ -37,6 +39,9 @@ import { WidgetComponentType } from '@metad/story/core'
import { TranslateModule } from '@ngx-translate/core'
import { filter, map, switchMap } from 'rxjs/operators'
import { CHARTS, getChartType } from './types'
+import { MatIconModule } from '@angular/material/icon'
+import { ResizerModule } from '@metad/ocap-angular/common'
+import { MatDialog, MatDialogModule, MatDialogRef } from '@angular/material/dialog'
@Component({
standalone: true,
@@ -51,6 +56,8 @@ import { CHARTS, getChartType } from './types'
MatButtonToggleModule,
MatDividerModule,
MatTooltipModule,
+ MatIconModule,
+ MatDialogModule,
DragDropModule,
NxTableModule,
NgmPrismHighlightComponent,
@@ -59,7 +66,8 @@ import { CHARTS, getChartType } from './types'
NgmMemberTreeComponent,
AnalyticalCardModule,
AnalyticalGridModule,
- PropertyModule
+ PropertyModule,
+ ResizerModule
],
selector: 'ngm-story-explorer',
templateUrl: 'explorer.component.html',
@@ -70,8 +78,10 @@ export class StoryExplorerComponent {
DisplayDensity = DisplayDensity
PropertyCapacity = PropertyCapacity
ComponentType = WidgetComponentType
+ FilterSelectionType = FilterSelectionType
private readonly dsCoreService = inject(NgmDSCoreService)
+ private readonly _dialog = inject(MatDialog)
@Input()
get data() {
@@ -89,6 +99,7 @@ export class StoryExplorerComponent {
})
this.rows.set(chartAnnotation.dimensions)
this.columns.set(chartAnnotation.measures)
+ this._dimensions.set(chartAnnotation.dimensions?.map((d) => d.dimension) ?? [])
}
}
@@ -97,6 +108,12 @@ export class StoryExplorerComponent {
@Output() closed = new EventEmitter
()
+ @ViewChild('addDimensionsTempl') addDimensionsTempl: TemplateRef
+
+ private dialogRef: MatDialogRef, any>
+
+ readonly _dimensionsCache = signal([])
+ private _dimensions = signal([])
dimensions = signal<{ dimension: Dimension; caption: string; hierarchies: Dimension[] }[]>([])
readonly entityType = toSignal(
@@ -109,9 +126,15 @@ export class StoryExplorerComponent {
)
)
)
-
+ readonly dimensionList = computed(() => {
+ return getEntityDimensions(this.entityType())
+ })
readonly measureList = computed(() => {
- return getEntityMeasures(this.entityType())
+ return getEntityMeasures(this.entityType()).map((property) => ({
+ dimension: C_MEASURES,
+ measure: property.name,
+ caption: property.caption
+ }))
})
readonly dataSettings = computed(() => {
return pick(this.data?.dataSettings, 'dataSource', 'entitySet') as DataSettings
@@ -147,7 +170,6 @@ export class StoryExplorerComponent {
chartAnnotation.dimensions = chartAnnotation.dimensions.filter((d) => d.dimension)
chartAnnotation.measures = chartAnnotation.measures.filter((d) => d.dimension)
- console.log('chartAnnotation:', chartAnnotation)
return {
...(this.data?.dataSettings ?? {}),
chartAnnotation
@@ -162,10 +184,16 @@ export class StoryExplorerComponent {
const analytics = {
...(this.data?.analytics ?? {}),
rows: this.rows(),
- columns: this.measures().map((measure) => ({
- dimension: C_MEASURES,
- measure
- }))
+ columns: [
+ ...this.columns(),
+ ...this.measures().map((measure) => ({
+ dimension: C_MEASURES,
+ measure,
+ formatting: {
+ shortNumber: true
+ }
+ }))
+ ]
}
console.log('analytics:', analytics)
return {
@@ -206,7 +234,7 @@ export class StoryExplorerComponent {
() => {
if (this.entityType()) {
this.dimensions.set(
- getEntityDimensions(this.entityType()).map(({ name, caption, hierarchies }) => ({
+ getEntityDimensions(this.entityType()).filter(({name}) => this._dimensions().includes(name)) .map(({ name, caption, hierarchies }) => ({
dimension: {
dimension: name,
displayBehaviour: DisplayBehaviour.descriptionOnly
@@ -252,21 +280,53 @@ export class StoryExplorerComponent {
}
dropRowPredicate(item: CdkDrag) {
- return true
+ return item.dropContainer.id === 'ngm-story-explorer__drop-list-dimensions-container'
}
dropRow(event: CdkDragDrop) {
- this.rows.set([...this.rows(), { ...event.item.data }])
+ const items = [...this.rows()]
+ if (event.previousContainer === event.container) {
+ moveItemInArray(items, event.previousIndex, event.currentIndex)
+ } else {
+ items.splice(event.currentIndex, 0, { ...event.item.data.dimension })
+ }
+ this.rows.set(items)
+ }
+
+ removeRow(i: number) {
+ const items = [...this.rows()]
+ items.splice(i, 1)
+ this.rows.set(items)
+ }
+
+ dropColumnPredicate(item: CdkDrag) {
+ return item.dropContainer.id === 'ngm-story-explorer__drop-list-measures'
}
dropColumn(event: CdkDragDrop) {
- this.columns.set([...this.columns(), { ...event.item.data }])
+ const items = [...this.columns()]
+ if (event.previousContainer === event.container) {
+ moveItemInArray(items, event.previousIndex, event.currentIndex)
+ } else {
+ items.splice(event.currentIndex, 0, { ...event.item.data })
+ }
+ this.columns.set(items)
+ }
+
+ removeColumn(i: number) {
+ const items = [...this.columns()]
+ items.splice(i, 1)
+ this.columns.set(items)
}
onRowChange(row: Dimension, i: number) {
this.rows.set([...this.rows().slice(0, i), row, ...this.rows().slice(i + 1)])
}
+ onColumnChange(row: Dimension, i: number) {
+ this.columns.set([...this.columns().slice(0, i), row, ...this.columns().slice(i + 1)])
+ }
+
onMeasuresChange(measures: string[]) {
this.measures.set(measures)
}
@@ -282,4 +342,26 @@ export class StoryExplorerComponent {
console.log(widget)
this.component.set(widget)
}
+
+ addDimensionToCache(event) {
+ this._dimensionsCache.set([...event])
+ }
+
+ openDimensions() {
+ this._dimensionsCache.set([...this._dimensions()])
+ this.dialogRef = this._dialog.open(this.addDimensionsTempl)
+ }
+
+ addDimensions() {
+ this._dimensions.set([...this._dimensionsCache()])
+ this.dialogRef.close()
+ }
+
+ moveDimension(event: CdkDragDrop) {
+ const items = [...this.dimensions()]
+ if (event.previousContainer === event.container) {
+ moveItemInArray(items, event.previousIndex, event.currentIndex)
+ this.dimensions.set(items)
+ }
+ }
}
diff --git a/packages/angular/controls/member-tree/member-tree.component.ts b/packages/angular/controls/member-tree/member-tree.component.ts
index dea1c26c7..ab514c035 100644
--- a/packages/angular/controls/member-tree/member-tree.component.ts
+++ b/packages/angular/controls/member-tree/member-tree.component.ts
@@ -1,9 +1,9 @@
import { SelectionModel } from '@angular/cdk/collections'
import { FlatTreeControl } from '@angular/cdk/tree'
-import { ChangeDetectionStrategy, Component, EventEmitter, forwardRef, HostBinding, inject, Input, OnChanges, OnInit, Output, SimpleChanges } from '@angular/core'
+import { ChangeDetectionStrategy, Component, EventEmitter, forwardRef, HostBinding, Input, OnChanges, OnInit, Output, SimpleChanges } from '@angular/core'
import { ControlValueAccessor, FormControl, NG_VALUE_ACCESSOR } from '@angular/forms'
import { MatTreeFlatDataSource, MatTreeFlattener } from '@angular/material/tree'
-import { DisplayDensity, NgmAppearance, NgmDSCoreService, OcapCoreModule } from '@metad/ocap-angular/core'
+import { DisplayDensity, NgmAppearance, OcapCoreModule } from '@metad/ocap-angular/core'
import {
DataSettings,
Dimension,
@@ -72,7 +72,7 @@ export class NgmMemberTreeComponent