Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 40 additions & 36 deletions src/app/features/analytics/analytics.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -42,45 +42,49 @@
</div>
}

<div class="flex flex-column flex-wrap gap-4 xl:flex-row" [class]="{ disabled: isMetricsError() }">
<osf-line-chart
class="chart"
[class.xl-half-width]="IS_X_LARGE()"
[isLoading]="isMetricsLoading()"
[title]="'project.analytics.charts.uniqueVisits'"
[labels]="visitsLabels"
[datasets]="visitsDataset"
></osf-line-chart>
@if (!isMetricsLoading() && !isRelatedCountsLoading()) {
<div class="flex flex-column flex-wrap gap-4 xl:flex-row" [class]="{ disabled: isMetricsError() }">
<osf-line-chart
class="chart"
[class.xl-half-width]="IS_X_LARGE()"
[isLoading]="isMetricsLoading()"
[title]="'project.analytics.charts.uniqueVisits'"
[labels]="visitsLabels"
[datasets]="visitsDataset"
></osf-line-chart>

<osf-bar-chart
class="chart"
[class.xl-half-width]="IS_X_LARGE()"
[isLoading]="isMetricsLoading()"
[title]="'project.analytics.charts.timeOfDayOfVisits'"
[labels]="totalVisitsLabels"
[datasets]="totalVisitsDataset"
[orientation]="'vertical'"
></osf-bar-chart>
<osf-bar-chart
class="chart"
[class.xl-half-width]="IS_X_LARGE()"
[isLoading]="isMetricsLoading()"
[title]="'project.analytics.charts.timeOfDayOfVisits'"
[labels]="totalVisitsLabels"
[datasets]="totalVisitsDataset"
[orientation]="'vertical'"
></osf-bar-chart>

<osf-pie-chart
class="chart"
[class.xl-half-width]="IS_X_LARGE()"
[isLoading]="isMetricsLoading()"
[title]="'project.analytics.charts.topReferrers'"
[labels]="topReferrersLabels"
[datasets]="topReferrersDataset"
[showLegend]="true"
></osf-pie-chart>
<osf-pie-chart
class="chart"
[class.xl-half-width]="IS_X_LARGE()"
[isLoading]="isMetricsLoading()"
[title]="'project.analytics.charts.topReferrers'"
[labels]="topReferrersLabels"
[datasets]="topReferrersDataset"
[showLegend]="true"
></osf-pie-chart>

<osf-bar-chart
class="chart"
[class.xl-half-width]="IS_X_LARGE()"
[isLoading]="isMetricsLoading()"
[title]="'project.analytics.charts.popularPages'"
[labels]="popularPagesLabels"
[datasets]="popularPagesDataset"
></osf-bar-chart>
</div>
<osf-bar-chart
class="chart"
[class.xl-half-width]="IS_X_LARGE()"
[isLoading]="isMetricsLoading()"
[title]="'project.analytics.charts.popularPages'"
[labels]="popularPagesLabels"
[datasets]="popularPagesDataset"
></osf-bar-chart>
</div>
} @else {
<osf-loading-spinner></osf-loading-spinner>
}

<div class="flex flex-column gap-3 mt-6 sm:flex-row sm:justify-content-between sm:gap-4">
<osf-analytics-kpi
Expand Down
8 changes: 3 additions & 5 deletions src/app/features/analytics/analytics.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { ActivatedRoute, Router } from '@angular/router';
import {
BarChartComponent,
LineChartComponent,
LoadingSpinnerComponent,
PieChartComponent,
SelectComponent,
SubHeaderComponent,
Expand All @@ -47,6 +48,7 @@ import { AnalyticsSelectors, ClearAnalytics, GetMetrics, GetRelatedCounts } from
BarChartComponent,
ViewOnlyLinkMessageComponent,
SelectComponent,
LoadingSpinnerComponent,
],
templateUrl: './analytics.component.html',
styleUrl: './analytics.component.scss',
Expand Down Expand Up @@ -123,11 +125,7 @@ export class AnalyticsComponent implements OnInit {
});

