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
Compare Revisions
4436d02cabe9bbb47edc8176a72e277127dff40e...262eb337eb318146180e8d34a89d8b1c59da68b7
Source
262eb337eb318146180e8d34a89d8b1c59da68b7
Select Git revision
...
Target
4436d02cabe9bbb47edc8176a72e277127dff40e
Select Git revision
Compare
Commits (2)
(feat): analytics v2 - router
· eece05bc
Olivia Madrid
authored
1 day ago
eece05bc
(feat): more analytics v2
· 262eb337
Olivia Madrid
authored
12 minutes ago
262eb337
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
545 additions
and
366 deletions
+545
-366
src/app/modules/analytics/analytics.module.ts
src/app/modules/analytics/analytics.module.ts
+4
-1
src/app/modules/analytics/v2/chart-palette.default.ts
src/app/modules/analytics/v2/chart-palette.default.ts
+52
-0
src/app/modules/analytics/v2/components/chart/chart.component.html
...odules/analytics/v2/components/chart/chart.component.html
+2
-1
src/app/modules/analytics/v2/components/chart/chart.component.ts
.../modules/analytics/v2/components/chart/chart.component.ts
+132
-251
src/app/modules/analytics/v2/components/filter/filter.component.html
...ules/analytics/v2/components/filter/filter.component.html
+1
-1
src/app/modules/analytics/v2/components/filter/filter.component.scss
...ules/analytics/v2/components/filter/filter.component.scss
+21
-5
src/app/modules/analytics/v2/components/filter/filter.component.ts
...odules/analytics/v2/components/filter/filter.component.ts
+45
-26
src/app/modules/analytics/v2/components/metrics/metrics.component.html
...es/analytics/v2/components/metrics/metrics.component.html
+1
-1
src/app/modules/analytics/v2/components/metrics/metrics.component.scss
...es/analytics/v2/components/metrics/metrics.component.scss
+10
-4
src/app/modules/analytics/v2/components/metrics/metrics.component.ts
...ules/analytics/v2/components/metrics/metrics.component.ts
+21
-22
src/app/modules/analytics/v2/dashboard.component.html
src/app/modules/analytics/v2/dashboard.component.html
+15
-9
src/app/modules/analytics/v2/dashboard.component.scss
src/app/modules/analytics/v2/dashboard.component.scss
+15
-4
src/app/modules/analytics/v2/dashboard.component.ts
src/app/modules/analytics/v2/dashboard.component.ts
+9
-15
src/app/modules/analytics/v2/dashboard.service.ts
src/app/modules/analytics/v2/dashboard.service.ts
+214
-26
src/app/modules/analytics/v2/layouts/layout-chart/layout-chart.component.scss
...ytics/v2/layouts/layout-chart/layout-chart.component.scss
+3
-0
No files found.
src/app/modules/analytics/analytics.module.ts
View file @
262eb337
...
...
@@ -90,7 +90,10 @@ const routes: Routes = [
{
path
:
'
dashboard
'
,
component
:
AnalyticsDashboardComponent
,
// children: [{ path: '', redirectTo: 'traffic', pathMatch: 'full' }],
children
:
[
{
path
:
''
,
redirectTo
:
'
traffic
'
,
pathMatch
:
'
full
'
},
{
path
:
'
:category
'
,
component
:
AnalyticsDashboardComponent
},
],
},
],
},
...
...
This diff is collapsed.
Click to expand it.
src/app/modules/analytics/v2/chart-palette.default.ts
0 → 100644
View file @
262eb337
const
chartPalette
:
Array
<
any
>
=
[
{
id
:
'
m-white
'
,
themeMap
:
[
'
#fff
'
,
'
#161616
'
],
},
{
id
:
'
m-transparent
'
,
themeMap
:
[
'
rgba(0,0,0,0)
'
,
'
rgba(0,0,0,0)
'
],
},
{
id
:
'
m-grey-50
'
,
themeMap
:
[
'
rgba(232,232,232,1)
'
,
'
rgba(53,53,53,1)
'
],
},
{
id
:
'
m-grey-70
'
,
themeMap
:
[
'
#eee
'
,
'
#333
'
],
},
{
id
:
'
m-grey-130
'
,
themeMap
:
[
'
#ccc
'
,
'
#555
'
],
},
{
id
:
'
m-grey-160
'
,
themeMap
:
[
'
#bbb
'
,
'
#555
'
],
},
{
id
:
'
m-grey-300
'
,
themeMap
:
[
'
#999
'
,
'
#666
'
],
},
{
id
:
'
m-blue
'
,
themeMap
:
[
'
#4690df
'
,
'
#44aaff
'
],
},
{
id
:
'
m-red-dark
'
,
themeMap
:
[
'
#c62828
'
,
'
#e57373
'
],
},
{
id
:
'
m-amber-dark
'
,
themeMap
:
[
'
#ffa000
'
,
'
#ffecb3
'
],
},
{
id
:
'
m-green-dark
'
,
themeMap
:
[
'
#388e3c
'
,
'
#8bc34a
'
],
},
{
id
:
'
m-blue-grey-500
'
,
themeMap
:
[
'
#607d8b
'
,
'
#607d8b
'
],
},
];
export
default
chartPalette
;
This diff is collapsed.
Click to expand it.
src/app/modules/analytics/v2/components/chart/chart.component.html
View file @
262eb337
...
...
@@ -6,6 +6,7 @@
<div>
<!-- <div id="graphDiv"></div> -->
<plotly-plot
id=
"graphDiv"
[divId]=
"graphDiv"
[data]=
"data"
[layout]=
"layout"
...
...
@@ -14,9 +15,9 @@
[style]=
"{ position: 'relative' }"
(hover)=
"onHover($event)"
(unhover)=
"onUnhover($event)"
(afterPlot)=
"updateGraph($event)"
>
</plotly-plot>
<!-- (afterPlot)="afterPlot()" -->
<div
id=
"hoverInfo"
class=
"hoverInfo"
>
<div
id=
"hoverInfo__x"
class=
"hoverInfo__row"
>
...
...
This diff is collapsed.
Click to expand it.
src/app/modules/analytics/v2/components/chart/chart.component.ts
View file @
262eb337
This diff is collapsed.
Click to expand it.
src/app/modules/analytics/v2/components/filter/filter.component.html
View file @
262eb337
...
...
@@ -18,7 +18,7 @@
(click)=
"updateFilter(option)"
*ngIf=
"option.label !== selectedOption.label"
[ngClass]=
"{
unavailable:
!option.availabl
e
unavailable:
option.available === fals
e
}"
>
<span>
{{ option.label }}
</span>
...
...
This diff is collapsed.
Click to expand it.
src/app/modules/analytics/v2/components/filter/filter.component.scss
View file @
262eb337
m-analytics__filter
{
position
:
relative
;
margin
:
16px
16px
0
0
;
}
.filterWrapper
{
cursor
:
pointer
;
border-radius
:
3px
;
margin
:
16px
16px
0
0
;
@include
m-theme
()
{
background-color
:
white
;
border
:
1px
solid
themed
(
$m-grey-100
);
...
...
@@ -9,12 +13,13 @@
}
&
.expanded
{
border-bottom-left-radius
:
0px
;
border-bottom-right-radius
:
0px
;
@include
m-theme
()
{
border-color
:
themed
(
$m-blue
);
}
.unselectedOptionsContainer
{
visibility
:
visible
;
height
:
auto
;
display
:
block
;
}
.option
{
&
:hover:not
(
.unavailable
)
{
...
...
@@ -27,6 +32,9 @@
}
.option
{
padding
:
4px
8px
;
@include
m-theme
()
{
background-color
:
themed
(
$m-white
);
}
&
.unavailable
{
text-decoration
:
line-through
;
...
...
@@ -37,6 +45,7 @@
}
.filterHeader
{
position
:
relative
;
display
:
flex
;
justify-content
:
space-between
;
.filterLabel
{
...
...
@@ -54,9 +63,16 @@
}
.unselectedOptionsContainer
{
visibility
:
hidden
;
height
:
0px
;
position
:
absolute
;
display
:
none
;
width
:
100%
;
border-bottom-left-radius
:
3px
;
border-bottom-right-radius
:
3px
;
box-sizing
:
border-box
;
left
:
0px
;
@include
m-theme
()
{
border
:
1px
solid
themed
(
$m-blue
);
border-top
:
1px
solid
themed
(
$m-grey-100
);
background-color
:
themed
(
$m-white
);
}
}
This diff is collapsed.
Click to expand it.
src/app/modules/analytics/v2/components/filter/filter.component.ts
View file @
262eb337
...
...
@@ -44,45 +44,64 @@ export class AnalyticsFilterComponent implements OnInit, OnDestroy {
this
.
subscription
=
this
.
vm$
.
subscribe
(
viewModel
=>
(
this
.
vm
=
viewModel
));
this
.
options
=
this
.
filter
.
options
;
this
.
selectedOption
=
this
.
options
.
find
(
option
=>
option
.
selected
===
true
)
||
this
.
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
];
}
}
updateFilter
(
option
:
Option
)
{
this
.
expanded
=
false
;
this
.
selectedOption
=
option
;
const
selectedFilterStr
=
`
${
this
.
filter
.
id
}
::
${
option
.
id
}
`
;
if
(
this
.
vm
.
filter
.
includes
(
selectedFilterStr
)
||
!
this
.
selectedOption
.
available
)
{
if
(
this
.
filter
.
id
===
'
timespan
'
)
{
this
.
analyticsService
.
updateTimespan
(
option
.
id
);
return
;
}
console
.
log
(
this
.
vm
.
filter
);
if
(
!
this
.
selectedOption
.
available
)
{
return
;
}
const
selectedFilterStr
=
`
${
this
.
filter
.
id
}
::
${
option
.
id
}
`
;
this
.
analyticsService
.
updateFilter
(
selectedFilterStr
);
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
);
// if (
// this.vm.filter.includes(selectedFilterStr) ||
// !this.selectedOption.available
// ) {
// return;
// }
console
.
log
(
filterIndex
);
// console.log(this.vm.filter
);
if
(
activeFilterIds
.
includes
(
selectedFilterStr
))
{
filterArr
.
splice
(
filterIndex
,
1
,
selectedFilterStr
);
}
else
{
filterArr
.
push
(
selectedFilterStr
);
}
console
.
log
(
filterArr
);
// 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
);
//
//
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/metrics/metrics.component.html
View file @
262eb337
...
...
@@ -6,7 +6,7 @@
[ngClass]=
"{ active: metric.visualisation }"
>
<div
class=
"metricLabel"
>
{{ metric.label }}
</div>
<!-- TODO the "
|
number" pipe should be from backend so it can dynamically handle diff decimals/currency formats -->
<!-- TODO the "number" pipe should be from backend so it can dynamically handle diff decimals/currency formats -->
<div
class=
"metricSummary"
>
{{ metric.summary.current_value | number }}
</div>
...
...
This diff is collapsed.
Click to expand it.
src/app/modules/analytics/v2/components/metrics/metrics.component.scss
View file @
262eb337
m-analytics__metrics
{
position
:
relative
;
z-index
:
999
;
}
.metricsContainer
{
display
:
flex
;
width
:
100%
;
// position: relative;
width
:
95%
;
padding
:
0
16px
;
@include
m-theme
()
{
border-bottom
:
1px
solid
themed
(
$m-grey-50
);
box-shadow
:
0px
0px
10px
-3px
rgba
(
themed
(
$m-black-always
)
,
0
.3
);
}
.metric
{
width
:
20%
;
padding
:
16
px
;
padding
:
20
px
;
font-size
:
12px
;
box-sizing
:
border-box
;
@include
m-theme
()
{
border-bottom
:
5px
solid
themed
(
$m-white
);
// border-bottom: 5px solid themed($m-white);
// border-bottom: 5px solid transparent;
color
:
themed
(
$m-grey-200
);
}
&
.active
{
...
...
This diff is collapsed.
Click to expand it.
src/app/modules/analytics/v2/components/metrics/metrics.component.ts
View file @
262eb337
...
...
@@ -44,32 +44,31 @@ export class AnalyticsMetricsComponent implements OnInit, OnDestroy {
constructor
(
private
analyticsService
:
AnalyticsDashboardService
)
{}
ngOnInit
()
{
this
.
metrics$
=
this
.
analyticsService
.
metrics$
.
pipe
(
map
(
_metrics
=>
{
const
metrics
=
_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
=
(
metric
.
summary
.
current_value
-
metric
.
summary
.
comparison_value
)
/
metric
.
summary
.
comparison_value
;
for
(
let
metric
of
metrics
)
{
const
delta
=
(
metric
.
summary
.
current_value
-
metric
.
summary
.
comparison_value
)
/
metric
.
summary
.
comparison_value
;
metric
[
'
delta
'
]
=
delta
;
metric
[
'
hasChanged
'
]
=
delta
===
0
?
false
:
true
;
metric
[
'
delta
'
]
=
delta
;
metric
[
'
hasChanged
'
]
=
delta
===
0
?
false
:
true
;
if
(
(
delta
>
0
&&
metric
.
summary
.
comparison_positive_inclination
)
||
(
delta
<
0
&&
!
metric
.
summary
.
comparison_positive_inclination
)
)
{
metric
[
'
positiveTrend
'
]
=
true
;
metric
[
'
positiveTrendy
'
]
=
true
;
}
else
{
metric
[
'
positiveTrend
'
]
=
false
;
if
(
(
delta
>
0
&&
metric
.
summary
.
comparison_positive_inclination
)
||
(
delta
<
0
&&
!
metric
.
summary
.
comparison_positive_inclination
)
)
{
metric
[
'
positiveTrend
'
]
=
true
;
}
else
{
metric
[
'
positiveTrend
'
]
=
false
;
}
}
}
return
metrics
;
}));
return
metrics
;
})
);
}
updateMetric
(
metric
)
{
...
...
@@ -77,6 +76,6 @@ export class AnalyticsMetricsComponent implements OnInit, OnDestroy {
}
ngOnDestroy
()
{
// this.subscription.unsubscribe();
// this.subscription.unsubscribe();
}
}
This diff is collapsed.
Click to expand it.
src/app/modules/analytics/v2/dashboard.component.html
View file @
262eb337
...
...
@@ -5,35 +5,40 @@
<div
class=
"catContainer"
>
<i
class=
"material-icons"
>
menu
</i>
<div
class=
"cat"
*ngFor=
"let cat of cats"
>
<
span
[ngClass]=
"{ selected: cat.id === (category$ | async) }
"
>
{{
<
a
[routerLink]=
"'./' + cat.id"
routerLinkActive=
"selected
"
>
{{
cat?.label
}}
</
span
>
}}
</
a
>
</div>
</div>
</section>
<section
class=
"main"
*ngIf=
"(ready$ | async)"
>
<!-- <section class="main" *ngIf="ready$ | async"> -->
<section
class=
"main"
>
<div
class=
"mainHeader"
>
<h3
class=
"selectedCatLabel"
>
{{ selectedCat?.label }}
</h3>
<div
class=
"globalFilters"
>
<!-- TODO enable only show to admins -->
<!-- <div *ngIf="session.isAdmin()" class="channelSearch"> -->
<div
class=
"channelSearch"
>
(todo: Channel search)
<!-- <input
type="text"
[formControl]="channelSearch"
placeholder="Search for a channel"
/> -->
</div>
<
!-- <
div class="timespanFilter">
<div
class=
"timespanFilter"
>
<m-analytics
__filter
[filter]=
"timespanFilter"
></m-analytics
__filter
>
</div>
-->
</div>
</div>
</div>
<m-analytics
__layout--chart
class=
"m-analytics__layout"
></m-analytics
__layout--chart
>
<!-- <m-analytics__layout--table
<div
class=
"layoutWrapper"
>
<m-analytics
__layout--chart
class=
"m-analytics__layout"
></m-analytics
__layout--chart
>
<!-- <m-analytics__layout--table
class="m-analytics__layout"
*ngIf="selectedCat?.type === 'table'"
></m-analytics__layout--table>
...
...
@@ -41,5 +46,6 @@
class="m-analytics__layout"
*ngIf="selectedCat?.type === 'summary'"
></m-analytics__layout--summary> -->
</div>
</section>
</div>
This diff is collapsed.
Click to expand it.
src/app/modules/analytics/v2/dashboard.component.scss
View file @
262eb337
...
...
@@ -22,11 +22,14 @@
.catContainer
{
.cat
{
padding
:
6px
0
;
@include
m-theme
()
{
color
:
themed
(
$m-grey-200
);
a
{
text-decoration
:
none
;
font-weight
:
400
;
@include
m-theme
()
{
color
:
themed
(
$m-grey-200
);
}
}
span
.selected
,
a
.selected
,
&
:hover
{
cursor
:
pointer
;
@include
m-theme
()
{
...
...
@@ -58,7 +61,14 @@
color
:
themed
(
$m-grey-100
);
}
}
m-analytics__filter
{
display
:
table
;
}
.timespanFilter
{
.filterWrapper
{
margin-top
:
0px
;
}
.filterLabel
{
display
:
none
;
}
...
...
@@ -66,6 +76,7 @@
}
.m-analytics__layout
{
position
:
relative
;
@include
m-theme
()
{
box-shadow
:
0px
0px
10px
-3px
rgba
(
themed
(
$m-black-always
)
,
0
.3
);
}
...
...
This diff is collapsed.
Click to expand it.
src/app/modules/analytics/v2/dashboard.component.ts
View file @
262eb337
...
...
@@ -28,7 +28,7 @@ import {
UserState
,
}
from
'
./dashboard.service
'
;
import
fakeData
from
'
./fake
'
;
//
import fakeData from './fake';
import
categories
from
'
./categories.default
'
;
import
isMobileOrTablet
from
'
../../../helpers/is-mobile-or-tablet
'
;
...
...
@@ -40,7 +40,6 @@ import isMobileOrTablet from '../../../helpers/is-mobile-or-tablet';
export
class
AnalyticsDashboardComponent
implements
OnInit
,
OnDestroy
{
isMobile
:
boolean
;
// TODO: get this from backend
cats
=
categories
;
subscription
:
Subscription
;
...
...
@@ -49,7 +48,7 @@ export class AnalyticsDashboardComponent implements OnInit, OnDestroy {
selectedTimespan
;
//string? or Timespan?
timespanFilter
:
Filter
=
{
id
:
'
timespan
'
,
label
:
'
t
imespan
'
,
label
:
'
T
imespan
'
,
options
:
[],
};
vm$
:
Observable
<
UserState
>
=
this
.
analyticsService
.
vm$
;
...
...
@@ -74,11 +73,9 @@ export class AnalyticsDashboardComponent implements OnInit, OnDestroy {
this
.
isMobile
=
isMobileOrTablet
();
this
.
title
.
setTitle
(
'
Analytics
'
);
// TODO: Autoset activeCat from url segment[2]
// console.log(this.route);
// console.log(this.route.snapshot.url);
// TODO: make timespans[] into a filter
this
.
route
.
params
.
subscribe
(
params
=>
{
this
.
updateCategory
(
params
[
'
category
'
]);
});
// TODO: implement channel filter
// const {channelGuid} = this.analyticsService.getStateSnapshot();
...
...
@@ -88,16 +85,13 @@ export class AnalyticsDashboardComponent implements OnInit, OnDestroy {
this
.
paramsSubscription
=
this
.
route
.
queryParams
.
subscribe
(
params
=>
{
// TODO: do the same filter, metric, channel
// TODO: something similar for category
if
(
params
[
'
timespan
'
]
&&
params
[
'
timespan
'
]
!==
this
.
vm
.
timespan
)
{
this
.
updateTimespan
(
params
[
'
timespan
'
]);
}
this
.
selectedCat
=
this
.
cats
.
find
(
// TODO get this from url segment[2]
cat
=>
cat
.
id
===
this
.
vm
.
category
);
this
.
selectedCat
=
this
.
cats
.
find
(
cat
=>
cat
.
id
===
this
.
vm
.
category
);
});
this
.
timespanFilter
.
options
=
this
.
vm
.
timespans
;
}
updateTimespan
(
timespanId
)
{
...
...
@@ -109,7 +103,7 @@ export class AnalyticsDashboardComponent implements OnInit, OnDestroy {
updateCategory
(
categoryId
)
{
// TODO
// update url
// this.analyticsService.update
Timespan
(categoryId);
// this.analyticsService.update
Category
(categoryId);
}
ngOnDestroy
()
{
...
...
This diff is collapsed.
Click to expand it.
src/app/modules/analytics/v2/dashboard.service.ts
View file @
262eb337
This diff is collapsed.
Click to expand it.
src/app/modules/analytics/v2/layouts/layout-chart/layout-chart.component.scss
View file @
262eb337
.filterableChartWrapper
{
position
:
relative
;
padding
:
16px
;
width
:
95%
;
@include
m-theme
()
{
border-top
:
1px
solid
themed
(
$m-grey-50
);
box-shadow
:
0px
0px
10px
-3px
rgba
(
themed
(
$m-black-always
)
,
0
.3
);
}
}
This diff is collapsed.
Click to expand it.