From a2f5429dd69bb095cca809a14b334ecf75e7524b Mon Sep 17 00:00:00 2001 From: meta-d Date: Mon, 18 Sep 2023 12:01:26 +0800 Subject: [PATCH] feat: public trending navigation --- README.md | 6 +- apps/cloud/src/app/_app.component.scss | 2 + apps/cloud/src/app/features/home/_home.scss | 23 +++++ .../home/dashboard/dashboard.component.scss | 22 ----- .../story-widget/story-widget.component.html | 9 +- .../story-widget/story-widget.component.ts | 83 ++++++++++--------- .../public/trending/trending.component.html | 20 ++++- .../app/public/trending/trending.componnet.ts | 2 + apps/cloud/src/assets/i18n/zh-CN.json | 3 +- apps/cloud/src/assets/i18n/zh-Hans.json | 3 +- apps/cloud/src/assets/i18n/zh-Hant.json | 3 +- .../story/embed-widget/widget.component.ts | 16 ++-- 12 files changed, 108 insertions(+), 84 deletions(-) create mode 100644 apps/cloud/src/app/features/home/_home.scss diff --git a/README.md b/README.md index 97b7ae703..89b911832 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ English | [中文](./README_zh.md) +![](https://avatars.githubusercontent.com/u/100019674?v=4) + # Metad Analytics Platform [uri_metad]: https://mtda.cloud/en/ @@ -23,9 +25,9 @@ We released new version which includes [AI Copilot](https://mtda.cloud/en/blog/c * **Indicator Management**: Easily define, manage, and monitor key performance indicators (KPIs) to ensure data quality, consistency, and effective performance analysis. * **AI Copilot**: Benefit from AI-driven insights and recommendations to enhance decision-making processes and identify actionable opportunities. -![Story Workspace](https://github.com/meta-d/meta-d/blob/main/img/story-workspace.png) +![Story Workspace](https://github.com/meta-d/meta-d/blob/main/img/en/indicator-application.png) -![Indicator Application](https://github.com/meta-d/meta-d/blob/main/img/indicator-application.png) +![Indicator Application](https://github.com/meta-d/meta-d/blob/main/img/en/indicator-application.png) ## ✨ Features diff --git a/apps/cloud/src/app/_app.component.scss b/apps/cloud/src/app/_app.component.scss index 7a1e7f75d..9d119e10f 100644 --- a/apps/cloud/src/app/_app.component.scss +++ b/apps/cloud/src/app/_app.component.scss @@ -1,3 +1,5 @@ +@import './features/home/_home'; + .nx-theme-dark, .dark { --ngm-card-bg-color: theme(colors.bluegray.800); --ngm-card-border-color: theme(colors.bluegray.700); diff --git a/apps/cloud/src/app/features/home/_home.scss b/apps/cloud/src/app/features/home/_home.scss new file mode 100644 index 000000000..2a65f5447 --- /dev/null +++ b/apps/cloud/src/app/features/home/_home.scss @@ -0,0 +1,23 @@ +.pac-home__content { + .pac-home__gridster-item { + background: transparent; + + .pac-home__widget-actions { + position: absolute; + right: -30px; + top: 0; + opacity: 0; + visibility: hidden; + display: flex; + flex-direction: column; + } + + &:hover { + z-index: 1000 !important; + .pac-home__widget-actions { + opacity: 1; + visibility: visible; + } + } + } +} diff --git a/apps/cloud/src/app/features/home/dashboard/dashboard.component.scss b/apps/cloud/src/app/features/home/dashboard/dashboard.component.scss index 5b95218bf..5913a63ea 100644 --- a/apps/cloud/src/app/features/home/dashboard/dashboard.component.scss +++ b/apps/cloud/src/app/features/home/dashboard/dashboard.component.scss @@ -44,28 +44,6 @@ gridster { height: 100%; } -.pac-home__gridster-item { - background: transparent; - - .pac-home__widget-actions { - position: absolute; - right: -30px; - top: 0; - opacity: 0; - visibility: hidden; - display: flex; - flex-direction: column; - } - - &:hover { - z-index: 1000 !important; - .pac-home__widget-actions { - opacity: 1; - visibility: visible; - } - } -} - .pac-home__assets-empty { height: 280px; text-align: center; diff --git a/apps/cloud/src/app/features/home/story-widget/story-widget.component.html b/apps/cloud/src/app/features/home/story-widget/story-widget.component.html index 035bdb430..d5d9fd2c8 100644 --- a/apps/cloud/src/app/features/home/story-widget/story-widget.component.html +++ b/apps/cloud/src/app/features/home/story-widget/story-widget.component.html @@ -1,9 +1,6 @@ - +
- {{error | json}} -
+ {{ error | json }} + \ No newline at end of file diff --git a/apps/cloud/src/app/features/home/story-widget/story-widget.component.ts b/apps/cloud/src/app/features/home/story-widget/story-widget.component.ts index 5ed9e0d53..35a00e8ea 100644 --- a/apps/cloud/src/app/features/home/story-widget/story-widget.component.ts +++ b/apps/cloud/src/app/features/home/story-widget/story-widget.component.ts @@ -1,10 +1,11 @@ -import { Component, Input, inject } from '@angular/core' +import { Component, Input, computed, inject } from '@angular/core' +import { toSignal } from '@angular/core/rxjs-interop' import { WidgetsService, convertStoryResult, convertStoryWidgetResult } from '@metad/cloud/state' import { WasmAgentService } from '@metad/ocap-angular/wasm-agent' import { AgentType } from '@metad/ocap-core' import { omit } from 'lodash-es' import { BehaviorSubject, EMPTY } from 'rxjs' -import { catchError, filter, map, shareReplay, switchMap, tap } from 'rxjs/operators' +import { catchError, filter, switchMap } from 'rxjs/operators' import { registerWasmAgentModel } from '../../../@core' @Component({ @@ -27,38 +28,40 @@ export class StoryWidgetFeedComponent { } private id$ = new BehaviorSubject(null) - public readonly widget$ = this.id$.pipe( - filter((value) => !!value), - switchMap((id) => - this.widgetsService - .getOne(id, [ - 'point', - 'point.story', - 'point.story.points', - 'createdBy', - // 'point.story.model', - // 'point.story.model.indicators', - // 'point.story.model.dataSource', - // 'point.story.model.dataSource.type' + public readonly widget = toSignal( + this.id$.pipe( + filter((value) => !!value), + switchMap((id) => + this.widgetsService + .getOne(id, [ + 'point', + 'point.story', + 'point.story.points', + 'createdBy', + // 'point.story.model', + // 'point.story.model.indicators', + // 'point.story.model.dataSource', + // 'point.story.model.dataSource.type' - 'point.story.models', - 'point.story.models.dataSource', - 'point.story.models.dataSource.type', - 'point.story.models.indicators' - ]) - .pipe( - catchError((err) => { - this.error$.next(err.error) - return EMPTY - }) - ) - ), - shareReplay(1) + 'point.story.models', + 'point.story.models.dataSource', + 'point.story.models.dataSource.type', + 'point.story.models.indicators' + ]) + .pipe( + catchError((err) => { + this.error$.next(err.error) + return EMPTY + }) + ) + ) + ) ) - public readonly story$ = this.widget$.pipe( - map((widget) => { - return convertStoryResult({ + public readonly story = computed(() => { + const widget = this.widget() + if (widget) { + const story = convertStoryResult({ ...widget.point.story, points: [ { @@ -68,21 +71,23 @@ export class StoryWidgetFeedComponent { } ] }) - }), - tap((story) => { + story.models?.forEach((model) => { if (model.agentType === AgentType.Wasm) { registerWasmAgentModel(this.wasmAgent, model) } }) - }) - ) - public readonly _widget$ = this.widget$.pipe( - map((widget) => { + return story + } + }) + + public readonly _widget = computed(() => { + const widget = this.widget() + if (widget) { return convertStoryWidgetResult(widget) - }) - ) + } + }) public error$ = new BehaviorSubject(null) } diff --git a/apps/cloud/src/app/public/trending/trending.component.html b/apps/cloud/src/app/public/trending/trending.component.html index ed2b4a7e9..bb0340b69 100644 --- a/apps/cloud/src/app/public/trending/trending.component.html +++ b/apps/cloud/src/app/public/trending/trending.component.html @@ -1,6 +1,20 @@ -
- - {{'PAC.title.short' | translate}} +
+
+ + {{'PAC.title.short' | translate}} +
+ +
+ + + +
diff --git a/apps/cloud/src/app/public/trending/trending.componnet.ts b/apps/cloud/src/app/public/trending/trending.componnet.ts index 36e2c0df3..0271a42d6 100644 --- a/apps/cloud/src/app/public/trending/trending.componnet.ts +++ b/apps/cloud/src/app/public/trending/trending.componnet.ts @@ -12,6 +12,7 @@ import { StoriesService } from '@metad/cloud/state' import { debounceTime, distinctUntilChanged, switchMap, tap } from 'rxjs' import { StoryCardComponent } from '../../@shared' import { IStory, listAnimation } from '../../@core' +import { MatButtonModule } from '@angular/material/button' @Component({ @@ -24,6 +25,7 @@ import { IStory, listAnimation } from '../../@core' RouterModule, IntersectionObserverModule, MatButtonToggleModule, + MatButtonModule, TranslateModule, NgmCommonModule, diff --git a/apps/cloud/src/assets/i18n/zh-CN.json b/apps/cloud/src/assets/i18n/zh-CN.json index ac8d164c2..a1c1a624c 100644 --- a/apps/cloud/src/assets/i18n/zh-CN.json +++ b/apps/cloud/src/assets/i18n/zh-CN.json @@ -156,7 +156,8 @@ "Role&Permissions": "角色 & 权限", "SemanticModels": "语义模型", "Stories": "故事", - "Indicators": "指标" + "Indicators": "指标", + "IndicatorMarket": "指标市场" }, "MENU": { "Certification": "认证", diff --git a/apps/cloud/src/assets/i18n/zh-Hans.json b/apps/cloud/src/assets/i18n/zh-Hans.json index ac8d164c2..a1c1a624c 100644 --- a/apps/cloud/src/assets/i18n/zh-Hans.json +++ b/apps/cloud/src/assets/i18n/zh-Hans.json @@ -156,7 +156,8 @@ "Role&Permissions": "角色 & 权限", "SemanticModels": "语义模型", "Stories": "故事", - "Indicators": "指标" + "Indicators": "指标", + "IndicatorMarket": "指标市场" }, "MENU": { "Certification": "认证", diff --git a/apps/cloud/src/assets/i18n/zh-Hant.json b/apps/cloud/src/assets/i18n/zh-Hant.json index 722c5d160..8ede8f645 100644 --- a/apps/cloud/src/assets/i18n/zh-Hant.json +++ b/apps/cloud/src/assets/i18n/zh-Hant.json @@ -156,7 +156,8 @@ "Role&Permissions": "角色 & 權限", "SemanticModels": "語義模型", "Stories": "故事", - "Indicators": "指標" + "Indicators": "指標", + "IndicatorMarket": "指標市場" }, "MENU": { "Certification": "認證", diff --git a/libs/story-angular/story/embed-widget/widget.component.ts b/libs/story-angular/story/embed-widget/widget.component.ts index c2a4d35b9..76cd8b0cf 100644 --- a/libs/story-angular/story/embed-widget/widget.component.ts +++ b/libs/story-angular/story/embed-widget/widget.component.ts @@ -1,8 +1,8 @@ import { CommonModule } from '@angular/common' -import { Component, Input, OnChanges, OnInit, SimpleChanges } from '@angular/core' +import { Component, Input, OnChanges, OnInit, SimpleChanges, inject } from '@angular/core' +import { NxCoreService } from '@metad/core' import { NgmDSCoreService, NgmSmartFilterBarService } from '@metad/ocap-angular/core' import { TimeGranularity } from '@metad/ocap-core' -import { NxCoreService } from '@metad/core' import { NxStoryService, Story, StoryWidget } from '@metad/story/core' import { NxStoryPointService } from '../story-point.service' import { NxStoryModule } from '../story.module' @@ -16,16 +16,14 @@ import { NxStoryModule } from '../story.module' providers: [NxStoryService, NxStoryPointService, NgmSmartFilterBarService, NxCoreService] }) export class EmbedWidgetComponent implements OnInit, OnChanges { + public storyService = inject(NxStoryService) + private pointService = inject(NxStoryPointService) + public smartFilterBarService = inject(NgmSmartFilterBarService) + private dsCoreService = inject(NgmDSCoreService) + @Input() story: Story @Input() widget: StoryWidget - constructor( - public storyService: NxStoryService, - private pointService: NxStoryPointService, - public smartFilterBarService: NgmSmartFilterBarService, - private dsCoreService: NgmDSCoreService - ) {} - ngOnInit(): void { this.dsCoreService.setTimeGranularity(TimeGranularity.Month) }