Skip to content
Next
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Switch to GitLab Next
Sign in / Register
Toggle navigation
Minds Frontend
Project
Project
Details
Activity
Releases
Cycle Analytics
Insights
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Locked Files
Issues
873
Issues
873
List
Boards
Labels
Service Desk
Milestones
Merge Requests
47
Merge Requests
47
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Security & Compliance
Security & Compliance
Dependency List
Packages
Packages
List
Container Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Minds
Minds Frontend
Commits
680f081b
Commit
680f081b
authored
22 minutes ago
by
Mark Harding
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
(feat): fixes graph to read production data
parent
262eb337
feat/entity-centric-metrics
1 merge request
!579
WIP: Entity centric metrics (analytics v2)
Pipeline
#87050651
failed with stages
in 7 minutes and 1 second
Changes
10
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
107 additions
and
113 deletions
+107
-113
src/app/modules/analytics/v2/components/chart/chart.component.scss
...odules/analytics/v2/components/chart/chart.component.scss
+1
-0
src/app/modules/analytics/v2/components/chart/chart.component.ts
.../modules/analytics/v2/components/chart/chart.component.ts
+49
-24
src/app/modules/analytics/v2/components/filter/filter.component.html
...ules/analytics/v2/components/filter/filter.component.html
+2
-7
src/app/modules/analytics/v2/components/filter/filter.component.scss
...ules/analytics/v2/components/filter/filter.component.scss
+1
-0
src/app/modules/analytics/v2/components/filter/filter.component.ts
...odules/analytics/v2/components/filter/filter.component.ts
+12
-46
src/app/modules/analytics/v2/components/filters/filters.component.html
...es/analytics/v2/components/filters/filters.component.html
+1
-1
src/app/modules/analytics/v2/components/filters/filters.component.ts
...ules/analytics/v2/components/filters/filters.component.ts
+1
-2
src/app/modules/analytics/v2/dashboard.component.html
src/app/modules/analytics/v2/dashboard.component.html
+3
-3
src/app/modules/analytics/v2/dashboard.component.ts
src/app/modules/analytics/v2/dashboard.component.ts
+18
-11
src/app/modules/analytics/v2/dashboard.service.ts
src/app/modules/analytics/v2/dashboard.service.ts
+19
-19
No files found.
src/app/modules/analytics/v2/components/chart/chart.component.scss
View file @
680f081b
...
...
@@ -3,6 +3,7 @@ m-analytics__chart {
.js-plotly-plot
,
.plot-container
{
height
:
44vh
;
display
:
block
;
}
}
#graphDiv
{
...
...
This diff is collapsed.
Click to expand it.
src/app/modules/analytics/v2/components/chart/chart.component.ts
View file @
680f081b
...
...
@@ -11,6 +11,7 @@ import {
Input
,
}
from
'
@angular/core
'
;
import
{
Observable
,
Subscription
}
from
'
rxjs
'
;
import
{
map
}
from
'
rxjs/operators
'
;
import
{
AnalyticsDashboardService
,
Category
,
...
...
@@ -38,14 +39,17 @@ import { ThemeService } from '../../../../../common/services/theme.service';
changeDetection
:
ChangeDetectionStrategy
.
OnPush
,
})
export
class
AnalyticsChartComponent
implements
OnInit
,
OnDestroy
{
// @Input('buckets') set bucket(buckets) {
// this.x = buckets.map((row) => row.date)); // or key(ms)?
// this.y = buckets.map((row) => row.value));
// };
subscription
:
Subscription
;
vm$
:
Observable
<
UserState
>
=
this
.
analyticsService
.
vm$
;
vm
:
UserState
;
selectedMetric$
=
this
.
analyticsService
.
metrics$
.
pipe
(
map
(
metrics
=>
{
console
.
log
(
metrics
,
metrics
.
find
(
metric
=>
metric
.
visualisation
!==
null
)
);
return
metrics
.
find
(
metric
=>
metric
.
visualisation
!==
null
);
})
);
selectedMetric
;
themeSubscription
:
Subscription
;
isDark
:
boolean
=
false
;
...
...
@@ -88,7 +92,14 @@ export class AnalyticsChartComponent implements OnInit, OnDestroy {
)
{}
ngOnInit
()
{
this
.
subscription
=
this
.
vm$
.
subscribe
(
viewModel
=>
(
this
.
vm
=
viewModel
));
this
.
subscription
=
this
.
selectedMetric$
.
subscribe
(
metric
=>
{
this
.
selectedMetric
=
metric
;
try
{
this
.
updateGraph
();
}
catch
(
err
)
{
console
.
log
(
err
);
}
});
this
.
themeService
.
isDark$
.
subscribe
(
isDark
=>
(
this
.
isDark
=
isDark
));
...
...
@@ -102,16 +113,20 @@ export class AnalyticsChartComponent implements OnInit, OnDestroy {
this
.
hoverInfoComparisonXyDiv
=
document
.
getElementById
(
'
hoverInfo__comparisonXy
'
);
}
this
.
segments
=
this
.
vm
.
metrics
.
find
(
metric
=>
metric
.
id
===
this
.
vm
.
metric
).
visualisation
.
segments
;
updateGraph
()
{
this
.
data
=
[];
this
.
shapes
=
[];
this
.
markerOpacities
=
[];
this
.
segments
=
this
.
selectedMetric
.
visualisation
.
segments
;
console
.
log
(
'
segments
'
,
this
.
segments
);
this
.
segmentLength
=
this
.
segments
[
0
].
buckets
.
length
;
this
.
timespan
=
this
.
vm
.
timespans
.
find
(
timespan
=>
timespan
.
id
===
this
.
vm
.
timespan
);
//
this.timespan = this.vm.timespans.find(
//
timespan => timespan.id === this.vm.timespan
//
);
// ----------------------------------------------
for
(
let
i
=
0
;
i
<
this
.
segmentLength
;
i
++
)
{
...
...
@@ -120,16 +135,17 @@ export class AnalyticsChartComponent implements OnInit, OnDestroy {
this
.
shapes
[
i
]
=
{
type
:
'
line
'
,
layer
:
'
below
'
,
x0
:
i
,
x0
:
this
.
segments
[
0
].
buckets
[
i
].
date
.
slice
(
0
,
10
)
,
y0
:
0
,
x1
:
i
,
y1
:
0
,
x1
:
this
.
segments
[
0
].
buckets
[
i
].
date
.
slice
(
0
,
10
)
,
y1
:
this
.
segments
[
0
].
buckets
[
i
].
value
,
line
:
{
color
:
this
.
getColor
(
'
m-transparent
'
),
width
:
2
,
},
};
}
// ----------------------------------------------
// LAYOUT
...
...
@@ -228,17 +244,25 @@ export class AnalyticsChartComponent implements OnInit, OnDestroy {
this
.
data
[
1
].
line
.
dash
=
'
dot
'
;
}
// Plotly.newPlot('graphDiv', this.data, this.layout);
this
.
cd
.
markForCheck
();
this
.
cd
.
detectChanges
();
//Plotly.purge('graphDiv');
//Plotly.newPlot('graphDiv', this.data, this.layout, { displayModeBar: false });
}
restyle
()
{
const
dataUpdate
=
this
.
data
;
Plotly
.
restyle
(
'
graphDiv
'
,
dataUpdate
);
// Plotly.restyle('graphDiv', dataUpdate);
this
.
cd
.
markForCheck
();
this
.
cd
.
detectChanges
();
}
relayout
()
{
const
layoutUpdate
=
this
.
layout
;
Plotly
.
relayout
(
'
graphDiv
'
,
layoutUpdate
);
//const layoutUpdate = this.layout;
//Plotly.relayout('graphDiv', layoutUpdate);
this
.
cd
.
markForCheck
();
this
.
cd
.
detectChanges
();
}
drawGraph
()
{}
...
...
@@ -295,9 +319,8 @@ export class AnalyticsChartComponent implements OnInit, OnDestroy {
// SHOW VERTICAL LINE
this
.
shapes
[
this
.
hoverPoint
].
line
.
color
=
this
.
getColor
(
'
m-grey-50
'
);
this
.
layout
.
shapes
[
this
.
hoverPoint
].
line
.
color
=
this
.
getColor
(
'
m-grey-50
'
);
// this.updateGraph();
this
.
restyle
();
this
.
relayout
();
}
...
...
@@ -306,12 +329,14 @@ export class AnalyticsChartComponent implements OnInit, OnDestroy {
this
.
shapes
[
this
.
hoverPoint
].
line
.
color
=
this
.
getColor
(
'
m-grey-50-transparent
'
);
// this.layout.shapes[this.hoverPoint].line.color = this.getColor(
// 'm-grey-50-transparent'
// );
// HIDE MARKER
this
.
hoverInfoDiv
.
style
.
opacity
=
0
;
this
.
markerOpacities
[
this
.
hoverPoint
]
=
0
;
this
.
restyle
();
this
.
relayout
();
}
...
...
This diff is collapsed.
Click to expand it.
src/app/modules/analytics/v2/components/filter/filter.component.html
View file @
680f081b
<div
class=
"filterWrapper"
*ngIf=
"vm$ | async as vm"
[ngClass]=
"{ expanded: expanded }"
>
<div
class=
"filterWrapper"
[ngClass]=
"{ expanded: expanded }"
>
<div
class=
"filterHeader"
(click)=
"expanded = !expanded"
>
<span
class=
"filterLabel"
>
{{ filter.label }}
</span>
<span
class=
"option option--selected"
>
...
...
@@ -12,11 +8,10 @@
<i
class=
"material-icons"
*ngIf=
"expanded"
>
keyboard_arrow_up
</i>
</div>
<div
class=
"unselectedOptionsContainer"
>
<ng-container
*ngFor=
"let option of options"
>
<ng-container
*ngFor=
"let option of
filter.
options"
>
<div
class=
"option"
(click)=
"updateFilter(option)"
*ngIf=
"option.label !== selectedOption.label"
[ngClass]=
"{
unavailable: option.available === false
}"
...
...
This diff is collapsed.
Click to expand it.
src/app/modules/analytics/v2/components/filter/filter.component.scss
View file @
680f081b
m-analytics__filter
{
position
:
relative
;
margin
:
16px
16px
0
0
;
z-index
:
1
;
}
.filterWrapper
{
...
...
This diff is collapsed.
Click to expand it.
src/app/modules/analytics/v2/components/filter/filter.component.ts
View file @
680f081b
...
...
@@ -36,25 +36,22 @@ export class AnalyticsFilterComponent implements OnInit, OnDestroy {
options
:
Array
<
any
>
=
[];
selectedOption
:
Option
;
subscription
;
vm$
:
Observable
<
UserState
>
=
this
.
analyticsService
.
vm$
;
vm
:
UserState
;
constructor
(
private
analyticsService
:
AnalyticsDashboardService
)
{}
ngOnInit
()
{
this
.
subscription
=
this
.
vm$
.
subscribe
(
viewModel
=>
(
this
.
vm
=
viewModel
));
this
.
options
=
this
.
filter
.
options
;
this
.
subscription
=
this
.
analyticsService
.
timespan$
.
subscribe
(
timespan
=>
{
if
(
this
.
filter
.
id
===
'
timespan
'
)
{
this
.
selectedOption
=
this
.
filter
.
options
.
find
(
option
=>
option
.
id
===
timespan
)
||
this
.
filter
.
options
[
0
];
if
(
this
.
filter
.
id
===
'
timespan
'
)
{
this
.
selectedOption
=
this
.
options
.
find
(
option
=>
option
.
id
===
this
.
vm
.
timespan
)
||
this
.
options
[
0
];
// TODO: make selected option at top of array?
}
else
{
this
.
selectedOption
=
this
.
options
.
find
(
option
=>
option
.
selected
===
true
)
||
this
.
options
[
0
];
}
// TODO: make selected option at top of array?
}
else
{
this
.
selectedOption
=
this
.
filter
.
options
.
find
(
option
=>
option
.
selected
===
true
)
||
this
.
filter
.
options
[
0
];
}
});
}
updateFilter
(
option
:
Option
)
{
...
...
@@ -71,37 +68,6 @@ export class AnalyticsFilterComponent implements OnInit, OnDestroy {
}
const
selectedFilterStr
=
`
${
this
.
filter
.
id
}
::
${
option
.
id
}
`
;
this
.
analyticsService
.
updateFilter
(
selectedFilterStr
);
// if (
// this.vm.filter.includes(selectedFilterStr) ||
// !this.selectedOption.available
// ) {
// return;
// }
// console.log(this.vm.filter);
// const filterArr = this.vm.filter;
// const activeFilterIds = filterArr.map(filterStr => {
// return filterStr.split('::')[0];
// });
// console.log(activeFilterIds);
// const filterIndex = activeFilterIds.findIndex(
// filterId => filterId === this.filter.id
// );
// console.log(filterIndex);
// if (activeFilterIds.includes(selectedFilterStr)) {
// filterArr.splice(filterIndex, 1, selectedFilterStr);
// } else {
// filterArr.push(selectedFilterStr);
// }
// console.log(filterArr);
// //TODO make incoming string filterStr instead of option
// // const filterStr = somethingToDoWith_optionLabel;
// this.analyticsService.updateFilter(filterArr);
}
ngOnDestroy
()
{
...
...
This diff is collapsed.
Click to expand it.
src/app/modules/analytics/v2/components/filters/filters.component.html
View file @
680f081b
<div
class=
"filtersContainer"
>
<ng-container
*ngFor=
"let filter of
(filters$ | async)
"
>
<ng-container
*ngFor=
"let filter of
filters$ | async
"
>
<m-analytics
__filter
class=
"filter"
[filter]=
"filter"
></m-analytics
__filter
>
</ng-container>
</div>
This diff is collapsed.
Click to expand it.
src/app/modules/analytics/v2/components/filters/filters.component.ts
View file @
680f081b
...
...
@@ -37,6 +37,5 @@ export class AnalyticsFiltersComponent implements OnInit, OnDestroy {
// TODO: might even be fine to just get rid of this component and put it in dashboard.ts
}
ngOnDestroy
()
{
}
ngOnDestroy
()
{}
}
This diff is collapsed.
Click to expand it.
src/app/modules/analytics/v2/dashboard.component.html
View file @
680f081b
...
...
@@ -15,7 +15,7 @@
<section
class=
"main"
>
<div
class=
"mainHeader"
>
<h3
class=
"selectedCatLabel"
>
{{
selectedCat?.label
}}
{{
category$ | async
}}
</h3>
<div
class=
"globalFilters"
>
<!-- TODO enable only show to admins -->
...
...
@@ -40,11 +40,11 @@
></m-analytics
__layout--chart
>
<!-- <m-analytics__layout--table
class="m-analytics__layout"
*ngIf="
selectedCat?
.type === 'table'"
*ngIf="
(category$ | async)
.type === 'table'"
></m-analytics__layout--table>
<m-analytics__layout--summary
class="m-analytics__layout"
*ngIf="
selectedCat?
.type === 'summary'"
*ngIf="
(category$ | async)
.type === 'summary'"
></m-analytics__layout--summary> -->
</div>
</section>
...
...
This diff is collapsed.
Click to expand it.
src/app/modules/analytics/v2/dashboard.component.ts
View file @
680f081b
...
...
@@ -4,6 +4,7 @@ import {
OnDestroy
,
Input
,
ChangeDetectionStrategy
,
ChangeDetectorRef
,
}
from
'
@angular/core
'
;
import
{
FormControl
}
from
'
@angular/forms
'
;
import
{
ActivatedRoute
,
Router
}
from
'
@angular/router
'
;
...
...
@@ -44,16 +45,15 @@ export class AnalyticsDashboardComponent implements OnInit, OnDestroy {
subscription
:
Subscription
;
paramsSubscription
:
Subscription
;
category$
=
this
.
analyticsService
.
category$
;
selectedCat
:
Category
;
selectedTimespan
;
//string? or Timespan?
timespanFilter
:
Filter
=
{
id
:
'
timespan
'
,
label
:
'
Timespan
'
,
options
:
[],
};
vm$
:
Observable
<
UserState
>
=
this
.
analyticsService
.
vm$
;
ready$
:
Observable
<
boolean
>
=
this
.
analyticsService
.
ready$
;
vm
:
UserState
;
constructor
(
public
client
:
Client
,
...
...
@@ -61,7 +61,8 @@ export class AnalyticsDashboardComponent implements OnInit, OnDestroy {
private
router
:
Router
,
public
session
:
Session
,
public
title
:
MindsTitle
,
public
analyticsService
:
AnalyticsDashboardService
public
analyticsService
:
AnalyticsDashboardService
,
private
cd
:
ChangeDetectorRef
)
{}
ngOnInit
()
{
...
...
@@ -81,17 +82,19 @@ export class AnalyticsDashboardComponent implements OnInit, OnDestroy {
// const {channelGuid} = this.analyticsService.getStateSnapshot();
// this.searchTerm = this.analyticsService.buildSearchTermControl();
// this.searchTerm.patchValue(channelGuid, { emitEvent: false });
this
.
subscription
=
this
.
vm$
.
subscribe
(
viewModel
=>
(
this
.
vm
=
viewModel
));
this
.
paramsSubscription
=
this
.
route
.
queryParams
.
subscribe
(
params
=>
{
// TODO: do the same filter, metric, channel
if
(
params
[
'
timespan
'
]
&&
params
[
'
timespan
'
]
!==
this
.
vm
.
timespan
)
{
this
.
updateTimespan
(
params
[
'
timespan
'
]);
}
this
.
selectedCat
=
this
.
cats
.
find
(
cat
=>
cat
.
id
===
this
.
vm
.
category
);
//
if (params['timespan'] && params['timespan'] !== this.vm.timespan) {
//
this.updateTimespan(params['timespan']);
//
}
//
this.selectedCat = this.cats.find(cat => cat.id === this.vm.category);
});
this
.
timespanFilter
.
options
=
this
.
vm
.
timespans
;
this
.
analyticsService
.
timespans$
.
subscribe
(
timespans
=>
{
this
.
timespanFilter
.
options
=
timespans
;
this
.
detectChanges
();
});
}
updateTimespan
(
timespanId
)
{
...
...
@@ -106,8 +109,12 @@ export class AnalyticsDashboardComponent implements OnInit, OnDestroy {
// this.analyticsService.updateCategory(categoryId);
}
detectChanges
()
{
this
.
cd
.
markForCheck
();
this
.
cd
.
detectChanges
();
}
ngOnDestroy
()
{
this
.
subscription
.
unsubscribe
();
this
.
paramsSubscription
.
unsubscribe
();
}
}
This diff is collapsed.
Click to expand it.
src/app/modules/analytics/v2/dashboard.service.ts
View file @
680f081b
...
...
@@ -111,7 +111,7 @@ export interface UserState {
let
_state
:
UserState
=
{
loading
:
false
,
category
:
'
traffic
'
,
timespan
:
'
1y
'
,
timespan
:
'
30d
'
,
timespans
:
[
{
id
:
'
30d
'
,
...
...
@@ -291,47 +291,47 @@ export class AnalyticsDashboardService {
// that are emitted only when something inside changes
category$
=
this
.
state$
.
pipe
(
map
(
state
=>
state
.
category
),
distinctUntilChanged
(
deepDiff
)
,
tap
(
category
=>
console
.
log
(
'
category changed
'
,
category
))
distinctUntilChanged
(
deepDiff
)
//
tap(category => console.log('category changed', category))
);
timespan$
=
this
.
state$
.
pipe
(
map
(
state
=>
state
.
timespan
),
distinctUntilChanged
(
deepDiff
)
,
tap
(
timespan
=>
console
.
log
(
'
timespan changed
'
,
timespan
))
distinctUntilChanged
(
deepDiff
)
//
tap(timespan => console.log('timespan changed', timespan))
);
timespans$
=
this
.
state$
.
pipe
(
map
(
state
=>
state
.
timespans
),
distinctUntilChanged
(
deepDiff
)
,
tap
(
timespans
=>
console
.
log
(
'
timespans changed
'
,
timespans
))
distinctUntilChanged
(
deepDiff
)
//
tap(timespans => console.log('timespans changed', timespans))
);
metric$
=
this
.
state$
.
pipe
(
map
(
state
=>
state
.
metric
),
//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
))
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
((
prev
,
curr
)
=>
{
console
.
log
(
JSON
.
stringify
(
prev
),
JSON
.
stringify
(
curr
));
//
console.log(JSON.stringify(prev), JSON.stringify(curr));
return
deepDiff
(
prev
,
curr
);
}),
tap
(
metrics
=>
console
.
log
(
'
metrics changed
'
,
metrics
))
);
filter$
=
this
.
state$
.
pipe
(
map
(
state
=>
state
.
filter
),
distinctUntilChanged
(
deepDiff
)
,
tap
(
filter
=>
console
.
log
(
'
filter changed
'
,
filter
))
distinctUntilChanged
(
deepDiff
)
//
tap(filter => console.log('filter changed', filter))
);
filters$
=
this
.
state$
.
pipe
(
map
(
state
=>
state
.
filters
),
distinctUntilChanged
(
deepDiff
)
,
tap
(
filters
=>
console
.
log
(
'
filters changed
'
,
filters
))
distinctUntilChanged
(
deepDiff
)
//
tap(filters => console.log('filters changed', filters))
);
loading$
=
this
.
state$
.
pipe
(
map
(
state
=>
state
.
loading
),
...
...
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment