diff --git a/scripts/langindex.json b/scripts/langindex.json index e8a39aa49..a20b51ddd 100644 --- a/scripts/langindex.json +++ b/scripts/langindex.json @@ -24,6 +24,8 @@ "addon.block_myoverview.title": "block_myoverview", "addon.block_recentlyaccessedcourses.nocourses": "block_recentlyaccessedcourses", "addon.block_recentlyaccessedcourses.pluginname": "block_recentlyaccessedcourses", + "addon.block_recentlyaccesseditems.noitems": "block_recentlyaccesseditems", + "addon.block_recentlyaccesseditems.pluginname": "block_recentlyaccesseditems", "addon.block_sitemainmenu.pluginname": "block_site_main_menu", "addon.block_timeline.duedate": "block_timeline", "addon.block_timeline.next30days": "block_timeline", diff --git a/src/addon/block/recentlyaccesseditems/components/components.module.ts b/src/addon/block/recentlyaccesseditems/components/components.module.ts new file mode 100644 index 000000000..1ce6d5557 --- /dev/null +++ b/src/addon/block/recentlyaccesseditems/components/components.module.ts @@ -0,0 +1,45 @@ +// (C) Copyright 2015 Martin Dougiamas +// +// 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 { CommonModule } from '@angular/common'; +import { IonicModule } from 'ionic-angular'; +import { TranslateModule } from '@ngx-translate/core'; +import { AddonBlockRecentlyAccessedItemsComponent } from './recentlyaccesseditems/recentlyaccesseditems'; +import { CoreComponentsModule } from '@components/components.module'; +import { CoreDirectivesModule } from '@directives/directives.module'; +import { CoreCourseComponentsModule } from '@core/course/components/components.module'; + +@NgModule({ + declarations: [ + AddonBlockRecentlyAccessedItemsComponent + ], + imports: [ + CommonModule, + IonicModule, + TranslateModule.forChild(), + CoreComponentsModule, + CoreDirectivesModule, + CoreCourseComponentsModule + ], + providers: [ + ], + exports: [ + AddonBlockRecentlyAccessedItemsComponent + ], + entryComponents: [ + AddonBlockRecentlyAccessedItemsComponent + ] +}) +export class AddonBlockRecentlyAccessedItemsComponentsModule {} diff --git a/src/addon/block/recentlyaccesseditems/components/recentlyaccesseditems/addon-block-recentlyaccesseditems.html b/src/addon/block/recentlyaccesseditems/components/recentlyaccesseditems/addon-block-recentlyaccesseditems.html new file mode 100644 index 000000000..5b514dc86 --- /dev/null +++ b/src/addon/block/recentlyaccesseditems/components/recentlyaccesseditems/addon-block-recentlyaccesseditems.html @@ -0,0 +1,15 @@ + +

{{ 'addon.block_recentlyaccesseditems.pluginname' | translate }}

+
+ + + + +

+

