...
 
Commits (5)
......@@ -25,7 +25,7 @@
<div #hoverInfoDiv id="hoverInfoDiv" class="hoverInfoDiv">
<div class="hoverInfo__row">
{{ hoverInfo.date | date: datePipe }}
{{ hoverInfo.date | utcDate | date: datePipe }}
</div>
<div [ngSwitch]="selectedMetric.unit" class="hoverInfo__row--primary">
<ng-template ngSwitchCase="number">
......@@ -52,7 +52,7 @@
{{ selectedMetric.unit }}
</ng-template>
</ng-container>
on {{ hoverInfo.comparisonDate | date }}
on {{ hoverInfo.comparisonDate | utcDate | date: datePipe }}
</div>
</div>
</div>
m-analytics__chart {
display: block;
position: relative;
.js-plotly-plot,
.plot-container {
......
......@@ -11,7 +11,7 @@ import {
ViewChild,
ElementRef,
} from '@angular/core';
import { Observable, Subscription } from 'rxjs';
import { Subscription } from 'rxjs';
import { map } from 'rxjs/operators';
import {
AnalyticsDashboardService,
......@@ -20,7 +20,6 @@ import {
} from '../../dashboard.service';
import * as Plotly from 'plotly.js';
import { Config, Data, Layout } from 'plotly.js'; // TODO: remove this?
import chartPalette from '../../chart-palette.default';
import { ThemeService } from '../../../../../common/services/theme.service';
......@@ -122,6 +121,7 @@ export class AnalyticsChartComponent implements OnInit, OnDestroy {
this.themeSubscription = this.themeService.isDark$.subscribe(isDark => {
this.isDark = isDark;
this.applyDimensions();
// this.relayout(this.getLayout());
// this.restyle(this.getData());
......@@ -370,8 +370,8 @@ export class AnalyticsChartComponent implements OnInit, OnDestroy {
getLayout() {
return {
// width: 0,
// height: 0,
width: 0,
height: 0,
hovermode: 'x',
paper_bgcolor: this.getColor('m-white'),
plot_bgcolor: this.getColor('m-white'),
......@@ -406,24 +406,24 @@ export class AnalyticsChartComponent implements OnInit, OnDestroy {
},
fixedrange: true,
},
// margin: {
// t: 16,
// b: 80,
// l: 24,
// r: 80,
// pad: 16,
// },
margin: {
t: 16,
b: 80,
l: 24,
r: 80,
// pad: 16,
},
shapes: this.shapes,
};
}
@HostListener('window:resize')
applyDimensions() {
// this.layout = {
// ...this.layout,
// width: this.graphDiv.clientWidth, //-16
// height: this.graphDiv.clientHeight, //-16
// };
this.layout = {
...this.layout,
width: this.graphDiv.clientWidth - 32,
height: this.graphDiv.clientHeight - 32,
};
this.setLineHeights();
this.detectChanges();
}
......
<ng-container *ngIf="true">
<div class="filterLabelWrapper" *ngIf="filter.id !== 'timespan'">
<span>{{ filter.label }}</span>
<m-tooltip icon="help">
<div class="filterDesc">{{ filter.description }}</div>
<ul class="filterOptions__descContainer">
<ng-container *ngFor="let option of filter.options">
<li class="filterOption__desc">
<span class="filterOption__descLabel">{{ option.label }}</span
><span class="filterOption__desc" *ngIf="option.description"
>: {{ option.description }}</span
>
</li>
</ng-container>
</ul>
</m-tooltip>
</div>
<div
class="filterWrapper"
[ngClass]="{
expanded: expanded,
isMobile: isMobile,
dropUp: dropUp
}"
(focus)="expanded = true"
(blur)="expanded = false"
>
<div class="filterHeader" (click)="expanded = !expanded">
<div class="row">
<span class="option option--selected">
{{ selectedOption.label }}
</span>
<i class="material-icons" *ngIf="!expanded">keyboard_arrow_down</i>
<i class="material-icons" *ngIf="expanded">keyboard_arrow_up</i>
</div>
</div>
<div class="unselectedOptionsContainer">
<div class="filterLabelWrapper" *ngIf="filter.id !== 'timespan'">
<span>{{ filter.label }}</span>
<m-tooltip icon="help">
<div class="filterDesc">{{ filter?.description }}</div>
<ul class="filterOptions__descContainer">
<ng-container *ngFor="let option of filter.options">
<div
class="option row"
(click)="updateFilter(option)"
[ngClass]="{
unavailable: option.available === false
}"
>
<span>{{ option.label }}</span>
</div>
<li class="filterOption__desc">
<span class="filterOption__descLabel">{{ option.label }}</span
><span class="filterOption__desc" *ngIf="option.description"
>: {{ option.description }}</span
>
</li>
</ng-container>
</ul>
</m-tooltip>
</div>
<div
class="filterWrapper"
[ngClass]="{
expanded: expanded,
isMobile: isMobile,
dropUp: dropUp
}"
(focus)="expanded = true"
(blur)="expanded = false"
>
<div class="filterHeader" (click)="expanded = !expanded">
<div class="row">
<span class="option option--selected">
{{ selectedOption.label }}
</span>
<i class="material-icons" *ngIf="!expanded">keyboard_arrow_down</i>
<i class="material-icons" *ngIf="expanded">keyboard_arrow_up</i>
</div>
</div>
</ng-container>
<div class="unselectedOptionsContainer">
<ng-container *ngFor="let option of filter.options">
<div
class="option row"
(click)="updateFilter(option)"
[ngClass]="{
unavailable: option.available === false
}"
>
<span>{{ option.label }}</span>
</div>
</ng-container>
</div>
</div>
......@@ -3,7 +3,7 @@ $rounded-bottom: 0 0 3px 3px;
m-analytics__filter {
position: relative;
margin: 16px 24px 0 0;
margin: 0 36px 0 0;
z-index: 2;
}
.filterLabelWrapper {
......@@ -13,6 +13,12 @@ m-analytics__filter {
@include m-theme() {
color: rgba(themed($m-grey-200), 0.9);
}
m-tooltip {
margin-right: 4px;
}
> * {
display: inline-block;
}
.m-tooltip {
i {
font-size: 12px;
......@@ -96,7 +102,7 @@ m-analytics__filter {
.filterHeader {
position: relative;
width: 100%;
padding: 6px 6px 6px 8px;
padding: 8px 6px 6px 10px;
border-radius: 3px;
transition: all 0.3s cubic-bezier(0.075, 0.82, 0.165, 1);
......@@ -126,7 +132,7 @@ m-analytics__filter {
// display: none;
visibility: hidden;
width: 100%;
padding: 6px 6px 6px 8px;
padding: 8px 6px 6px 10px;
border-radius: 3px;
left: 0px;
transition: box-shadow 0.3s cubic-bezier(0.075, 0.82, 0.165, 1);
......@@ -166,7 +172,7 @@ m-analytics__filter {
}
}
.isMobile {
.filterWrapper.isMobile {
.filterHeader {
i {
display: none;
......
......@@ -37,7 +37,6 @@ export class AnalyticsFilterComponent implements OnInit {
expanded = false;
options: Array<any> = [];
selectedOption: Option;
// subscription;
constructor(
private analyticsService: AnalyticsDashboardService,
public session: Session
......@@ -58,8 +57,6 @@ export class AnalyticsFilterComponent implements OnInit {
// }
// });
console.log(this.filter, this.filter.id);
this.selectedOption =
this.filter.options.find(option => option.selected === true) ||
this.filter.options[0];
......
<div class="filtersContainer">
<ng-container *ngFor="let filter of filters$ | async">
<!-- <ng-container *ngFor="let filter of filters$ | async"> -->
<ng-container *ngFor="let filter of filters">
<m-analytics__filter
class="filter"
[filter]="filter"
......
......@@ -3,4 +3,5 @@
flex-wrap: wrap;
padding: 16px;
position: relative;
margin-top: 36px;
}
......@@ -3,22 +3,10 @@ import {
OnInit,
OnDestroy,
ChangeDetectionStrategy,
ChangeDetectorRef,
} from '@angular/core';
import { Observable, Subscription } from 'rxjs';
import {
AnalyticsDashboardService,
Category,
Response,
Dashboard,
Filter,
Option,
Metric,
Summary,
Visualisation,
Bucket,
Timespan,
UserState,
} from '../../dashboard.service';
import { Subscription } from 'rxjs';
import { AnalyticsDashboardService, Filter } from '../../dashboard.service';
@Component({
selector: 'm-analytics__filters',
......@@ -29,12 +17,35 @@ export class AnalyticsFiltersComponent implements OnInit, OnDestroy {
subscription: Subscription;
filters$ = this.analyticsService.filters$;
filters: Filter[];
constructor(private analyticsService: AnalyticsDashboardService) {}
constructor(
private analyticsService: AnalyticsDashboardService,
private cd: ChangeDetectorRef
) {}
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
// TODO: remove all of this once channel search is ready
// Temporarily remove channel search from channel filter options
this.analyticsService.filters$.subscribe(filters => {
this.filters = filters;
const channelFilter = filters.find(filter => filter.id === 'channel');
channelFilter.options = channelFilter.options.filter(option => {
return option.id === 'all' || option.id === 'self';
});
this.filters.find(filter => filter.id === 'channel').options =
channelFilter.options;
this.detectChanges();
});
}
// TODO: remove all of this once channel search is ready
detectChanges() {
this.cd.markForCheck();
this.cd.detectChanges();
}
ngOnDestroy() {}
......
......@@ -18,10 +18,12 @@
/>
<div class="details">
<div class="name">{{ user.name }}</div>
<!-- TODO: remove username once subscriberCount is working -->
<div class="username">@{{ user.username }}</div>
<!-- TODO: get subscriberCount -->
<div class="subscribers">
<!-- <div class="subscribers">
{{ user.subscribers_count | abbr }} subscribers
</div>
</div> -->
</div>
</a>
......
......@@ -3,7 +3,14 @@
// display: none;
// }
.page.isMobile m-analytics__menu {
margin-right: -32px;
flex: 0 1 0px;
}
m-analytics__menu {
display: block;
max-width: 160px;
// ----------------------------------------
// MOBILE
......@@ -60,7 +67,7 @@ m-analytics__menu {
position: fixed;
top: 0;
bottom: 0;
left: -340px;
left: -360px;
transition: left 0.5s cubic-bezier(0.075, 0.82, 0.165, 1);
padding: 0 24px;
width: 300px;
......@@ -107,10 +114,15 @@ m-analytics__menu {
.name {
font-weight: bold;
}
.username {
@include m-theme() {
color: themed($m-grey-200);
}
}
.subscribers {
font-size: 11px;
@include m-theme() {
color: themed($m-grey-300);
color: themed($m-grey-200);
}
}
}
......
......@@ -169,3 +169,10 @@ m-analytics__metrics {
}
}
}
.metricsSection.isMobile {
.metricsContainer {
.metric {
flex: 1 0 auto;
}
}
}
<div class="tableWrapper" [hidden]="loading">
<div class="header row">
<div
*ngFor="let col of visualisation.columns; let first = first"
[ngClass]="{
first: first
}"
class="cell"
>
<div class="tableWrapper" [hidden]="loading" [ngClass]="{ isMobile: isMobile }">
<div class="row--header">
<div *ngFor="let col of columns | slice: 0:1" class="col--entity cell">
{{ col.label }}
</div>
<div class="col--values">
<ng-container *ngFor="let col of columns | slice: 1">
<div class="subCol--value cell">{{ col.label }}</div>
</ng-container>
</div>
</div>
<div class="body">
<ng-container *ngFor="let row of reformattedBuckets">
<a class="row" [routerLink]="row.entity.route">
<div class="entity cell" *ngIf="row.entity">
<div class="entityTitle">
<span>{{ row.entity.title }}</span>
<i class="material-icons">open_in_new</i>
</div>
<div class="entityDetails">
<span class="usernameWrapper">
<a [routerLink]="'/' + row.entity.name"
>@{{ row.entity.username }}</a
>
</span>
<span *ngIf="!isMobile">{{ row.entity.type | titlecase }}</span>
<span *ngIf="!isMobile"
>Published {{ row.entity.time_created * 1000 | date }}</span
>
</div>
<ng-container *ngFor="let row of reformattedBuckets">
<a class="row--data" [routerLink]="row.entity.route">
<div class="col--entity cell" *ngIf="row.entity">
<div class="entityTitle">
<span>{{ row.entity.title }}</span>
<i class="material-icons">open_in_new</i>
</div>
<div class="valuesContainer">
<ng-container *ngFor="let value of row.values">
<div class="value cell">{{ value | abbr }}</div>
</ng-container>
<div class="entityDetails">
<span class="usernameWrapper">
<a [routerLink]="'/' + row.entity.name"
>@{{ row.entity.username }}</a
>
</span>
<span *ngIf="!isMobile">{{ row.entity.type | titlecase }}</span>
<span *ngIf="!isMobile"
>Published {{ row.entity.time_created * 1000 | date }}</span
>
</div>
</a>
</ng-container>
</div>
</div>
<div class="col--values">
<ng-container *ngFor="let value of row.values">
<div class="subCol--value cell">{{ value | abbr }}</div>
</ng-container>
</div>
</a>
</ng-container>
</div>
.tableWrapper {
// * {
// border: 1px solid salmon;
// }
font-size: 13px;
font-weight: 400;
@include m-theme() {
......@@ -11,117 +14,189 @@
color: themed($m-grey-800);
}
}
.row {
[class*='row'] {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
&.header {
transition: background-color 0.3s cubic-bezier(0.23, 1, 0.32, 1);
&.row--header {
@include m-theme() {
border-bottom: 1px solid themed($m-grey-50);
color: themed($m-grey-200);
}
.cell {
flex: 1 1 0;
&.first {
flex: 7 2 0;
.col--entity {
flex-direction: row;
align-items: flex-end;
}
.col--values {
.subCol--value.cell {
align-items: flex-end;
}
}
}
&.row--data {
&:hover {
@include m-theme() {
background-color: rgba(themed($m-blue-grey-50), 0.5);
}
.col--entity .entityTitle i {
display: inline-block;
}
}
.col--entity {
@include m-theme() {
border-right: 1px solid themed($m-grey-50);
}
}
// .col--entity,
// .col--entity *,
// .col--values,
// .col--values *,
[class*='col'],
[class*='col'] * {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
// .subCol--value {
// align-items: center;
// }
}
.cell {
flex: 1 1 0;
display: flex;
// align-items: center;
flex-direction: column;
overflow: hidden;
white-space: nowrap;
height: 50px;
padding: 8px 8px 8px 0;
}
.col--entity {
flex-direction: column;
padding-left: 24px;
flex-basis: 20vw;
&.entity {
padding-left: 5%;
min-width: 200px;
flex: 7 2 0;
.usernameWrapper a {
font-weight: 400;
text-decoration: none;
}
.entityTitle {
display: flex;
> * {
display: inline-block;
}
i {
font-size: 12px;
margin: 3px 0 0 3px;
display: none;
@include m-theme() {
color: themed($m-grey-800);
}
}
}
.entityDetails {
display: inline;
@include m-theme() {
border-right: 1px solid themed($m-grey-50);
color: themed($m-grey-200);
}
a {
font-weight: 400;
text-decoration: none;
> * {
margin-right: $minds-margin;
}
.entityTitle {
display: flex;
// align-items: center;
.usernameWrapper {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
i {
font-size: 13px;
display: none;
@include m-theme() {
color: themed($m-grey-800);
}
}
}
.entityDetails {
display: inline;
a {
@include m-theme() {
color: themed($m-grey-200);
}
> * {
margin-right: $minds-margin;
}
.usernameWrapper {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
a {
@include m-theme() {
color: themed($m-grey-200);
}
color: themed($m-grey-300);
}
}
}
&.value {
}
.col--values {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
.subCol--value {
flex: 1 1 16vw;
&:first-of-type {
padding-left: 8px;
padding-left: 24px;
}
&:last-of-type {
padding-right: 5%;
padding-right: 16px;
}
}
}
}
.valuesContainer {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
flex: 3 1 0;
}
.col--entity {
flex: 2 3 0;
}
.col--values {
flex: 1 2 0;
}
// MOBILE /////////////////////
.tableWrapper.isMobile {
.col--entity {
flex: 1 3 0;
}
.body {
.row {
transition: background-color 0.3s cubic-bezier(0.23, 1, 0.32, 1);
&:hover {
@include m-theme() {
background-color: rgba(themed($m-blue-grey-50), 0.5);
}
.entityTitle i {
display: inline-block;
}
}
}
.col--values {
flex: 2 1 0;
}
}
.spinnerContainer {
height: 30%;
width: 100%;
display: flex;
justify-content: center;
align-items: center;
@include m-theme() {
background-color: themed($m-white);
.row--header {
border: none !important;
}
.row--data {
.col--entity.cell {
border: none !important;
}
}
}
///////////////////////////@at-root @media screen and (max-width: 800px) {
// @media screen and (max-width: 910px) {
// .m-referrals-dashboard__row.m-referrals-dashboard__headerRow {
// span {
// white-space: normal !important;
// max-width: 35px;
// }
// .m-referrals-dashboard__registerCol,
// .m-referrals-dashboard__rewardsCol {
// align-items: flex-start !important;
// }
// .m-referrals-dashboard__rewardsCol span {
// max-width: 46px;
// }
// }
// .m-referrals-dashboard__cell.m-referrals-dashboard__rewardsCol {
// flex: 2 3 0;
// .m-referrals-dashboard__pingButtonContainer button {
// padding: 8px;
// span {
// display: none;
// }
// }
// }
// }
// .m-referrals-dashboard__cell.m-referrals-dashboard__registerCol {
// display: none;
// }
// .m-referrals-dashboard__userCol {
// min-width: 100px;
// }
// .m-referrals-dashboard__statusCol {
// min-width: 60px;
// }
// .m-referrals-dashboard__rewardsCol {
// max-width: 75px;
// }
// }
......@@ -31,6 +31,7 @@ export class AnalyticsTableComponent implements OnInit, OnDestroy {
isMobile: boolean;
loadingSubscription: Subscription;
loading: boolean;
valueColCount: number = 1;
selectedMetric$ = this.analyticsService.metrics$.pipe(
map(metrics => {
......@@ -50,10 +51,8 @@ export class AnalyticsTableComponent implements OnInit, OnDestroy {
this.selectedMetric = metric;
this.visualisation = metric.visualisation;
this.columns = metric.visualisation.columns;
this.valueColCount = this.columns.length - 1;
// .sort((a, b) =>
// a.order > b.order ? 1 : -1
// );
this.loadingSubscription = this.analyticsService.loading$.subscribe(
loading => {
this.loading = loading;
......
<div class="page" [ngClass]="{ isMobile: isMobile }">
<m-analytics__menu></m-analytics__menu>
<!-- TODO: uncomment this -->
<!-- <section class="main" *ngIf="ready$ | async"> -->
<section class="main" [ngClass]="{ isMobile: isMobile }">
<section
class="main"
*ngIf="ready$ | async"
[ngClass]="{ isMobile: isMobile }"
>
<!-- <section class="main" [ngClass]="{ isMobile: isMobile }"> -->
<div class="mainHeader">
<div class="dashboardTitle">
<h3 class="selectedCatLabel">
......@@ -33,13 +36,13 @@
</p>
</div>
<div class="globalFilters">
<!-- TODO: *ngIf for global_filter bool -->
<!-- TODO: enable only show to admins -->
<!-- <div *ngIf="session.isAdmin()" class="channelSearch"> -->
<div class="channelSearch">
<!-- <div class="channelSearch">
<m-analytics__search></m-analytics__search>
</div> -->
<div class="channelFilter" *ngIf="session.isAdmin()">
<m-analytics__filter [filter]="channelFilter"></m-analytics__filter>
</div>
<!-- TODO: timespan filter will be a date filter -->
<div class="timespanFilter">
<m-analytics__filter [filter]="timespanFilter"></m-analytics__filter>
</div>
......
m-analytics__dashboard {
display: block;
width: 100%;
}
// ----------------------------------------
// MOBILE
.isMobile {
&.page {
padding: 0;
.main {
padding: 0;
.mainHeader {
padding-left: 24px;
display: block;
}
.layoutWrapper {
box-shadow: none;
padding: 0;
}
}
}
.layoutWrapper {
box-shadow: none;
padding: 0;
}
.main {
padding: 0;
}
.m-analytics__menu {
padding: 0 8px;
}
......@@ -22,7 +32,7 @@
display: flex;
flex-direction: row;
height: 100%;
// width: 100%;
width: 100%;
@include m-theme() {
background-color: themed($m-white);
color: themed($m-grey-800);
......@@ -37,17 +47,16 @@
.main {
flex: 4 1 0px;
padding: 16px;
min-width: 600px;
.mainHeader {
display: flex;
justify-content: space-between;
align-items: flex-start;
h3 {
line-height: 0;
margin-top: 40px;
}
// h3 {
// line-height: 0;
// margin-top: 40px;
// }
p {
@include m-theme() {
color: themed($m-grey-300);
......@@ -94,6 +103,8 @@
.m-analytics__layout {
position: relative;
display: block;
width: 100%;
}
}
......
......@@ -31,16 +31,18 @@ export class AnalyticsDashboardComponent implements OnInit, OnDestroy {
// subscription: Subscription;
paramsSubscription: Subscription;
category$ = this.analyticsService.category$;
description$ = this.analyticsService.description$;
selectedCat: string;
selectedTimespan; //string? or Timespan?
selectedTimespan;
timespanFilter: Filter = {
id: 'timespan',
label: 'Timespan',
options: [],
};
channelFilter: Filter;
constructor(
public client: Client,
......@@ -83,6 +85,16 @@ export class AnalyticsDashboardComponent implements OnInit, OnDestroy {
this.analyticsService.metrics$.subscribe(metrics => {
this.detectChanges();
});
this.analyticsService.filters$.subscribe(filters => {
this.channelFilter = filters.find(filter => filter.id === 'channel');
// TODO: remove this once channel search is ready
// Temporarily remove channel search from filter options
this.channelFilter.options = this.channelFilter.options.filter(option => {
return option.id === 'all' || option.id === 'self';
});
this.detectChanges();
});
if (!this.session.isAdmin()) {
this.analyticsService.updateFilter('channel::self');
......
......@@ -31,6 +31,7 @@ export interface Response {
export interface Dashboard {
category: string;
description?: string;
timespan: string;
timespans: Timespan[];
metric: string;
......@@ -257,11 +258,6 @@ export class AnalyticsDashboardService {
// return channelSearch;
// }
// TODO: this in UpdateFilter() instead
// updateChannel(channel: string) {
// this.updateState({ ..._state, criteria, loading: true });
// }
updateCategory(category: string) {
this.updateState({
..._state,
......
......@@ -3,6 +3,7 @@ const fakeData: Array<any> = [
// CHART TESTS
loading: false,
category: 'traffic',
description: 'imma traffic description',
timespan: '30d',
timespans: [
{
......@@ -44,28 +45,28 @@ const fakeData: Array<any> = [
{
id: 'channel',
label: 'Channel',
description: 'Filter by channel type:',
description: null,
options: [
{
id: 'all',
label: 'All',
available: true,
selected: false,
description: 'bibbble',
selected: true,
description: null,
},
{
id: 'browser',
label: 'Browser',
id: 'self',
label: 'Self',
available: true,
selected: false,
description: 'bliblabla',
description: null,
},
{
id: 'mobile',
label: 'Mobile',
id: 'search',
label: 'Search',
available: true,
selected: false,
description: 'blubber',
description: null,
},
],
},
......@@ -287,6 +288,7 @@ const fakeData: Array<any> = [
{
loading: false,
category: 'earnings',
description: 'imma earnings description',
timespan: '30d',
timespans: [
{
......@@ -308,6 +310,34 @@ const fakeData: Array<any> = [
],
filter: ['channel::all'],
filters: [
{
id: 'channel',
label: 'Channel',
description: 'Filter by channel type:',
options: [
{
id: 'all',
label: 'All',
available: true,
selected: true,
description: 'bibbble',
},
{
id: 'self',
label: 'Self',
available: true,
selected: false,
description: 'bliblabla',
},
{
id: 'search',
label: 'cantSeeMe',
available: true,
selected: false,
description: 'should not be shown',
},
],
},
{
id: 'platform',
label: 'Platform',
......
......@@ -5,7 +5,10 @@
<m-analytics__metrics
*ngIf="selectedMetric.visualisation.type === 'chart'"
></m-analytics__metrics>
<div class="filterableChartWrapper" [ngClass]="{ isTable: isTable }">
<div
class="filterableChartWrapper"
[ngClass]="{ isTable: isTable, isMobile: isMobile }"
>
<m-analytics__chart
*ngIf="selectedMetric.visualisation.type === 'chart'"
></m-analytics__chart>
......
.filterableChartWrapper {
position: relative;
padding: 16px;
width: 100%;
width: 80%;
@include m-theme() {
border-top: 1px solid themed($m-grey-50);
}
......@@ -9,4 +9,17 @@
padding: 0;
width: 100%;
}
&.isMobile {
border-top: none;
}
}
.spinnerContainer {
height: 30%;
width: 100%;
display: flex;
justify-content: center;
align-items: center;
@include m-theme() {
background-color: themed($m-white);
}
}
......@@ -7,6 +7,7 @@ import {
import { Observable, Subscription, combineLatest } from 'rxjs';
import { map } from 'rxjs/operators';
import { AnalyticsDashboardService } from '../../dashboard.service';
import isMobileOrTablet from '../../../../../helpers/is-mobile-or-tablet';
@Component({
selector: 'm-analytics__layout--chart',
......@@ -27,6 +28,7 @@ export class AnalyticsLayoutChartComponent implements OnInit {
);
selectedMetric;
isTable: boolean = false;
isMobile: boolean;
constructor(
private analyticsService: AnalyticsDashboardService,
......@@ -44,6 +46,7 @@ export class AnalyticsLayoutChartComponent implements OnInit {
this.selectedMetric.visualisation.type === 'table';
this.detectChanges();
});
this.isMobile = isMobileOrTablet();
}
detectChanges() {
......