effect(() => {
const analytics = this.analytics();

if (analytics) {
this.setData();
}
this.setData();
});
}

Expand Down
13 changes: 10 additions & 3 deletions src/app/features/analytics/mappers/analytics.mapper.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
import { AnalyticsMetricsGetResponse, AnalyticsMetricsModel } from '../models';
import { NodeAnalyticsDataJsonApi, NodeAnalyticsModel, RefererDomainJsonApi, RefererDomainModel } from '../models';

export class AnalyticsMetricsMapper {
static fromResponse(response: AnalyticsMetricsGetResponse): AnalyticsMetricsModel {
static fromResponse(response: NodeAnalyticsDataJsonApi): NodeAnalyticsModel {
return {
id: response.id,
type: response.type,
popularPages: response.attributes.popular_pages,
uniqueVisits: response.attributes.unique_visits,
refererDomain: response.attributes.referer_domain,
refererDomain: response.attributes.referer_domain.map((item) => this.getReferDomain(item)),
timeOfDay: response.attributes.time_of_day,
};
}

static getReferDomain(data: RefererDomainJsonApi): RefererDomainModel {
return {
refererDomain: data.referer_domain,
count: data.count,
};
}
}
44 changes: 0 additions & 44 deletions src/app/features/analytics/models/analytics-metrics.model.ts

This file was deleted.

3 changes: 2 additions & 1 deletion src/app/features/analytics/models/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export * from './analytics-metrics.model';
export * from './date-range-option.model';
export * from './node-analytics.model';
export * from './node-analytics-json-api.model';
export * from './related-counts.model';
export * from './related-counts-json-api.model';
38 changes: 38 additions & 0 deletions src/app/features/analytics/models/node-analytics-json-api.model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { ResponseDataJsonApi } from '@osf/shared/models';

export type NodeAnalyticsResponseJsonApi = ResponseDataJsonApi<NodeAnalyticsDataJsonApi>;

export interface NodeAnalyticsDataJsonApi {
id: string;
type: 'node-analytics';
attributes: NodeAnalyticsAttributesJsonApi;
}

export interface NodeAnalyticsAttributesJsonApi {
popular_pages: PopularPageJsonApi[];
unique_visits: UniqueVisitJsonApi[];
time_of_day: TimeOfDayJsonApi[];
referer_domain: RefererDomainJsonApi[];
}

export interface PopularPageJsonApi {
path: string;
route: string;
title: string;
count: number;
}

export interface UniqueVisitJsonApi {
date: string;
count: number;
}

export interface TimeOfDayJsonApi {
hour: number;
count: number;
}

export interface RefererDomainJsonApi {
referer_domain: string;
count: number;
}
31 changes: 31 additions & 0 deletions src/app/features/analytics/models/node-analytics.model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
export interface NodeAnalyticsModel {
id: string;
type: string;
popularPages: PopularPageModel[];
uniqueVisits: UniqueVisitModel[];
timeOfDay: TimeOfDayModel[];
refererDomain: RefererDomainModel[];
lastFetched?: number;
}

export interface PopularPageModel {
path: string;
route: string;
title: string;
count: number;
}

export interface UniqueVisitModel {
date: string;
count: number;
}

export interface TimeOfDayModel {
hour: number;
count: number;
}

export interface RefererDomainModel {
refererDomain: string;
count: number;
}
7 changes: 3 additions & 4 deletions src/app/features/analytics/services/analytics.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,10 @@ import { inject, Injectable } from '@angular/core';

import { ENVIRONMENT } from '@core/provider/environment.provider';
import { ResourceType } from '@osf/shared/enums';
import { JsonApiResponse } from '@osf/shared/models';
import { JsonApiService } from '@osf/shared/services';

import { AnalyticsMetricsMapper, RelatedCountsMapper } from '../mappers';
import { AnalyticsMetricsGetResponse, AnalyticsMetricsModel, RelatedCountsGetResponse } from '../models';
import { NodeAnalyticsModel, NodeAnalyticsResponseJsonApi, RelatedCountsGetResponse } from '../models';

@Injectable({
providedIn: 'root',
Expand All @@ -26,11 +25,11 @@ export class AnalyticsService {
[ResourceType.Registration, 'registrations'],
]);

getMetrics(resourceId: string, dateRange: string): Observable<AnalyticsMetricsModel> {
getMetrics(resourceId: string, dateRange: string): Observable<NodeAnalyticsModel> {
const baseUrl = `${this.apiDomainUrl}/_/metrics/query/node_analytics`;

return this.jsonApiService
.get<JsonApiResponse<AnalyticsMetricsGetResponse, null>>(`${baseUrl}/${resourceId}/${dateRange}/`)
.get<NodeAnalyticsResponseJsonApi>(`${baseUrl}/${resourceId}/${dateRange}/`)
.pipe(map((response) => AnalyticsMetricsMapper.fromResponse(response.data)));
}

Expand Down
4 changes: 2 additions & 2 deletions src/app/features/analytics/store/analytics.model.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { AsyncStateModel } from '@osf/shared/models/store';

import { AnalyticsMetricsModel, RelatedCountsModel } from '../models';
import { NodeAnalyticsModel, RelatedCountsModel } from '../models';

export interface AnalyticsStateModel {
metrics: AsyncStateModel<AnalyticsMetricsModel[]>;
metrics: AsyncStateModel<NodeAnalyticsModel[]>;
relatedCounts: AsyncStateModel<RelatedCountsModel[]>;
}

Expand Down
6 changes: 3 additions & 3 deletions src/app/features/analytics/store/analytics.state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { inject, Injectable } from '@angular/core';

import { handleSectionError } from '@osf/shared/helpers';

import { AnalyticsMetricsModel, RelatedCountsModel } from '../models';
import { NodeAnalyticsModel, RelatedCountsModel } from '../models';
import { AnalyticsService } from '../services';

import { ClearAnalytics, GetMetrics, GetRelatedCounts } from './analytics.actions';
Expand Down Expand Up @@ -52,8 +52,8 @@ export class AnalyticsState {
ctx.patchState({
metrics: {
data: exists
? updateItem<AnalyticsMetricsModel>((m) => m.id === metrics.id, metrics)(state.metrics.data)
: insertItem<AnalyticsMetricsModel>(metrics)(state.metrics.data),
? updateItem<NodeAnalyticsModel>((m) => m.id === metrics.id, metrics)(state.metrics.data)
: insertItem<NodeAnalyticsModel>(metrics)(state.metrics.data),
isLoading: false,
error: null,
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,13 @@
<p-skeleton width="12rem" height="2.25rem" />
</div>
} @else {
<div class="flex flex-column gap-3 md:flex-row">
<a
class="flex flex-column gap-3 custom-light-hover dark-blue-link md:flex-row"
[routerLink]="['/preprints', preprintProvider()?.id, 'discover']"
>
<img class="fit-contain" alt="Provider Logo" height="36" [src]="preprintProvider()!.brand.heroLogoImageUrl" />
<h1>{{ preprint()!.title }}</h1>
</div>
</a>
}

@if (moderationMode()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import {
OnInit,
} from '@angular/core';
import { takeUntilDestroyed, toObservable, toSignal } from '@angular/core/rxjs-interop';
import { ActivatedRoute, Router } from '@angular/router';
import { ActivatedRoute, Router, RouterLink } from '@angular/router';

import { ENVIRONMENT } from '@core/provider/environment.provider';
import { HelpScoutService } from '@core/services/help-scout.service';
Expand Down Expand Up @@ -71,6 +71,7 @@ import { PreprintWarningBannerComponent } from '../../components/preprint-detail
PreprintWarningBannerComponent,
ModerationStatusBannerComponent,
MakeDecisionComponent,
RouterLink,
],
templateUrl: './preprint-details.component.html',
styleUrl: './preprint-details.component.scss',
Expand Down
Loading
Loading