+
+
+ + + +
diff --git a/src/addon/block/recentlyaccesseditems/components/recentlyaccesseditems/recentlyaccesseditems.ts b/src/addon/block/recentlyaccesseditems/components/recentlyaccesseditems/recentlyaccesseditems.ts new file mode 100644 index 000000000..e1c9bf372 --- /dev/null +++ b/src/addon/block/recentlyaccesseditems/components/recentlyaccesseditems/recentlyaccesseditems.ts @@ -0,0 +1,90 @@ +// (C) Copyright 2015 Martin Dougiamas +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { Component, OnInit, Injector, Optional } from '@angular/core'; +import { NavController } from 'ionic-angular'; +import { CoreSitesProvider } from '@providers/sites'; +import { CoreBlockBaseComponent } from '@core/block/classes/base-block-component'; +import { AddonBlockRecentlyAccessedItemsProvider } from '../../providers/recentlyaccesseditems'; +import { CoreTextUtilsProvider } from '@providers/utils/text'; +import { CoreContentLinksHelperProvider } from '@core/contentlinks/providers/helper'; + +/** + * Component to render a recently accessed items block. + */ +@Component({ + selector: 'addon-block-recentlyaccesseditems', + templateUrl: 'addon-block-recentlyaccesseditems.html' +}) +export class AddonBlockRecentlyAccessedItemsComponent extends CoreBlockBaseComponent implements OnInit { + items = []; + + protected fetchContentDefaultError = 'Error getting recently accessed items data.'; + + constructor(injector: Injector, @Optional() private navCtrl: NavController, + private sitesProvider: CoreSitesProvider, private textUtils: CoreTextUtilsProvider, + private recentItemsProvider: AddonBlockRecentlyAccessedItemsProvider, + private contentLinksHelper: CoreContentLinksHelperProvider) { + + super(injector, 'AddonBlockRecentlyAccessedItemsComponent'); + } + + /** + * Component being initialized. + */ + ngOnInit(): void { + super.ngOnInit(); + } + + /** + * Perform the invalidate content function. + * + * @return {Promise} Resolved when done. + */ + protected invalidateContent(): Promise { + return this.recentItemsProvider.invalidateRecentItems(); + } + + /** + * Fetch the data to render the block. + * + * @return {Promise} Promise resolved when done. + */ + protected fetchContent(): Promise { + return this.recentItemsProvider.getRecentItems().then((items) => { + this.items = items; + }); + } + + /** + * Event clicked. + * + * @param {Event} e Click event. + * @param {any} item Activity item info. + */ + action(e: Event, item: any): void { + e.preventDefault(); + e.stopPropagation(); + + const url = this.textUtils.decodeHTMLEntities(item.viewurl); + const modal = this.domUtils.showModalLoading(); + this.contentLinksHelper.handleLink(url, undefined, this.navCtrl).then((treated) => { + if (!treated) { + return this.sitesProvider.getCurrentSite().openInBrowserWithAutoLoginIfSameSite(url); + } + }).finally(() => { + modal.dismiss(); + }); + } +} diff --git a/src/addon/block/recentlyaccesseditems/lang/en.json b/src/addon/block/recentlyaccesseditems/lang/en.json new file mode 100644 index 000000000..47311d281 --- /dev/null +++ b/src/addon/block/recentlyaccesseditems/lang/en.json @@ -0,0 +1,4 @@ +{ + "noitems": "No recent items", + "pluginname": "Recently accessed items" +} diff --git a/src/addon/block/recentlyaccesseditems/providers/block-handler.ts b/src/addon/block/recentlyaccesseditems/providers/block-handler.ts new file mode 100644 index 000000000..2963017e8 --- /dev/null +++ b/src/addon/block/recentlyaccesseditems/providers/block-handler.ts @@ -0,0 +1,50 @@ +// (C) Copyright 2015 Martin Dougiamas +// +// 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, Injector } from '@angular/core'; +import { CoreBlockHandlerData } from '@core/block/providers/delegate'; +import { AddonBlockRecentlyAccessedItemsComponent } from '../components/recentlyaccesseditems/recentlyaccesseditems'; +import { CoreBlockBaseHandler } from '@core/block/classes/base-block-handler'; + +/** + * Block handler. + */ +@Injectable() +export class AddonBlockRecentlyAccessedItemsHandler extends CoreBlockBaseHandler { + name = 'AddonBlockRecentlyAccessedItems'; + blockName = 'recentlyaccesseditems'; + + constructor() { + super(); + } + + /** + * Returns the data needed to render the block. + * + * @param {Injector} injector Injector. + * @param {any} block The block to render. + * @param {string} contextLevel The context where the block will be used. + * @param {number} instanceId The instance ID associated with the context level. + * @return {CoreBlockHandlerData|Promise} Data or promise resolved with the data. + */ + getDisplayData?(injector: Injector, block: any, contextLevel: string, instanceId: number) + : CoreBlockHandlerData | Promise { + + return { + title: 'addon.block_recentlyaccesseditems.pluginname', + class: 'addon-block-recentlyaccesseditems', + component: AddonBlockRecentlyAccessedItemsComponent + }; + } +} diff --git a/src/addon/block/recentlyaccesseditems/providers/recentlyaccesseditems.ts b/src/addon/block/recentlyaccesseditems/providers/recentlyaccesseditems.ts new file mode 100644 index 000000000..e20e41b1f --- /dev/null +++ b/src/addon/block/recentlyaccesseditems/providers/recentlyaccesseditems.ts @@ -0,0 +1,71 @@ +// (C) Copyright 2015 Martin Dougiamas +// +// 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 { CoreSitesProvider } from '@providers/sites'; +import { CoreCourseProvider } from '@core/course/providers/course'; + +/** + * Service that provides some features regarding recently accessed items. + */ +@Injectable() +export class AddonBlockRecentlyAccessedItemsProvider { + protected ROOT_CACHE_KEY = 'AddonBlockRecentlyAccessedItems:'; + + constructor(private sitesProvider: CoreSitesProvider, private courseProvider: CoreCourseProvider) { } + + /** + * Get cache key for get last accessed items value WS call. + * + * @return {string} Cache key. + */ + protected getRecentItemsCacheKey(): string { + return this.ROOT_CACHE_KEY + ':recentitems'; + } + + /** + * Get last accessed items. + * + * @param {string} [siteId] Site ID. If not defined, use current site. + * @return {Promise} Promise resolved when the info is retrieved. + */ + getRecentItems(siteId?: string): Promise { + + return this.sitesProvider.getSite(siteId).then((site) => { + const preSets = { + cacheKey: this.getRecentItemsCacheKey() + }; + + return site.read('block_recentlyaccesseditems_get_recent_items', undefined, preSets).then((items) => { + return items.map((item) => { + item.iconUrl = this.courseProvider.getModuleIconSrc(item.modname); + + return item; + }); + }); + }); + } + + /** + * Invalidates get last accessed items WS call. + * + * @param {string} [siteId] Site ID to invalidate. If not defined, use current site. + * @return {Promise} Promise resolved when the data is invalidated. + */ + invalidateRecentItems(siteId?: string): Promise { + return this.sitesProvider.getSite(siteId).then((site) => { + return site.invalidateWsCacheForKey(this.getRecentItemsCacheKey()); + }); + } +} diff --git a/src/addon/block/recentlyaccesseditems/recentlyaccesseditems.module.ts b/src/addon/block/recentlyaccesseditems/recentlyaccesseditems.module.ts new file mode 100644 index 000000000..5df77fe5f --- /dev/null +++ b/src/addon/block/recentlyaccesseditems/recentlyaccesseditems.module.ts @@ -0,0 +1,42 @@ +// (C) Copyright 2015 Martin Dougiamas +// +// 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 { IonicModule } from 'ionic-angular'; +import { TranslateModule } from '@ngx-translate/core'; +import { AddonBlockRecentlyAccessedItemsComponentsModule } from './components/components.module'; +import { CoreBlockDelegate } from '@core/block/providers/delegate'; +import { AddonBlockRecentlyAccessedItemsHandler } from './providers/block-handler'; +import { AddonBlockRecentlyAccessedItemsProvider } from './providers/recentlyaccesseditems'; + +@NgModule({ + declarations: [ + ], + imports: [ + IonicModule, + AddonBlockRecentlyAccessedItemsComponentsModule, + TranslateModule.forChild() + ], + exports: [ + ], + providers: [ + AddonBlockRecentlyAccessedItemsHandler, + AddonBlockRecentlyAccessedItemsProvider + ] +}) +export class AddonBlockRecentlyAccessedItemsModule { + constructor(blockDelegate: CoreBlockDelegate, blockHandler: AddonBlockRecentlyAccessedItemsHandler) { + blockDelegate.registerHandler(blockHandler); + } +} diff --git a/src/app/app.module.ts b/src/app/app.module.ts index d54c8dfe3..ca4cd023b 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -89,6 +89,7 @@ import { AddonBlockMyOverviewModule } from '@addon/block/myoverview/myoverview.m import { AddonBlockSiteMainMenuModule } from '@addon/block/sitemainmenu/sitemainmenu.module'; import { AddonBlockTimelineModule } from '@addon/block/timeline/timeline.module'; import { AddonBlockRecentlyAccessedCoursesModule } from '@addon/block/recentlyaccessedcourses/recentlyaccessedcourses.module'; +import { AddonBlockRecentlyAccessedItemsModule } from '@addon/block/recentlyaccesseditems/recentlyaccesseditems.module'; import { AddonModAssignModule } from '@addon/mod/assign/assign.module'; import { AddonModBookModule } from '@addon/mod/book/book.module'; import { AddonModChatModule } from '@addon/mod/chat/chat.module'; @@ -204,6 +205,7 @@ export const CORE_PROVIDERS: any[] = [ AddonBlockSiteMainMenuModule, AddonBlockTimelineModule, AddonBlockRecentlyAccessedCoursesModule, + AddonBlockRecentlyAccessedItemsModule, AddonModAssignModule, AddonModBookModule, AddonModChatModule, diff --git a/src/assets/lang/en.json b/src/assets/lang/en.json index ba1ffd309..7de748385 100644 --- a/src/assets/lang/en.json +++ b/src/assets/lang/en.json @@ -24,6 +24,8 @@ "addon.block_myoverview.title": "Title", "addon.block_recentlyaccessedcourses.nocourses": "No recent courses", "addon.block_recentlyaccessedcourses.pluginname": "Recently accessed courses", + "addon.block_recentlyaccesseditems.noitems": "No recent items", + "addon.block_recentlyaccesseditems.pluginname": "Recently accessed items", "addon.block_sitemainmenu.pluginname": "Main menu", "addon.block_timeline.duedate": "Due date", "addon.block_timeline.next30days": "Next 30 days", @@ -1647,4 +1649,4 @@ "core.year": "year", "core.years": "years", "core.yes": "Yes" -} \ No newline at end of file +}