MOBILE-4077 ReportBuilder: Create page and module

main
Alfonso Salces 2023-01-31 12:50:45 +01:00
parent 6f869d1453
commit cb2d17af9b
16 changed files with 824 additions and 0 deletions

View File

@ -43,6 +43,7 @@ import { CoreUserModule } from './user/user.module';
import { CoreUserToursModule } from './usertours/user-tours.module'; import { CoreUserToursModule } from './usertours/user-tours.module';
import { CoreViewerModule } from './viewer/viewer.module'; import { CoreViewerModule } from './viewer/viewer.module';
import { CoreXAPIModule } from './xapi/xapi.module'; import { CoreXAPIModule } from './xapi/xapi.module';
import { CoreReportBuilderModule } from './reportbuilder/reportbuilder.module';
@NgModule({ @NgModule({
imports: [ imports: [
@ -74,6 +75,7 @@ import { CoreXAPIModule } from './xapi/xapi.module';
CoreUserToursModule, CoreUserToursModule,
CoreViewerModule, CoreViewerModule,
CoreXAPIModule, CoreXAPIModule,
CoreReportBuilderModule,
// Import last to allow overrides. // Import last to allow overrides.
CoreEmulatorModule, CoreEmulatorModule,

View File

@ -0,0 +1,36 @@
// (C) Copyright 2015 Moodle Pty Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import { NgModule } from '@angular/core';
import { CoreSharedModule } from '@/core/shared.module';
import { CoreReportBuilderReportColumnComponent } from './report-column/report-column';
import { CoreReportBuilderReportDetailComponent } from './report-detail/report-detail';
import { CoreReportBuilderReportSummaryComponent } from './report-summary/report-summary';
@NgModule({
imports: [
CoreSharedModule,
],
declarations: [
CoreReportBuilderReportDetailComponent,
CoreReportBuilderReportColumnComponent,
CoreReportBuilderReportSummaryComponent,
],
exports: [
CoreReportBuilderReportDetailComponent,
CoreReportBuilderReportColumnComponent,
CoreReportBuilderReportSummaryComponent,
],
})
export class CoreReportBuilderComponentsModule {}

View File

@ -0,0 +1,11 @@
<ion-item class="ion-text-wrap" lines="inset" [detail]="false" [button]="isExpandable" [attr.aria-expanded]="isExpanded"
[attr.aria-controls]="'core-report-builder-column-' + rowIndex"
[attr.aria-label]="(isExpanded ? 'core.hidecolumns' : 'core.showcolumns') | translate" (click)="toggleRow()">
<ion-label>
<h3 *ngIf="columnIndex !== 0 || (columnIndex === 0 && showFirstTitle)"> {{ header }} </h3>
<core-format-text [text]="column" contextLevel="site" [contextInstanceId]="contextId"></core-format-text>
</ion-label>
<ion-icon [class.expandable-status-icon-expanded]="!isExpanded" slot="end" aria-hidden="true" name="fas-chevron-up"
class="expandable-status-icon" *ngIf="isExpandable" flip-rtl>
</ion-icon>
</ion-item>

View File

@ -0,0 +1,11 @@
@import "~theme/globals";
:host {
--rotate-expandable: rotate(180deg);
.expandable-status-icon {
font-size: var(--text-size);
@include margin-horizontal(0, 2px);
@include core-transition(transform, 200ms);
}
}

View File

@ -0,0 +1,41 @@
// (C) Copyright 2015 Moodle Pty Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import { Component, EventEmitter, Input, Output } from '@angular/core';
@Component({
selector: 'core-report-builder-report-column',
templateUrl: './report-column.html',
styleUrls: ['./report-column.scss'],
})
export class CoreReportBuilderReportColumnComponent {
@Input() isExpanded = false;
@Input() isExpandable = false;
@Input() showFirstTitle = false;
@Input() columnIndex!: number;
@Input() rowIndex!: number;
@Input() column!: string;
@Input() contextId!: number;
@Input() header!: string;
@Output() onToggleRow: EventEmitter<number> = new EventEmitter();
/**
* Emits row click
*/
toggleRow(): void {
this.onToggleRow.emit(this.rowIndex);
}
}

View File

@ -0,0 +1,60 @@
<ng-container *ngIf="state$ | async as state">
<core-loading [hideUntil]="state.loaded">
<ng-container *ngIf="state.report?.data?.rows && state.report?.data?.headers && state.report?.details; else empty">
<ion-refresher slot="fixed" [disabled]="!state.loaded" (ionRefresh)="refreshReport($event.target)">
<ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content>
</ion-refresher>
<ng-container *ngIf="isCardLayout">
<ion-card *ngFor="let row of state.report.data.rows; let rowIndex = index">
<ion-list class="ion-text-wrap">
<core-report-builder-report-column *ngFor="let column of row.columns | slice:0:row.isExpanded ?
row.columns.length : state.cardVisibleColumns; let columnIndex = index" [columnIndex]="columnIndex"
[rowIndex]="rowIndex" [isExpandable]="columnIndex === 0 && row.columns.length > state.cardVisibleColumns"
[isExpanded]="row.isExpanded" [showFirstTitle]="state.cardviewShowFirstTitle"
[contextId]="state.report.details.contextid" [header]="state.report.data.headers[columnIndex]" [column]="column"
(onToggleRow)="toggleRow(rowIndex)">
</core-report-builder-report-column>
</ion-list>
</ion-card>
</ng-container>
<ng-container *ngIf="!isCardLayout">
<table>
<thead>
<tr>
<th *ngFor="let header of state.report.data.headers">
{{ header }}
</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let row of state.report.data.rows">
<td *ngFor="let column of row.columns">
<core-format-text [text]="column" [contextLevel]="'site'"
[contextInstanceId]="state.report.details.contextid">
</core-format-text>
</td>
</tr>
</tbody>
</table>
</ng-container>
</ng-container>
<ng-template #empty>
<core-empty-box *ngIf="!state.report?.data?.rows || !state.report?.data?.headers || !state.report?.details" icon="fa-list-alt"
[message]="'core.course.nocontentavailable' | translate"></core-empty-box>
</ng-template>
<core-infinite-loading *ngIf="!isBlock && state.report?.data?.rows && state.report?.data?.headers && state.report?.details"
[enabled]="state.canLoadMoreRows" (action)="fetchMoreInfo($event)" [error]="state.errorLoadingRows">
</core-infinite-loading>
</core-loading>
</ng-container>

View File

@ -0,0 +1,44 @@
@import "~theme/globals";
:host {
--header-background: var(--white);
--border-color: var(--stroke);
.report-title {
ion-item {
width: 100%;
}
}
table {
width: 98%;
margin: 1em auto;
border-collapse: collapse;
color: var(--ion-text-color);
overflow-x: auto;
display: block;
tbody {
display: table;
}
th {
background-color: var(--header-background);
}
tr {
border-bottom: 1px solid var(--border-color);
&:nth-child(even) {
background: var(--light);
}
}
th, td {
@include padding(8px, 8px, 8px, null);
text-align: start;
min-width: 200px;
}
}
}

View File

@ -0,0 +1,201 @@
// (C) Copyright 2015 Moodle Pty Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import { ChangeDetectionStrategy, Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { CoreError } from '@classes/errors/error';
import {
CoreReportBuilder,
CoreReportBuilderReportDetail,
CoreReportBuilderRetrieveReportMapped,
REPORT_ROWS_LIMIT,
} from '@features/reportbuilder/services/reportbuilder';
import { IonRefresher } from '@ionic/angular';
import { CoreNavigator } from '@services/navigator';
import { CoreScreen } from '@services/screen';
import { CoreDomUtils } from '@services/utils/dom';
import { CoreUtils } from '@services/utils/utils';
import { BehaviorSubject } from 'rxjs';
@Component({
selector: 'core-report-builder-report-detail',
templateUrl: './report-detail.html',
styleUrls: ['./report-detail.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class CoreReportBuilderReportDetailComponent implements OnInit {
@Input() reportId!: string;
@Input() isBlock = true;
@Input() perPage?: number;
@Input() layout: 'card' | 'table' | 'adaptative' = 'adaptative';
@Output() onReportLoaded = new EventEmitter<CoreReportBuilderReportDetail>();
get isCardLayout(): boolean {
return this.layout === 'card' || (CoreScreen.isMobile && this.layout === 'adaptative');
}
state$: Readonly<BehaviorSubject<CoreReportBuilderReportDetailState>> = new BehaviorSubject({
report: null,
loaded: false,
canLoadMoreRows: true,
errorLoadingRows: false,
cardviewShowFirstTitle: false,
cardVisibleColumns: 1,
page: 0,
});
/**
* @inheritdoc
*/
async ngOnInit(): Promise<void> {
await this.getReport();
this.updateState({ loaded: true });
}
/**
* Get report data.
*/
async getReport(): Promise<void> {
if (!this.reportId) {
CoreDomUtils.showErrorModal(new CoreError('No report found'));
CoreNavigator.back();
return;
}
const { page } = this.state$.getValue();
const report = await CoreReportBuilder.loadReport(parseInt(this.reportId), page,this.perPage ?? REPORT_ROWS_LIMIT);
if (!report) {
CoreDomUtils.showErrorModal(new CoreError('No report found'));
CoreNavigator.back();
return;
}
await CoreReportBuilder.viewReport(this.reportId);
this.updateState({
report,
cardVisibleColumns: report.details.settingsdata.cardviewVisibleColumns,
cardviewShowFirstTitle: report.details.settingsdata.cardviewShowFirstTitle,
});
this.onReportLoaded.emit(report.details);
}
updateState(state: Partial<CoreReportBuilderReportDetailState>): void {
const previousState = this.state$.getValue();
this.state$.next({ ...previousState, ...state });
}
/**
* Update report data.
*
* @param ionRefresher ionic refresher.
*/
async refreshReport(ionRefresher?: IonRefresher): Promise<void> {
await CoreUtils.ignoreErrors(CoreReportBuilder.invalidateReport());
this.updateState({ page: 0, canLoadMoreRows: false });
await CoreUtils.ignoreErrors(this.getReport());
await ionRefresher?.complete();
this.updateState({ canLoadMoreRows: true });
}
/**
* Increment page of report rows.
*/
protected incrementPage(): void {
const { page } = this.state$.getValue();
this.updateState({ page: page + 1 });
}
/**
* Load a new batch of pages.
*
* @param complete Completion callback.
*/
async fetchMoreInfo(complete: () => void): Promise<void> {
const { canLoadMoreRows, report } = this.state$.getValue();
if (!canLoadMoreRows) {
complete();
return;
}
try {
this.incrementPage();
const { page: currentPage } = this.state$.getValue();
const newReport = await CoreReportBuilder.loadReport(parseInt(this.reportId), currentPage, REPORT_ROWS_LIMIT);
if (!report || !newReport || newReport.data.rows.length === 0) {
this.updateState({ canLoadMoreRows: false });
complete();
return;
}
this.updateState({
report: {
...report,
data: {
...report.data,
rows: [
...report.data.rows,
...newReport.data.rows,
],
},
},
});
} catch (error) {
CoreDomUtils.showErrorModalDefault(error, 'Error loading more reports');
this.updateState({ canLoadMoreRows: false });
this.updateState({ errorLoadingRows: true });
}
complete();
}
/**
* Expand or close card.
*
* @param rowIndex card to expand or close.
*/
toggleRow(rowIndex: number): void {
const { report } = this.state$.getValue();
if (!report?.data?.rows[rowIndex]) {
return;
}
report.data.rows[rowIndex].isExpanded = !report.data.rows[rowIndex].isExpanded;
this.updateState({ report });
}
}
export type CoreReportBuilderReportDetailState = {
report: CoreReportBuilderRetrieveReportMapped | null;
loaded: boolean;
canLoadMoreRows: boolean;
errorLoadingRows: boolean;
cardviewShowFirstTitle: boolean;
cardVisibleColumns: number;
page: number;
};

View File

@ -0,0 +1,39 @@
<ion-header class="no-title">
<ion-toolbar>
<ion-buttons slot="start">
<ion-back-button [text]="'core.back' | translate"></ion-back-button>
</ion-buttons>
<ion-title>
</ion-title>
<ion-buttons slot="end">
<ion-button fill="clear" (click)="closeModal()" [attr.aria-label]="'core.close' | translate">
<ion-icon slot="icon-only" name="fas-times" aria-hidden="true"></ion-icon>
</ion-button>
</ion-buttons>
</ion-toolbar>
</ion-header>
<ion-content>
<div class="list-item-limited-width">
<ion-item class="ion-text-wrap course-name">
<ion-label>
<h1>
<core-format-text [text]="reportDetail.name" contextLevel="report" [contextInstanceId]="reportDetail.id">
</core-format-text>
</h1>
</ion-label>
<ion-button fill="clear" [href]="reportUrl" core-link [showBrowserWarning]="false"
[attr.aria-label]="'core.openinbrowser' | translate" slot="end">
<ion-icon name="fas-external-link-alt" slot="icon-only" aria-hidden="true"></ion-icon>
</ion-button>
</ion-item>
<ion-item class="ion-text-wrap" [detail]="false" *ngFor="let item of reportDetailToDisplay">
<ion-label>
<p>{{ item.title | translate }}</p>
<core-format-text [text]="item.text" contextLevel="report" [contextInstanceId]="reportDetail.id">
</core-format-text>
</ion-label>
</ion-item>
</div>
</ion-content>

View File

@ -0,0 +1,60 @@
// (C) Copyright 2015 Moodle Pty Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import { ChangeDetectionStrategy, Component, Input, OnInit } from '@angular/core';
import { CoreReportBuilderReportDetail } from '@features/reportbuilder/services/reportbuilder';
import { CoreFormatDatePipe } from '@pipes/format-date';
import { CoreSites } from '@services/sites';
import { ModalController } from '@singletons';
@Component({
selector: 'core-report-builder-report-summary',
templateUrl: './report-summary.html',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class CoreReportBuilderReportSummaryComponent implements OnInit {
@Input() reportDetail!: CoreReportBuilderReportDetail;
reportUrl!: string;
reportDetailToDisplay!: { title: string; text: string }[];
ngOnInit(): void {
const formatDate = new CoreFormatDatePipe();
const site = CoreSites.getRequiredCurrentSite();
this.reportUrl = `${site.getURL()}/reportbuilder/view.php?id=${this.reportDetail.id}`;
this.reportDetailToDisplay = [
{
title: 'core.reportbuilder.reportsource',
text: this.reportDetail.sourcename,
},
{
title: 'core.reportbuilder.timecreated',
text: formatDate.transform(this.reportDetail.timecreated * 1000),
},
{
title: 'addon.mod_data.timemodified',
text: formatDate.transform(this.reportDetail.timemodified * 1000),
},
{
title: 'core.reportbuilder.modifiedby',
text: this.reportDetail.modifiedby.fullname,
},
];
}
closeModal(): void {
ModalController.dismiss();
}
}

View File

@ -0,0 +1,35 @@
<ion-header>
<ion-toolbar>
<ion-buttons slot="start">
<ion-back-button [text]="'core.back' | translate"></ion-back-button>
</ion-buttons>
<ion-title>
<h1>{{ 'core.reportbuilder.reportstab' | translate }}</h1>
</ion-title>
</ion-toolbar>
</ion-header>
<ion-content *ngIf="state$ | async as state">
<ion-refresher slot="fixed" [disabled]="!state.loaded" (ionRefresh)="refreshReports($event.target)">
<ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content>
</ion-refresher>
<core-loading [hideUntil]="state.loaded">
<ion-list *ngIf="reports.items?.length; else empty">
<ion-item [attr.aria-current]="reports.getItemAriaCurrent(report)" [detail]="true" class="ion-text-wrap" [button]="true"
*ngFor="let report of reports.items" (click)="reports.select(report)">
<ion-label>
<h3>{{ report.name }}</h3>
<p>{{ report.sourcename }}</p>
</ion-label>
</ion-item>
</ion-list>
<ng-template #empty>
<core-empty-box *ngIf="!reports.items?.length" icon="fa-list-alt" [message]="'core.course.nocontentavailable' | translate">
</core-empty-box>
</ng-template>
<core-infinite-loading *ngIf="reports.items?.length" [enabled]="reports.loaded && !reports.completed"
(action)="fetchMoreReports($event)" [error]="state.loadMoreError">
</core-infinite-loading>
</core-loading>
</ion-content>

View File

@ -0,0 +1,128 @@
// (C) Copyright 2015 Moodle Pty Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import { AfterViewInit, ChangeDetectionStrategy, Component, OnDestroy } from '@angular/core';
import { CoreListItemsManager } from '@classes/items-management/list-items-manager';
import { CoreRoutedItemsManagerSourcesTracker } from '@classes/items-management/routed-items-manager-sources-tracker';
import { CoreReportBuilderReportsSource } from '@features/reportbuilder/classes/reports-source';
import { CoreReportBuilder, CoreReportBuilderReport, REPORTS_LIST_LIMIT } from '@features/reportbuilder/services/reportbuilder';
import { IonRefresher } from '@ionic/angular';
import { CoreNavigator } from '@services/navigator';
import { CoreDomUtils } from '@services/utils/dom';
import { CoreUtils } from '@services/utils/utils';
import { BehaviorSubject } from 'rxjs';
@Component({
selector: 'core-report-builder-list',
templateUrl: './list.html',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class CoreReportBuilderListPage implements AfterViewInit, OnDestroy {
reports!: CoreListItemsManager<CoreReportBuilderReport, CoreReportBuilderReportsSource>;
state$: Readonly<BehaviorSubject<CoreReportBuilderListState>> = new BehaviorSubject({
page: 1,
perpage: REPORTS_LIST_LIMIT,
loaded: false,
loadMoreError: false,
});
constructor() {
try {
const source = CoreRoutedItemsManagerSourcesTracker.getOrCreateSource(CoreReportBuilderReportsSource, []);
this.reports = new CoreListItemsManager(source, CoreReportBuilderListPage);
} catch (error) {
CoreDomUtils.showErrorModal(error);
CoreNavigator.back();
}
}
/**
* @inheritdoc
*/
async ngAfterViewInit(): Promise<void> {
try {
await this.fetchReports(true);
this.updateState({ loaded: true });
} catch (error) {
CoreDomUtils.showErrorModalDefault(error, 'Error loading reports');
this.reports.reset();
}
}
/**
* Update reports list or loads it.
*
* @param reload is reoading or not.
*/
async fetchReports(reload: boolean): Promise<void> {
reload ? await this.reports.reload() : await this.reports.load();
this.updateState({ loadMoreError: false });
}
/**
* Properties of the state to update.
*
* @param state Object to update.
*/
updateState(state: Partial<CoreReportBuilderListState>): void {
const previousState = this.state$.getValue();
this.state$.next({ ...previousState, ...state });
}
/**
* Load a new batch of Reports.
*
* @param complete Completion callback.
*/
async fetchMoreReports(complete: () => void): Promise<void> {
try {
await this.fetchReports(false);
} catch (error) {
CoreDomUtils.showErrorModalDefault(error, 'Error loading more reports');
this.updateState({ loadMoreError: true });
}
complete();
}
/**
* Refresh reports list.
*
* @param ionRefresher ionRefresher.
*/
async refreshReports(ionRefresher?: IonRefresher): Promise<void> {
await CoreUtils.ignoreErrors(CoreReportBuilder.invalidateReportsList());
await CoreUtils.ignoreErrors(this.fetchReports(true));
await ionRefresher?.complete();
}
/**
* @inheritdoc
*/
ngOnDestroy(): void {
this.reports.destroy();
}
}
type CoreReportBuilderListState = {
page: number;
perpage: number;
loaded: boolean;
loadMoreError: boolean;
};

View File

@ -0,0 +1,21 @@
<ion-header>
<ion-toolbar>
<ion-buttons slot="start">
<ion-back-button [text]="'core.back' | translate"></ion-back-button>
</ion-buttons>
<ion-buttons slot="end">
<ion-button fill="clear" (click)="openInfo()" [attr.aria-label]="'core.close' | translate">
<ion-icon slot="icon-only" name="fas-info-circle" aria-hidden="true"></ion-icon>
</ion-button>
</ion-buttons>
<ion-title *ngIf="reportDetail">
<h1> {{ reportDetail.name }} </h1>
<p class="subheading"> {{ reportDetail.sourcename }} </p>
</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<core-report-builder-report-detail [isBlock]="false" [reportId]="reportId" (onReportLoaded)="loadReportDetail($event)">
</core-report-builder-report-detail>
</ion-content>

View File

@ -0,0 +1,52 @@
// (C) Copyright 2015 Moodle Pty Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import { Component, OnInit } from '@angular/core';
import { CoreReportBuilderReportSummaryComponent } from '@features/reportbuilder/components/report-summary/report-summary';
import { CoreReportBuilderReportDetail } from '@features/reportbuilder/services/reportbuilder';
import { CoreNavigator } from '@services/navigator';
import { CoreDomUtils } from '@services/utils/dom';
@Component({
selector: 'core-report-builder-report',
templateUrl: './report.html',
})
export class CoreReportBuilderReportPage implements OnInit {
reportId!: string;
reportDetail?: CoreReportBuilderReportDetail;
/**
* @inheritdoc
*/
ngOnInit(): void {
this.reportId = CoreNavigator.getRequiredRouteParam('id');
}
/**
* Save the report detail
*
* @param reportDetail it contents the detail of the report.
*/
loadReportDetail(reportDetail: CoreReportBuilderReportDetail): void {
this.reportDetail = reportDetail;
}
openInfo(): void {
CoreDomUtils.openSideModal<void>({
component: CoreReportBuilderReportSummaryComponent,
componentProps: { reportDetail: this.reportDetail },
});
}
}

View File

@ -0,0 +1,44 @@
// (C) Copyright 2015 Moodle Pty Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import { CoreSharedModule } from '@/core/shared.module';
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { CoreReportBuilderComponentsModule } from './components/components.module';
import { CoreReportBuilderListPage } from './pages/list/list';
import { CoreReportBuilderReportPage } from './pages/report/report';
const routes: Routes = [
{
path: '',
component: CoreReportBuilderListPage,
},
{
path: ':id',
component: CoreReportBuilderReportPage,
},
];
@NgModule({
imports: [
CoreSharedModule,
CoreReportBuilderComponentsModule,
RouterModule.forChild(routes),
],
declarations: [
CoreReportBuilderListPage,
CoreReportBuilderReportPage,
],
})
export class CoreReportBuilderLazyModule {}

View File

@ -0,0 +1,39 @@
// (C) Copyright 2015 Moodle Pty Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import { APP_INITIALIZER, NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { CoreUserDelegate } from '@features/user/services/user-delegate';
import { CoreReportBuilderHandler, CoreReportBuilderHandlerService } from './services/handlers/reportbuilder';
const routes: Routes = [
{
path: CoreReportBuilderHandlerService.PAGE_NAME,
loadChildren: () => import('./reportbuilder-lazy.module').then(m => m.CoreReportBuilderLazyModule),
},
];
@NgModule({
imports: [RouterModule.forChild(routes)],
providers: [
{
provide: APP_INITIALIZER,
multi: true,
useValue: () => {
CoreUserDelegate.registerHandler(CoreReportBuilderHandler.instance);
},
},
],
})
export class CoreReportBuilderModule {}