MOBILE-3656 wiki: Migrate services
parent
a9df9c6411
commit
0dee685130
|
@ -18,6 +18,7 @@ import { CoreCourseCommonModWSOptions } from '@features/course/services/course';
|
|||
import { CoreCourseLogHelper } from '@features/course/services/log-helper';
|
||||
import { CoreFileEntry } from '@features/fileuploader/services/fileuploader';
|
||||
import { CoreRatingInfo } from '@features/rating/services/rating';
|
||||
import { CoreTagItem } from '@features/tag/services/tag';
|
||||
import { CoreUser } from '@features/user/services/user';
|
||||
import { CoreApp } from '@services/app';
|
||||
import { CoreFilepool } from '@services/filepool';
|
||||
|
@ -1513,18 +1514,7 @@ export type AddonModForumLegacyPost = {
|
|||
userpictureurl?: string; // Post author picture.
|
||||
deleted: boolean; // This post has been removed.
|
||||
isprivatereply: boolean; // The post is a private reply.
|
||||
tags?: { // Tags.
|
||||
id: number; // Tag id.
|
||||
name: string; // Tag name.
|
||||
rawname: string; // The raw, unnormalised name for the tag as entered by users.
|
||||
isstandard: boolean; // Whether this tag is standard.
|
||||
tagcollid: number; // Tag collection id.
|
||||
taginstanceid: number; // Tag instance id.
|
||||
taginstancecontextid: number; // Context the tag instance belongs to.
|
||||
itemid: number; // Id of the record tagged.
|
||||
ordering: number; // Tag ordering.
|
||||
flag: number; // Whether the tag is flagged as inappropriate.
|
||||
}[];
|
||||
tags?: CoreTagItem[]; // Tags.
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -31,6 +31,7 @@ import { AddonModH5PActivityModule } from './h5pactivity/h5pactivity.module';
|
|||
import { AddonModSurveyModule } from './survey/survey.module';
|
||||
import { AddonModScormModule } from './scorm/scorm.module';
|
||||
import { AddonModChoiceModule } from './choice/choice.module';
|
||||
import { AddonModWikiModule } from './wiki/wiki.module';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
|
@ -51,6 +52,7 @@ import { AddonModChoiceModule } from './choice/choice.module';
|
|||
AddonModSurveyModule,
|
||||
AddonModScormModule,
|
||||
AddonModChoiceModule,
|
||||
AddonModWikiModule,
|
||||
],
|
||||
})
|
||||
export class AddonModModule { }
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"cannoteditpage": "You can not edit this page.",
|
||||
"createpage": "Create page",
|
||||
"editingpage": "Editing this page '{{$a}}'",
|
||||
"errorloadingpage": "An error occurred while loading the page.",
|
||||
"errornowikiavailable": "This wiki does not have any content yet.",
|
||||
"gowikihome": "Go to the wiki first page",
|
||||
"map": "Map",
|
||||
"modulenameplural": "Wikis",
|
||||
"newpagehdr": "New page",
|
||||
"newpagetitle": "New page title",
|
||||
"nocontent": "There is no content for this page",
|
||||
"notingroup": "Not in group",
|
||||
"pageexists": "This page already exists.",
|
||||
"pagename": "Page name",
|
||||
"subwiki": "Sub-wiki",
|
||||
"tagarea_wiki_pages": "Wiki pages",
|
||||
"titleshouldnotbeempty": "The title should not be empty",
|
||||
"viewpage": "View page",
|
||||
"wikipage": "Wiki page",
|
||||
"wrongversionlock": "Another user has edited this page while you were editing and your content is obsolete."
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
// (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 { CoreSiteSchema } from '@services/sites';
|
||||
|
||||
/**
|
||||
* Database variables for AddonModWikiOfflineProvider.
|
||||
*/
|
||||
export const NEW_PAGES_TABLE_NAME = 'addon_mod_wiki_new_pages_store';
|
||||
export const OFFLINE_SITE_SCHEMA: CoreSiteSchema = {
|
||||
name: 'AddonModWikiOfflineProvider',
|
||||
version: 1,
|
||||
tables: [
|
||||
{
|
||||
name: NEW_PAGES_TABLE_NAME,
|
||||
columns: [
|
||||
{
|
||||
name: 'wikiid',
|
||||
type: 'INTEGER',
|
||||
},
|
||||
{
|
||||
name: 'subwikiid',
|
||||
type: 'INTEGER',
|
||||
},
|
||||
{
|
||||
name: 'userid',
|
||||
type: 'INTEGER',
|
||||
},
|
||||
{
|
||||
name: 'groupid',
|
||||
type: 'INTEGER',
|
||||
},
|
||||
{
|
||||
name: 'title',
|
||||
type: 'TEXT',
|
||||
},
|
||||
{
|
||||
name: 'cachedcontent',
|
||||
type: 'TEXT',
|
||||
},
|
||||
{
|
||||
name: 'contentformat',
|
||||
type: 'TEXT',
|
||||
},
|
||||
{
|
||||
name: 'courseid',
|
||||
type: 'INTEGER',
|
||||
},
|
||||
{
|
||||
name: 'timecreated',
|
||||
type: 'INTEGER',
|
||||
},
|
||||
{
|
||||
name: 'timemodified',
|
||||
type: 'INTEGER',
|
||||
},
|
||||
{
|
||||
name: 'caneditpage',
|
||||
type: 'INTEGER',
|
||||
},
|
||||
],
|
||||
primaryKeys: ['wikiid', 'subwikiid', 'userid', 'groupid', 'title'],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
/**
|
||||
* Wiki new page data.
|
||||
*/
|
||||
export type AddonModWikiPageDBRecord = {
|
||||
wikiid: number;
|
||||
subwikiid: number;
|
||||
userid: number;
|
||||
groupid: number;
|
||||
title: string;
|
||||
cachedcontent: string;
|
||||
contentformat: string;
|
||||
courseid?: null; // Currently not used.
|
||||
timecreated: number;
|
||||
timemodified: number;
|
||||
caneditpage: number;
|
||||
};
|
|
@ -0,0 +1,148 @@
|
|||
// (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 { Injectable } from '@angular/core';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { CoreContentLinksHandlerBase } from '@features/contentlinks/classes/base-handler';
|
||||
import { CoreContentLinksAction } from '@features/contentlinks/services/contentlinks-delegate';
|
||||
import { CoreCourse, CoreCourseAnyModuleData } from '@features/course/services/course';
|
||||
import { CoreNavigator } from '@services/navigator';
|
||||
import { CoreSitesReadingStrategy } from '@services/sites';
|
||||
import { CoreDomUtils } from '@services/utils/dom';
|
||||
import { makeSingleton, Translate } from '@singletons';
|
||||
import { AddonModWikiIndexPage } from '../../pages/index';
|
||||
import { AddonModWiki } from '../wiki';
|
||||
import { AddonModWikiModuleHandlerService } from './module';
|
||||
|
||||
/**
|
||||
* Handler to treat links to create a wiki page.
|
||||
*/
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class AddonModWikiCreateLinkHandlerService extends CoreContentLinksHandlerBase {
|
||||
|
||||
name = 'AddonModWikiCreateLinkHandler';
|
||||
featureName = 'CoreCourseModuleDelegate_AddonModWiki';
|
||||
pattern = /\/mod\/wiki\/create\.php.*([&?]swid=\d+)/;
|
||||
|
||||
/**
|
||||
* Check if the current view is a wiki page of the same wiki.
|
||||
*
|
||||
* @param route Activated route if current route is wiki index page, null otherwise.
|
||||
* @param subwikiId Subwiki ID to check.
|
||||
* @param siteId Site ID.
|
||||
* @return Promise resolved with boolean: whether current view belongs to the same wiki.
|
||||
*/
|
||||
protected async currentStateIsSameWiki(route: ActivatedRoute | null, subwikiId: number, siteId: string): Promise<boolean> {
|
||||
if (!route) {
|
||||
// Current view isn't wiki index.
|
||||
return false;
|
||||
}
|
||||
|
||||
const params = route.snapshot.params;
|
||||
const queryParams = route.snapshot.queryParams;
|
||||
|
||||
if (queryParams.subwikiId == subwikiId) {
|
||||
// Same subwiki, so it's same wiki.
|
||||
return true;
|
||||
}
|
||||
|
||||
const options = {
|
||||
cmId: params.cmId,
|
||||
readingStrategy: CoreSitesReadingStrategy.PreferCache,
|
||||
siteId,
|
||||
};
|
||||
|
||||
if (queryParams.pageId) {
|
||||
// Get the page contents to check the subwiki.
|
||||
try {
|
||||
const page = await AddonModWiki.getPageContents(queryParams.pageId, options);
|
||||
|
||||
return page.subwikiid == subwikiId;
|
||||
} catch {
|
||||
// Not found, check next case.
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
// Get the wiki.
|
||||
const wiki = await AddonModWiki.getWiki(params.courseId, params.cmId, options);
|
||||
|
||||
// Check if the subwiki belongs to this wiki.
|
||||
return await AddonModWiki.wikiHasSubwiki(wiki.id, subwikiId, options);
|
||||
} catch {
|
||||
// Not found, return false.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
getActions(
|
||||
siteIds: string[],
|
||||
url: string,
|
||||
params: Record<string, string>,
|
||||
courseId?: number,
|
||||
): CoreContentLinksAction[] | Promise<CoreContentLinksAction[]> {
|
||||
courseId = Number(courseId || params.courseid || params.cid);
|
||||
|
||||
return [{
|
||||
action: async (siteId: string) => {
|
||||
const modal = await CoreDomUtils.showModalLoading();
|
||||
|
||||
try {
|
||||
const route = CoreNavigator.getCurrentRoute({ pageComponent: AddonModWikiIndexPage });
|
||||
const subwikiId = parseInt(params.swid, 10);
|
||||
const wikiId = parseInt(params.wid, 10);
|
||||
let module: CoreCourseAnyModuleData;
|
||||
|
||||
// Check if the link is inside the same wiki.
|
||||
const isSameWiki = await this.currentStateIsSameWiki(route, subwikiId, siteId);
|
||||
|
||||
if (isSameWiki) {
|
||||
// User is seeing the wiki, we can get the module from the wiki params.
|
||||
module = route!.snapshot.queryParams.module;
|
||||
} else if (wikiId) {
|
||||
// The URL specifies which wiki it belongs to. Get the module.
|
||||
module = await CoreCourse.getModuleBasicInfoByInstance(wikiId, 'wiki', siteId);
|
||||
} else {
|
||||
// Not enough data.
|
||||
CoreDomUtils.showErrorModal(Translate.instant('addon.mod_wiki.errorloadingpage'));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Open the page.
|
||||
CoreNavigator.navigateToSitePath(
|
||||
AddonModWikiModuleHandlerService.PAGE_NAME + `/${courseId}/${module.id}/edit`,
|
||||
{
|
||||
params: {
|
||||
module: module,
|
||||
courseId: courseId || module.course || route?.snapshot.params.courseId,
|
||||
pageTitle: params.title,
|
||||
subwikiId: subwikiId,
|
||||
},
|
||||
siteId,
|
||||
},
|
||||
);
|
||||
} finally {
|
||||
modal.dismiss();
|
||||
}
|
||||
},
|
||||
}];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export const AddonModWikiCreateLinkHandler = makeSingleton(AddonModWikiCreateLinkHandlerService);
|
|
@ -0,0 +1,62 @@
|
|||
// (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 { Injectable } from '@angular/core';
|
||||
import { CoreContentLinksHandlerBase } from '@features/contentlinks/classes/base-handler';
|
||||
import { CoreContentLinksAction } from '@features/contentlinks/services/contentlinks-delegate';
|
||||
import { makeSingleton } from '@singletons';
|
||||
|
||||
/**
|
||||
* Handler to treat links to edit a wiki page.
|
||||
*/
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class AddonModWikiEditLinkHandlerService extends CoreContentLinksHandlerBase {
|
||||
|
||||
name = 'AddonModWikiEditLinkHandler';
|
||||
featureName = 'CoreCourseModuleDelegate_AddonModWiki';
|
||||
pattern = /\/mod\/wiki\/edit\.php.*([&?]pageid=\d+)/;
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
getActions(
|
||||
siteIds: string[],
|
||||
url: string,
|
||||
params: Record<string, string>,
|
||||
courseId?: number,
|
||||
): CoreContentLinksAction[] | Promise<CoreContentLinksAction[]> {
|
||||
courseId = Number(courseId || params.courseid || params.cid);
|
||||
|
||||
return [{
|
||||
action: (siteId: string) => {
|
||||
|
||||
let section = '';
|
||||
if (typeof params.section != 'undefined') {
|
||||
section = params.section.replace(/\+/g, ' ');
|
||||
}
|
||||
|
||||
const pageParams = {
|
||||
courseId: courseId,
|
||||
section: section,
|
||||
pageId: parseInt(params.pageid, 10),
|
||||
};
|
||||
|
||||
// @todo this.linkHelper.goInSite(navCtrl, 'AddonModWikiEditPage', pageParams, siteId);
|
||||
},
|
||||
}];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export const AddonModWikiEditLinkHandler = makeSingleton(AddonModWikiEditLinkHandlerService);
|
|
@ -0,0 +1,33 @@
|
|||
// (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 { Injectable } from '@angular/core';
|
||||
import { CoreContentLinksModuleIndexHandler } from '@features/contentlinks/classes/module-index-handler';
|
||||
import { makeSingleton } from '@singletons';
|
||||
|
||||
/**
|
||||
* Handler to treat links to wiki index.
|
||||
*/
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class AddonModWikiIndexLinkHandlerService extends CoreContentLinksModuleIndexHandler {
|
||||
|
||||
name = 'AddonModWikiIndexLinkHandler';
|
||||
|
||||
constructor() {
|
||||
super('AddonModWiki', 'wiki', 'wid');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export const AddonModWikiIndexLinkHandler = makeSingleton(AddonModWikiIndexLinkHandlerService);
|
|
@ -0,0 +1,33 @@
|
|||
// (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 { Injectable } from '@angular/core';
|
||||
import { CoreContentLinksModuleListHandler } from '@features/contentlinks/classes/module-list-handler';
|
||||
import { makeSingleton } from '@singletons';
|
||||
|
||||
/**
|
||||
* Handler to treat links to wiki list page.
|
||||
*/
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class AddonModWikiListLinkHandlerService extends CoreContentLinksModuleListHandler {
|
||||
|
||||
name = 'AddonModWikiListLinkHandler';
|
||||
|
||||
constructor() {
|
||||
super('AddonModWiki', 'wiki');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export const AddonModWikiListLinkHandler = makeSingleton(AddonModWikiListLinkHandlerService);
|
|
@ -0,0 +1,84 @@
|
|||
// (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 { CoreConstants } from '@/core/constants';
|
||||
import { Injectable, Type } from '@angular/core';
|
||||
import { CoreCourse, CoreCourseAnyModuleData } from '@features/course/services/course';
|
||||
import { CoreCourseModule } from '@features/course/services/course-helper';
|
||||
import { CoreCourseModuleHandler, CoreCourseModuleHandlerData } from '@features/course/services/module-delegate';
|
||||
import { CoreNavigationOptions, CoreNavigator } from '@services/navigator';
|
||||
import { makeSingleton } from '@singletons';
|
||||
import { AddonModWikiIndexComponent } from '../../components/index';
|
||||
|
||||
/**
|
||||
* Handler to support wiki modules.
|
||||
*/
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class AddonModWikiModuleHandlerService implements CoreCourseModuleHandler {
|
||||
|
||||
static readonly PAGE_NAME = 'mod_wiki';
|
||||
|
||||
name = 'AddonModWiki';
|
||||
modName = 'wiki';
|
||||
|
||||
supportedFeatures = {
|
||||
[CoreConstants.FEATURE_GROUPS]: true,
|
||||
[CoreConstants.FEATURE_GROUPINGS]: true,
|
||||
[CoreConstants.FEATURE_MOD_INTRO]: true,
|
||||
[CoreConstants.FEATURE_COMPLETION_TRACKS_VIEWS]: true,
|
||||
[CoreConstants.FEATURE_GRADE_HAS_GRADE]: false,
|
||||
[CoreConstants.FEATURE_GRADE_OUTCOMES]: false,
|
||||
[CoreConstants.FEATURE_BACKUP_MOODLE2]: true,
|
||||
[CoreConstants.FEATURE_SHOW_DESCRIPTION]: true,
|
||||
[CoreConstants.FEATURE_RATE]: false,
|
||||
[CoreConstants.FEATURE_COMMENT]: true,
|
||||
};
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
async isEnabled(): Promise<boolean> {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
getData(module: CoreCourseAnyModuleData): CoreCourseModuleHandlerData {
|
||||
return {
|
||||
icon: CoreCourse.getModuleIconSrc(this.modName, 'modicon' in module ? module.modicon : undefined),
|
||||
title: module.name,
|
||||
class: 'addon-mod_wiki-handler',
|
||||
showDownloadButton: true,
|
||||
action: (event: Event, module: CoreCourseModule, courseId: number, options?: CoreNavigationOptions) => {
|
||||
options = options || {};
|
||||
options.params = options.params || {};
|
||||
Object.assign(options.params, { module });
|
||||
const routeParams = `/${courseId}/${module.id}/root`;
|
||||
|
||||
CoreNavigator.navigateToSitePath(AddonModWikiModuleHandlerService.PAGE_NAME + routeParams, options);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
async getMainComponent(): Promise<Type<unknown>> {
|
||||
return AddonModWikiIndexComponent;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export const AddonModWikiModuleHandler = makeSingleton(AddonModWikiModuleHandlerService);
|
|
@ -0,0 +1,109 @@
|
|||
// (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 { Injectable } from '@angular/core';
|
||||
import { CoreContentLinksHandlerBase } from '@features/contentlinks/classes/base-handler';
|
||||
import { CoreContentLinksAction } from '@features/contentlinks/services/contentlinks-delegate';
|
||||
import { CoreCourse } from '@features/course/services/course';
|
||||
import { CoreNavigator } from '@services/navigator';
|
||||
import { CoreDomUtils } from '@services/utils/dom';
|
||||
import { makeSingleton } from '@singletons';
|
||||
import { Md5 } from 'ts-md5';
|
||||
import { AddonModWiki } from '../wiki';
|
||||
import { AddonModWikiModuleHandlerService } from './module';
|
||||
|
||||
/**
|
||||
* Handler to treat links to a wiki page or the wiki map.
|
||||
*/
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class AddonModWikiPageOrMapLinkHandlerService extends CoreContentLinksHandlerBase {
|
||||
|
||||
name = 'AddonModWikiPageOrMapLinkHandler';
|
||||
featureName = 'CoreCourseModuleDelegate_AddonModWiki';
|
||||
pattern = /\/mod\/wiki\/(view|map)\.php.*([&?]pageid=\d+)/;
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
getActions(
|
||||
siteIds: string[],
|
||||
url: string,
|
||||
params: Record<string, string>,
|
||||
courseId?: number,
|
||||
): CoreContentLinksAction[] | Promise<CoreContentLinksAction[]> {
|
||||
|
||||
courseId = Number(courseId || params.courseid || params.cid);
|
||||
|
||||
return [{
|
||||
action: async (siteId: string) => {
|
||||
const modal = await CoreDomUtils.showModalLoading();
|
||||
const pageId = parseInt(params.pageid, 10);
|
||||
const action = url.indexOf('mod/wiki/map.php') != -1 ? 'map' : 'page';
|
||||
|
||||
try {
|
||||
// Get the page data to obtain wikiId, subwikiId, etc.
|
||||
const page = await AddonModWiki.getPageContents(pageId, { siteId });
|
||||
|
||||
const module = await CoreCourse.getModuleBasicInfoByInstance(page.wikiid, 'wiki', siteId);
|
||||
|
||||
const hash = <string> Md5.hashAsciiStr(JSON.stringify({
|
||||
pageId: page.id,
|
||||
pageTitle: page.title,
|
||||
subwikiId: page.subwikiid,
|
||||
action: action,
|
||||
timestamp: Date.now(),
|
||||
}));
|
||||
courseId = courseId || module.course;
|
||||
|
||||
CoreNavigator.navigateToSitePath(
|
||||
AddonModWikiModuleHandlerService.PAGE_NAME + `/${courseId}/${module.id}/${hash}`,
|
||||
{
|
||||
params: {
|
||||
pageId: page.id,
|
||||
pageTitle: page.title,
|
||||
subwikiId: page.subwikiid,
|
||||
action: action,
|
||||
},
|
||||
siteId,
|
||||
},
|
||||
);
|
||||
} catch (error) {
|
||||
CoreDomUtils.showErrorModalDefault(error, 'addon.mod_wiki.errorloadingpage', true);
|
||||
} finally {
|
||||
modal.dismiss();
|
||||
}
|
||||
},
|
||||
}];
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
async isEnabled(siteId: string, url: string, params: Record<string, string>): Promise<boolean> {
|
||||
const isMap = url.indexOf('mod/wiki/map.php') != -1;
|
||||
|
||||
if (params.id && !isMap) {
|
||||
// ID param is more prioritary than pageid in index page, it's a index URL.
|
||||
return false;
|
||||
} else if (isMap && typeof params.option != 'undefined' && params.option != '5') {
|
||||
// Map link but the option isn't "Page list", not supported.
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export const AddonModWikiPageOrMapLinkHandler = makeSingleton(AddonModWikiPageOrMapLinkHandlerService);
|
|
@ -0,0 +1,206 @@
|
|||
// (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 { Injectable } from '@angular/core';
|
||||
import { CoreCourseActivityPrefetchHandlerBase } from '@features/course/classes/activity-prefetch-handler';
|
||||
import { CoreCourseAnyModuleData } from '@features/course/services/course';
|
||||
import { CoreCourseHelper } from '@features/course/services/course-helper';
|
||||
import { CoreFilepool } from '@services/filepool';
|
||||
import { CoreGroups } from '@services/groups';
|
||||
import { CoreFileSizeSum, CorePluginFileDelegate } from '@services/plugin-file-delegate';
|
||||
import { CoreSites, CoreSitesCommonWSOptions, CoreSitesReadingStrategy } from '@services/sites';
|
||||
import { CoreUtils } from '@services/utils/utils';
|
||||
import { CoreWSExternalFile } from '@services/ws';
|
||||
import { makeSingleton } from '@singletons';
|
||||
import { AddonModWiki, AddonModWikiProvider, AddonModWikiSubwikiPage } from '../wiki';
|
||||
import { AddonModWikiSync, AddonModWikiSyncWikiResult } from '../wiki-sync';
|
||||
|
||||
/**
|
||||
* Handler to prefetch wikis.
|
||||
*/
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class AddonModWikiPrefetchHandlerService extends CoreCourseActivityPrefetchHandlerBase {
|
||||
|
||||
name = 'AddonModWiki';
|
||||
modName = 'wiki';
|
||||
component = AddonModWikiProvider.COMPONENT;
|
||||
updatesNames = /^.*files$|^pages$/;
|
||||
|
||||
/**
|
||||
* Returns a list of pages that can be downloaded.
|
||||
*
|
||||
* @param module The module object returned by WS.
|
||||
* @param courseId The course ID.
|
||||
* @param options Other options.
|
||||
* @return List of pages.
|
||||
*/
|
||||
protected async getAllPages(
|
||||
module: CoreCourseAnyModuleData,
|
||||
courseId: number,
|
||||
options: CoreSitesCommonWSOptions = {},
|
||||
): Promise<AddonModWikiSubwikiPage[]> {
|
||||
options.siteId = options.siteId || CoreSites.getCurrentSiteId();
|
||||
|
||||
try {
|
||||
const wiki = await AddonModWiki.getWiki(courseId, module.id, options);
|
||||
|
||||
return await AddonModWiki.getWikiPageList(wiki, options);
|
||||
} catch {
|
||||
// Wiki not found, return empty list.
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
async getDownloadSize(module: CoreCourseAnyModuleData, courseId: number, single?: boolean): Promise<CoreFileSizeSum> {
|
||||
const promises: Promise<CoreFileSizeSum>[] = [];
|
||||
const siteId = CoreSites.getCurrentSiteId();
|
||||
|
||||
promises.push(this.getFiles(module, courseId, single, siteId).then((files) =>
|
||||
CorePluginFileDelegate.getFilesDownloadSize(files)));
|
||||
|
||||
promises.push(this.getAllPages(module, courseId, {
|
||||
readingStrategy: CoreSitesReadingStrategy.OnlyNetwork,
|
||||
siteId,
|
||||
}).then((pages) => {
|
||||
let size = 0;
|
||||
|
||||
pages.forEach((page) => {
|
||||
if (page.contentsize) {
|
||||
size = size + page.contentsize;
|
||||
}
|
||||
});
|
||||
|
||||
return { size: size, total: true };
|
||||
}));
|
||||
|
||||
const sizes = await Promise.all(promises);
|
||||
|
||||
return {
|
||||
size: sizes[0].size + sizes[1].size,
|
||||
total: sizes[0].total && sizes[1].total,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
async getFiles(
|
||||
module: CoreCourseAnyModuleData,
|
||||
courseId: number,
|
||||
single?: boolean,
|
||||
siteId?: string,
|
||||
): Promise<CoreWSExternalFile[]> {
|
||||
siteId = siteId || CoreSites.getCurrentSiteId();
|
||||
|
||||
try {
|
||||
const wiki = await AddonModWiki.getWiki(courseId, module.id, { siteId });
|
||||
|
||||
const introFiles = this.getIntroFilesFromInstance(module, wiki);
|
||||
|
||||
const files = await AddonModWiki.getWikiFileList(wiki, { siteId });
|
||||
|
||||
return introFiles.concat(files);
|
||||
} catch {
|
||||
// Wiki not found, return empty list.
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
invalidateContent(moduleId: number, courseId: number): Promise<void> {
|
||||
return AddonModWiki.invalidateContent(moduleId, courseId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
async prefetch(module: CoreCourseAnyModuleData, courseId?: number, single?: boolean): Promise<void> {
|
||||
// Get the download time of the package before starting the download (otherwise we'd always get current time).
|
||||
const siteId = CoreSites.getCurrentSiteId();
|
||||
|
||||
const data = await CoreUtils.ignoreErrors(CoreFilepool.getPackageData(siteId, this.component, module.id));
|
||||
|
||||
const downloadTime = data?.downloadTime || 0;
|
||||
|
||||
return this.prefetchPackage(module, courseId, this.prefetchWiki.bind(this, module, courseId, single, downloadTime, siteId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Prefetch a wiki.
|
||||
*
|
||||
* @param module Module.
|
||||
* @param courseId Course ID the module belongs to.
|
||||
* @param single True if we're downloading a single module, false if we're downloading a whole section.
|
||||
* @param downloadTime The previous download time, 0 if no previous download.
|
||||
* @param siteId Site ID.
|
||||
* @return Promise resolved when done.
|
||||
*/
|
||||
protected async prefetchWiki(
|
||||
module: CoreCourseAnyModuleData,
|
||||
courseId: number,
|
||||
single: boolean,
|
||||
downloadTime: number,
|
||||
siteId: string,
|
||||
): Promise<void> {
|
||||
const userId = CoreSites.getCurrentSiteUserId();
|
||||
|
||||
const commonOptions = {
|
||||
readingStrategy: CoreSitesReadingStrategy.OnlyNetwork,
|
||||
siteId,
|
||||
};
|
||||
const modOptions = {
|
||||
cmId: module.id,
|
||||
...commonOptions, // Include all common options.
|
||||
};
|
||||
|
||||
// Get the list of pages.
|
||||
const pages = await this.getAllPages(module, courseId, commonOptions);
|
||||
const promises: Promise<unknown>[] = [];
|
||||
|
||||
pages.forEach((page) => {
|
||||
// Fetch page contents if it needs to be fetched.
|
||||
if (page.timemodified > downloadTime) {
|
||||
promises.push(AddonModWiki.getPageContents(page.id, modOptions));
|
||||
}
|
||||
});
|
||||
|
||||
// Fetch group data.
|
||||
promises.push(CoreGroups.getActivityGroupInfo(module.id, false, userId, siteId));
|
||||
|
||||
// Fetch info to provide wiki links.
|
||||
promises.push(AddonModWiki.getWiki(courseId, module.id, { siteId }).then((wiki) =>
|
||||
CoreCourseHelper.getModuleCourseIdByInstance(wiki.id, 'wiki', siteId)));
|
||||
|
||||
// Get related page files and fetch them.
|
||||
promises.push(this.getFiles(module, courseId, single, siteId).then((files) =>
|
||||
CoreFilepool.addFilesToQueue(siteId, files, this.component, module.id)));
|
||||
|
||||
await Promise.all(promises);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
sync(module: CoreCourseAnyModuleData, courseId: number, siteId?: string): Promise<AddonModWikiSyncWikiResult> {
|
||||
return AddonModWikiSync.syncWiki(module.instance!, module.course, module.id, siteId);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export const AddonModWikiPrefetchHandler = makeSingleton(AddonModWikiPrefetchHandlerService);
|
|
@ -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 { Injectable } from '@angular/core';
|
||||
import { CoreCronHandler } from '@services/cron';
|
||||
import { makeSingleton } from '@singletons';
|
||||
import { AddonModWikiSync } from '../wiki-sync';
|
||||
|
||||
/**
|
||||
* Synchronization cron handler.
|
||||
*/
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class AddonModWikiSyncCronHandlerService implements CoreCronHandler {
|
||||
|
||||
name = 'AddonModWikiSyncCronHandler';
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
execute(siteId?: string, force?: boolean): Promise<void> {
|
||||
return AddonModWikiSync.syncAllWikis(siteId, force);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
getInterval(): number {
|
||||
return AddonModWikiSync.syncInterval;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export const AddonModWikiSyncCronHandler = makeSingleton(AddonModWikiSyncCronHandlerService);
|
|
@ -0,0 +1,53 @@
|
|||
// (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 { Injectable, Type } from '@angular/core';
|
||||
import { CoreTagFeedComponent } from '@features/tag/components/feed/feed';
|
||||
import { CoreTagAreaHandler } from '@features/tag/services/tag-area-delegate';
|
||||
import { CoreTagFeedElement, CoreTagHelper } from '@features/tag/services/tag-helper';
|
||||
import { makeSingleton } from '@singletons';
|
||||
|
||||
/**
|
||||
* Handler to support tags.
|
||||
*/
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class AddonModWikiTagAreaHandlerService implements CoreTagAreaHandler {
|
||||
|
||||
name = 'AddonModWikiTagAreaHandler';
|
||||
type = 'mod_wiki/wiki_pages';
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
async isEnabled(): Promise<boolean> {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
parseContent(content: string): CoreTagFeedElement[] {
|
||||
return CoreTagHelper.parseFeedContent(content);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
getComponent(): Type<unknown> {
|
||||
return CoreTagFeedComponent;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export const AddonModWikiTagAreaHandler = makeSingleton(AddonModWikiTagAreaHandlerService);
|
|
@ -0,0 +1,233 @@
|
|||
// (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 { Injectable } from '@angular/core';
|
||||
import { CoreSites } from '@services/sites';
|
||||
import { makeSingleton } from '@singletons';
|
||||
import { AddonModWikiPageDBRecord, NEW_PAGES_TABLE_NAME } from './database/wiki';
|
||||
import { AddonModWikiSubwiki } from './wiki';
|
||||
|
||||
/**
|
||||
* Service to handle offline wiki.
|
||||
*/
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class AddonModWikiOfflineProvider {
|
||||
|
||||
/**
|
||||
* Convert a value to a positive number. If not a number or less than 0, 0 will be returned.
|
||||
*
|
||||
* @param value Value to convert.
|
||||
* @return Converted value.
|
||||
*/
|
||||
convertToPositiveNumber(value: string | number | undefined): number {
|
||||
value = Number(value);
|
||||
|
||||
return value > 0 ? value : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a new page.
|
||||
*
|
||||
* @param title Title of the page.
|
||||
* @param subwikiId Subwiki ID. If not defined, wikiId, userId and groupId should be defined.
|
||||
* @param wikiId Wiki ID. Optional, will be used create subwiki if not informed.
|
||||
* @param userId User ID. Optional, will be used create subwiki if not informed.
|
||||
* @param groupId Group ID. Optional, will be used create subwiki if not informed.
|
||||
* @param siteId Site ID. If not defined, current site.
|
||||
* @return Promise resolved if deleted, rejected if failure.
|
||||
*/
|
||||
async deleteNewPage(
|
||||
title: string,
|
||||
subwikiId?: number,
|
||||
wikiId?: number,
|
||||
userId?: number,
|
||||
groupId?: number,
|
||||
siteId?: string,
|
||||
): Promise<void> {
|
||||
|
||||
const site = await CoreSites.getSite(siteId);
|
||||
|
||||
subwikiId = this.convertToPositiveNumber(subwikiId);
|
||||
wikiId = this.convertToPositiveNumber(wikiId);
|
||||
userId = this.convertToPositiveNumber(userId);
|
||||
groupId = this.convertToPositiveNumber(groupId);
|
||||
|
||||
await site.getDb().deleteRecords(NEW_PAGES_TABLE_NAME, <Partial<AddonModWikiPageDBRecord>> {
|
||||
subwikiid: subwikiId,
|
||||
wikiid: wikiId,
|
||||
userid: userId,
|
||||
groupid: groupId,
|
||||
title: title,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all the stored new pages from all the wikis.
|
||||
*
|
||||
* @param siteId Site ID. If not defined, current site.
|
||||
* @return Promise resolved with pages.
|
||||
*/
|
||||
async getAllNewPages(siteId?: string): Promise<AddonModWikiPageDBRecord[]> {
|
||||
const site = await CoreSites.getSite(siteId);
|
||||
|
||||
return site.getDb().getAllRecords(NEW_PAGES_TABLE_NAME);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a stored new page.
|
||||
*
|
||||
* @param title Title of the page.
|
||||
* @param subwikiId Subwiki ID. If not defined, wikiId, userId and groupId should be defined.
|
||||
* @param wikiId Wiki ID. Optional, will be used create subwiki if not informed.
|
||||
* @param userId User ID. Optional, will be used create subwiki if not informed.
|
||||
* @param groupId Group ID. Optional, will be used create subwiki if not informed.
|
||||
* @param siteId Site ID. If not defined, current site.
|
||||
* @return Promise resolved with page.
|
||||
*/
|
||||
async getNewPage(
|
||||
title: string,
|
||||
subwikiId?: number,
|
||||
wikiId?: number,
|
||||
userId?: number,
|
||||
groupId?: number,
|
||||
siteId?: string,
|
||||
): Promise<AddonModWikiPageDBRecord> {
|
||||
const site = await CoreSites.getSite(siteId);
|
||||
|
||||
subwikiId = this.convertToPositiveNumber(subwikiId);
|
||||
wikiId = this.convertToPositiveNumber(wikiId);
|
||||
userId = this.convertToPositiveNumber(userId);
|
||||
groupId = this.convertToPositiveNumber(groupId);
|
||||
|
||||
return site.getDb().getRecord(NEW_PAGES_TABLE_NAME, <Partial<AddonModWikiPageDBRecord>> {
|
||||
subwikiid: subwikiId,
|
||||
wikiid: wikiId,
|
||||
userid: userId,
|
||||
groupid: groupId,
|
||||
title: title,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all the stored new pages from a certain subwiki.
|
||||
*
|
||||
* @param subwikiId Subwiki ID. If not defined, wikiId, userId and groupId should be defined.
|
||||
* @param wikiId Wiki ID. Optional, will be used create subwiki if not informed.
|
||||
* @param userId User ID. Optional, will be used create subwiki if not informed.
|
||||
* @param groupId Group ID. Optional, will be used create subwiki if not informed.
|
||||
* @param siteId Site ID. If not defined, current site.
|
||||
* @return Promise resolved with pages.
|
||||
*/
|
||||
async getSubwikiNewPages(
|
||||
subwikiId?: number,
|
||||
wikiId?: number,
|
||||
userId?: number,
|
||||
groupId?: number,
|
||||
siteId?: string,
|
||||
): Promise<AddonModWikiPageDBRecord[]> {
|
||||
const site = await CoreSites.getSite(siteId);
|
||||
|
||||
subwikiId = this.convertToPositiveNumber(subwikiId);
|
||||
wikiId = this.convertToPositiveNumber(wikiId);
|
||||
userId = this.convertToPositiveNumber(userId);
|
||||
groupId = this.convertToPositiveNumber(groupId);
|
||||
|
||||
return site.getDb().getRecords(NEW_PAGES_TABLE_NAME, <Partial<AddonModWikiPageDBRecord>> {
|
||||
subwikiid: subwikiId,
|
||||
wikiid: wikiId,
|
||||
userid: userId,
|
||||
groupid: groupId,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all the stored new pages from a list of subwikis.
|
||||
*
|
||||
* @param subwikis List of subwiki.
|
||||
* @param siteId Site ID. If not defined, current site.
|
||||
* @return Promise resolved with pages.
|
||||
*/
|
||||
async getSubwikisNewPages(subwikis: AddonModWikiSubwiki[], siteId?: string): Promise<AddonModWikiPageDBRecord[]> {
|
||||
let pages: AddonModWikiPageDBRecord[] = [];
|
||||
|
||||
await Promise.all(subwikis.map(async (subwiki) => {
|
||||
const subwikiPages = await this.getSubwikiNewPages(subwiki.id, subwiki.wikiid, subwiki.userid, subwiki.groupid, siteId);
|
||||
|
||||
pages = pages.concat(subwikiPages);
|
||||
}));
|
||||
|
||||
return pages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save a new page to be sent later.
|
||||
*
|
||||
* @param title Title of the page.
|
||||
* @param content Content of the page.
|
||||
* @param subwikiId Subwiki ID. If not defined, wikiId, userId and groupId should be defined.
|
||||
* @param wikiId Wiki ID. Optional, will be used create subwiki if not informed.
|
||||
* @param userId User ID. Optional, will be used create subwiki if not informed.
|
||||
* @param groupId Group ID. Optional, will be used create subwiki if not informed.
|
||||
* @param siteId Site ID. If not defined, current site.
|
||||
* @return Promise resolved if stored, rejected if failure.
|
||||
*/
|
||||
async saveNewPage(
|
||||
title: string,
|
||||
content: string,
|
||||
subwikiId?: number,
|
||||
wikiId?: number,
|
||||
userId?: number,
|
||||
groupId?: number,
|
||||
siteId?: string,
|
||||
): Promise<void> {
|
||||
const site = await CoreSites.getSite(siteId);
|
||||
|
||||
const now = Date.now();
|
||||
const entry: AddonModWikiPageDBRecord = {
|
||||
title: title,
|
||||
cachedcontent: content,
|
||||
subwikiid: this.convertToPositiveNumber(subwikiId),
|
||||
wikiid: this.convertToPositiveNumber(wikiId),
|
||||
userid: this.convertToPositiveNumber(userId),
|
||||
groupid: this.convertToPositiveNumber(groupId),
|
||||
contentformat: 'html',
|
||||
timecreated: now,
|
||||
timemodified: now,
|
||||
caneditpage: 1,
|
||||
};
|
||||
|
||||
await site.getDb().insertRecord(NEW_PAGES_TABLE_NAME, entry);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a list of subwikis have offline data stored.
|
||||
*
|
||||
* @param subwikis List of subwikis.
|
||||
* @param siteId Site ID. If not defined, current site.
|
||||
* @return Promise resolved with boolean: whether it has offline data.
|
||||
*/
|
||||
async subwikisHaveOfflineData(subwikis: AddonModWikiSubwiki[], siteId?: string): Promise<boolean> {
|
||||
try {
|
||||
const pages = await this.getSubwikisNewPages(subwikis, siteId);
|
||||
|
||||
return !!pages.length;
|
||||
} catch {
|
||||
// Error, return false.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export const AddonModWikiOffline = makeSingleton(AddonModWikiOfflineProvider);
|
|
@ -0,0 +1,417 @@
|
|||
// (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 { Injectable } from '@angular/core';
|
||||
import { CoreSyncBaseProvider, CoreSyncBlockedError } from '@classes/base-sync';
|
||||
import { CoreNetworkError } from '@classes/errors/network-error';
|
||||
import { CoreCourseLogHelper } from '@features/course/services/log-helper';
|
||||
import { CoreApp } from '@services/app';
|
||||
import { CoreGroups } from '@services/groups';
|
||||
import { CoreSites } from '@services/sites';
|
||||
import { CoreSync } from '@services/sync';
|
||||
import { CoreTextUtils } from '@services/utils/text';
|
||||
import { CoreUtils } from '@services/utils/utils';
|
||||
import { makeSingleton, Translate } from '@singletons';
|
||||
import { CoreEvents } from '@singletons/events';
|
||||
import { AddonModWikiPageDBRecord } from './database/wiki';
|
||||
import { AddonModWiki, AddonModWikiProvider } from './wiki';
|
||||
import { AddonModWikiOffline } from './wiki-offline';
|
||||
|
||||
/**
|
||||
* Service to sync wikis.
|
||||
*/
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class AddonModWikiSyncProvider extends CoreSyncBaseProvider<AddonModWikiSyncSubwikiResult> {
|
||||
|
||||
static readonly AUTO_SYNCED = 'addon_mod_wiki_autom_synced';
|
||||
static readonly MANUAL_SYNCED = 'addon_mod_wiki_manual_synced';
|
||||
|
||||
protected componentTranslatableString = 'wiki';
|
||||
|
||||
constructor() {
|
||||
super('AddonModWikiSyncProvider');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a string to identify a subwiki. If it doesn't have a subwiki ID it will be identified by wiki ID, user ID and group ID.
|
||||
*
|
||||
* @param subwikiId Subwiki ID. If not defined, wikiId, userId and groupId should be defined.
|
||||
* @param wikiId Wiki ID. Optional, will be used to create the subwiki if subwiki ID not provided.
|
||||
* @param userId User ID. Optional, will be used to create the subwiki if subwiki ID not provided.
|
||||
* @param groupId Group ID. Optional, will be used to create the subwiki if subwiki ID not provided.
|
||||
* @return Identifier.
|
||||
*/
|
||||
getSubwikiBlockId(subwikiId: number, wikiId?: number, userId?: number, groupId?: number): string {
|
||||
subwikiId = AddonModWikiOffline.convertToPositiveNumber(subwikiId);
|
||||
|
||||
if (subwikiId && subwikiId > 0) {
|
||||
return String(subwikiId);
|
||||
}
|
||||
|
||||
wikiId = AddonModWikiOffline.convertToPositiveNumber(wikiId);
|
||||
userId = AddonModWikiOffline.convertToPositiveNumber(userId);
|
||||
groupId = AddonModWikiOffline.convertToPositiveNumber(groupId);
|
||||
|
||||
return `${wikiId}:${userId}:${groupId}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to synchronize all the wikis in a certain site or in all sites.
|
||||
*
|
||||
* @param siteId Site ID to sync. If not defined, sync all sites.
|
||||
* @param force Wether to force sync not depending on last execution.
|
||||
* @return Promise resolved if sync is successful, rejected if sync fails.
|
||||
*/
|
||||
syncAllWikis(siteId?: string, force?: boolean): Promise<void> {
|
||||
return this.syncOnSites('all wikis', this.syncAllWikisFunc.bind(this, !!force), siteId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sync all wikis on a site.
|
||||
*
|
||||
* @param force Wether to force sync not depending on last execution.
|
||||
* @param siteId Site ID to sync.
|
||||
* @param Promise resolved if sync is successful, rejected if sync fails.
|
||||
*/
|
||||
protected async syncAllWikisFunc(force: boolean, siteId: string): Promise<void> {
|
||||
// Get all the pages created in offline.
|
||||
const pages = await AddonModWikiOffline.getAllNewPages(siteId);
|
||||
|
||||
const subwikis: Record<string, boolean> = {};
|
||||
|
||||
// Sync all subwikis.
|
||||
await Promise.all(pages.map(async (page) => {
|
||||
const index = this.getSubwikiBlockId(page.subwikiid, page.wikiid, page.userid, page.groupid);
|
||||
|
||||
if (subwikis[index]) {
|
||||
// Already synced.
|
||||
return;
|
||||
}
|
||||
|
||||
subwikis[index] = true;
|
||||
|
||||
const result = force ?
|
||||
await this.syncSubwiki(page.subwikiid, page.wikiid, page.userid, page.groupid, siteId) :
|
||||
await this.syncSubwikiIfNeeded(page.subwikiid, page.wikiid, page.userid, page.groupid, siteId);
|
||||
|
||||
if (result?.updated) {
|
||||
// Sync successful, send event.
|
||||
CoreEvents.trigger(AddonModWikiSyncProvider.AUTO_SYNCED, {
|
||||
siteId: siteId,
|
||||
subwikiId: page.subwikiid,
|
||||
wikiId: page.wikiid,
|
||||
userId: page.userid,
|
||||
groupId: page.groupid,
|
||||
created: result.created,
|
||||
discarded: result.discarded,
|
||||
warnings: result.warnings,
|
||||
});
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sync a subwiki only if a certain time has passed since the last time.
|
||||
*
|
||||
* @param subwikiId Subwiki ID. If not defined, wikiId, userId and groupId should be defined.
|
||||
* @param wikiId Wiki ID. Optional, will be used to create the subwiki if subwiki ID not provided.
|
||||
* @param userId User ID. Optional, will be used to create the subwiki if subwiki ID not provided.
|
||||
* @param groupId Group ID. Optional, will be used to create the subwiki if subwiki ID not provided.
|
||||
* @param siteId Site ID. If not defined, current site.
|
||||
* @return Promise resolved when subwiki is synced or doesn't need to be synced.
|
||||
*/
|
||||
async syncSubwikiIfNeeded(
|
||||
subwikiId: number,
|
||||
wikiId?: number,
|
||||
userId?: number,
|
||||
groupId?: number,
|
||||
siteId?: string,
|
||||
): Promise<AddonModWikiSyncSubwikiResult | undefined> {
|
||||
|
||||
const blockId = this.getSubwikiBlockId(subwikiId, wikiId, userId, groupId);
|
||||
|
||||
const needed = await this.isSyncNeeded(blockId, siteId);
|
||||
|
||||
if (needed) {
|
||||
return this.syncSubwiki(subwikiId, wikiId, userId, groupId, siteId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Synchronize a subwiki.
|
||||
*
|
||||
* @param subwikiId Subwiki ID. If not defined, wikiId, userId and groupId should be defined.
|
||||
* @param wikiId Wiki ID. Optional, will be used to create the subwiki if subwiki ID not provided.
|
||||
* @param userId User ID. Optional, will be used to create the subwiki if subwiki ID not provided.
|
||||
* @param groupId Group ID. Optional, will be used to create the subwiki if subwiki ID not provided.
|
||||
* @param siteId Site ID. If not defined, current site.
|
||||
* @return Promise resolved if sync is successful, rejected otherwise.
|
||||
*/
|
||||
syncSubwiki(
|
||||
subwikiId: number,
|
||||
wikiId?: number,
|
||||
userId?: number,
|
||||
groupId?: number,
|
||||
siteId?: string,
|
||||
): Promise<AddonModWikiSyncSubwikiResult> {
|
||||
siteId = siteId || CoreSites.getCurrentSiteId();
|
||||
|
||||
const subwikiBlockId = this.getSubwikiBlockId(subwikiId, wikiId, userId, groupId);
|
||||
|
||||
if (this.isSyncing(subwikiBlockId, siteId)) {
|
||||
// There's already a sync ongoing for this subwiki, return the promise.
|
||||
return this.getOngoingSync(subwikiBlockId, siteId)!;
|
||||
}
|
||||
|
||||
// Verify that subwiki isn't blocked.
|
||||
if (CoreSync.isBlocked(AddonModWikiProvider.COMPONENT, subwikiBlockId, siteId)) {
|
||||
this.logger.debug(`Cannot sync subwiki ${subwikiBlockId} because it is blocked.`);
|
||||
|
||||
throw new CoreSyncBlockedError(Translate.instant('core.errorsyncblocked', { $a: this.componentTranslate }));
|
||||
}
|
||||
|
||||
this.logger.debug(`Try to sync subwiki ${subwikiBlockId}`);
|
||||
|
||||
return this.addOngoingSync(subwikiBlockId, this.performSyncSubwiki(subwikiId, wikiId, userId, groupId, siteId), siteId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Synchronize a subwiki.
|
||||
*
|
||||
* @param subwikiId Subwiki ID. If not defined, wikiId, userId and groupId should be defined.
|
||||
* @param wikiId Wiki ID. Optional, will be used to create the subwiki if subwiki ID not provided.
|
||||
* @param userId User ID. Optional, will be used to create the subwiki if subwiki ID not provided.
|
||||
* @param groupId Group ID. Optional, will be used to create the subwiki if subwiki ID not provided.
|
||||
* @param siteId Site ID. If not defined, current site.
|
||||
* @return Promise resolved if sync is successful, rejected otherwise.
|
||||
*/
|
||||
protected async performSyncSubwiki(
|
||||
subwikiId: number,
|
||||
wikiId?: number,
|
||||
userId?: number,
|
||||
groupId?: number,
|
||||
siteId?: string,
|
||||
): Promise<AddonModWikiSyncSubwikiResult> {
|
||||
const result: AddonModWikiSyncSubwikiResult = {
|
||||
warnings: [],
|
||||
updated: false,
|
||||
created: [],
|
||||
discarded: [],
|
||||
};
|
||||
const subwikiBlockId = this.getSubwikiBlockId(subwikiId, wikiId, userId, groupId);
|
||||
|
||||
// Get offline pages to be sent.
|
||||
const pages = await CoreUtils.ignoreErrors(
|
||||
AddonModWikiOffline.getSubwikiNewPages(subwikiId, wikiId, userId, groupId, siteId),
|
||||
<AddonModWikiPageDBRecord[]> [],
|
||||
);
|
||||
|
||||
if (!pages || !pages.length) {
|
||||
// Nothing to sync.
|
||||
await CoreUtils.ignoreErrors(this.setSyncTime(subwikiBlockId, siteId));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
if (!CoreApp.isOnline()) {
|
||||
// Cannot sync in offline.
|
||||
throw new CoreNetworkError();
|
||||
}
|
||||
|
||||
// Send the pages.
|
||||
await Promise.all(pages.map(async (page) => {
|
||||
try {
|
||||
const pageId = await AddonModWiki.newPageOnline(page.title, page.cachedcontent, {
|
||||
subwikiId,
|
||||
wikiId,
|
||||
userId,
|
||||
groupId,
|
||||
siteId,
|
||||
});
|
||||
|
||||
result.updated = true;
|
||||
result.created.push({
|
||||
pageId: pageId,
|
||||
title: page.title,
|
||||
});
|
||||
|
||||
// Delete the local page.
|
||||
await AddonModWikiOffline.deleteNewPage(page.title, subwikiId, wikiId, userId, groupId, siteId);
|
||||
} catch (error) {
|
||||
if (!CoreUtils.isWebServiceError(error)) {
|
||||
// Couldn't connect to server, reject.
|
||||
throw error;
|
||||
}
|
||||
|
||||
// The WebService has thrown an error, this means that the page cannot be submitted. Delete it.
|
||||
await AddonModWikiOffline.deleteNewPage(page.title, subwikiId, wikiId, userId, groupId, siteId);
|
||||
|
||||
result.updated = true;
|
||||
|
||||
// Page deleted, add the page to discarded pages and add a warning.
|
||||
const warning = Translate.instant('core.warningofflinedatadeleted', {
|
||||
component: Translate.instant('addon.mod_wiki.wikipage'),
|
||||
name: page.title,
|
||||
error: CoreTextUtils.getErrorMessageFromError(error),
|
||||
});
|
||||
|
||||
result.discarded.push({
|
||||
title: page.title,
|
||||
warning: warning,
|
||||
});
|
||||
|
||||
result.warnings.push(warning);
|
||||
}
|
||||
}));
|
||||
|
||||
// Sync finished, set sync time.
|
||||
await CoreUtils.ignoreErrors(this.setSyncTime(subwikiBlockId, siteId));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to synchronize a wiki.
|
||||
*
|
||||
* @param wikiId Wiki ID.
|
||||
* @param courseId Course ID.
|
||||
* @param cmId Wiki course module ID.
|
||||
* @param siteId Site ID. If not defined, current site.
|
||||
* @return Promise resolved if sync is successful, rejected otherwise.
|
||||
*/
|
||||
async syncWiki(wikiId: number, courseId?: number, cmId?: number, siteId?: string): Promise<AddonModWikiSyncWikiResult> {
|
||||
siteId = siteId || CoreSites.getCurrentSiteId();
|
||||
|
||||
// Sync offline logs.
|
||||
await CoreUtils.ignoreErrors(CoreCourseLogHelper.syncActivity(AddonModWikiProvider.COMPONENT, wikiId, siteId));
|
||||
|
||||
// Sync is done at subwiki level, get all the subwikis.
|
||||
const subwikis = await AddonModWiki.getSubwikis(wikiId, { cmId, siteId });
|
||||
|
||||
const result: AddonModWikiSyncWikiResult = {
|
||||
warnings: [],
|
||||
updated: false,
|
||||
subwikis: {},
|
||||
siteId: siteId,
|
||||
};
|
||||
|
||||
await Promise.all(subwikis.map(async (subwiki) => {
|
||||
const data = await this.syncSubwiki(subwiki.id, subwiki.wikiid, subwiki.userid, subwiki.groupid, siteId);
|
||||
|
||||
if (data && data.updated) {
|
||||
result.warnings = result.warnings.concat(data.warnings);
|
||||
result.updated = true;
|
||||
result.subwikis[subwiki.id] = {
|
||||
created: data.created,
|
||||
discarded: data.discarded,
|
||||
};
|
||||
}
|
||||
}));
|
||||
|
||||
if (result.updated) {
|
||||
const promises: Promise<void>[] = [];
|
||||
|
||||
// Something has changed, invalidate data.
|
||||
if (wikiId) {
|
||||
promises.push(AddonModWiki.invalidateSubwikis(wikiId));
|
||||
promises.push(AddonModWiki.invalidateSubwikiPages(wikiId));
|
||||
promises.push(AddonModWiki.invalidateSubwikiFiles(wikiId));
|
||||
}
|
||||
if (courseId) {
|
||||
promises.push(AddonModWiki.invalidateWikiData(courseId));
|
||||
}
|
||||
if (cmId) {
|
||||
promises.push(CoreGroups.invalidateActivityAllowedGroups(cmId));
|
||||
promises.push(CoreGroups.invalidateActivityGroupMode(cmId));
|
||||
}
|
||||
|
||||
await CoreUtils.ignoreErrors(Promise.all(promises));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export const AddonModWikiSync = makeSingleton(AddonModWikiSyncProvider);
|
||||
|
||||
/**
|
||||
* Data returned by a subwiki sync.
|
||||
*/
|
||||
export type AddonModWikiSyncSubwikiResult = {
|
||||
warnings: string[]; // List of warnings.
|
||||
updated: boolean; // Whether data was updated in the site.
|
||||
created: AddonModWikiCreatedPage[]; // List of created pages.
|
||||
discarded: AddonModWikiDiscardedPage[]; // List of discarded pages.
|
||||
};
|
||||
|
||||
/**
|
||||
* Data returned by a wiki sync.
|
||||
*/
|
||||
export type AddonModWikiSyncWikiResult = {
|
||||
warnings: string[]; // List of warnings.
|
||||
updated: boolean; // Whether data was updated in the site.
|
||||
subwikis: {
|
||||
[subwikiId: number]: { // List of subwikis.
|
||||
created: AddonModWikiCreatedPage[];
|
||||
discarded: AddonModWikiDiscardedPage[];
|
||||
};
|
||||
};
|
||||
siteId: string; // Site ID.
|
||||
};
|
||||
|
||||
/**
|
||||
* Data returned by a wiki sync for each subwiki synced.
|
||||
*/
|
||||
export type AddonModWikiSyncWikiSubwiki = {
|
||||
created: AddonModWikiCreatedPage[];
|
||||
discarded: AddonModWikiDiscardedPage[];
|
||||
};
|
||||
|
||||
/**
|
||||
* Data to identify a page created in sync.
|
||||
*/
|
||||
export type AddonModWikiCreatedPage = {
|
||||
pageId: number;
|
||||
title: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* Data to identify a page discarded in sync.
|
||||
*/
|
||||
export type AddonModWikiDiscardedPage = {
|
||||
title: string;
|
||||
warning: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* Data passed to AUTO_SYNCED event.
|
||||
*/
|
||||
export type AddonModWikiAutoSyncData = {
|
||||
siteId: string;
|
||||
subwikiId: number;
|
||||
wikiId: number;
|
||||
userId: number;
|
||||
groupId: number;
|
||||
created: AddonModWikiCreatedPage[];
|
||||
discarded: AddonModWikiDiscardedPage[];
|
||||
warnings: string[];
|
||||
};
|
||||
|
||||
/**
|
||||
* Data passed to MANUAL_SYNCED event.
|
||||
*/
|
||||
export type AddonModWikiManualSyncData = AddonModWikiSyncWikiResult & {
|
||||
wikiId: number;
|
||||
};
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,38 @@
|
|||
// (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 { RouterModule, Routes } from '@angular/router';
|
||||
import { CoreSharedModule } from '@/core/shared.module';
|
||||
import { AddonModWikiComponentsModule } from './components/components.module';
|
||||
import { AddonModWikiIndexPage } from './pages/index/index';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: ':courseId/:cmId/:hash',
|
||||
component: AddonModWikiIndexPage,
|
||||
},
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
RouterModule.forChild(routes),
|
||||
CoreSharedModule,
|
||||
AddonModWikiComponentsModule,
|
||||
],
|
||||
declarations: [
|
||||
AddonModWikiIndexPage,
|
||||
],
|
||||
})
|
||||
export class AddonModWikiLazyModule {}
|
|
@ -0,0 +1,81 @@
|
|||
// (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, Type } from '@angular/core';
|
||||
import { Routes } from '@angular/router';
|
||||
import { CoreContentLinksDelegate } from '@features/contentlinks/services/contentlinks-delegate';
|
||||
import { CoreCourseModuleDelegate } from '@features/course/services/module-delegate';
|
||||
import { CoreCourseModulePrefetchDelegate } from '@features/course/services/module-prefetch-delegate';
|
||||
import { CoreMainMenuTabRoutingModule } from '@features/mainmenu/mainmenu-tab-routing.module';
|
||||
import { CoreTagAreaDelegate } from '@features/tag/services/tag-area-delegate';
|
||||
import { CoreCronDelegate } from '@services/cron';
|
||||
import { CORE_SITE_SCHEMAS } from '@services/sites';
|
||||
import { AddonModWikiComponentsModule } from './components/components.module';
|
||||
import { OFFLINE_SITE_SCHEMA } from './services/database/wiki';
|
||||
import { AddonModWikiCreateLinkHandler } from './services/handlers/create-link';
|
||||
import { AddonModWikiEditLinkHandler } from './services/handlers/edit-link';
|
||||
import { AddonModWikiIndexLinkHandler } from './services/handlers/index-link';
|
||||
import { AddonModWikiListLinkHandler } from './services/handlers/list-link';
|
||||
import { AddonModWikiModuleHandler, AddonModWikiModuleHandlerService } from './services/handlers/module';
|
||||
import { AddonModWikiPageOrMapLinkHandler } from './services/handlers/page-or-map-link';
|
||||
import { AddonModWikiPrefetchHandler } from './services/handlers/prefetch';
|
||||
import { AddonModWikiSyncCronHandler } from './services/handlers/sync-cron';
|
||||
import { AddonModWikiTagAreaHandler } from './services/handlers/tag-area';
|
||||
import { AddonModWikiProvider } from './services/wiki';
|
||||
import { AddonModWikiOfflineProvider } from './services/wiki-offline';
|
||||
import { AddonModWikiSyncProvider } from './services/wiki-sync';
|
||||
|
||||
export const ADDON_MOD_WIKI_SERVICES: Type<unknown>[] = [
|
||||
AddonModWikiProvider,
|
||||
AddonModWikiOfflineProvider,
|
||||
AddonModWikiSyncProvider,
|
||||
];
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: AddonModWikiModuleHandlerService.PAGE_NAME,
|
||||
loadChildren: () => import('./wiki-lazy.module').then(m => m.AddonModWikiLazyModule),
|
||||
},
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CoreMainMenuTabRoutingModule.forChild(routes),
|
||||
AddonModWikiComponentsModule,
|
||||
],
|
||||
providers: [
|
||||
{
|
||||
provide: CORE_SITE_SCHEMAS,
|
||||
useValue: [OFFLINE_SITE_SCHEMA],
|
||||
multi: true,
|
||||
},
|
||||
{
|
||||
provide: APP_INITIALIZER,
|
||||
multi: true,
|
||||
deps: [],
|
||||
useFactory: () => () => {
|
||||
CoreCourseModuleDelegate.registerHandler(AddonModWikiModuleHandler.instance);
|
||||
CoreCourseModulePrefetchDelegate.registerHandler(AddonModWikiPrefetchHandler.instance);
|
||||
CoreCronDelegate.register(AddonModWikiSyncCronHandler.instance);
|
||||
CoreContentLinksDelegate.registerHandler(AddonModWikiIndexLinkHandler.instance);
|
||||
CoreContentLinksDelegate.registerHandler(AddonModWikiListLinkHandler.instance);
|
||||
CoreContentLinksDelegate.registerHandler(AddonModWikiCreateLinkHandler.instance);
|
||||
CoreContentLinksDelegate.registerHandler(AddonModWikiEditLinkHandler.instance);
|
||||
CoreContentLinksDelegate.registerHandler(AddonModWikiPageOrMapLinkHandler.instance);
|
||||
CoreTagAreaDelegate.registerHandler(AddonModWikiTagAreaHandler.instance);
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
export class AddonModWikiModule {}
|
|
@ -141,7 +141,7 @@ import { ADDON_MOD_RESOURCE_SERVICES } from '@addons/mod/resource/resource.modul
|
|||
import { ADDON_MOD_SCORM_SERVICES } from '@addons/mod/scorm/scorm.module';
|
||||
import { ADDON_MOD_SURVEY_SERVICES } from '@addons/mod/survey/survey.module';
|
||||
import { ADDON_MOD_URL_SERVICES } from '@addons/mod/url/url.module';
|
||||
// @todo import { ADDON_MOD_WIKI_SERVICES } from '@addons/mod/wiki/wiki.module';
|
||||
import { ADDON_MOD_WIKI_SERVICES } from '@addons/mod/wiki/wiki.module';
|
||||
// @todo import { ADDON_MOD_WORKSHOP_SERVICES } from '@addons/mod/workshop/workshop.module';
|
||||
import { ADDON_NOTES_SERVICES } from '@addons/notes/notes.module';
|
||||
import { ADDON_NOTIFICATIONS_SERVICES } from '@addons/notifications/notifications.module';
|
||||
|
@ -307,7 +307,7 @@ export class CoreCompileProvider {
|
|||
...ADDON_MOD_SCORM_SERVICES,
|
||||
...ADDON_MOD_SURVEY_SERVICES,
|
||||
...ADDON_MOD_URL_SERVICES,
|
||||
// @todo ...ADDON_MOD_WIKI_SERVICES,
|
||||
...ADDON_MOD_WIKI_SERVICES,
|
||||
// @todo ...ADDON_MOD_WORKSHOP_SERVICES,
|
||||
...ADDON_NOTES_SERVICES,
|
||||
...ADDON_NOTIFICATIONS_SERVICES,
|
||||
|
|
|
@ -42,6 +42,7 @@ import { CoreCronDelegate } from '@services/cron';
|
|||
import { CoreCourseLogCronHandler } from './handlers/log-cron';
|
||||
import { CoreSitePlugins } from '@features/siteplugins/services/siteplugins';
|
||||
import { CoreCourseAutoSyncData, CoreCourseSyncProvider } from './sync';
|
||||
import { CoreTagItem } from '@features/tag/services/tag';
|
||||
|
||||
const ROOT_CACHE_KEY = 'mmCourse:';
|
||||
|
||||
|
@ -1473,18 +1474,7 @@ export type CoreCourseModuleContentFile = {
|
|||
userid: number; // User who added this content to moodle.
|
||||
author: string; // Content owner.
|
||||
license: string; // Content license.
|
||||
tags?: { // Tags.
|
||||
id: number; // Tag id.
|
||||
name: string; // Tag name.
|
||||
rawname: string; // The raw, unnormalised name for the tag as entered by users.
|
||||
isstandard: boolean; // Whether this tag is standard.
|
||||
tagcollid: number; // Tag collection id.
|
||||
taginstanceid: number; // Tag instance id.
|
||||
taginstancecontextid: number; // Context the tag instance belongs to.
|
||||
itemid: number; // Id of the record tagged.
|
||||
ordering: number; // Tag ordering.
|
||||
flag: number; // Whether the tag is flagged as inappropriate.
|
||||
}[];
|
||||
tags?: CoreTagItem[]; // Tags.
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -428,14 +428,14 @@ export type CoreTagIndex = {
|
|||
* Structure of a tag item returned by WS.
|
||||
*/
|
||||
export type CoreTagItem = {
|
||||
id: number;
|
||||
name: string;
|
||||
rawname: string;
|
||||
isstandard: boolean;
|
||||
tagcollid: number;
|
||||
taginstanceid: number;
|
||||
taginstancecontextid: number;
|
||||
itemid: number;
|
||||
ordering: number;
|
||||
flag: number;
|
||||
id: number; // Tag id.
|
||||
name: string; // Tag name.
|
||||
rawname: string; // The raw, unnormalised name for the tag as entered by users.
|
||||
isstandard: boolean; // Whether this tag is standard.
|
||||
tagcollid: number; // Tag collection id.
|
||||
taginstanceid: number; // Tag instance id.
|
||||
taginstancecontextid: number; // Context the tag instance belongs to.
|
||||
itemid: number; // Id of the record tagged.
|
||||
ordering: number; // Tag ordering.
|
||||
flag: number; // Whether the tag is flagged as inappropriate.
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue