commit
568f161550
|
@ -32,10 +32,11 @@ export abstract class AddonModDataFieldPluginComponent implements OnInit, OnChan
|
|||
@Input() error?: string; // Error when editing.
|
||||
@Input() form?: FormGroup; // Form where to add the form control. Just required for edit and search modes.
|
||||
@Input() searchFields?: CoreFormFields; // The search value of all fields.
|
||||
@Output() gotoEntry: EventEmitter<number>; // Action to perform.
|
||||
@Output() gotoEntry = new EventEmitter<number>(); // Action to perform.
|
||||
// Output called when the field is initialized with a value and it didn't have one already.
|
||||
@Output() onFieldInit = new EventEmitter<AddonModDataEntryFieldInitialized>();
|
||||
|
||||
constructor(protected fb: FormBuilder) {
|
||||
this.gotoEntry = new EventEmitter();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -114,3 +115,11 @@ export abstract class AddonModDataFieldPluginComponent implements OnInit, OnChan
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Data for an initialized field.
|
||||
*/
|
||||
export type AddonModDataEntryFieldInitialized = Partial<AddonModDataEntryField> & {
|
||||
fieldid: number;
|
||||
content: string;
|
||||
};
|
||||
|
|
|
@ -16,6 +16,7 @@ import { Component, OnInit, OnChanges, ViewChild, Input, Output, SimpleChange, T
|
|||
import { FormGroup } from '@angular/forms';
|
||||
import { CoreDynamicComponent } from '@components/dynamic-component/dynamic-component';
|
||||
import { CoreFormFields } from '@singletons/form';
|
||||
import { AddonModDataEntryFieldInitialized } from '../../classes/field-plugin-component';
|
||||
import { AddonModDataData, AddonModDataField, AddonModDataTemplateMode } from '../../services/data';
|
||||
import { AddonModDataFieldsDelegate } from '../../services/data-fields-delegate';
|
||||
|
||||
|
@ -37,7 +38,9 @@ export class AddonModDataFieldPluginComponent implements OnInit, OnChanges {
|
|||
@Input() error?: string; // Error when editing.
|
||||
@Input() form?: FormGroup; // Form where to add the form control. Just required for edit and search modes.
|
||||
@Input() searchFields?: CoreFormFields; // The search value of all fields.
|
||||
@Output() gotoEntry = new EventEmitter(); // Action to perform.
|
||||
@Output() gotoEntry = new EventEmitter<number>(); // Action to perform.
|
||||
// Output called when the field is initialized with a value and it didn't have one already.
|
||||
@Output() onFieldInit = new EventEmitter<AddonModDataEntryFieldInitialized>();
|
||||
|
||||
fieldComponent?: Type<unknown>; // Component to render the plugin.
|
||||
pluginData?: AddonDataFieldPluginComponentData; // Data to pass to the component.
|
||||
|
@ -65,9 +68,10 @@ export class AddonModDataFieldPluginComponent implements OnInit, OnChanges {
|
|||
value: this.value,
|
||||
database: this.database,
|
||||
error: this.error,
|
||||
gotoEntry: this.gotoEntry,
|
||||
form: this.form,
|
||||
searchFields: this.searchFields,
|
||||
gotoEntry: this.gotoEntry,
|
||||
onFieldInit: this.onFieldInit,
|
||||
};
|
||||
}
|
||||
} finally {
|
||||
|
@ -99,5 +103,6 @@ export type AddonDataFieldPluginComponentData = {
|
|||
error?: string; // Error when editing.
|
||||
form?: FormGroup; // Form where to add the form control. Just required for edit and search modes.
|
||||
searchFields?: CoreFormFields; // The search value of all fields.
|
||||
gotoEntry: EventEmitter<unknown>;
|
||||
gotoEntry: EventEmitter<number>;
|
||||
onFieldInit: EventEmitter<AddonModDataEntryFieldInitialized>;
|
||||
};
|
||||
|
|
|
@ -68,7 +68,16 @@ export class AddonModDataFieldDateComponent extends AddonModDataFieldPluginCompo
|
|||
|
||||
}
|
||||
|
||||
this.addControl('f_' + this.field.id, CoreTimeUtils.toDatetimeFormat(date.getTime()));
|
||||
const seconds = Math.floor(date.getTime() / 1000);
|
||||
|
||||
this.addControl('f_' + this.field.id, CoreTimeUtils.toDatetimeFormat(seconds * 1000));
|
||||
|
||||
if (!this.searchMode && !this.value?.content) {
|
||||
this.onFieldInit.emit({
|
||||
fieldid: this.field.id,
|
||||
content: String(seconds),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@ import {
|
|||
} from '../../services/data';
|
||||
import { AddonModDataHelper } from '../../services/data-helper';
|
||||
import { CoreDom } from '@singletons/dom';
|
||||
import { AddonModDataEntryFieldInitialized } from '../../classes/field-plugin-component';
|
||||
|
||||
/**
|
||||
* Page that displays the view edit page.
|
||||
|
@ -62,6 +63,7 @@ export class AddonModDataEditPage implements OnInit {
|
|||
protected forceLeave = false; // To allow leaving the page without checking for changes.
|
||||
protected initialSelectedGroup?: number;
|
||||
protected isEditing = false;
|
||||
protected originalData: AddonModDataEntryFields = {};
|
||||
|
||||
entry?: AddonModDataEntry;
|
||||
fields: Record<number, AddonModDataField> = {};
|
||||
|
@ -83,6 +85,7 @@ export class AddonModDataEditPage implements OnInit {
|
|||
contents: AddonModDataEntryFields;
|
||||
errors?: Record<number, string>;
|
||||
form: FormGroup;
|
||||
onFieldInit: (data: AddonModDataEntryFieldInitialized) => void;
|
||||
};
|
||||
|
||||
errors: Record<number, string> = {};
|
||||
|
@ -128,7 +131,7 @@ export class AddonModDataEditPage implements OnInit {
|
|||
|
||||
const inputData = this.editForm.value;
|
||||
|
||||
let changed = AddonModDataHelper.hasEditDataChanged(inputData, this.fieldsArray, this.entry.contents);
|
||||
let changed = AddonModDataHelper.hasEditDataChanged(inputData, this.fieldsArray, this.originalData);
|
||||
changed = changed || (!this.isEditing && this.initialSelectedGroup != this.selectedGroup);
|
||||
|
||||
if (changed) {
|
||||
|
@ -162,6 +165,7 @@ export class AddonModDataEditPage implements OnInit {
|
|||
|
||||
const entry = await AddonModDataHelper.fetchEntry(this.database, this.fieldsArray, this.entryId || 0);
|
||||
this.entry = entry.entry;
|
||||
this.originalData = CoreUtils.clone(this.entry.contents);
|
||||
|
||||
if (this.entryId) {
|
||||
// Load correct group.
|
||||
|
@ -401,6 +405,7 @@ export class AddonModDataEditPage implements OnInit {
|
|||
form: this.editForm,
|
||||
database: this.database,
|
||||
errors: this.errors,
|
||||
onFieldInit: this.onFieldInit.bind(this),
|
||||
};
|
||||
|
||||
let template = AddonModDataHelper.getTemplate(this.database!, AddonModDataTemplateType.ADD, this.fieldsArray);
|
||||
|
@ -414,7 +419,7 @@ export class AddonModDataEditPage implements OnInit {
|
|||
// Replace field by a generic directive.
|
||||
const render = '<addon-mod-data-field-plugin [class.has-errors]="!!errors[' + field.id + ']" mode="edit" \
|
||||
[field]="fields[' + field.id + ']" [value]="contents[' + field.id + ']" [form]="form" [database]="database" \
|
||||
[error]="errors[' + field.id + ']"></addon-mod-data-field-plugin>';
|
||||
[error]="errors[' + field.id + ']" (onFieldInit)="onFieldInit($event)"></addon-mod-data-field-plugin>';
|
||||
template = template.replace(replaceRegEx, render);
|
||||
|
||||
// Replace the field id tag.
|
||||
|
@ -435,6 +440,27 @@ export class AddonModDataEditPage implements OnInit {
|
|||
return template;
|
||||
}
|
||||
|
||||
/**
|
||||
* A certain value has been initialized.
|
||||
*
|
||||
* @param data Data.
|
||||
*/
|
||||
onFieldInit(data: AddonModDataEntryFieldInitialized): void {
|
||||
if (!this.originalData[data.fieldid]) {
|
||||
this.originalData[data.fieldid] = {
|
||||
id: 0,
|
||||
recordid: this.entry?.id ?? 0,
|
||||
fieldid: data.fieldid,
|
||||
content: data.content,
|
||||
content1: data.content1 ?? null,
|
||||
content2: data.content2 ?? null,
|
||||
content3: data.content3 ?? null,
|
||||
content4: data.content4 ?? null,
|
||||
files: data.files ?? [],
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return to the entry list (previous page) discarding temp data.
|
||||
*
|
||||
|
|
|
@ -212,7 +212,7 @@ export class AddonModDataEntryPage implements OnInit, OnDestroy {
|
|||
this.logAfterFetch = false;
|
||||
await CoreUtils.ignoreErrors(AddonModData.logView(this.database.id, this.database.name));
|
||||
|
||||
// Store module viewed. It's done in this page because it can be reached using a link.
|
||||
// Store module viewed because this page also updates recent accessed items block.
|
||||
CoreCourse.storeModuleViewed(this.courseId, this.moduleId);
|
||||
}
|
||||
} catch (error) {
|
||||
|
|
|
@ -213,8 +213,8 @@ export class AddonModDataHelperProvider {
|
|||
|
||||
// Replace field by a generic directive.
|
||||
const render = '<addon-mod-data-field-plugin [field]="fields[' + field.id + ']" [value]="entries[' + entry.id +
|
||||
'].contents[' + field.id + ']" mode="' + mode + '" [database]="database" (gotoEntry)="gotoEntry(' + entry.id +
|
||||
')"></addon-mod-data-field-plugin>';
|
||||
'].contents[' + field.id + ']" mode="' + mode + '" [database]="database" (gotoEntry)="gotoEntry($event)">' +
|
||||
'</addon-mod-data-field-plugin>';
|
||||
template = template.replace(replaceRegex, render);
|
||||
});
|
||||
|
||||
|
|
|
@ -1134,10 +1134,10 @@ export type AddonModDataEntryField = {
|
|||
fieldid: number; // The field type of the content.
|
||||
recordid: number; // The record this content belongs to.
|
||||
content: string; // Contents.
|
||||
content1: string; // Contents.
|
||||
content2: string; // Contents.
|
||||
content3: string; // Contents.
|
||||
content4: string; // Contents.
|
||||
content1: string | null; // Contents.
|
||||
content2: string | null; // Contents.
|
||||
content3: string | null; // Contents.
|
||||
content4: string | null; // Contents.
|
||||
files: CoreFileEntry[];
|
||||
};
|
||||
|
||||
|
|
|
@ -16,7 +16,6 @@ import { Component, OnDestroy, OnInit } from '@angular/core';
|
|||
import { ActivatedRouteSnapshot } from '@angular/router';
|
||||
import { CoreRoutedItemsManagerSourcesTracker } from '@classes/items-management/routed-items-manager-sources-tracker';
|
||||
import { CoreSwipeNavigationItemsManager } from '@classes/items-management/swipe-navigation-items-manager';
|
||||
import { CoreCourse } from '@features/course/services/course';
|
||||
import { CoreNavigator } from '@services/navigator';
|
||||
import { CoreDomUtils } from '@services/utils/dom';
|
||||
import { CoreTextUtils } from '@services/utils/text';
|
||||
|
@ -50,7 +49,6 @@ export class AddonModFeedbackAttemptPage implements OnInit, OnDestroy {
|
|||
loaded = false;
|
||||
|
||||
protected attemptId: number;
|
||||
protected fetchSuccess = false;
|
||||
|
||||
constructor() {
|
||||
this.cmId = CoreNavigator.getRequiredRouteNumberParam('cmId');
|
||||
|
@ -132,12 +130,6 @@ export class AddonModFeedbackAttemptPage implements OnInit, OnDestroy {
|
|||
|
||||
return attemptItem;
|
||||
}).filter((itemData) => itemData); // Filter items with errors.
|
||||
|
||||
if (!this.fetchSuccess) {
|
||||
this.fetchSuccess = true;
|
||||
// Store module viewed. It's done in this page because it can be reached using a link.
|
||||
CoreCourse.storeModuleViewed(this.courseId, this.cmId);
|
||||
}
|
||||
} catch (message) {
|
||||
// Some call failed on fetch, go back.
|
||||
CoreDomUtils.showErrorModalDefault(message, 'core.course.errorgetmodule', true);
|
||||
|
|
|
@ -25,7 +25,6 @@ import { CoreDomUtils } from '@services/utils/dom';
|
|||
import { CoreUtils } from '@services/utils/utils';
|
||||
import { AddonModFeedbackAttemptItem, AddonModFeedbackAttemptsSource } from '../../classes/feedback-attempts-source';
|
||||
import { AddonModFeedbackWSAnonAttempt, AddonModFeedbackWSAttempt } from '../../services/feedback';
|
||||
import { CoreCourse } from '@features/course/services/course';
|
||||
|
||||
/**
|
||||
* Page that displays feedback attempts.
|
||||
|
@ -187,13 +186,4 @@ export class AddonModFeedbackAttemptsPage implements AfterViewInit, OnDestroy {
|
|||
* Attempts manager.
|
||||
*/
|
||||
class AddonModFeedbackAttemptsManager extends CoreListItemsManager<AddonModFeedbackAttemptItem, AddonModFeedbackAttemptsSource> {
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
protected async logActivity(): Promise<void> {
|
||||
// Store module viewed. It's done in this page because it can be reached using a link.
|
||||
CoreCourse.storeModuleViewed(this.getSource().COURSE_ID, this.getSource().CM_ID);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
// limitations under the License.
|
||||
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { CoreCourse } from '@features/course/services/course';
|
||||
import { IonRefresher } from '@ionic/angular';
|
||||
import { CoreGroupInfo, CoreGroups } from '@services/groups';
|
||||
import { CoreNavigator } from '@services/navigator';
|
||||
|
@ -35,7 +34,6 @@ export class AddonModFeedbackNonRespondentsPage implements OnInit {
|
|||
protected courseId!: number;
|
||||
protected feedback?: AddonModFeedbackWSFeedback;
|
||||
protected page = 0;
|
||||
protected fetchSuccess = false;
|
||||
|
||||
selectedGroup!: number;
|
||||
groupInfo?: CoreGroupInfo;
|
||||
|
@ -83,12 +81,6 @@ export class AddonModFeedbackNonRespondentsPage implements OnInit {
|
|||
this.selectedGroup = CoreGroups.validateGroupId(this.selectedGroup, this.groupInfo);
|
||||
|
||||
await this.loadGroupUsers(this.selectedGroup);
|
||||
|
||||
if (!this.fetchSuccess) {
|
||||
this.fetchSuccess = true;
|
||||
// Store module viewed. It's done in this page because it can be reached using a link.
|
||||
CoreCourse.storeModuleViewed(this.courseId, this.cmId);
|
||||
}
|
||||
} catch (message) {
|
||||
CoreDomUtils.showErrorModalDefault(message, 'core.course.errorgetmodule', true);
|
||||
|
||||
|
|
|
@ -17,7 +17,6 @@ import { Component, OnDestroy, ViewChild, OnInit, AfterViewInit, ElementRef, Opt
|
|||
import { ActivatedRoute, ActivatedRouteSnapshot } from '@angular/router';
|
||||
import { CoreRoutedItemsManagerSourcesTracker } from '@classes/items-management/routed-items-manager-sources-tracker';
|
||||
import { CoreSplitViewComponent } from '@components/split-view/split-view';
|
||||
import { CoreCourse } from '@features/course/services/course';
|
||||
import { CoreFileUploader } from '@features/fileuploader/services/fileuploader';
|
||||
import { CoreRatingInfo, CoreRatingProvider } from '@features/rating/services/rating';
|
||||
import { CoreRatingOffline } from '@features/rating/services/rating-offline';
|
||||
|
@ -120,7 +119,6 @@ export class AddonModForumDiscussionPage implements OnInit, AfterViewInit, OnDes
|
|||
protected ratingOfflineObserver?: CoreEventObserver;
|
||||
protected ratingSyncObserver?: CoreEventObserver;
|
||||
protected changeDiscObserver?: CoreEventObserver;
|
||||
protected fetchSuccess = false;
|
||||
|
||||
constructor(
|
||||
@Optional() protected splitView: CoreSplitViewComponent,
|
||||
|
@ -547,12 +545,6 @@ export class AddonModForumDiscussionPage implements OnInit, AfterViewInit, OnDes
|
|||
|
||||
this.hasOfflineRatings =
|
||||
await CoreRatingOffline.hasRatings('mod_forum', 'post', ContextLevel.MODULE, this.cmId, this.discussionId);
|
||||
|
||||
if (!this.fetchSuccess) {
|
||||
this.fetchSuccess = true;
|
||||
// Store module viewed. It's done in this page because it can be reached using a link.
|
||||
this.courseId && this.cmId && CoreCourse.storeModuleViewed(this.courseId, this.cmId);
|
||||
}
|
||||
} catch (error) {
|
||||
CoreDomUtils.showErrorModal(error);
|
||||
} finally {
|
||||
|
|
|
@ -17,7 +17,6 @@ import { ActivatedRoute, ActivatedRouteSnapshot } from '@angular/router';
|
|||
import { CoreRoutedItemsManagerSourcesTracker } from '@classes/items-management/routed-items-manager-sources-tracker';
|
||||
import { CoreCommentsCommentsComponent } from '@features/comments/components/comments/comments';
|
||||
import { CoreComments } from '@features/comments/services/comments';
|
||||
import { CoreCourse } from '@features/course/services/course';
|
||||
import { CoreRatingInfo } from '@features/rating/services/rating';
|
||||
import { CoreTag } from '@features/tag/services/tag';
|
||||
import { IonRefresher } from '@ionic/angular';
|
||||
|
@ -59,7 +58,6 @@ export class AddonModGlossaryEntryPage implements OnInit, OnDestroy {
|
|||
cmId?: number;
|
||||
|
||||
protected entryId!: number;
|
||||
protected fetchSuccess = false;
|
||||
|
||||
constructor(protected route: ActivatedRoute) {}
|
||||
|
||||
|
@ -148,12 +146,6 @@ export class AddonModGlossaryEntryPage implements OnInit, OnDestroy {
|
|||
this.entry = result.entry;
|
||||
this.ratingInfo = result.ratinginfo;
|
||||
|
||||
if (!this.fetchSuccess) {
|
||||
this.fetchSuccess = true;
|
||||
// Store module viewed. It's done in this page because it can be reached using a link.
|
||||
this.cmId && CoreCourse.storeModuleViewed(this.courseId, this.cmId);
|
||||
}
|
||||
|
||||
if (this.glossary) {
|
||||
// Glossary already loaded, nothing else to load.
|
||||
return;
|
||||
|
|
|
@ -25,7 +25,6 @@ import {
|
|||
AddonModH5PActivityData,
|
||||
AddonModH5PActivityAttemptResults,
|
||||
} from '../../services/h5pactivity';
|
||||
import { CoreCourse } from '@features/course/services/course';
|
||||
|
||||
/**
|
||||
* Page that displays results of an attempt.
|
||||
|
@ -100,9 +99,6 @@ export class AddonModH5PActivityAttemptResultsPage implements OnInit {
|
|||
this.h5pActivity.name,
|
||||
{ attemptId: this.attemptId },
|
||||
));
|
||||
|
||||
// Store module viewed. It's done in this page because it can be reached using a link.
|
||||
CoreCourse.storeModuleViewed(this.courseId, this.cmId);
|
||||
}
|
||||
} catch (error) {
|
||||
CoreDomUtils.showErrorModalDefault(error, 'Error loading attempt.');
|
||||
|
|
|
@ -26,7 +26,6 @@ import {
|
|||
AddonModH5PActivityData,
|
||||
AddonModH5PActivityUserAttempts,
|
||||
} from '../../services/h5pactivity';
|
||||
import { CoreCourse } from '@features/course/services/course';
|
||||
|
||||
/**
|
||||
* Page that displays user attempts of a certain user.
|
||||
|
@ -102,9 +101,6 @@ export class AddonModH5PActivityUserAttemptsPage implements OnInit {
|
|||
this.h5pActivity.name,
|
||||
{ userId: this.userId },
|
||||
));
|
||||
|
||||
// Store module viewed. It's done in this page because it can be reached using a link.
|
||||
CoreCourse.storeModuleViewed(this.courseId, this.cmId);
|
||||
}
|
||||
} catch (error) {
|
||||
CoreDomUtils.showErrorModalDefault(error, 'Error loading attempts.');
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
// limitations under the License.
|
||||
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { CoreCourse } from '@features/course/services/course';
|
||||
import { CoreUser, CoreUserProfile } from '@features/user/services/user';
|
||||
import { IonRefresher } from '@ionic/angular';
|
||||
|
||||
|
@ -93,9 +92,6 @@ export class AddonModH5PActivityUsersAttemptsPage implements OnInit {
|
|||
if (!this.fetchSuccess) {
|
||||
this.fetchSuccess = true;
|
||||
CoreUtils.ignoreErrors(AddonModH5PActivity.logViewReport(this.h5pActivity.id, this.h5pActivity.name));
|
||||
|
||||
// Store module viewed. It's done in this page because it can be reached using a link.
|
||||
CoreCourse.storeModuleViewed(this.courseId, this.cmId);
|
||||
}
|
||||
} catch (error) {
|
||||
CoreDomUtils.showErrorModalDefault(error, 'Error loading attempts.');
|
||||
|
|
|
@ -34,7 +34,6 @@ import {
|
|||
AddonModLessonUserAttemptAnswerPageWSData,
|
||||
} from '../../services/lesson';
|
||||
import { AddonModLessonAnswerData, AddonModLessonHelper } from '../../services/lesson-helper';
|
||||
import { CoreCourse } from '@features/course/services/course';
|
||||
import { CoreTime } from '@singletons/time';
|
||||
|
||||
/**
|
||||
|
@ -60,7 +59,6 @@ export class AddonModLessonUserRetakePage implements OnInit {
|
|||
protected userId?: number; // User ID to see the retakes.
|
||||
protected retakeNumber?: number; // Number of the initial retake to see.
|
||||
protected previousSelectedRetake?: number; // To be able to detect the previous selected retake when it has changed.
|
||||
protected fetchSuccess = false;
|
||||
|
||||
/**
|
||||
* Component being initialized.
|
||||
|
@ -162,12 +160,6 @@ export class AddonModLessonUserRetakePage implements OnInit {
|
|||
this.student.profileimageurl = user?.profileimageurl;
|
||||
|
||||
await this.setRetake(this.selectedRetake);
|
||||
|
||||
if (!this.fetchSuccess) {
|
||||
this.fetchSuccess = true;
|
||||
// Store module viewed. It's done in this page because it can be reached using a link.
|
||||
CoreCourse.storeModuleViewed(this.courseId, this.cmId);
|
||||
}
|
||||
} catch (error) {
|
||||
CoreDomUtils.showErrorModalDefault(error, 'Error getting data.', true);
|
||||
}
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
// limitations under the License.
|
||||
|
||||
import { Component, ElementRef, OnInit, ViewChild } from '@angular/core';
|
||||
import { CoreCourse } from '@features/course/services/course';
|
||||
import { CoreQuestionQuestionParsed } from '@features/question/services/question';
|
||||
import { CoreQuestionHelper } from '@features/question/services/question-helper';
|
||||
import { IonContent, IonRefresher } from '@ionic/angular';
|
||||
|
@ -162,9 +161,6 @@ export class AddonModQuizReviewPage implements OnInit {
|
|||
CoreUtils.ignoreErrors(
|
||||
AddonModQuiz.logViewAttemptReview(this.attemptId, this.quiz.id, this.quiz.name),
|
||||
);
|
||||
|
||||
// Store module viewed. It's done in this page because it can be reached using a link.
|
||||
CoreCourse.storeModuleViewed(this.courseId, this.cmId);
|
||||
}
|
||||
} catch (error) {
|
||||
CoreDomUtils.showErrorModalDefault(error, 'addon.mod_quiz.errorgetquiz', true);
|
||||
|
|
|
@ -447,6 +447,16 @@ export class AddonModWikiIndexComponent extends CoreCourseModuleMainActivityComp
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
protected async storeModuleViewed(): Promise<void> {
|
||||
// Only store module viewed when viewing the main page.
|
||||
if (!this.pageId) {
|
||||
await super.storeModuleViewed();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get path to the wiki home view. If cannot determine or it's current view, return undefined.
|
||||
*
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
<core-context-menu-item [hidden]="!(commentsLoaded && !hasOffline)" [priority]="100" [content]="'core.refresh' | translate"
|
||||
(action)="refreshComments(false)" [iconAction]="refreshIcon" [closeOnClick]="true">
|
||||
</core-context-menu-item>
|
||||
<core-context-menu-item [hidden]="!(commentsLoaded && hasOffline)" [priority]="100"
|
||||
<core-context-menu-item [hidden]="!(commentsLoaded && hasOffline && isOnline)" [priority]="100"
|
||||
[content]="'core.settings.synchronizenow' | translate" (action)="refreshComments(true)" [iconAction]="syncIcon"
|
||||
[closeOnClick]="false">
|
||||
</core-context-menu-item>
|
||||
|
@ -31,7 +31,7 @@
|
|||
<ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content>
|
||||
</ion-refresher>
|
||||
<core-loading [hideUntil]="commentsLoaded">
|
||||
<core-empty-box *ngIf="!comments || !comments.length" icon="fas-comments" [message]="'core.comments.nocomments' | translate">
|
||||
<core-empty-box *ngIf="!comments?.length && !offlineComment" icon="fas-comments" [message]="'core.comments.nocomments' | translate">
|
||||
</core-empty-box>
|
||||
|
||||
<!-- Load previous messages. -->
|
||||
|
|
|
@ -30,7 +30,7 @@ import {
|
|||
import { IonContent, IonRefresher } from '@ionic/angular';
|
||||
import { ContextLevel, CoreConstants } from '@/core/constants';
|
||||
import { CoreNavigator } from '@services/navigator';
|
||||
import { Translate } from '@singletons';
|
||||
import { Network, NgZone, Translate } from '@singletons';
|
||||
import { CoreUtils } from '@services/utils/utils';
|
||||
import { CoreDomUtils } from '@services/utils/dom';
|
||||
import { CoreUser } from '@features/user/services/user';
|
||||
|
@ -41,6 +41,7 @@ import { CoreCommentsDBRecord } from '@features/comments/services/database/comme
|
|||
import { CoreTimeUtils } from '@services/utils/time';
|
||||
import { CoreApp } from '@services/app';
|
||||
import moment from 'moment';
|
||||
import { Subscription } from 'rxjs';
|
||||
|
||||
/**
|
||||
* Page that displays comments.
|
||||
|
@ -77,9 +78,11 @@ export class CoreCommentsViewerPage implements OnInit, OnDestroy {
|
|||
currentUserId: number;
|
||||
sending = false;
|
||||
newComment = '';
|
||||
isOnline: boolean;
|
||||
|
||||
protected addDeleteCommentsAvailable = false;
|
||||
protected syncObserver?: CoreEventObserver;
|
||||
protected onlineObserver: Subscription;
|
||||
protected viewDestroyed = false;
|
||||
|
||||
constructor(
|
||||
|
@ -104,6 +107,14 @@ export class CoreCommentsViewerPage implements OnInit, OnDestroy {
|
|||
this.fetchComments(false);
|
||||
}
|
||||
}, CoreSites.getCurrentSiteId());
|
||||
|
||||
this.isOnline = CoreApp.isOnline();
|
||||
this.onlineObserver = Network.onChange().subscribe(() => {
|
||||
// Execute the callback in the Angular zone, so change detection doesn't stop working.
|
||||
NgZone.run(() => {
|
||||
this.isOnline = CoreApp.isOnline();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -596,6 +607,7 @@ export class CoreCommentsViewerPage implements OnInit, OnDestroy {
|
|||
*/
|
||||
ngOnDestroy(): void {
|
||||
this.syncObserver?.off();
|
||||
this.onlineObserver.unsubscribe();
|
||||
this.viewDestroyed = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -442,7 +442,7 @@ export class CoreCourseModuleMainResourceComponent implements OnInit, OnDestroy,
|
|||
}
|
||||
|
||||
this.fetchSuccess = true;
|
||||
CoreCourse.storeModuleViewed(this.courseId, this.module.id, { sectionId: this.module.section });
|
||||
this.storeModuleViewed();
|
||||
|
||||
// Log activity now.
|
||||
try {
|
||||
|
@ -456,6 +456,15 @@ export class CoreCourseModuleMainResourceComponent implements OnInit, OnDestroy,
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Store module as viewed.
|
||||
*
|
||||
* @return Promise resolved when done.
|
||||
*/
|
||||
protected async storeModuleViewed(): Promise<void> {
|
||||
await CoreCourse.storeModuleViewed(this.courseId, this.module.id, { sectionId: this.module.section });
|
||||
}
|
||||
|
||||
/**
|
||||
* Log activity.
|
||||
*
|
||||
|
|
|
@ -79,12 +79,15 @@ export class CoreMainMenuUserMenuComponent implements OnInit, OnDestroy {
|
|||
return;
|
||||
}
|
||||
|
||||
this.handlers = [];
|
||||
handlers.forEach((handler) => {
|
||||
if (handler.type == CoreUserDelegateService.TYPE_NEW_PAGE) {
|
||||
this.handlers.push(handler.data);
|
||||
}
|
||||
});
|
||||
const newHandlers = handlers
|
||||
.filter((handler) => handler.type === CoreUserDelegateService.TYPE_NEW_PAGE)
|
||||
.map((handler) => handler.data);
|
||||
|
||||
// Only update handlers if they have changed, to prevent a blink effect.
|
||||
if (newHandlers.length !== this.handlers.length ||
|
||||
JSON.stringify(newHandlers) !== JSON.stringify(this.handlers)) {
|
||||
this.handlers = newHandlers;
|
||||
}
|
||||
|
||||
this.handlersLoaded = CoreUserDelegate.areHandlersLoaded(this.user.id, CoreUserDelegateContext.USER_MENU);
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue