Commit 4436d02c authored by Mark Harding's avatar Mark Harding

(wip): fixes various looping issues and removes combineLatest logic

1 merge request!579WIP: Entity centric metrics (analytics v2)
Pipeline #86630237 failed with stages
in 6 minutes and 57 seconds
......@@ -113,8 +113,6 @@ export class AnalyticsChartComponent implements OnInit, OnDestroy {
// ---------------------------------------------------
visualisation: Visualisation;
vm$: Observable<UserState> = this.analyticsService.vm$;
vm: UserState;
isDark: boolean = false;
subscription: Subscription;
......@@ -218,7 +216,6 @@ export class AnalyticsChartComponent implements OnInit, OnDestroy {
) {}
ngOnInit() {
this.subscription = this.vm$.subscribe(viewModel => (this.vm = viewModel));
this.themeService.isDark$.subscribe(isDark => (this.isDark = isDark));
this.graphDiv = document.getElementById('graphDiv');
......@@ -377,9 +374,7 @@ export class AnalyticsChartComponent implements OnInit, OnDestroy {
{ interval: 'day', tickFormat: '%m/%d' },
{ interval: 'month', tickFormat: '%d/%y' },
];
const selectedInterval = this.vm.timespans.find(
t => t.id === this.vm.timespan
).interval;
const selectedInterval = 'monthly';
return timespanTickFormats.find(t => t.interval === selectedInterval)
.tickFormat;
}
......@@ -396,8 +391,9 @@ export class AnalyticsChartComponent implements OnInit, OnDestroy {
updateGraph() {
// TODO: add latest shapes and marker settings to the updates
const dataUpdate = this.setData();
const layoutUpdate = this.setLayout();
// THIS IS CAUSING A LOOP (MH)
//const dataUpdate = this.setData();
//const layoutUpdate = this.setLayout();
// Plotly.update('graphDiv', dataUpdate, layoutUpdate);
}
......@@ -465,7 +461,6 @@ export class AnalyticsChartComponent implements OnInit, OnDestroy {
}
ngOnDestroy() {
this.subscription.unsubscribe();
this.themeSubscription.unsubscribe();
}
}
<div class="filtersContainer" *ngIf="vm$ | async as vm">
<ng-container *ngFor="let filter of vm.filters">
<div class="filtersContainer">
<ng-container *ngFor="let filter of (filters$ | async)">
<m-analytics__filter class="filter" [filter]="filter"></m-analytics__filter>
</ng-container>
</div>
......@@ -27,17 +27,16 @@ import {
})
export class AnalyticsFiltersComponent implements OnInit, OnDestroy {
subscription: Subscription;
vm$: Observable<UserState> = this.analyticsService.vm$;
vm: UserState;
filters$ = this.analyticsService.filters$;
constructor(private analyticsService: AnalyticsDashboardService) {}
ngOnInit() {
// TODO: remove subscription because everything is happening in html
// TODO: might even be fine to just get rid of this component and put it in dashboard.ts
this.subscription = this.vm$.subscribe(viewModel => (this.vm = viewModel));
}
ngOnDestroy() {
this.subscription.unsubscribe();
}
}
......@@ -39,14 +39,15 @@ export class AnalyticsMetricsComponent implements OnInit, OnDestroy {
subscription: Subscription;
//TODO: (maybe) interface ViewMetric implements Metric {}
vm$: Observable<UserState> = this.analyticsService.vm$;
metrics$;
constructor(private analyticsService: AnalyticsDashboardService) {}
ngOnInit() {
this.metrics$ = this.vm$.pipe(map(vm => {
const metrics = vm.metrics.map(metric => ({...metric})); // Clone to avoid updating
this.metrics$ = this.analyticsService.metrics$
.pipe(
map(_metrics => {
const metrics = _metrics.map(metric => ({...metric})); // Clone to avoid updating
for (let metric of metrics) {
const delta =
......@@ -72,7 +73,7 @@ export class AnalyticsMetricsComponent implements OnInit, OnDestroy {
}
updateMetric(metric) {
this.analyticsService.updateMetric(metric);
this.analyticsService.updateMetric(metric.id);
}
ngOnDestroy() {
......
<div class="page" *ngIf="vm$ | async as vm" [ngClass]="{ isMobile: isMobile }">
<div class="page" [ngClass]="{ isMobile: isMobile }">
<section class="sidebar">
<h3>Analytics</h3>
<div *ngIf="isMobile">{{ vm.category }}</div>
<div *ngIf="isMobile">{{ category$ | async }}</div>
<div class="catContainer">
<i class="material-icons">menu</i>
<div class="cat" *ngFor="let cat of cats">
<span [ngClass]="{ selected: cat.id === vm.category }">{{
<span [ngClass]="{ selected: cat.id === (category$ | async) }">{{
cat?.label
}}</span>
</div>
......
......@@ -35,7 +35,7 @@ export interface Dashboard {
category: string;
timespan: string;
timespans: Timespan[];
metric: Metric;
metric: string;
metrics: Metric[];
filter: string[];
filters: Filter[];
......@@ -93,7 +93,7 @@ export interface UserState {
category: string;
timespan: string;
timespans: Timespan[];
metric: Metric;
metric: string;
metrics: Metric[];
filter: string[];
filters: Filter[];
......@@ -107,7 +107,7 @@ let _state: UserState = {
timespans: [],
filter: [ "platform::browser" ],
filters: [ ],
metric: { id: 'views' },
metric: 'views',
metrics: [],
};
......@@ -144,12 +144,17 @@ export class AnalyticsDashboardService {
);
metric$ = this.state$.pipe(
map(state => state.metric),
distinctUntilChanged(deepDiff),
//distinctUntilChanged(deepDiff),
distinctUntilChanged((prev, curr) => {
console.log('distinctUntilChanged() on metric$');
console.log(JSON.stringify(prev), JSON.stringify(curr));
return deepDiff(prev, curr);
}),
tap(metric => console.log('metric changed', metric))
);
metrics$ = this.state$.pipe(
map(state => state.metrics),
distinctUntilChanged(deepDiff),
//distinctUntilChanged(deepDiff),
distinctUntilChanged((prev, curr) => {
console.log(JSON.stringify(prev), JSON.stringify(curr));
return deepDiff(prev, curr);
......@@ -172,7 +177,7 @@ export class AnalyticsDashboardService {
/**
* Viewmodel that resolves once all the data is ready (or updated)
*/
vm$: Observable<UserState> = combineLatest(
/*vm$: Observable<UserState> = combineLatest(
this.category$,
this.timespan$,
this.timespans$,
......@@ -205,7 +210,8 @@ export class AnalyticsDashboardService {
};
}
),
);
);*/
vm$: Observable<UserState> = new BehaviorSubject(_state);
/**
* Watch 5 streams to trigger user loads and state updates
......@@ -218,7 +224,7 @@ export class AnalyticsDashboardService {
loadFromRemote() {
combineLatest([this.category$, this.timespan$, this.metric$, this.filter$])
.pipe(
debounceTime(300),
///debounceTime(300),
tap(() => console.log('load from remote called')),
distinctUntilChanged(deepDiff),
switchMap(([category, timespan, metric, filter]) => {
......@@ -280,7 +286,7 @@ export class AnalyticsDashboardService {
updateTimespan(timespan: string) {
this.updateState({ ..._state, timespan, loading: true });
}
updateMetric(metric: Metric) {
updateMetric(metric: string) {
this.updateState({ ..._state, metric, loading: true });
}
updateFilter(filter: string[]) {
......@@ -302,7 +308,7 @@ export class AnalyticsDashboardService {
private getDashboardResponse(
category: string,
timespan: string,
metric: Metric,
metric: string,
filter: string[]
): Observable<Response> {
const url = buildQueryUrl(category, timespan, metric, filter);
......@@ -317,12 +323,12 @@ export class AnalyticsDashboardService {
function buildQueryUrl(
category: string,
timespan: string,
metric: Metric,
metric: string,
filter: string[]
): string {
const url = 'https://walrus.minds.com/api/v2/analytics/dashboards/';
const filterStr: string = filter.join();
const metricId: string = metric.id;
const metricId: string = metric;
return `${url}${category}?metric=${metricId}&timespan=${timespan}&filter=${filterStr}`;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment