commit
b81e49b46d
|
@ -0,0 +1,19 @@
|
||||||
|
# Editor configuration, see https://editorconfig.org
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 4
|
||||||
|
insert_final_newline = true
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
|
||||||
|
[*.json]
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
|
[*.ts]
|
||||||
|
quote_type = single
|
||||||
|
|
||||||
|
[*.md]
|
||||||
|
max_line_length = off
|
||||||
|
trim_trailing_whitespace = false
|
|
@ -1,18 +0,0 @@
|
||||||
name: Migration checks
|
|
||||||
|
|
||||||
on: workflow_dispatch
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
checks:
|
|
||||||
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
- uses: actions/setup-node@v3
|
|
||||||
with:
|
|
||||||
node-version-file: '.nvmrc'
|
|
||||||
- run: npm ci --no-audit
|
|
||||||
- run: result=$(find src -type f -iname '*.html' -exec sh -c 'cat {} | tr "\n" " " | grep -Eo "class=\"[^\"]+\"[^>]+class=\"" ' \; | wc -l); test $result -eq 0
|
|
||||||
- run: npm install -D @ionic/v4-migration-tslint
|
|
||||||
- run: npx tslint -c ionic-migration.json -p tsconfig.json
|
|
|
@ -6,32 +6,70 @@
|
||||||
.tmp
|
.tmp
|
||||||
*.tmp
|
*.tmp
|
||||||
*.tmp.*
|
*.tmp.*
|
||||||
*.sublime-project
|
|
||||||
*.sublime-workspace
|
|
||||||
.DS_Store
|
|
||||||
Thumbs.db
|
|
||||||
UserInterfaceState.xcuserstate
|
UserInterfaceState.xcuserstate
|
||||||
$RECYCLE.BIN/
|
$RECYCLE.BIN/
|
||||||
|
|
||||||
*.log
|
*.log
|
||||||
log.txt
|
log.txt
|
||||||
npm-debug.log*
|
|
||||||
|
|
||||||
/.idea
|
|
||||||
/.ionic
|
|
||||||
/.sass-cache
|
|
||||||
/.sourcemaps
|
/.sourcemaps
|
||||||
/.versions
|
/.versions
|
||||||
/coverage
|
/coverage
|
||||||
/dist
|
|
||||||
/node_modules
|
# Ionic
|
||||||
|
/.ionic
|
||||||
|
/www
|
||||||
/platforms
|
/platforms
|
||||||
/plugins
|
/plugins
|
||||||
/www
|
|
||||||
|
# Compiled output
|
||||||
|
/dist
|
||||||
|
/tmp
|
||||||
|
/out-tsc
|
||||||
|
/bazel-out
|
||||||
|
|
||||||
|
# Node
|
||||||
|
/node_modules
|
||||||
|
npm-debug.log
|
||||||
|
yarn-error.log
|
||||||
|
|
||||||
|
# IDEs and editors
|
||||||
|
.idea/
|
||||||
|
.project
|
||||||
|
.classpath
|
||||||
|
.c9/
|
||||||
|
*.launch
|
||||||
|
.settings/
|
||||||
|
*.sublime-project
|
||||||
|
*.sublime-workspace
|
||||||
|
|
||||||
|
# Visual Studio Code
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/settings.json
|
||||||
|
!.vscode/tasks.json
|
||||||
|
!.vscode/launch.json
|
||||||
|
!.vscode/extensions.json
|
||||||
|
.history/*
|
||||||
|
|
||||||
|
|
||||||
|
# Miscellaneous
|
||||||
|
/.angular
|
||||||
|
/.angular/cache
|
||||||
|
.sass-cache/
|
||||||
|
/connect.lock
|
||||||
|
/coverage
|
||||||
|
/libpeerconnection.log
|
||||||
|
testem.log
|
||||||
|
/typings
|
||||||
|
|
||||||
|
# System files
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
|
|
||||||
|
# Moodle App
|
||||||
/src/assets/lib
|
/src/assets/lib
|
||||||
|
/src/assets/lang/*
|
||||||
|
/src/assets/env.json
|
||||||
|
|
||||||
/moodle.config.*.json
|
/moodle.config.*.json
|
||||||
!/moodle.config.example.json
|
!/moodle.config.example.json
|
||||||
|
|
||||||
/src/assets/lang/*
|
|
||||||
/src/assets/env.json
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
{
|
{
|
||||||
"recommendations": [
|
"recommendations": [
|
||||||
|
"ionic.ionic",
|
||||||
"dbaeumer.vscode-eslint",
|
"dbaeumer.vscode-eslint",
|
||||||
"angular.ng-template"
|
"angular.ng-template"
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<?xml version='1.0' encoding='utf-8'?>
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
<widget android-versionCode="43001" id="com.moodle.moodlemobile" ios-CFBundleVersion="4.3.0.1" version="4.3.0" versionCode="43001" xmlns="http://www.w3.org/ns/widgets" xmlns:android="http://schemas.android.com/apk/res/android" xmlns:cdv="http://cordova.apache.org/ns/1.0">
|
<widget android-versionCode="44000" id="com.moodle.moodlemobile" ios-CFBundleVersion="4.4.0.0" version="4.4.0" versionCode="44000" xmlns="http://www.w3.org/ns/widgets" xmlns:android="http://schemas.android.com/apk/res/android" xmlns:cdv="http://cordova.apache.org/ns/1.0">
|
||||||
<name>Moodle</name>
|
<name>Moodle</name>
|
||||||
<description>Moodle official app</description>
|
<description>Moodle official app</description>
|
||||||
<author email="mobile@moodle.com" href="http://moodle.com">Moodle Mobile team</author>
|
<author email="mobile@moodle.com" href="http://moodle.com">Moodle Mobile team</author>
|
||||||
|
@ -28,7 +28,7 @@
|
||||||
<preference name="UIWebViewBounce" value="false" />
|
<preference name="UIWebViewBounce" value="false" />
|
||||||
<preference name="DisallowOverscroll" value="true" />
|
<preference name="DisallowOverscroll" value="true" />
|
||||||
<preference name="prerendered-icon" value="true" />
|
<preference name="prerendered-icon" value="true" />
|
||||||
<preference name="AppendUserAgent" value="MoodleMobile 4.3.0 (43001)" />
|
<preference name="AppendUserAgent" value="MoodleMobile 4.4.0 (44000)" />
|
||||||
<preference name="BackupWebStorage" value="none" />
|
<preference name="BackupWebStorage" value="none" />
|
||||||
<preference name="ScrollEnabled" value="false" />
|
<preference name="ScrollEnabled" value="false" />
|
||||||
<preference name="KeyboardDisplayRequiresUserAction" value="false" />
|
<preference name="KeyboardDisplayRequiresUserAction" value="false" />
|
||||||
|
@ -220,7 +220,7 @@
|
||||||
<true />
|
<true />
|
||||||
</edit-config>
|
</edit-config>
|
||||||
<edit-config file="*-Info.plist" mode="merge" target="CFBundleShortVersionString">
|
<edit-config file="*-Info.plist" mode="merge" target="CFBundleShortVersionString">
|
||||||
<string>4.3.0</string>
|
<string>4.4.0</string>
|
||||||
</edit-config>
|
</edit-config>
|
||||||
<edit-config file="*-Info.plist" mode="overwrite" target="CFBundleLocalizations">
|
<edit-config file="*-Info.plist" mode="overwrite" target="CFBundleLocalizations">
|
||||||
<array>
|
<array>
|
||||||
|
|
|
@ -1,43 +0,0 @@
|
||||||
{
|
|
||||||
"rulesDirectory": ["@ionic/v4-migration-tslint/rules"],
|
|
||||||
"rules": {
|
|
||||||
"ion-action-sheet-method-create-parameters-renamed": true,
|
|
||||||
"ion-alert-method-create-parameters-renamed": true,
|
|
||||||
"ion-back-button-not-added-by-default": { "options": [true], "severity": "warning" },
|
|
||||||
"ion-button-attributes-renamed": true,
|
|
||||||
"ion-button-is-now-an-element": true,
|
|
||||||
"ion-buttons-attributes-renamed": true,
|
|
||||||
"ion-col-attributes-renamed": true,
|
|
||||||
"ion-datetime-capitalization-changed": true,
|
|
||||||
"ion-fab-attributes-renamed": true,
|
|
||||||
"ion-fab-button-is-now-an-element": true,
|
|
||||||
"ion-fab-fixed-content": true,
|
|
||||||
"ion-icon-attribute-is-active-removed": true,
|
|
||||||
"ion-item-attributes-renamed": true,
|
|
||||||
"ion-item-divider-ion-label-required": true,
|
|
||||||
"ion-item-ion-label-required": true,
|
|
||||||
"ion-item-is-now-an-element": true,
|
|
||||||
"ion-item-option-is-now-an-element": true,
|
|
||||||
"ion-item-option-method-get-sliding-percent-renamed": true,
|
|
||||||
"ion-item-options-attribute-values-renamed": true,
|
|
||||||
"ion-label-attributes-renamed": true,
|
|
||||||
"ion-list-header-ion-label-required": true,
|
|
||||||
"ion-loading-method-create-parameters-renamed": true,
|
|
||||||
"ion-menu-events-renamed": true,
|
|
||||||
"ion-menu-toggle-is-now-an-element": true,
|
|
||||||
"ion-navbar-is-now-ion-toolbar": true,
|
|
||||||
"ion-option-is-now-ion-select-option": true,
|
|
||||||
"ion-overlay-method-create-should-use-await": true,
|
|
||||||
"ion-overlay-method-present-should-use-await": { "options": [true], "severity": "warning" },
|
|
||||||
"ion-radio-attributes-renamed": true,
|
|
||||||
"ion-radio-group-is-now-an-element": true,
|
|
||||||
"ion-radio-slot-required": true,
|
|
||||||
"ion-range-attributes-renamed": true,
|
|
||||||
"ion-segment-button-ion-label-required": true,
|
|
||||||
"ion-spinner-attribute-values-renamed": true,
|
|
||||||
"ion-tabs-refactored": { "options": [true], "severity": "warning" },
|
|
||||||
"ion-text-is-now-an-element": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
{
|
{
|
||||||
"app_id": "com.moodle.moodlemobile",
|
"app_id": "com.moodle.moodlemobile",
|
||||||
"appname": "Moodle Mobile",
|
"appname": "Moodle Mobile",
|
||||||
"versioncode": 43001,
|
"versioncode": 44000,
|
||||||
"versionname": "4.3.0",
|
"versionname": "4.4.0",
|
||||||
"cache_update_frequency_usually": 420000,
|
"cache_update_frequency_usually": 420000,
|
||||||
"cache_update_frequency_often": 1200000,
|
"cache_update_frequency_often": 1200000,
|
||||||
"cache_update_frequency_sometimes": 3600000,
|
"cache_update_frequency_sometimes": 3600000,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "moodlemobile",
|
"name": "moodlemobile",
|
||||||
"version": "4.3.0",
|
"version": "4.4.0",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "moodlemobile",
|
"name": "moodlemobile",
|
||||||
"version": "4.3.0",
|
"version": "4.4.0",
|
||||||
"description": "The official app for Moodle.",
|
"description": "The official app for Moodle.",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "Moodle Pty Ltd.",
|
"name": "Moodle Pty Ltd.",
|
||||||
|
|
|
@ -13,7 +13,6 @@
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import { Component, OnDestroy, OnInit } from '@angular/core';
|
import { Component, OnDestroy, OnInit } from '@angular/core';
|
||||||
import { IonRefresher } from '@ionic/angular';
|
|
||||||
import { CoreTimeUtils } from '@services/utils/time';
|
import { CoreTimeUtils } from '@services/utils/time';
|
||||||
import { CoreDomUtils } from '@services/utils/dom';
|
import { CoreDomUtils } from '@services/utils/dom';
|
||||||
import { CoreSites } from '@services/sites';
|
import { CoreSites } from '@services/sites';
|
||||||
|
@ -130,7 +129,7 @@ export class AddonBadgesIssuedBadgePage implements OnInit, OnDestroy {
|
||||||
*
|
*
|
||||||
* @param refresher Refresher.
|
* @param refresher Refresher.
|
||||||
*/
|
*/
|
||||||
async refreshBadges(refresher?: IonRefresher): Promise<void> {
|
async refreshBadges(refresher?: HTMLIonRefresherElement): Promise<void> {
|
||||||
await CoreUtils.ignoreErrors(Promise.all([
|
await CoreUtils.ignoreErrors(Promise.all([
|
||||||
AddonBadges.invalidateUserBadges(this.courseId, this.userId),
|
AddonBadges.invalidateUserBadges(this.courseId, this.userId),
|
||||||
]));
|
]));
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
|
|
||||||
<ion-list *ngIf="!badges.empty" class="ion-no-margin">
|
<ion-list *ngIf="!badges.empty" class="ion-no-margin">
|
||||||
<ion-item button class="ion-text-wrap" *ngFor="let badge of badges.items" [attr.aria-label]="badge.name"
|
<ion-item button class="ion-text-wrap" *ngFor="let badge of badges.items" [attr.aria-label]="badge.name"
|
||||||
(click)="badges.select(badge)" [attr.aria-current]="badges.getItemAriaCurrent(badge)" detail="true">
|
(click)="badges.select(badge)" [attr.aria-current]="badges.getItemAriaCurrent(badge)" [detail]="true">
|
||||||
<ion-avatar slot="start">
|
<ion-avatar slot="start">
|
||||||
<img [src]="badge.badgeurl" [alt]="badge.name" core-external-content>
|
<img [src]="badge.badgeurl" [alt]="badge.name" core-external-content>
|
||||||
</ion-avatar>
|
</ion-avatar>
|
||||||
|
|
|
@ -13,7 +13,6 @@
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import { AfterViewInit, Component, OnDestroy, ViewChild } from '@angular/core';
|
import { AfterViewInit, Component, OnDestroy, ViewChild } from '@angular/core';
|
||||||
import { IonRefresher } from '@ionic/angular';
|
|
||||||
import { AddonBadges, AddonBadgesUserBadge } from '../../services/badges';
|
import { AddonBadges, AddonBadgesUserBadge } from '../../services/badges';
|
||||||
import { CoreTimeUtils } from '@services/utils/time';
|
import { CoreTimeUtils } from '@services/utils/time';
|
||||||
import { CoreDomUtils } from '@services/utils/dom';
|
import { CoreDomUtils } from '@services/utils/dom';
|
||||||
|
@ -90,7 +89,7 @@ export class AddonBadgesUserBadgesPage implements AfterViewInit, OnDestroy {
|
||||||
*
|
*
|
||||||
* @param refresher Refresher.
|
* @param refresher Refresher.
|
||||||
*/
|
*/
|
||||||
async refreshBadges(refresher?: IonRefresher): Promise<void> {
|
async refreshBadges(refresher?: HTMLIonRefresherElement): Promise<void> {
|
||||||
await CoreUtils.ignoreErrors(
|
await CoreUtils.ignoreErrors(
|
||||||
AddonBadges.invalidateUserBadges(
|
AddonBadges.invalidateUserBadges(
|
||||||
this.badges.getSource().COURSE_ID,
|
this.badges.getSource().COURSE_ID,
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
<ion-item-divider sticky="true">
|
<ion-item-divider [sticky]="true">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<h2>{{ 'addon.block_activitymodules.pluginname' | translate }}</h2>
|
<h2>{{ 'addon.block_activitymodules.pluginname' | translate }}</h2>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
</ion-item-divider>
|
</ion-item-divider>
|
||||||
<core-loading [hideUntil]="loaded">
|
<core-loading [hideUntil]="loaded">
|
||||||
<ion-item class="ion-text-wrap" *ngFor="let entry of entries" detail="true" button (click)="gotoCoureListModType(entry)">
|
<ion-item class="ion-text-wrap" *ngFor="let entry of entries" [detail]="true" button (click)="gotoCoureListModType(entry)">
|
||||||
<core-mod-icon slot="start" [modicon]="entry.icon" [modname]="entry.iconModName" [showAlt]="false">
|
<core-mod-icon slot="start" [modicon]="entry.icon" [modname]="entry.iconModName" [showAlt]="false">
|
||||||
</core-mod-icon>
|
</core-mod-icon>
|
||||||
<ion-label>{{ entry.name }}</ion-label>
|
<ion-label>{{ entry.name }}</ion-label>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<ion-item-divider sticky="true">
|
<ion-item-divider [sticky]="true">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<h2>{{ 'addon.block_myoverview.pluginname' | translate }}</h2>
|
<h2>{{ 'addon.block_myoverview.pluginname' | translate }}</h2>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
|
@ -88,11 +88,11 @@
|
||||||
</core-combobox>
|
</core-combobox>
|
||||||
</ion-col>
|
</ion-col>
|
||||||
<ion-col size="auto" *ngIf="isLayoutSwitcherAvailable">
|
<ion-col size="auto" *ngIf="isLayoutSwitcherAvailable">
|
||||||
<ion-button *ngIf="layout == 'card'" fill="outline" (click)="toggleLayout('list')"
|
<ion-button *ngIf="layout === 'card'" fill="outline" (click)="toggleLayout('list')"
|
||||||
[attr.aria-label]="'addon.block_myoverview.aria:list' | translate">
|
[attr.aria-label]="'addon.block_myoverview.aria:list' | translate">
|
||||||
<ion-icon slot="icon-only" name="fas-list" aria-hidden="true"></ion-icon>
|
<ion-icon slot="icon-only" name="fas-list" aria-hidden="true"></ion-icon>
|
||||||
</ion-button>
|
</ion-button>
|
||||||
<ion-button *ngIf="layout == 'list'" fill="outline" (click)="toggleLayout('card')"
|
<ion-button *ngIf="layout === 'list'" fill="outline" (click)="toggleLayout('card')"
|
||||||
[attr.aria-label]="'addon.block_myoverview.aria:card' | translate">
|
[attr.aria-label]="'addon.block_myoverview.aria:card' | translate">
|
||||||
<ion-icon slot="icon-only" name="fas-table-cells-large" aria-hidden="true"></ion-icon>
|
<ion-icon slot="icon-only" name="fas-table-cells-large" aria-hidden="true"></ion-icon>
|
||||||
</ion-button>
|
</ion-button>
|
||||||
|
@ -123,7 +123,7 @@
|
||||||
|
|
||||||
<!-- List of courses. -->
|
<!-- List of courses. -->
|
||||||
<div class="safe-area-padding" *ngIf="hasCourses">
|
<div class="safe-area-padding" *ngIf="hasCourses">
|
||||||
<ion-grid class="ion-no-padding" [class.core-no-grid]="layout != 'card'" [class.list-item-limited-width]="layout != 'card'">
|
<ion-grid class="ion-no-padding" [class.core-no-grid]="layout !== 'card'" [class.list-item-limited-width]="layout !== 'card'">
|
||||||
<ion-row class="ion-no-padding">
|
<ion-row class="ion-no-padding">
|
||||||
<ion-col *ngFor="let course of filteredCourses" class="ion-no-padding" size="12" size-sm="6" size-md="6" size-lg="4"
|
<ion-col *ngFor="let course of filteredCourses" class="ion-no-padding" size="12" size-sm="6" size-md="6" size-lg="4"
|
||||||
size-xl="3">
|
size-xl="3">
|
||||||
|
|
|
@ -31,7 +31,7 @@ import { CoreUtils } from '@services/utils/utils';
|
||||||
import { CoreDomUtils } from '@services/utils/dom';
|
import { CoreDomUtils } from '@services/utils/dom';
|
||||||
import { CoreTextUtils } from '@services/utils/text';
|
import { CoreTextUtils } from '@services/utils/text';
|
||||||
import { AddonCourseCompletion } from '@addons/coursecompletion/services/coursecompletion';
|
import { AddonCourseCompletion } from '@addons/coursecompletion/services/coursecompletion';
|
||||||
import { IonRefresher, IonSearchbar } from '@ionic/angular';
|
import { IonSearchbar } from '@ionic/angular';
|
||||||
import { CoreNavigator } from '@services/navigator';
|
import { CoreNavigator } from '@services/navigator';
|
||||||
import { PageLoadWatcher } from '@classes/page-load-watcher';
|
import { PageLoadWatcher } from '@classes/page-load-watcher';
|
||||||
import { PageLoadsManager } from '@classes/page-loads-manager';
|
import { PageLoadsManager } from '@classes/page-loads-manager';
|
||||||
|
@ -191,7 +191,7 @@ export class AddonBlockMyOverviewComponent extends CoreBlockBaseComponent implem
|
||||||
* @param done Function to call when done.
|
* @param done Function to call when done.
|
||||||
* @returns Promise resolved when done.
|
* @returns Promise resolved when done.
|
||||||
*/
|
*/
|
||||||
async doRefresh(refresher?: IonRefresher, done?: () => void): Promise<void> {
|
async doRefresh(refresher?: HTMLIonRefresherElement, done?: () => void): Promise<void> {
|
||||||
if (this.loaded) {
|
if (this.loaded) {
|
||||||
return this.refreshContent().finally(() => {
|
return this.refreshContent().finally(() => {
|
||||||
refresher?.complete();
|
refresher?.complete();
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
@import "~theme/globals";
|
@use "theme/globals" as *;
|
||||||
:host {
|
:host {
|
||||||
--core-avatar-size: 30px;
|
--core-avatar-size: 30px;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
@import "~theme/globals";
|
@use "theme/globals" as *;
|
||||||
|
|
||||||
:host .core-block-content ::ng-deep {
|
:host .core-block-content ::ng-deep {
|
||||||
.activitydate, .activityhead {
|
.activitydate, .activityhead {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<ion-item-divider sticky="true">
|
<ion-item-divider [sticky]="true">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<h2>{{ 'addon.block_recentlyaccessedcourses.pluginname' | translate }}</h2>
|
<h2>{{ 'addon.block_recentlyaccessedcourses.pluginname' | translate }}</h2>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<ion-item-divider sticky="true">
|
<ion-item-divider [sticky]="true">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<h2>{{ 'addon.block_recentlyaccesseditems.pluginname' | translate }}</h2>
|
<h2>{{ 'addon.block_recentlyaccesseditems.pluginname' | translate }}</h2>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
|
@ -14,7 +14,7 @@
|
||||||
<div class="safe-area-pseudo-padding-start"></div>
|
<div class="safe-area-pseudo-padding-start"></div>
|
||||||
<div *ngFor="let item of items" class="core-horizontal-scroll-item">
|
<div *ngFor="let item of items" class="core-horizontal-scroll-item">
|
||||||
<ion-card>
|
<ion-card>
|
||||||
<ion-item class="core-course-module-handler ion-text-wrap" detail="false" (click)="action($event, item)" button>
|
<ion-item class="core-course-module-handler ion-text-wrap" [detail]="false" (click)="action($event, item)" button>
|
||||||
<core-mod-icon slot="start" *ngIf="item.iconUrl" [modicon]="item.iconUrl" [modname]="item.modname"
|
<core-mod-icon slot="start" *ngIf="item.iconUrl" [modicon]="item.iconUrl" [modname]="item.modname"
|
||||||
[componentId]="item.cmid" [showAlt]="false" [purpose]="item.purpose">
|
[componentId]="item.cmid" [showAlt]="false" [purpose]="item.purpose">
|
||||||
</core-mod-icon>
|
</core-mod-icon>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
@import "~theme/globals";
|
@use "theme/globals" as *;
|
||||||
|
|
||||||
:host {
|
:host {
|
||||||
.core-horizontal-scroll div.core-horizontal-scroll-item {
|
.core-horizontal-scroll div.core-horizontal-scroll-item {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<ion-item-divider sticky="true">
|
<ion-item-divider [sticky]="true">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<h2>{{ 'addon.block_sitemainmenu.pluginname' | translate }}</h2>
|
<h2>{{ 'addon.block_sitemainmenu.pluginname' | translate }}</h2>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<ion-item-divider sticky="true">
|
<ion-item-divider [sticky]="true">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<h2>{{ 'addon.block_starredcourses.pluginname' | translate }}</h2>
|
<h2>{{ 'addon.block_starredcourses.pluginname' | translate }}</h2>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
|
|
|
@ -44,7 +44,7 @@ export class AddonBlockTimelineSection {
|
||||||
this.overdue = overdue;
|
this.overdue = overdue;
|
||||||
this.dateRange = dateRange;
|
this.dateRange = dateRange;
|
||||||
this.course = course;
|
this.course = course;
|
||||||
this.dataSubject$ = new BehaviorSubject({
|
this.dataSubject$ = new BehaviorSubject<AddonBlockTimelineSectionData>({
|
||||||
events: [],
|
events: [],
|
||||||
lastEventId: canLoadMore,
|
lastEventId: canLoadMore,
|
||||||
canLoadMore: typeof canLoadMore !== 'undefined',
|
canLoadMore: typeof canLoadMore !== 'undefined',
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
</ion-label>
|
</ion-label>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
<ng-container *ngFor="let event of dayEvents.events">
|
<ng-container *ngFor="let event of dayEvents.events">
|
||||||
<ion-item class="addon-block-timeline-activity" detail="false" (click)="action($event, event.url)" [attr.aria-label]="event.name"
|
<ion-item class="addon-block-timeline-activity" [detail]="false" (click)="action($event, event.url)" [attr.aria-label]="event.name"
|
||||||
button lines="full">
|
button lines="full">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<ion-row class="ion-justify-content-between ion-align-items-center ion-no-padding">
|
<ion-row class="ion-justify-content-between ion-align-items-center ion-no-padding">
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
@import "~theme/globals";
|
@use "theme/globals" as *;
|
||||||
|
|
||||||
h3 {
|
h3 {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<ion-item-divider sticky="true">
|
<ion-item-divider [sticky]="true">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<h2>{{ 'addon.block_timeline.pluginname' | translate }}</h2>
|
<h2>{{ 'addon.block_timeline.pluginname' | translate }}</h2>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
|
|
|
@ -56,7 +56,7 @@ export class AddonBlockTimelineComponent implements OnInit, ICoreBlockComponent
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.logger = CoreLogger.getInstance('AddonBlockTimelineComponent');
|
this.logger = CoreLogger.getInstance('AddonBlockTimelineComponent');
|
||||||
this.search$ = new BehaviorSubject(null);
|
this.search$ = new BehaviorSubject<string | null>(null);
|
||||||
this.initializeSort();
|
this.initializeSort();
|
||||||
this.initializeFilter();
|
this.initializeFilter();
|
||||||
this.initializeSections();
|
this.initializeSections();
|
||||||
|
|
|
@ -65,7 +65,7 @@
|
||||||
<core-file *ngFor="let file of entry.attachmentfiles" [file]="file" [component]="this.component"
|
<core-file *ngFor="let file of entry.attachmentfiles" [file]="file" [component]="this.component"
|
||||||
[componentId]="entry.id">
|
[componentId]="entry.id">
|
||||||
</core-file>
|
</core-file>
|
||||||
<ion-item *ngIf="entry.uniquehash" [href]="entry.uniquehash" core-link detail="true">
|
<ion-item *ngIf="entry.uniquehash" [href]="entry.uniquehash" core-link [detail]="true">
|
||||||
<ion-label>{{ 'addon.blog.linktooriginalentry' | translate }}</ion-label>
|
<ion-label>{{ 'addon.blog.linktooriginalentry' | translate }}</ion-label>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
</ion-card-content>
|
</ion-card-content>
|
||||||
|
|
|
@ -19,7 +19,6 @@ import { CoreComments } from '@features/comments/services/comments';
|
||||||
import { CoreMainMenuDeepLinkManager } from '@features/mainmenu/classes/deep-link-manager';
|
import { CoreMainMenuDeepLinkManager } from '@features/mainmenu/classes/deep-link-manager';
|
||||||
import { CoreTag } from '@features/tag/services/tag';
|
import { CoreTag } from '@features/tag/services/tag';
|
||||||
import { CoreUser, CoreUserProfile } from '@features/user/services/user';
|
import { CoreUser, CoreUserProfile } from '@features/user/services/user';
|
||||||
import { IonRefresher } from '@ionic/angular';
|
|
||||||
import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
|
import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
|
||||||
import { CoreNavigator } from '@services/navigator';
|
import { CoreNavigator } from '@services/navigator';
|
||||||
import { CoreSites } from '@services/sites';
|
import { CoreSites } from '@services/sites';
|
||||||
|
@ -272,7 +271,7 @@ export class AddonBlogEntriesPage implements OnInit {
|
||||||
*
|
*
|
||||||
* @param refresher Refresher instance.
|
* @param refresher Refresher instance.
|
||||||
*/
|
*/
|
||||||
refresh(refresher?: IonRefresher): void {
|
refresh(refresher?: HTMLIonRefresherElement): void {
|
||||||
const promises = this.entries.map((entry) =>
|
const promises = this.entries.map((entry) =>
|
||||||
CoreComments.invalidateCommentsData('user', entry.userid, this.component, entry.id, 'format_blog'));
|
CoreComments.invalidateCommentsData('user', entry.userid, this.component, entry.id, 'format_blog'));
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
@import "~theme/globals";
|
@use "theme/globals" as *;
|
||||||
|
|
||||||
:host {
|
:host {
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
@import "~theme/globals";
|
@use "theme/globals" as *;
|
||||||
|
|
||||||
:host {
|
:host {
|
||||||
--addon-calendar-blank-day-background-color: var(--light);
|
--addon-calendar-blank-day-background-color: var(--light);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
@import "~theme/globals";
|
@use "theme/globals" as *;
|
||||||
|
|
||||||
:host {
|
:host {
|
||||||
ion-item {
|
ion-item {
|
||||||
|
|
|
@ -13,7 +13,6 @@
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import { Component, OnInit, OnDestroy, ViewChild } from '@angular/core';
|
import { Component, OnInit, OnDestroy, ViewChild } from '@angular/core';
|
||||||
import { IonRefresher } from '@ionic/angular';
|
|
||||||
import { CoreNetwork } from '@services/network';
|
import { CoreNetwork } from '@services/network';
|
||||||
import { CoreEventObserver, CoreEvents } from '@singletons/events';
|
import { CoreEventObserver, CoreEvents } from '@singletons/events';
|
||||||
import { CoreSites } from '@services/sites';
|
import { CoreSites } from '@services/sites';
|
||||||
|
@ -301,7 +300,7 @@ export class AddonCalendarDayPage implements OnInit, OnDestroy {
|
||||||
* @param done Function to call when done.
|
* @param done Function to call when done.
|
||||||
* @returns Promise resolved when done.
|
* @returns Promise resolved when done.
|
||||||
*/
|
*/
|
||||||
async doRefresh(refresher?: IonRefresher, done?: () => void): Promise<void> {
|
async doRefresh(refresher?: HTMLIonRefresherElement, done?: () => void): Promise<void> {
|
||||||
if (!this.loaded) {
|
if (!this.loaded) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,7 +51,7 @@
|
||||||
</ion-item>
|
</ion-item>
|
||||||
|
|
||||||
<!-- Category. -->
|
<!-- Category. -->
|
||||||
<ion-item class="ion-text-wrap" *ngIf="typeControl.value == 'category'">
|
<ion-item class="ion-text-wrap" *ngIf="typeControl.value === 'category'">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<p class="item-heading" [core-mark-required]="true">{{ 'core.category' | translate }}</p>
|
<p class="item-heading" [core-mark-required]="true">{{ 'core.category' | translate }}</p>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
|
@ -64,7 +64,7 @@
|
||||||
</ion-item>
|
</ion-item>
|
||||||
|
|
||||||
<!-- Course. -->
|
<!-- Course. -->
|
||||||
<ion-item class="ion-text-wrap" *ngIf="typeControl.value == 'course'">
|
<ion-item class="ion-text-wrap" *ngIf="typeControl.value === 'course'">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<p class="item-heading" [core-mark-required]="true">{{ 'core.course' | translate }}</p>
|
<p class="item-heading" [core-mark-required]="true">{{ 'core.course' | translate }}</p>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
|
@ -75,7 +75,7 @@
|
||||||
</ion-item>
|
</ion-item>
|
||||||
|
|
||||||
<!-- Group. -->
|
<!-- Group. -->
|
||||||
<ng-container *ngIf="typeControl.value == 'group'">
|
<ng-container *ngIf="typeControl.value === 'group'">
|
||||||
<!-- Select the course. -->
|
<!-- Select the course. -->
|
||||||
<ion-item class="ion-text-wrap">
|
<ion-item class="ion-text-wrap">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
|
|
|
@ -14,7 +14,6 @@
|
||||||
|
|
||||||
import { Component, OnInit, OnDestroy, ViewChild, ElementRef } from '@angular/core';
|
import { Component, OnInit, OnDestroy, ViewChild, ElementRef } from '@angular/core';
|
||||||
import { FormControl, FormGroup, FormBuilder, Validators } from '@angular/forms';
|
import { FormControl, FormGroup, FormBuilder, Validators } from '@angular/forms';
|
||||||
import { IonRefresher } from '@ionic/angular';
|
|
||||||
import { CoreEvents } from '@singletons/events';
|
import { CoreEvents } from '@singletons/events';
|
||||||
import { CoreGroup, CoreGroups } from '@services/groups';
|
import { CoreGroup, CoreGroups } from '@services/groups';
|
||||||
import { CoreSites } from '@services/sites';
|
import { CoreSites } from '@services/sites';
|
||||||
|
@ -383,7 +382,7 @@ export class AddonCalendarEditEventPage implements OnInit, OnDestroy, CanLeave {
|
||||||
*
|
*
|
||||||
* @param refresher Refresher.
|
* @param refresher Refresher.
|
||||||
*/
|
*/
|
||||||
refreshData(refresher?: IonRefresher): void {
|
refreshData(refresher?: HTMLIonRefresherElement): void {
|
||||||
const promises = [
|
const promises = [
|
||||||
AddonCalendar.invalidateAccessInformation(this.courseId),
|
AddonCalendar.invalidateAccessInformation(this.courseId),
|
||||||
AddonCalendar.invalidateAllowedEventTypes(this.courseId),
|
AddonCalendar.invalidateAllowedEventTypes(this.courseId),
|
||||||
|
|
|
@ -72,7 +72,7 @@
|
||||||
<p>{{ 'addon.calendar.type' + event.formattedType | translate }}</p>
|
<p>{{ 'addon.calendar.type' + event.formattedType | translate }}</p>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
<ion-item class="ion-text-wrap" *ngIf="courseName" [href]="courseUrl" core-link capture="true" detail="true">
|
<ion-item class="ion-text-wrap" *ngIf="courseName" [href]="courseUrl" core-link capture="true" [detail]="true">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<p class="item-heading">{{ 'core.course' | translate}}</p>
|
<p class="item-heading">{{ 'core.course' | translate}}</p>
|
||||||
<p>
|
<p>
|
||||||
|
|
|
@ -13,7 +13,6 @@
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import { Component, OnDestroy, OnInit } from '@angular/core';
|
import { Component, OnDestroy, OnInit } from '@angular/core';
|
||||||
import { IonRefresher } from '@ionic/angular';
|
|
||||||
import { AlertOptions } from '@ionic/core';
|
import { AlertOptions } from '@ionic/core';
|
||||||
import {
|
import {
|
||||||
AddonCalendar,
|
AddonCalendar,
|
||||||
|
@ -419,7 +418,7 @@ export class AddonCalendarEventPage implements OnInit, OnDestroy {
|
||||||
* @param showErrors Whether to show sync errors to the user.
|
* @param showErrors Whether to show sync errors to the user.
|
||||||
* @returns Promise resolved when done.
|
* @returns Promise resolved when done.
|
||||||
*/
|
*/
|
||||||
async doRefresh(refresher?: IonRefresher, done?: () => void, showErrors= false): Promise<void> {
|
async doRefresh(refresher?: HTMLIonRefresherElement, done?: () => void, showErrors= false): Promise<void> {
|
||||||
if (!this.eventLoaded) {
|
if (!this.eventLoaded) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,6 @@
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import { Component, OnInit, OnDestroy, ViewChild } from '@angular/core';
|
import { Component, OnInit, OnDestroy, ViewChild } from '@angular/core';
|
||||||
import { IonRefresher } from '@ionic/angular';
|
|
||||||
import { CoreNetwork } from '@services/network';
|
import { CoreNetwork } from '@services/network';
|
||||||
import { CoreEventObserver, CoreEvents } from '@singletons/events';
|
import { CoreEventObserver, CoreEvents } from '@singletons/events';
|
||||||
import { CoreSites } from '@services/sites';
|
import { CoreSites } from '@services/sites';
|
||||||
|
@ -263,7 +262,7 @@ export class AddonCalendarIndexPage implements OnInit, OnDestroy {
|
||||||
* @param showErrors Whether to show sync errors to the user.
|
* @param showErrors Whether to show sync errors to the user.
|
||||||
* @returns Promise resolved when done.
|
* @returns Promise resolved when done.
|
||||||
*/
|
*/
|
||||||
async doRefresh(refresher?: IonRefresher, done?: () => void, showErrors?: boolean): Promise<void> {
|
async doRefresh(refresher?: HTMLIonRefresherElement, done?: () => void, showErrors?: boolean): Promise<void> {
|
||||||
if (!this.loaded) {
|
if (!this.loaded) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
<ion-list>
|
<ion-list>
|
||||||
<ion-item class="ion-text-wrap" *ngFor="let competency of competencies.items"
|
<ion-item class="ion-text-wrap" *ngFor="let competency of competencies.items"
|
||||||
[attr.aria-label]="competency.competency.shortname" (click)="competencies.select(competency)"
|
[attr.aria-label]="competency.competency.shortname" (click)="competencies.select(competency)"
|
||||||
[attr.aria-current]="competencies.getItemAriaCurrent(competency)" button detail="true">
|
[attr.aria-current]="competencies.getItemAriaCurrent(competency)" button [detail]="true">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<p class="item-heading">
|
<p class="item-heading">
|
||||||
<core-format-text [text]="competency.competency.shortname" [contextLevel]="contextLevel"
|
<core-format-text [text]="competency.competency.shortname" [contextLevel]="contextLevel"
|
||||||
|
|
|
@ -13,7 +13,6 @@
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import { AfterViewInit, Component, OnDestroy, ViewChild } from '@angular/core';
|
import { AfterViewInit, Component, OnDestroy, ViewChild } from '@angular/core';
|
||||||
import { IonRefresher } from '@ionic/angular';
|
|
||||||
import { CoreDomUtils } from '@services/utils/dom';
|
import { CoreDomUtils } from '@services/utils/dom';
|
||||||
import { CoreSplitViewComponent } from '@components/split-view/split-view';
|
import { CoreSplitViewComponent } from '@components/split-view/split-view';
|
||||||
import {
|
import {
|
||||||
|
@ -121,7 +120,7 @@ export class AddonCompetencyCompetenciesPage implements AfterViewInit, OnDestroy
|
||||||
*
|
*
|
||||||
* @param refresher Refresher.
|
* @param refresher Refresher.
|
||||||
*/
|
*/
|
||||||
async refreshCompetencies(refresher?: IonRefresher): Promise<void> {
|
async refreshCompetencies(refresher?: HTMLIonRefresherElement): Promise<void> {
|
||||||
await this.competencies.getSource().invalidateCache();
|
await this.competencies.getSource().invalidateCache();
|
||||||
|
|
||||||
this.competencies.getSource().setDirty(true);
|
this.competencies.getSource().setDirty(true);
|
||||||
|
|
|
@ -30,7 +30,6 @@ import {
|
||||||
AddonCompetencyProvider,
|
AddonCompetencyProvider,
|
||||||
} from '@addons/competency/services/competency';
|
} from '@addons/competency/services/competency';
|
||||||
import { CoreNavigator } from '@services/navigator';
|
import { CoreNavigator } from '@services/navigator';
|
||||||
import { IonRefresher } from '@ionic/angular';
|
|
||||||
import { ContextLevel } from '@/core/constants';
|
import { ContextLevel } from '@/core/constants';
|
||||||
import { CoreUtils } from '@services/utils/utils';
|
import { CoreUtils } from '@services/utils/utils';
|
||||||
import { ADDON_COMPETENCY_SUMMARY_PAGE } from '@addons/competency/competency.module';
|
import { ADDON_COMPETENCY_SUMMARY_PAGE } from '@addons/competency/competency.module';
|
||||||
|
@ -173,7 +172,7 @@ export class AddonCompetencyCompetencyPage implements OnInit, OnDestroy {
|
||||||
*
|
*
|
||||||
* @param refresher Refresher.
|
* @param refresher Refresher.
|
||||||
*/
|
*/
|
||||||
async refreshCompetency(refresher: IonRefresher): Promise<void> {
|
async refreshCompetency(refresher: HTMLIonRefresherElement): Promise<void> {
|
||||||
const source = this.competencies.getSource();
|
const source = this.competencies.getSource();
|
||||||
|
|
||||||
await CoreUtils.ignoreErrors(
|
await CoreUtils.ignoreErrors(
|
||||||
|
|
|
@ -15,7 +15,6 @@
|
||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { ContextLevel } from '@/core/constants';
|
import { ContextLevel } from '@/core/constants';
|
||||||
import { AddonCompetencySummary, AddonCompetency } from '@addons/competency/services/competency';
|
import { AddonCompetencySummary, AddonCompetency } from '@addons/competency/services/competency';
|
||||||
import { IonRefresher } from '@ionic/angular';
|
|
||||||
import { CoreNavigator } from '@services/navigator';
|
import { CoreNavigator } from '@services/navigator';
|
||||||
import { CoreDomUtils } from '@services/utils/dom';
|
import { CoreDomUtils } from '@services/utils/dom';
|
||||||
import { CoreUtils } from '@services/utils/utils';
|
import { CoreUtils } from '@services/utils/utils';
|
||||||
|
@ -113,7 +112,7 @@ export class AddonCompetencyCompetencySummaryPage implements OnInit {
|
||||||
*
|
*
|
||||||
* @param refresher Refresher.
|
* @param refresher Refresher.
|
||||||
*/
|
*/
|
||||||
refreshCompetency(refresher: IonRefresher): void {
|
refreshCompetency(refresher: HTMLIonRefresherElement): void {
|
||||||
AddonCompetency.invalidateCompetencySummary(this.competencyId).finally(() => {
|
AddonCompetency.invalidateCompetencySummary(this.competencyId).finally(() => {
|
||||||
this.fetchCompetency().finally(() => {
|
this.fetchCompetency().finally(() => {
|
||||||
refresher?.complete();
|
refresher?.complete();
|
||||||
|
|
|
@ -65,7 +65,7 @@
|
||||||
<div *ngIf="competencies.loaded">
|
<div *ngIf="competencies.loaded">
|
||||||
<ion-card *ngFor="let competency of competencies.items">
|
<ion-card *ngFor="let competency of competencies.items">
|
||||||
<ion-item class="ion-text-wrap" (click)="competencies.select(competency)"
|
<ion-item class="ion-text-wrap" (click)="competencies.select(competency)"
|
||||||
[attr.aria-label]="competency.competency.shortname" detail="true" button>
|
[attr.aria-label]="competency.competency.shortname" [detail]="true" button>
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<p class="item-heading">
|
<p class="item-heading">
|
||||||
<core-format-text [text]="competency.competency.shortname" contextLevel="course" [contextInstanceId]="courseId">
|
<core-format-text [text]="competency.competency.shortname" contextLevel="course" [contextInstanceId]="courseId">
|
||||||
|
|
|
@ -18,7 +18,6 @@ import {
|
||||||
AddonCompetencyDataForCourseCompetenciesPageCompetency,
|
AddonCompetencyDataForCourseCompetenciesPageCompetency,
|
||||||
} from '@addons/competency/services/competency';
|
} from '@addons/competency/services/competency';
|
||||||
import { CoreUserProfile } from '@features/user/services/user';
|
import { CoreUserProfile } from '@features/user/services/user';
|
||||||
import { IonRefresher } from '@ionic/angular';
|
|
||||||
import { CoreNavigator } from '@services/navigator';
|
import { CoreNavigator } from '@services/navigator';
|
||||||
import { CoreDomUtils } from '@services/utils/dom';
|
import { CoreDomUtils } from '@services/utils/dom';
|
||||||
import { ContextLevel } from '@/core/constants';
|
import { ContextLevel } from '@/core/constants';
|
||||||
|
@ -148,7 +147,7 @@ export class AddonCompetencyCourseCompetenciesPage implements OnInit, OnDestroy
|
||||||
*
|
*
|
||||||
* @param refresher Refresher.
|
* @param refresher Refresher.
|
||||||
*/
|
*/
|
||||||
async refreshCourseCompetencies(refresher?: IonRefresher): Promise<void> {
|
async refreshCourseCompetencies(refresher?: HTMLIonRefresherElement): Promise<void> {
|
||||||
await this.competencies.getSource().invalidateCache();
|
await this.competencies.getSource().invalidateCache();
|
||||||
|
|
||||||
this.fetchCourseCompetencies().finally(() => {
|
this.fetchCourseCompetencies().finally(() => {
|
||||||
|
|
|
@ -81,7 +81,7 @@
|
||||||
</ion-label>
|
</ion-label>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
<ion-item class="ion-text-wrap" *ngFor="let competency of competencies.items" (click)="competencies.select(competency)"
|
<ion-item class="ion-text-wrap" *ngFor="let competency of competencies.items" (click)="competencies.select(competency)"
|
||||||
[attr.aria-label]="competency.competency.shortname" detail="true" button>
|
[attr.aria-label]="competency.competency.shortname" [detail]="true" button>
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<p class="item-heading">
|
<p class="item-heading">
|
||||||
<core-format-text [text]="competency.competency.shortname" contextLevel="user"
|
<core-format-text [text]="competency.competency.shortname" contextLevel="user"
|
||||||
|
|
|
@ -17,7 +17,6 @@ import { CoreDomUtils } from '@services/utils/dom';
|
||||||
import { AddonCompetencyDataForPlanPageCompetency, AddonCompetencyDataForPlanPageWSResponse } from '../../services/competency';
|
import { AddonCompetencyDataForPlanPageCompetency, AddonCompetencyDataForPlanPageWSResponse } from '../../services/competency';
|
||||||
import { CoreNavigator } from '@services/navigator';
|
import { CoreNavigator } from '@services/navigator';
|
||||||
import { CoreUserProfile } from '@features/user/services/user';
|
import { CoreUserProfile } from '@features/user/services/user';
|
||||||
import { IonRefresher } from '@ionic/angular';
|
|
||||||
import { CoreSwipeNavigationItemsManager } from '@classes/items-management/swipe-navigation-items-manager';
|
import { CoreSwipeNavigationItemsManager } from '@classes/items-management/swipe-navigation-items-manager';
|
||||||
import { CoreRoutedItemsManagerSourcesTracker } from '@classes/items-management/routed-items-manager-sources-tracker';
|
import { CoreRoutedItemsManagerSourcesTracker } from '@classes/items-management/routed-items-manager-sources-tracker';
|
||||||
import { AddonCompetencyPlansSource } from '@addons/competency/classes/competency-plans-source';
|
import { AddonCompetencyPlansSource } from '@addons/competency/classes/competency-plans-source';
|
||||||
|
@ -111,7 +110,7 @@ export class AddonCompetencyPlanPage implements OnInit, OnDestroy {
|
||||||
*
|
*
|
||||||
* @param refresher Refresher.
|
* @param refresher Refresher.
|
||||||
*/
|
*/
|
||||||
async refreshLearningPlan(refresher: IonRefresher): Promise<void> {
|
async refreshLearningPlan(refresher: HTMLIonRefresherElement): Promise<void> {
|
||||||
await this.competencies.getSource().invalidateCache();
|
await this.competencies.getSource().invalidateCache();
|
||||||
|
|
||||||
this.fetchLearningPlan().finally(() => {
|
this.fetchLearningPlan().finally(() => {
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
</core-empty-box>
|
</core-empty-box>
|
||||||
<ion-list *ngIf="!plans.empty" class="ion-no-margin">
|
<ion-list *ngIf="!plans.empty" class="ion-no-margin">
|
||||||
<ion-item class="ion-text-wrap" *ngFor="let plan of plans.items" [attr.aria-label]="plan.name" (click)="plans.select(plan)"
|
<ion-item class="ion-text-wrap" *ngFor="let plan of plans.items" [attr.aria-label]="plan.name" (click)="plans.select(plan)"
|
||||||
[attr.aria-current]="plans.getItemAriaCurrent(plan)" button detail="true">
|
[attr.aria-current]="plans.getItemAriaCurrent(plan)" button [detail]="true">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<p class="item-heading">
|
<p class="item-heading">
|
||||||
<core-format-text [text]="plan.name" contextLevel="user" [contextInstanceId]="plan.userid">
|
<core-format-text [text]="plan.name" contextLevel="user" [contextInstanceId]="plan.userid">
|
||||||
|
|
|
@ -13,7 +13,6 @@
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import { AfterViewInit, Component, OnDestroy, ViewChild } from '@angular/core';
|
import { AfterViewInit, Component, OnDestroy, ViewChild } from '@angular/core';
|
||||||
import { IonRefresher } from '@ionic/angular';
|
|
||||||
import { CoreDomUtils } from '@services/utils/dom';
|
import { CoreDomUtils } from '@services/utils/dom';
|
||||||
import { CoreSplitViewComponent } from '@components/split-view/split-view';
|
import { CoreSplitViewComponent } from '@components/split-view/split-view';
|
||||||
import { CoreNavigator } from '@services/navigator';
|
import { CoreNavigator } from '@services/navigator';
|
||||||
|
@ -86,7 +85,7 @@ export class AddonCompetencyPlanListPage implements AfterViewInit, OnDestroy {
|
||||||
*
|
*
|
||||||
* @param refresher Refresher.
|
* @param refresher Refresher.
|
||||||
*/
|
*/
|
||||||
async refreshLearningPlans(refresher: IonRefresher): Promise<void> {
|
async refreshLearningPlans(refresher: HTMLIonRefresherElement): Promise<void> {
|
||||||
await this.plans.getSource().invalidateCache();
|
await this.plans.getSource().invalidateCache();
|
||||||
|
|
||||||
this.plans.getSource().setDirty(true);
|
this.plans.getSource().setDirty(true);
|
||||||
|
|
|
@ -18,7 +18,6 @@ import {
|
||||||
} from '@addons/coursecompletion/services/coursecompletion';
|
} from '@addons/coursecompletion/services/coursecompletion';
|
||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { CoreUser, CoreUserProfile } from '@features/user/services/user';
|
import { CoreUser, CoreUserProfile } from '@features/user/services/user';
|
||||||
import { IonRefresher } from '@ionic/angular';
|
|
||||||
import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
|
import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
|
||||||
import { CoreNavigator } from '@services/navigator';
|
import { CoreNavigator } from '@services/navigator';
|
||||||
import { CoreSites } from '@services/sites';
|
import { CoreSites } from '@services/sites';
|
||||||
|
@ -112,7 +111,7 @@ export class AddonCourseCompletionReportPage implements OnInit {
|
||||||
*
|
*
|
||||||
* @param refresher Refresher instance.
|
* @param refresher Refresher instance.
|
||||||
*/
|
*/
|
||||||
async refreshCompletion(refresher?: IonRefresher): Promise<void> {
|
async refreshCompletion(refresher?: HTMLIonRefresherElement): Promise<void> {
|
||||||
await AddonCourseCompletion.invalidateCourseCompletion(this.courseId, this.userId).finally(() => {
|
await AddonCourseCompletion.invalidateCourseCompletion(this.courseId, this.userId).finally(() => {
|
||||||
this.fetchCompletion().finally(() => {
|
this.fetchCompletion().finally(() => {
|
||||||
refresher?.complete();
|
refresher?.complete();
|
||||||
|
|
|
@ -98,7 +98,7 @@ export class AddonEnrolGuestHandlerService implements CoreEnrolGuestHandler {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const validatePassword = async (password: string): Promise<CorePasswordModalResponse> => {
|
const validatePassword = async (password = ''): Promise<CorePasswordModalResponse> => {
|
||||||
const modal = await CoreDomUtils.showModalLoading('core.loading', true);
|
const modal = await CoreDomUtils.showModalLoading('core.loading', true);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -407,8 +407,8 @@ type MathJaxWindow = Window & {
|
||||||
MathJax?: any; // eslint-disable-line @typescript-eslint/naming-convention, @typescript-eslint/no-explicit-any
|
MathJax?: any; // eslint-disable-line @typescript-eslint/naming-convention, @typescript-eslint/no-explicit-any
|
||||||
M?: { // eslint-disable-line @typescript-eslint/naming-convention
|
M?: { // eslint-disable-line @typescript-eslint/naming-convention
|
||||||
filter_mathjaxloader?: { // eslint-disable-line @typescript-eslint/naming-convention
|
filter_mathjaxloader?: { // eslint-disable-line @typescript-eslint/naming-convention
|
||||||
_lang: ''; // eslint-disable-line @typescript-eslint/naming-convention
|
_lang: string; // eslint-disable-line @typescript-eslint/naming-convention
|
||||||
_configured: false; // eslint-disable-line @typescript-eslint/naming-convention
|
_configured: boolean; // eslint-disable-line @typescript-eslint/naming-convention
|
||||||
// Add the configuration to the head and set the lang.
|
// Add the configuration to the head and set the lang.
|
||||||
configure: (params: Record<string, unknown>) => void;
|
configure: (params: Record<string, unknown>) => void;
|
||||||
_setLocale: () => void; // eslint-disable-line @typescript-eslint/naming-convention
|
_setLocale: () => void; // eslint-disable-line @typescript-eslint/naming-convention
|
||||||
|
|
|
@ -13,7 +13,6 @@
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import { Component, OnDestroy, OnInit } from '@angular/core';
|
import { Component, OnDestroy, OnInit } from '@angular/core';
|
||||||
import { IonRefresher } from '@ionic/angular';
|
|
||||||
|
|
||||||
import { CoreDomUtils } from '@services/utils/dom';
|
import { CoreDomUtils } from '@services/utils/dom';
|
||||||
import { CorePushNotifications } from '@features/pushnotifications/services/pushnotifications';
|
import { CorePushNotifications } from '@features/pushnotifications/services/pushnotifications';
|
||||||
|
@ -123,7 +122,7 @@ export class AddonMessageOutputAirnotifierDevicesPage implements OnInit, OnDestr
|
||||||
*
|
*
|
||||||
* @param refresher Refresher.
|
* @param refresher Refresher.
|
||||||
*/
|
*/
|
||||||
async refreshDevices(refresher: IonRefresher): Promise<void> {
|
async refreshDevices(refresher: HTMLIonRefresherElement): Promise<void> {
|
||||||
try {
|
try {
|
||||||
await CoreUtils.ignoreErrors(AddonMessageOutputAirnotifier.invalidateUserDevices());
|
await CoreUtils.ignoreErrors(AddonMessageOutputAirnotifier.invalidateUserDevices());
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,6 @@
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import { Component, Input, OnInit } from '@angular/core';
|
import { Component, Input, OnInit } from '@angular/core';
|
||||||
import { IonRefresher } from '@ionic/angular';
|
|
||||||
import {
|
import {
|
||||||
AddonMessagesConversationFormatted,
|
AddonMessagesConversationFormatted,
|
||||||
AddonMessagesConversationMember,
|
AddonMessagesConversationMember,
|
||||||
|
@ -116,7 +115,7 @@ export class AddonMessagesConversationInfoComponent implements OnInit {
|
||||||
* @param refresher Refresher.
|
* @param refresher Refresher.
|
||||||
* @returns Promise resolved when done.
|
* @returns Promise resolved when done.
|
||||||
*/
|
*/
|
||||||
async refreshData(refresher?: IonRefresher): Promise<void> {
|
async refreshData(refresher?: HTMLIonRefresherElement): Promise<void> {
|
||||||
const promises: Promise<void>[] = [];
|
const promises: Promise<void>[] = [];
|
||||||
|
|
||||||
promises.push(AddonMessages.invalidateConversation(this.conversationId));
|
promises.push(AddonMessages.invalidateConversation(this.conversationId));
|
||||||
|
|
|
@ -35,7 +35,7 @@
|
||||||
</ion-item>
|
</ion-item>
|
||||||
|
|
||||||
<ion-item class="ion-text-wrap addon-messages-conversation-item" *ngFor="let member of members" (click)="closeModal(member.id)"
|
<ion-item class="ion-text-wrap addon-messages-conversation-item" *ngFor="let member of members" (click)="closeModal(member.id)"
|
||||||
detail="true" button>
|
[detail]="true" button>
|
||||||
<core-user-avatar [user]="member" [linkProfile]="false" [checkOnline]="member.showonlinestatus" slot="start">
|
<core-user-avatar [user]="member" [linkProfile]="false" [checkOnline]="member.showonlinestatus" slot="start">
|
||||||
</core-user-avatar>
|
</core-user-avatar>
|
||||||
<ion-label>
|
<ion-label>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
@import "~theme/globals";
|
@use "theme/globals" as *;
|
||||||
|
|
||||||
:host {
|
:host {
|
||||||
.addon-messages-conversation-item,
|
.addon-messages-conversation-item,
|
||||||
|
|
|
@ -22,10 +22,10 @@
|
||||||
autocorrect="off" spellcheck="false" lengthCheck="2" [disabled]="!loaded" searchArea="AddonMessagesContacts"></core-search-box>
|
autocorrect="off" spellcheck="false" lengthCheck="2" [disabled]="!loaded" searchArea="AddonMessagesContacts"></core-search-box>
|
||||||
|
|
||||||
<core-loading [hideUntil]="loaded" [message]="loadingMessage">
|
<core-loading [hideUntil]="loaded" [message]="loadingMessage">
|
||||||
<core-empty-box *ngIf="!hasContacts && searchString == ''" icon="fas-address-book"
|
<core-empty-box *ngIf="!hasContacts && searchString === ''" icon="fas-address-book"
|
||||||
[message]="'addon.messages.contactlistempty' | translate"></core-empty-box>
|
[message]="'addon.messages.contactlistempty' | translate"></core-empty-box>
|
||||||
|
|
||||||
<core-empty-box *ngIf="!hasContacts && searchString != ''" icon="fas-address-book"
|
<core-empty-box *ngIf="!hasContacts && searchString !== ''" icon="fas-address-book"
|
||||||
[message]="'addon.messages.nousersfound' | translate"></core-empty-box>
|
[message]="'addon.messages.nousersfound' | translate"></core-empty-box>
|
||||||
|
|
||||||
<ion-list *ngFor="let contactType of contactTypes" class="ion-no-margin">
|
<ion-list *ngFor="let contactType of contactTypes" class="ion-no-margin">
|
||||||
|
@ -42,7 +42,7 @@
|
||||||
<!-- Don't show deleted users -->
|
<!-- Don't show deleted users -->
|
||||||
<ion-item class="ion-text-wrap addon-messages-conversation-item"
|
<ion-item class="ion-text-wrap addon-messages-conversation-item"
|
||||||
*ngIf="contact.profileimageurl || contact.profileimageurlsmall" [attr.aria-label]="contact.fullname"
|
*ngIf="contact.profileimageurl || contact.profileimageurlsmall" [attr.aria-label]="contact.fullname"
|
||||||
(click)="gotoDiscussion(contact.id)" detail="true" button
|
(click)="gotoDiscussion(contact.id)" [detail]="true" button
|
||||||
[attr.aria-current]="contact.id == discussionUserId ? 'page' : 'false'">
|
[attr.aria-current]="contact.id == discussionUserId ? 'page' : 'false'">
|
||||||
<core-user-avatar [user]="contact" slot="start" [checkOnline]="contact.showonlinestatus"></core-user-avatar>
|
<core-user-avatar [user]="contact" slot="start" [checkOnline]="contact.showonlinestatus"></core-user-avatar>
|
||||||
<ion-label>
|
<ion-label>
|
||||||
|
|
|
@ -13,7 +13,6 @@
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import { Component, OnDestroy, OnInit, ViewChild } from '@angular/core';
|
import { Component, OnDestroy, OnInit, ViewChild } from '@angular/core';
|
||||||
import { IonRefresher } from '@ionic/angular';
|
|
||||||
import { CoreSites } from '@services/sites';
|
import { CoreSites } from '@services/sites';
|
||||||
import {
|
import {
|
||||||
AddonMessagesProvider,
|
AddonMessagesProvider,
|
||||||
|
@ -129,7 +128,7 @@ export class AddonMessagesContacts35Page implements OnInit, OnDestroy {
|
||||||
* @param refresher Refresher.
|
* @param refresher Refresher.
|
||||||
* @returns Promise resolved when done.
|
* @returns Promise resolved when done.
|
||||||
*/
|
*/
|
||||||
async refreshData(refresher?: IonRefresher): Promise<void> {
|
async refreshData(refresher?: HTMLIonRefresherElement): Promise<void> {
|
||||||
try {
|
try {
|
||||||
if (this.searchString) {
|
if (this.searchString) {
|
||||||
// User has searched, update the search.
|
// User has searched, update the search.
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
<core-loading [hideUntil]="confirmedLoaded">
|
<core-loading [hideUntil]="confirmedLoaded">
|
||||||
<ion-list class="ion-no-margin" *ngIf="confirmedContacts.length">
|
<ion-list class="ion-no-margin" *ngIf="confirmedContacts.length">
|
||||||
<ion-item class="ion-text-wrap addon-messages-conversation-item" (click)="selectUser(contact.id)" button
|
<ion-item class="ion-text-wrap addon-messages-conversation-item" (click)="selectUser(contact.id)" button
|
||||||
*ngFor="let contact of confirmedContacts" [attr.aria-label]="contact.fullname" detail="true"
|
*ngFor="let contact of confirmedContacts" [attr.aria-label]="contact.fullname" [detail]="true"
|
||||||
[attr.aria-current]="contact.id == selectedUserId ? 'page' : 'false'">
|
[attr.aria-current]="contact.id == selectedUserId ? 'page' : 'false'">
|
||||||
<core-user-avatar slot="start" [user]="contact" [checkOnline]="contact.showonlinestatus"
|
<core-user-avatar slot="start" [user]="contact" [checkOnline]="contact.showonlinestatus"
|
||||||
[linkProfile]="false">
|
[linkProfile]="false">
|
||||||
|
@ -67,7 +67,7 @@
|
||||||
<ion-list class="ion-no-margin" *ngIf="requests.length">
|
<ion-list class="ion-no-margin" *ngIf="requests.length">
|
||||||
<ion-item class="ion-text-wrap addon-messages-conversation-item" *ngFor="let request of requests"
|
<ion-item class="ion-text-wrap addon-messages-conversation-item" *ngFor="let request of requests"
|
||||||
[attr.aria-label]="request.fullname" (click)="selectUser(request.id)" button
|
[attr.aria-label]="request.fullname" (click)="selectUser(request.id)" button
|
||||||
[attr.aria-current]="request.id == selectedUserId ? 'page' : 'false'" detail="true">
|
[attr.aria-current]="request.id == selectedUserId ? 'page' : 'false'" [detail]="true">
|
||||||
<core-user-avatar slot="start" [user]="request" [linkProfile]="false"></core-user-avatar>
|
<core-user-avatar slot="start" [user]="request" [linkProfile]="false"></core-user-avatar>
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<core-format-text [text]="request.fullname" contextLevel="system" [contextInstanceId]="0">
|
<core-format-text [text]="request.fullname" contextLevel="system" [contextInstanceId]="0">
|
||||||
|
|
|
@ -23,7 +23,6 @@ import {
|
||||||
import { CoreNavigator } from '@services/navigator';
|
import { CoreNavigator } from '@services/navigator';
|
||||||
import { CoreScreen } from '@services/screen';
|
import { CoreScreen } from '@services/screen';
|
||||||
import { CoreDomUtils } from '@services/utils/dom';
|
import { CoreDomUtils } from '@services/utils/dom';
|
||||||
import { IonRefresher } from '@ionic/angular';
|
|
||||||
import { CoreSplitViewComponent } from '@components/split-view/split-view';
|
import { CoreSplitViewComponent } from '@components/split-view/split-view';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -216,7 +215,7 @@ export class AddonMessagesContactsPage implements OnInit, OnDestroy {
|
||||||
* @param refresher Refresher.
|
* @param refresher Refresher.
|
||||||
* @returns Promise resolved when done.
|
* @returns Promise resolved when done.
|
||||||
*/
|
*/
|
||||||
async refreshData(refresher?: IonRefresher): Promise<void> {
|
async refreshData(refresher?: HTMLIonRefresherElement): Promise<void> {
|
||||||
try {
|
try {
|
||||||
if (this.selected == 'confirmed') {
|
if (this.selected == 'confirmed') {
|
||||||
// No need to invalidate contacts, we always try to get the latest.
|
// No need to invalidate contacts, we always try to get the latest.
|
||||||
|
|
|
@ -103,17 +103,17 @@
|
||||||
</ion-fab>
|
</ion-fab>
|
||||||
</ion-content>
|
</ion-content>
|
||||||
<ion-footer class="footer-adjustable" *ngIf="loaded && (!conversationId || conversation)">
|
<ion-footer class="footer-adjustable" *ngIf="loaded && (!conversationId || conversation)">
|
||||||
<ion-toolbar [color]="footerType == 'message' ? null : 'light'">
|
<ion-toolbar [color]="footerType === 'message' ? null : 'light'">
|
||||||
<p *ngIf="footerType == 'unable'" class="ion-text-center ion-margin-horizontal">
|
<p *ngIf="footerType === 'unable'" class="ion-text-center ion-margin-horizontal">
|
||||||
{{ 'addon.messages.unabletomessage' | translate }}
|
{{ 'addon.messages.unabletomessage' | translate }}
|
||||||
</p>
|
</p>
|
||||||
<div *ngIf="footerType == 'blocked'" class="ion-padding-horizontal">
|
<div *ngIf="footerType === 'blocked'" class="ion-padding-horizontal">
|
||||||
<p class="ion-text-center">{{ 'addon.messages.youhaveblockeduser' | translate }}</p>
|
<p class="ion-text-center">{{ 'addon.messages.youhaveblockeduser' | translate }}</p>
|
||||||
<ion-button expand="block" class="ion-text-wrap ion-margin-bottom" (click)="unblockUser()">
|
<ion-button expand="block" class="ion-text-wrap ion-margin-bottom" (click)="unblockUser()">
|
||||||
{{ 'addon.messages.unblockuser' | translate }}
|
{{ 'addon.messages.unblockuser' | translate }}
|
||||||
</ion-button>
|
</ion-button>
|
||||||
</div>
|
</div>
|
||||||
<div *ngIf="footerType == 'requiresContact' && otherMember" class="ion-padding-horizontal">
|
<div *ngIf="footerType === 'requiresContact' && otherMember" class="ion-padding-horizontal">
|
||||||
<p class="ion-text-center">
|
<p class="ion-text-center">
|
||||||
<strong>{{ 'addon.messages.isnotinyourcontacts' | translate: {$a: otherMember.fullname} }}</strong>
|
<strong>{{ 'addon.messages.isnotinyourcontacts' | translate: {$a: otherMember.fullname} }}</strong>
|
||||||
</p>
|
</p>
|
||||||
|
@ -122,7 +122,7 @@
|
||||||
{{ 'addon.messages.sendcontactrequest' | translate }}
|
{{ 'addon.messages.sendcontactrequest' | translate }}
|
||||||
</ion-button>
|
</ion-button>
|
||||||
</div>
|
</div>
|
||||||
<div *ngIf="footerType == 'requestReceived' && otherMember" class="ion-padding-horizontal">
|
<div *ngIf="footerType === 'requestReceived' && otherMember" class="ion-padding-horizontal">
|
||||||
<p class="ion-text-center">{{ 'addon.messages.userwouldliketocontactyou' | translate: {$a: otherMember.fullname} }}</p>
|
<p class="ion-text-center">{{ 'addon.messages.userwouldliketocontactyou' | translate: {$a: otherMember.fullname} }}</p>
|
||||||
<ion-button expand="block" class="ion-text-wrap ion-margin-bottom" (click)="confirmContactRequest()">
|
<ion-button expand="block" class="ion-text-wrap ion-margin-bottom" (click)="confirmContactRequest()">
|
||||||
{{ 'addon.messages.acceptandaddcontact' | translate }}
|
{{ 'addon.messages.acceptandaddcontact' | translate }}
|
||||||
|
@ -131,13 +131,13 @@
|
||||||
{{ 'addon.messages.decline' | translate }}
|
{{ 'addon.messages.decline' | translate }}
|
||||||
</ion-button>
|
</ion-button>
|
||||||
</div>
|
</div>
|
||||||
<div *ngIf="footerType == 'requestSent' || (footerType == 'message' && requestContactSent)" class="ion-padding-horizontal">
|
<div *ngIf="footerType === 'requestSent' || (footerType === 'message' && requestContactSent)" class="ion-padding-horizontal">
|
||||||
<p class="ion-text-center"><strong>{{ 'addon.messages.contactrequestsent' | translate }}</strong></p>
|
<p class="ion-text-center"><strong>{{ 'addon.messages.contactrequestsent' | translate }}</strong></p>
|
||||||
<p class="ion-text-center" *ngIf="otherMember">
|
<p class="ion-text-center" *ngIf="otherMember">
|
||||||
{{ 'addon.messages.yourcontactrequestpending' | translate: {$a: otherMember.fullname} }}
|
{{ 'addon.messages.yourcontactrequestpending' | translate: {$a: otherMember.fullname} }}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<core-send-message-form *ngIf="footerType == 'message'" (onSubmit)="sendMessage($event)" [showKeyboard]="showKeyboard"
|
<core-send-message-form *ngIf="footerType === 'message'" (onSubmit)="sendMessage($event)" [showKeyboard]="showKeyboard"
|
||||||
[placeholder]="'addon.messages.newmessage' | translate"></core-send-message-form>
|
[placeholder]="'addon.messages.newmessage' | translate"></core-send-message-form>
|
||||||
</ion-toolbar>
|
</ion-toolbar>
|
||||||
</ion-footer>
|
</ion-footer>
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
@import "~theme/components/discussion.scss";
|
@use "theme/globals" as *;
|
||||||
@import "~theme/globals.scss";
|
|
||||||
|
|
||||||
:host {
|
:host {
|
||||||
|
|
||||||
|
|
|
@ -51,7 +51,7 @@ import { CoreDom } from '@singletons/dom';
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'page-addon-messages-discussion',
|
selector: 'page-addon-messages-discussion',
|
||||||
templateUrl: 'discussion.html',
|
templateUrl: 'discussion.html',
|
||||||
styleUrls: ['discussion.scss'],
|
styleUrls: ['../../../../theme/components/discussion.scss', 'discussion.scss'],
|
||||||
})
|
})
|
||||||
export class AddonMessagesDiscussionPage implements OnInit, OnDestroy, AfterViewInit {
|
export class AddonMessagesDiscussionPage implements OnInit, OnDestroy, AfterViewInit {
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
<ion-list class="ion-no-margin">
|
<ion-list class="ion-no-margin">
|
||||||
|
|
||||||
<ion-item class="ion-text-wrap addon-message-discussion" (click)="gotoContacts()"
|
<ion-item class="ion-text-wrap addon-message-discussion" (click)="gotoContacts()"
|
||||||
[attr.aria-label]="'addon.messages.contacts' | translate" detail="true" button>
|
[attr.aria-label]="'addon.messages.contacts' | translate" [detail]="true" button>
|
||||||
<ion-icon name="fas-address-book" slot="start" aria-hidden="true"></ion-icon>
|
<ion-icon name="fas-address-book" slot="start" aria-hidden="true"></ion-icon>
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<p class="item-heading">{{ 'addon.messages.contacts' | translate }}</p>
|
<p class="item-heading">{{ 'addon.messages.contacts' | translate }}</p>
|
||||||
|
@ -46,7 +46,7 @@
|
||||||
</ion-item-divider>
|
</ion-item-divider>
|
||||||
<ion-item class="ion-text-wrap addon-message-discussion" *ngFor="let result of search.results" button
|
<ion-item class="ion-text-wrap addon-message-discussion" *ngFor="let result of search.results" button
|
||||||
[attr.aria-label]="result.fullname" (click)="gotoDiscussion(result.userid, result.messageid)"
|
[attr.aria-label]="result.fullname" (click)="gotoDiscussion(result.userid, result.messageid)"
|
||||||
[attr.aria-current]="result.userid == discussionUserId ? 'page' : 'false'" detail="false">
|
[attr.aria-current]="result.userid == discussionUserId ? 'page' : 'false'" [detail]="false">
|
||||||
<core-user-avatar [user]="result" slot="start" [checkOnline]="result.showonlinestatus"></core-user-avatar>
|
<core-user-avatar [user]="result" slot="start" [checkOnline]="result.showonlinestatus"></core-user-avatar>
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<p class="item-heading">{{ result.fullname }}</p>
|
<p class="item-heading">{{ result.fullname }}</p>
|
||||||
|
@ -60,7 +60,7 @@
|
||||||
<ng-container *ngIf="!search.showResults">
|
<ng-container *ngIf="!search.showResults">
|
||||||
<ion-item class="ion-text-wrap addon-message-discussion" *ngFor="let discussion of discussions" button
|
<ion-item class="ion-text-wrap addon-message-discussion" *ngFor="let discussion of discussions" button
|
||||||
[attr.aria-label]="discussion.fullname" (click)="gotoDiscussion(discussion.message!.user)"
|
[attr.aria-label]="discussion.fullname" (click)="gotoDiscussion(discussion.message!.user)"
|
||||||
[attr.aria-current]="discussion.message!.user == discussionUserId ? 'page' : 'false'" detail="false">
|
[attr.aria-current]="discussion.message!.user == discussionUserId ? 'page' : 'false'" [detail]="false">
|
||||||
<core-user-avatar [user]="discussion" slot="start" checkOnline="false"></core-user-avatar>
|
<core-user-avatar [user]="discussion" slot="start" checkOnline="false"></core-user-avatar>
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<div class="flex-row ion-justify-content-between">
|
<div class="flex-row ion-justify-content-between">
|
||||||
|
|
|
@ -29,7 +29,6 @@ import { CorePushNotificationsNotificationBasicData } from '@features/pushnotifi
|
||||||
import { CorePushNotificationsDelegate } from '@features/pushnotifications/services/push-delegate';
|
import { CorePushNotificationsDelegate } from '@features/pushnotifications/services/push-delegate';
|
||||||
import { Subscription } from 'rxjs';
|
import { Subscription } from 'rxjs';
|
||||||
import { Translate } from '@singletons';
|
import { Translate } from '@singletons';
|
||||||
import { IonRefresher } from '@ionic/angular';
|
|
||||||
import { CoreNavigator } from '@services/navigator';
|
import { CoreNavigator } from '@services/navigator';
|
||||||
import { CoreScreen } from '@services/screen';
|
import { CoreScreen } from '@services/screen';
|
||||||
import { CoreMainMenuDeepLinkManager } from '@features/mainmenu/classes/deep-link-manager';
|
import { CoreMainMenuDeepLinkManager } from '@features/mainmenu/classes/deep-link-manager';
|
||||||
|
@ -166,7 +165,7 @@ export class AddonMessagesDiscussions35Page implements OnInit, OnDestroy {
|
||||||
* @param refreshUnreadCounts Whteher to refresh unread counts.
|
* @param refreshUnreadCounts Whteher to refresh unread counts.
|
||||||
* @returns Promise resolved when done.
|
* @returns Promise resolved when done.
|
||||||
*/
|
*/
|
||||||
async refreshData(refresher?: IonRefresher, refreshUnreadCounts: boolean = true): Promise<void> {
|
async refreshData(refresher?: HTMLIonRefresherElement, refreshUnreadCounts: boolean = true): Promise<void> {
|
||||||
const promises: Promise<void>[] = [];
|
const promises: Promise<void>[] = [];
|
||||||
promises.push(AddonMessages.invalidateDiscussionsCache(this.siteId));
|
promises.push(AddonMessages.invalidateDiscussionsCache(this.siteId));
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
|
|
||||||
<core-loading [hideUntil]="loaded" [message]="loadingMessage">
|
<core-loading [hideUntil]="loaded" [message]="loadingMessage">
|
||||||
<ion-list>
|
<ion-list>
|
||||||
<ion-item class="ion-text-wrap addon-message-discussion" (click)="gotoContacts()" detail="true" button>
|
<ion-item class="ion-text-wrap addon-message-discussion" (click)="gotoContacts()" [detail]="true" button>
|
||||||
<ion-icon name="fas-address-book" slot="start" aria-hidden="true"></ion-icon>
|
<ion-icon name="fas-address-book" slot="start" aria-hidden="true"></ion-icon>
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<h2>{{ 'addon.messages.contacts' | translate }}</h2>
|
<h2>{{ 'addon.messages.contacts' | translate }}</h2>
|
||||||
|
@ -38,10 +38,10 @@
|
||||||
</span>
|
</span>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
<!-- Favourite conversations. -->
|
<!-- Favourite conversations. -->
|
||||||
<ion-item button class="ion-text-wrap divider" (click)="toggle(favourites)" sticky="true"
|
<ion-item button class="ion-text-wrap divider" (click)="toggle(favourites)"
|
||||||
[attr.aria-label]="(favourites.expanded ? 'core.collapse' : 'core.expand') | translate"
|
[attr.aria-label]="(favourites.expanded ? 'core.collapse' : 'core.expand') | translate"
|
||||||
[attr.aria-expanded]="favourites.expanded" aria-controls="addon-messages-groupconversations-favourite" role="heading"
|
[attr.aria-expanded]="favourites.expanded" aria-controls="addon-messages-groupconversations-favourite" role="heading"
|
||||||
detail="false">
|
[detail]="false">
|
||||||
<ion-icon name="fas-chevron-right" flip-rtl slot="start" aria-hidden="true" class="expandable-status-icon"
|
<ion-icon name="fas-chevron-right" flip-rtl slot="start" aria-hidden="true" class="expandable-status-icon"
|
||||||
[class.expandable-status-icon-expanded]="favourites.expanded">
|
[class.expandable-status-icon-expanded]="favourites.expanded">
|
||||||
</ion-icon>
|
</ion-icon>
|
||||||
|
@ -73,9 +73,9 @@
|
||||||
</ion-item>
|
</ion-item>
|
||||||
|
|
||||||
<!-- Group conversations. -->
|
<!-- Group conversations. -->
|
||||||
<ion-item button class="divider ion-text-wrap" (click)="toggle(group)" sticky="true"
|
<ion-item button class="divider ion-text-wrap" (click)="toggle(group)"
|
||||||
[attr.aria-label]="(group.expanded ? 'core.collapse' : 'core.expand') | translate" [attr.aria-expanded]="group.expanded"
|
[attr.aria-label]="(group.expanded ? 'core.collapse' : 'core.expand') | translate" [attr.aria-expanded]="group.expanded"
|
||||||
aria-controls="addon-messages-groupconversations-group" role="heading" detail="false">
|
aria-controls="addon-messages-groupconversations-group" role="heading" [detail]="false">
|
||||||
<ion-icon name="fas-chevron-right" flip-rtl slot="start" aria-hidden="true" class="expandable-status-icon"
|
<ion-icon name="fas-chevron-right" flip-rtl slot="start" aria-hidden="true" class="expandable-status-icon"
|
||||||
[class.expandable-status-icon-expanded]="group.expanded">
|
[class.expandable-status-icon-expanded]="group.expanded">
|
||||||
</ion-icon>
|
</ion-icon>
|
||||||
|
@ -106,10 +106,10 @@
|
||||||
</ion-label>
|
</ion-label>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
|
|
||||||
<ion-item button class="divider ion-text-wrap" (click)="toggle(individual)" sticky="true"
|
<ion-item button class="divider ion-text-wrap" (click)="toggle(individual)"
|
||||||
[attr.aria-label]="(individual.expanded ? 'core.collapse' : 'core.expand') | translate"
|
[attr.aria-label]="(individual.expanded ? 'core.collapse' : 'core.expand') | translate"
|
||||||
[attr.aria-expanded]="individual.expanded" aria-controls="addon-messages-groupconversations-individual" role="heading"
|
[attr.aria-expanded]="individual.expanded" aria-controls="addon-messages-groupconversations-individual" role="heading"
|
||||||
detail="false">
|
[detail]="false">
|
||||||
<ion-icon name="fas-chevron-right" flip-rtl slot="start" aria-hidden="true" class="expandable-status-icon"
|
<ion-icon name="fas-chevron-right" flip-rtl slot="start" aria-hidden="true" class="expandable-status-icon"
|
||||||
[class.expandable-status-icon-expanded]="individual.expanded">
|
[class.expandable-status-icon-expanded]="individual.expanded">
|
||||||
</ion-icon>
|
</ion-icon>
|
||||||
|
@ -147,7 +147,7 @@
|
||||||
|
|
||||||
<!-- Template to render a list of conversations. -->
|
<!-- Template to render a list of conversations. -->
|
||||||
<ng-template #conversationsTemplate let-conversations="conversations">
|
<ng-template #conversationsTemplate let-conversations="conversations">
|
||||||
<ion-item class="ion-text-wrap addon-message-discussion" *ngFor="let conversation of conversations" button detail="false"
|
<ion-item class="ion-text-wrap addon-message-discussion" *ngFor="let conversation of conversations" button [detail]="false"
|
||||||
(click)="gotoConversation(conversation.id, conversation.userid)"
|
(click)="gotoConversation(conversation.id, conversation.userid)"
|
||||||
[attr.aria-current]="((conversation.id &&
|
[attr.aria-current]="((conversation.id &&
|
||||||
conversation.id == selectedConversationId) || (conversation.userid && conversation.userid == selectedUserId)) ? 'page': 'false'"
|
conversation.id == selectedConversationId) || (conversation.userid && conversation.userid == selectedUserId)) ? 'page': 'false'"
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import { Component, OnInit, OnDestroy, ViewChild, ElementRef } from '@angular/core';
|
import { Component, OnInit, OnDestroy, ViewChild, ElementRef } from '@angular/core';
|
||||||
import { IonContent, IonRefresher } from '@ionic/angular';
|
import { IonContent } from '@ionic/angular';
|
||||||
import { CoreEventObserver, CoreEvents } from '@singletons/events';
|
import { CoreEventObserver, CoreEvents } from '@singletons/events';
|
||||||
import { CoreSites } from '@services/sites';
|
import { CoreSites } from '@services/sites';
|
||||||
import {
|
import {
|
||||||
|
@ -719,7 +719,7 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy {
|
||||||
* @param refreshUnreadCounts Whether to refresh unread counts.
|
* @param refreshUnreadCounts Whether to refresh unread counts.
|
||||||
* @returns Promise resolved when done.
|
* @returns Promise resolved when done.
|
||||||
*/
|
*/
|
||||||
async refreshData(refresher?: IonRefresher, refreshUnreadCounts: boolean = true): Promise<void> {
|
async refreshData(refresher?: HTMLIonRefresherElement, refreshUnreadCounts: boolean = true): Promise<void> {
|
||||||
// Don't invalidate conversations and so, they always try to get latest data.
|
// Don't invalidate conversations and so, they always try to get latest data.
|
||||||
try {
|
try {
|
||||||
await AddonMessages.invalidateContactRequestsCountCache(this.siteId);
|
await AddonMessages.invalidateContactRequestsCountCache(this.siteId);
|
||||||
|
|
|
@ -45,7 +45,7 @@
|
||||||
|
|
||||||
<!-- List of results -->
|
<!-- List of results -->
|
||||||
<ion-item class="addon-message-discussion ion-text-wrap" *ngFor="let result of item.results" [attr.aria-label]="result.fullname"
|
<ion-item class="addon-message-discussion ion-text-wrap" *ngFor="let result of item.results" [attr.aria-label]="result.fullname"
|
||||||
(click)="openConversation(result)" [attr.aria-current]="result == selectedResult ? 'page' : 'false'" detail="true" button>
|
(click)="openConversation(result)" [attr.aria-current]="result == selectedResult ? 'page' : 'false'" [detail]="true" button>
|
||||||
<core-user-avatar slot="start" [user]="result" [checkOnline]="true" [linkProfile]="false"></core-user-avatar>
|
<core-user-avatar slot="start" [user]="result" [checkOnline]="true" [linkProfile]="false"></core-user-avatar>
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<p class="item-heading">
|
<p class="item-heading">
|
||||||
|
@ -68,7 +68,7 @@
|
||||||
</ion-item>
|
</ion-item>
|
||||||
|
|
||||||
<!-- Load more button for contacts and non-contacts -->
|
<!-- Load more button for contacts and non-contacts -->
|
||||||
<ng-container *ngIf="item.type != 'messages'">
|
<ng-container *ngIf="item.type !== 'messages'">
|
||||||
<div class="ion-padding-horizontal" *ngIf="item.canLoadMore && !item.loadingMore">
|
<div class="ion-padding-horizontal" *ngIf="item.canLoadMore && !item.loadingMore">
|
||||||
<ion-button expand="block" fill="outline" (click)="search(query, item.type)">
|
<ion-button expand="block" fill="outline" (click)="search(query, item.type)">
|
||||||
{{ 'core.loadmore' | translate }}
|
{{ 'core.loadmore' | translate }}
|
||||||
|
|
|
@ -25,7 +25,6 @@ import { CoreEvents } from '@singletons/events';
|
||||||
import { CoreSites } from '@services/sites';
|
import { CoreSites } from '@services/sites';
|
||||||
import { CoreDomUtils } from '@services/utils/dom';
|
import { CoreDomUtils } from '@services/utils/dom';
|
||||||
import { CoreConstants } from '@/core/constants';
|
import { CoreConstants } from '@/core/constants';
|
||||||
import { IonRefresher } from '@ionic/angular';
|
|
||||||
import { AddonNotificationsPreferencesNotificationProcessorState } from '@addons/notifications/services/notifications';
|
import { AddonNotificationsPreferencesNotificationProcessorState } from '@addons/notifications/services/notifications';
|
||||||
import { CorePlatform } from '@services/platform';
|
import { CorePlatform } from '@services/platform';
|
||||||
|
|
||||||
|
@ -251,7 +250,7 @@ export class AddonMessagesSettingsPage implements OnInit, OnDestroy {
|
||||||
*
|
*
|
||||||
* @param refresher Refresher.
|
* @param refresher Refresher.
|
||||||
*/
|
*/
|
||||||
refreshPreferences(refresher?: IonRefresher): void {
|
refreshPreferences(refresher?: HTMLIonRefresherElement): void {
|
||||||
AddonMessages.invalidateMessagePreferences().finally(() => {
|
AddonMessages.invalidateMessagePreferences().finally(() => {
|
||||||
this.fetchPreferences().finally(() => {
|
this.fetchPreferences().finally(() => {
|
||||||
refresher?.complete();
|
refresher?.complete();
|
||||||
|
|
|
@ -46,7 +46,8 @@
|
||||||
</ion-item>
|
</ion-item>
|
||||||
|
|
||||||
<!-- Summary of all submissions. -->
|
<!-- Summary of all submissions. -->
|
||||||
<ion-item class="ion-text-wrap" *ngIf="summary && summary.participantcount" (click)="goToSubmissionList()" detail="true" button>
|
<ion-item class="ion-text-wrap" *ngIf="summary && summary.participantcount" (click)="goToSubmissionList()" [detail]="true"
|
||||||
|
button>
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<p class="item-heading" *ngIf="assign.teamsubmission">{{ 'addon.mod_assign.numberofteams' | translate }}</p>
|
<p class="item-heading" *ngIf="assign.teamsubmission">{{ 'addon.mod_assign.numberofteams' | translate }}</p>
|
||||||
<p class="item-heading" *ngIf="!assign.teamsubmission">{{ 'addon.mod_assign.numberofparticipants' | translate }}</p>
|
<p class="item-heading" *ngIf="!assign.teamsubmission">{{ 'addon.mod_assign.numberofparticipants' | translate }}</p>
|
||||||
|
|
|
@ -54,7 +54,7 @@ import { AddonModAssignSubmissionComponent } from '../submission/submission';
|
||||||
})
|
})
|
||||||
export class AddonModAssignIndexComponent extends CoreCourseModuleMainActivityComponent implements OnInit, OnDestroy {
|
export class AddonModAssignIndexComponent extends CoreCourseModuleMainActivityComponent implements OnInit, OnDestroy {
|
||||||
|
|
||||||
@ViewChild(AddonModAssignSubmissionComponent) submissionComponent?: AddonModAssignSubmissionComponent;
|
@ViewChild(AddonModAssignSubmissionComponent) submissionComponent?: AddonModAssignSubmissionComponent;
|
||||||
|
|
||||||
component = AddonModAssignProvider.COMPONENT;
|
component = AddonModAssignProvider.COMPONENT;
|
||||||
pluginName = 'assign';
|
pluginName = 'assign';
|
||||||
|
|
|
@ -264,7 +264,7 @@
|
||||||
<ng-template>
|
<ng-template>
|
||||||
<!-- Current grade if method is advanced. -->
|
<!-- Current grade if method is advanced. -->
|
||||||
<ion-item class="ion-text-wrap core-grading-summary"
|
<ion-item class="ion-text-wrap core-grading-summary"
|
||||||
*ngIf="feedback?.gradefordisplay && (!isGrading || grade.method != 'simple')">
|
*ngIf="feedback?.gradefordisplay && (!isGrading || grade.method !== 'simple')">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<p class="item-heading">{{ 'addon.mod_assign.currentgrade' | translate }}</p>
|
<p class="item-heading">{{ 'addon.mod_assign.currentgrade' | translate }}</p>
|
||||||
<p>
|
<p>
|
||||||
|
@ -280,7 +280,7 @@
|
||||||
<ng-container *ngIf="isGrading">
|
<ng-container *ngIf="isGrading">
|
||||||
<!-- Numeric grade.
|
<!-- Numeric grade.
|
||||||
Use a text input because otherwise we cannot readthe value if it has an invalid character. -->
|
Use a text input because otherwise we cannot readthe value if it has an invalid character. -->
|
||||||
<ion-item class="ion-text-wrap" *ngIf="grade.method == 'simple' && !grade.scale">
|
<ion-item class="ion-text-wrap" *ngIf="grade.method === 'simple' && !grade.scale">
|
||||||
<ion-label position="stacked">
|
<ion-label position="stacked">
|
||||||
<p class="item-heading">{{ 'addon.mod_assign.gradeoutof' | translate: {$a: gradeInfo!.grade} }}</p>
|
<p class="item-heading">{{ 'addon.mod_assign.gradeoutof' | translate: {$a: gradeInfo!.grade} }}</p>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
|
@ -291,7 +291,7 @@
|
||||||
</ion-item>
|
</ion-item>
|
||||||
|
|
||||||
<!-- Grade using a scale. -->
|
<!-- Grade using a scale. -->
|
||||||
<ion-item class="ion-text-wrap" *ngIf="grade.method == 'simple' && grade.scale">
|
<ion-item class="ion-text-wrap" *ngIf="grade.method === 'simple' && grade.scale">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<p class="item-heading">{{ 'addon.mod_assign.grade' | translate }}</p>
|
<p class="item-heading">{{ 'addon.mod_assign.grade' | translate }}</p>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
|
@ -323,13 +323,13 @@
|
||||||
<ion-item class="ion-text-wrap" *ngIf="gradeInfo && grade.unreleasedGrade !== undefined">
|
<ion-item class="ion-text-wrap" *ngIf="gradeInfo && grade.unreleasedGrade !== undefined">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<p class="item-heading">{{ 'addon.mod_assign.currentassigngrade' | translate }}</p>
|
<p class="item-heading">{{ 'addon.mod_assign.currentassigngrade' | translate }}</p>
|
||||||
<p *ngIf="grade.method != 'simple' || !grade.scale">{{ grade.unreleasedGrade}} / {{ gradeInfo.grade }}</p>
|
<p *ngIf="grade.method !== 'simple' || !grade.scale">{{ grade.unreleasedGrade}} / {{ gradeInfo.grade }}</p>
|
||||||
<p *ngIf="grade.method == 'simple' && grade.scale">{{ grade.unreleasedGrade }}</p>
|
<p *ngIf="grade.method === 'simple' && grade.scale">{{ grade.unreleasedGrade }}</p>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
|
|
||||||
<!-- Gradebook grade for simple grading. -->
|
<!-- Gradebook grade for simple grading. -->
|
||||||
<ion-item class="ion-text-wrap" *ngIf="grade.method == 'simple'">
|
<ion-item class="ion-text-wrap" *ngIf="grade.method === 'simple'">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<p class="item-heading">{{ 'addon.mod_assign.currentgrade' | translate }}</p>
|
<p class="item-heading">{{ 'addon.mod_assign.currentgrade' | translate }}</p>
|
||||||
<p *ngIf="grade.gradebookGrade && !grade.scale">
|
<p *ngIf="grade.gradebookGrade && !grade.scale">
|
||||||
|
@ -393,7 +393,7 @@
|
||||||
|
|
||||||
<!-- Data about the grader (teacher who graded). -->
|
<!-- Data about the grader (teacher who graded). -->
|
||||||
<ion-item class="ion-text-wrap" *ngIf="grader" core-user-link [userId]="grader!.id" [courseId]="courseId"
|
<ion-item class="ion-text-wrap" *ngIf="grader" core-user-link [userId]="grader!.id" [courseId]="courseId"
|
||||||
[attr.aria-label]="grader!.fullname" detail="true">
|
[attr.aria-label]="grader!.fullname" [detail]="true">
|
||||||
<core-user-avatar [user]="grader" slot="start" [linkProfile]="false"></core-user-avatar>
|
<core-user-avatar [user]="grader" slot="start" [linkProfile]="false"></core-user-avatar>
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<p class="item-heading">{{ 'addon.mod_assign.gradedby' | translate }}</p>
|
<p class="item-heading">{{ 'addon.mod_assign.gradedby' | translate }}</p>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
</ion-buttons>
|
</ion-buttons>
|
||||||
<ion-title>
|
<ion-title>
|
||||||
<h1>
|
<h1>
|
||||||
<core-format-text [text]="title" contextLevel="module" [contextInstanceId]="module?.id" [courseId]="courseId">
|
<core-format-text [text]="title" contextLevel="module" [contextInstanceId]="module.id" [courseId]="courseId">
|
||||||
</core-format-text>
|
</core-format-text>
|
||||||
</h1>
|
</h1>
|
||||||
</ion-title>
|
</ion-title>
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
<!-- List of submissions. -->
|
<!-- List of submissions. -->
|
||||||
<ng-container *ngFor="let submission of submissions.items">
|
<ng-container *ngFor="let submission of submissions.items">
|
||||||
<ion-item class="ion-text-wrap" (click)="submissions.select(submission)" button
|
<ion-item class="ion-text-wrap" (click)="submissions.select(submission)" button
|
||||||
[attr.aria-current]="submissions.getItemAriaCurrent(submission)" detail="true">
|
[attr.aria-current]="submissions.getItemAriaCurrent(submission)" [detail]="true">
|
||||||
<core-user-avatar [user]="submission" [linkProfile]="false" slot="start"></core-user-avatar>
|
<core-user-avatar [user]="submission" [linkProfile]="false" slot="start"></core-user-avatar>
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<p class="item-heading" *ngIf="submission.userfullname">{{submission.userfullname}}</p>
|
<p class="item-heading" *ngIf="submission.userfullname">{{submission.userfullname}}</p>
|
||||||
|
|
|
@ -16,7 +16,6 @@ import { Component, OnDestroy, AfterViewInit, ViewChild } from '@angular/core';
|
||||||
import { CoreListItemsManager } from '@classes/items-management/list-items-manager';
|
import { CoreListItemsManager } from '@classes/items-management/list-items-manager';
|
||||||
import { CoreRoutedItemsManagerSourcesTracker } from '@classes/items-management/routed-items-manager-sources-tracker';
|
import { CoreRoutedItemsManagerSourcesTracker } from '@classes/items-management/routed-items-manager-sources-tracker';
|
||||||
import { CoreSplitViewComponent } from '@components/split-view/split-view';
|
import { CoreSplitViewComponent } from '@components/split-view/split-view';
|
||||||
import { IonRefresher } from '@ionic/angular';
|
|
||||||
import { CoreGroupInfo } from '@services/groups';
|
import { CoreGroupInfo } from '@services/groups';
|
||||||
import { CoreNavigator } from '@services/navigator';
|
import { CoreNavigator } from '@services/navigator';
|
||||||
import { CoreSites } from '@services/sites';
|
import { CoreSites } from '@services/sites';
|
||||||
|
@ -208,7 +207,7 @@ export class AddonModAssignSubmissionListPage implements AfterViewInit, OnDestro
|
||||||
*
|
*
|
||||||
* @param refresher Refresher.
|
* @param refresher Refresher.
|
||||||
*/
|
*/
|
||||||
refreshList(refresher?: IonRefresher): void {
|
refreshList(refresher?: HTMLIonRefresherElement): void {
|
||||||
this.refreshAllData(true).finally(() => {
|
this.refreshAllData(true).finally(() => {
|
||||||
refresher?.complete();
|
refresher?.complete();
|
||||||
});
|
});
|
||||||
|
|
|
@ -18,7 +18,6 @@ import { CoreRoutedItemsManagerSourcesTracker } from '@classes/items-management/
|
||||||
import { CoreSwipeNavigationItemsManager } from '@classes/items-management/swipe-navigation-items-manager';
|
import { CoreSwipeNavigationItemsManager } from '@classes/items-management/swipe-navigation-items-manager';
|
||||||
import { CoreCourse } from '@features/course/services/course';
|
import { CoreCourse } from '@features/course/services/course';
|
||||||
import { CanLeave } from '@guards/can-leave';
|
import { CanLeave } from '@guards/can-leave';
|
||||||
import { IonRefresher } from '@ionic/angular';
|
|
||||||
import { CoreNavigator } from '@services/navigator';
|
import { CoreNavigator } from '@services/navigator';
|
||||||
import { CoreScreen } from '@services/screen';
|
import { CoreScreen } from '@services/screen';
|
||||||
import { CoreDomUtils } from '@services/utils/dom';
|
import { CoreDomUtils } from '@services/utils/dom';
|
||||||
|
@ -210,7 +209,7 @@ export class AddonModAssignSubmissionReviewPage implements OnInit, OnDestroy, Ca
|
||||||
*
|
*
|
||||||
* @param refresher Refresher.
|
* @param refresher Refresher.
|
||||||
*/
|
*/
|
||||||
refreshSubmission(refresher?: IonRefresher): void {
|
refreshSubmission(refresher?: HTMLIonRefresherElement): void {
|
||||||
this.refreshAllData().finally(() => {
|
this.refreshAllData().finally(() => {
|
||||||
refresher?.complete();
|
refresher?.complete();
|
||||||
});
|
});
|
||||||
|
|
|
@ -28,6 +28,7 @@ import {
|
||||||
SUBMISSIONS_GRADES_TABLE,
|
SUBMISSIONS_GRADES_TABLE,
|
||||||
SUBMISSIONS_TABLE,
|
SUBMISSIONS_TABLE,
|
||||||
} from './database/assign';
|
} from './database/assign';
|
||||||
|
import { CoreArray } from '@singletons/array';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Service to handle offline assign.
|
* Service to handle offline assign.
|
||||||
|
@ -86,8 +87,8 @@ export class AddonModAssignOfflineProvider {
|
||||||
|
|
||||||
const results = await Promise.all(promises);
|
const results = await Promise.all(promises);
|
||||||
// Flatten array.
|
// Flatten array.
|
||||||
const flatten: (AddonModAssignSubmissionsDBRecord | AddonModAssignSubmissionsGradingDBRecord)[] =
|
const flatten = CoreArray
|
||||||
[].concat.apply([], results);
|
.flatten<AddonModAssignSubmissionsDBRecordFormatted | AddonModAssignSubmissionsGradingDBRecordFormatted>(results);
|
||||||
|
|
||||||
// Get assign id.
|
// Get assign id.
|
||||||
let assignIds: number[] = flatten.map((assign) => assign.assignid);
|
let assignIds: number[] = flatten.map((assign) => assign.assignid);
|
||||||
|
|
|
@ -166,7 +166,7 @@ export class AddonModAssignPrefetchHandlerService extends CoreCourseActivityPref
|
||||||
|
|
||||||
// Get intro and activity files from the submission status if it's a student.
|
// Get intro and activity files from the submission status if it's a student.
|
||||||
// It's ok if they were already obtained from the assignment instance, they won't be downloaded twice.
|
// It's ok if they were already obtained from the assignment instance, they won't be downloaded twice.
|
||||||
const files = canViewAllSubmissions ?
|
const files: CoreWSFile[] = canViewAllSubmissions ?
|
||||||
[] :
|
[] :
|
||||||
(submissionStatus.assignmentdata?.attachments?.intro || [])
|
(submissionStatus.assignmentdata?.attachments?.intro || [])
|
||||||
.concat(submissionStatus.assignmentdata?.attachments?.activity || []);
|
.concat(submissionStatus.assignmentdata?.attachments?.activity || []);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<ion-item *ngIf="commentsEnabled" class="ion-text-wrap" (click)="showComments($event)" detail="true" button>
|
<ion-item *ngIf="commentsEnabled" class="ion-text-wrap" (click)="showComments($event)" [detail]="true" button>
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<h2>{{plugin.name}}</h2>
|
<h2>{{plugin.name}}</h2>
|
||||||
<core-comments contextLevel="module" [instanceId]="assign.cmid" component="assignsubmission_comments" [itemId]="submission.id"
|
<core-comments contextLevel="module" [instanceId]="assign.cmid" component="assignsubmission_comments" [itemId]="submission.id"
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
<!-- Edit -->
|
<!-- Edit -->
|
||||||
<div *ngIf="edit">
|
<div *ngIf="edit">
|
||||||
<ion-item-divider class="ion-text-wrap" sticky="true">
|
<ion-item-divider class="ion-text-wrap" [sticky]="true">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<h2>{{ plugin.name }}</h2>
|
<h2>{{ plugin.name }}</h2>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
|
|
||||||
<!-- Edit -->
|
<!-- Edit -->
|
||||||
<div *ngIf="edit && loaded">
|
<div *ngIf="edit && loaded">
|
||||||
<ion-item-divider class="ion-text-wrap" sticky="true">
|
<ion-item-divider class="ion-text-wrap" [sticky]="true">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<h2>{{ plugin.name }}</h2>
|
<h2>{{ plugin.name }}</h2>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
|
|
|
@ -92,7 +92,7 @@
|
||||||
</ion-item>
|
</ion-item>
|
||||||
<ng-container *ngFor="let recording of recordings">
|
<ng-container *ngFor="let recording of recordings">
|
||||||
<ion-item button class="addon-mod_bbb-recording-title" [attr.aria-expanded]="recording.expanded" (click)="toggle(recording)"
|
<ion-item button class="addon-mod_bbb-recording-title" [attr.aria-expanded]="recording.expanded" (click)="toggle(recording)"
|
||||||
[attr.aria-label]="(recording.expanded ? 'core.collapse' : 'core.expand') | translate" detail="false">
|
[attr.aria-label]="(recording.expanded ? 'core.collapse' : 'core.expand') | translate" [detail]="false">
|
||||||
<ion-icon name="fas-chevron-right" flip-rtl slot="start" aria-hidden="true" class="expandable-status-icon"
|
<ion-icon name="fas-chevron-right" flip-rtl slot="start" aria-hidden="true" class="expandable-status-icon"
|
||||||
[class.expandable-status-icon-expanded]="recording.expanded">
|
[class.expandable-status-icon-expanded]="recording.expanded">
|
||||||
</ion-icon>
|
</ion-icon>
|
||||||
|
@ -108,7 +108,7 @@
|
||||||
<p class="item-heading">{{ recording.playbackLabel }}</p>
|
<p class="item-heading">{{ recording.playbackLabel }}</p>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
<ion-item *ngFor="let playback of recording.playbacks" button (click)="openPlayback($event, playback)" detail="false"
|
<ion-item *ngFor="let playback of recording.playbacks" button (click)="openPlayback($event, playback)" [detail]="false"
|
||||||
class="ion-text-wrap addon-mod_bbb-recording-playback-item">
|
class="ion-text-wrap addon-mod_bbb-recording-playback-item">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<p>{{ playback.name }}</p>
|
<p>{{ playback.name }}</p>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
</ion-buttons>
|
</ion-buttons>
|
||||||
<ion-title>
|
<ion-title>
|
||||||
<h1>
|
<h1>
|
||||||
<core-format-text [text]="title" contextLevel="module" [contextInstanceId]="module?.id" [courseId]="courseId">
|
<core-format-text [text]="title" contextLevel="module" [contextInstanceId]="module.id" [courseId]="courseId">
|
||||||
</core-format-text>
|
</core-format-text>
|
||||||
</h1>
|
</h1>
|
||||||
</ion-title>
|
</ion-title>
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
</ion-label>
|
</ion-label>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
|
|
||||||
<ion-item class="ion-text-wrap" *ngFor="let chapter of chapters" [class.item-dimmed]="chapter.hidden" button detail="true"
|
<ion-item class="ion-text-wrap" *ngFor="let chapter of chapters" [class.item-dimmed]="chapter.hidden" button [detail]="true"
|
||||||
(click)="openBook(chapter.id)">
|
(click)="openBook(chapter.id)">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<p [class.ion-padding-start]="addPadding && chapter.level == 1 ? true : null">
|
<p [class.ion-padding-start]="addPadding && chapter.level == 1 ? true : null">
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
<nav>
|
<nav>
|
||||||
<ion-list>
|
<ion-list>
|
||||||
<ion-item class="ion-text-wrap" *ngFor="let chapter of chapters" (click)="loadChapter(chapter.id)"
|
<ion-item class="ion-text-wrap" *ngFor="let chapter of chapters" (click)="loadChapter(chapter.id)"
|
||||||
[attr.aria-current]="selected == chapter.id ? 'page' : 'false'" button [class.item-dimmed]="chapter.hidden" detail="false">
|
[attr.aria-current]="selected == chapter.id ? 'page' : 'false'" button [class.item-dimmed]="chapter.hidden" [detail]="false">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<p [class.ion-padding-start]="addPadding && chapter.level == 1 ? true : null" class="item-heading">
|
<p [class.ion-padding-start]="addPadding && chapter.level == 1 ? true : null" class="item-heading">
|
||||||
<span *ngIf="showNumbers" class="addon-mod-book-number">{{chapter.indexNumber}} </span>
|
<span *ngIf="showNumbers" class="addon-mod-book-number">{{chapter.indexNumber}} </span>
|
||||||
|
|
|
@ -24,7 +24,6 @@ import { CoreCourse } from '@features/course/services/course';
|
||||||
import { CoreCourseModuleData } from '@features/course/services/course-helper';
|
import { CoreCourseModuleData } from '@features/course/services/course-helper';
|
||||||
import { CoreCourseModulePrefetchDelegate } from '@features/course/services/module-prefetch-delegate';
|
import { CoreCourseModulePrefetchDelegate } from '@features/course/services/module-prefetch-delegate';
|
||||||
import { CoreTag, CoreTagItem } from '@features/tag/services/tag';
|
import { CoreTag, CoreTagItem } from '@features/tag/services/tag';
|
||||||
import { IonRefresher } from '@ionic/angular';
|
|
||||||
import { CoreNetwork } from '@services/network';
|
import { CoreNetwork } from '@services/network';
|
||||||
import { CoreNavigator } from '@services/navigator';
|
import { CoreNavigator } from '@services/navigator';
|
||||||
import { CoreDomUtils } from '@services/utils/dom';
|
import { CoreDomUtils } from '@services/utils/dom';
|
||||||
|
@ -232,7 +231,7 @@ export class AddonModBookContentsPage implements OnInit, OnDestroy {
|
||||||
* @param refresher Refresher.
|
* @param refresher Refresher.
|
||||||
* @returns Promise resolved when done.
|
* @returns Promise resolved when done.
|
||||||
*/
|
*/
|
||||||
async doRefresh(refresher?: IonRefresher): Promise<void> {
|
async doRefresh(refresher?: HTMLIonRefresherElement): Promise<void> {
|
||||||
if (this.manager) {
|
if (this.manager) {
|
||||||
await CoreUtils.ignoreErrors(Promise.all([
|
await CoreUtils.ignoreErrors(Promise.all([
|
||||||
this.manager.getSource().invalidateContent(),
|
this.manager.getSource().invalidateContent(),
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
</ion-buttons>
|
</ion-buttons>
|
||||||
<ion-title>
|
<ion-title>
|
||||||
<h1>
|
<h1>
|
||||||
<core-format-text [text]="title" contextLevel="module" [contextInstanceId]="module?.id" [courseId]="courseId">
|
<core-format-text [text]="title" contextLevel="module" [contextInstanceId]="module.id" [courseId]="courseId">
|
||||||
</core-format-text>
|
</core-format-text>
|
||||||
</h1>
|
</h1>
|
||||||
</ion-title>
|
</ion-title>
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div class="ion-text-center addon-mod_chat-notice" *ngIf="message.special">
|
<div class="ion-text-center addon-mod_chat-notice" *ngIf="message.special">
|
||||||
<ion-badge class="ion-text-wrap" color="success" *ngIf="message.system && message.message == 'enter'">
|
<ion-badge class="ion-text-wrap" color="success" *ngIf="message.system && message.message === 'enter'">
|
||||||
<span>
|
<span>
|
||||||
<ion-icon name="fas-right-to-bracket" aria-hidden="true"></ion-icon>
|
<ion-icon name="fas-right-to-bracket" aria-hidden="true"></ion-icon>
|
||||||
{{ message.timestamp * 1000 | coreFormatDate:"strftimetime" }}
|
{{ message.timestamp * 1000 | coreFormatDate:"strftimetime" }}
|
||||||
|
@ -34,7 +34,7 @@
|
||||||
</span>
|
</span>
|
||||||
</ion-badge>
|
</ion-badge>
|
||||||
|
|
||||||
<ion-badge class="ion-text-wrap" color="danger" *ngIf="message.system && message.message == 'exit'">
|
<ion-badge class="ion-text-wrap" color="danger" *ngIf="message.system && message.message === 'exit'">
|
||||||
<span>
|
<span>
|
||||||
<ion-icon name="fas-right-from-bracket" aria-hidden="true"></ion-icon>
|
<ion-icon name="fas-right-from-bracket" aria-hidden="true"></ion-icon>
|
||||||
{{ message.timestamp * 1000 | coreFormatDate:"strftimetime" }}
|
{{ message.timestamp * 1000 | coreFormatDate:"strftimetime" }}
|
||||||
|
@ -42,7 +42,7 @@
|
||||||
</span>
|
</span>
|
||||||
</ion-badge>
|
</ion-badge>
|
||||||
|
|
||||||
<ion-badge class="ion-text-wrap" color="primary" *ngIf="message.beep == 'all'">
|
<ion-badge class="ion-text-wrap" color="primary" *ngIf="message.beep === 'all'">
|
||||||
<span>
|
<span>
|
||||||
<ion-icon name="fas-bell" aria-hidden="true"></ion-icon>
|
<ion-icon name="fas-bell" aria-hidden="true"></ion-icon>
|
||||||
{{ message.timestamp * 1000 | coreFormatDate:"strftimetime" }}
|
{{ message.timestamp * 1000 | coreFormatDate:"strftimetime" }}
|
||||||
|
@ -60,7 +60,7 @@
|
||||||
</ion-badge>
|
</ion-badge>
|
||||||
|
|
||||||
<ion-badge class="ion-text-wrap" color="light"
|
<ion-badge class="ion-text-wrap" color="light"
|
||||||
*ngIf="message.userid == currentUserId && message.beep && message.beep != 'all'">
|
*ngIf="message.userid === currentUserId && message.beep && message.beep !== 'all'">
|
||||||
<span>
|
<span>
|
||||||
<ion-icon name="fas-bell" aria-hidden="true"></ion-icon>
|
<ion-icon name="fas-bell" aria-hidden="true"></ion-icon>
|
||||||
{{ message.timestamp * 1000 | coreFormatDate:"strftimetime" }}
|
{{ message.timestamp * 1000 | coreFormatDate:"strftimetime" }}
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
@import "~theme/components/discussion.scss";
|
|
||||||
|
|
||||||
:host {
|
:host {
|
||||||
.addon-mod_chat-notice {
|
.addon-mod_chat-notice {
|
||||||
margin-top: 8px;
|
margin-top: 8px;
|
||||||
|
|
|
@ -37,7 +37,7 @@ import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'page-addon-mod-chat-chat',
|
selector: 'page-addon-mod-chat-chat',
|
||||||
templateUrl: 'chat.html',
|
templateUrl: 'chat.html',
|
||||||
styleUrls: ['chat.scss'],
|
styleUrls: ['../../../../../theme/components/discussion.scss', 'chat.scss'],
|
||||||
})
|
})
|
||||||
export class AddonModChatChatPage implements OnInit, OnDestroy, CanLeave {
|
export class AddonModChatChatPage implements OnInit, OnDestroy, CanLeave {
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
</ion-buttons>
|
</ion-buttons>
|
||||||
<ion-title>
|
<ion-title>
|
||||||
<h1>
|
<h1>
|
||||||
<core-format-text [text]="title" contextLevel="module" [contextInstanceId]="module?.id" [courseId]="courseId">
|
<core-format-text [text]="title" contextLevel="module" [contextInstanceId]="module.id" [courseId]="courseId">
|
||||||
</core-format-text>
|
</core-format-text>
|
||||||
</h1>
|
</h1>
|
||||||
</ion-title>
|
</ion-title>
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="ion-text-center addon-mod_chat-notice" *ngIf="message.special">
|
<div class="ion-text-center addon-mod_chat-notice" *ngIf="message.special">
|
||||||
<ion-badge class="ion-text-wrap" color="success" *ngIf="message.issystem && message.message == 'enter'">
|
<ion-badge class="ion-text-wrap" color="success" *ngIf="message.issystem && message.message === 'enter'">
|
||||||
<span>
|
<span>
|
||||||
<ion-icon name="fas-right-to-bracket" aria-hidden="true"></ion-icon>
|
<ion-icon name="fas-right-to-bracket" aria-hidden="true"></ion-icon>
|
||||||
{{ message.timestamp * 1000 | coreFormatDate:"strftimetime" }}
|
{{ message.timestamp * 1000 | coreFormatDate:"strftimetime" }}
|
||||||
|
@ -29,7 +29,7 @@
|
||||||
</span>
|
</span>
|
||||||
</ion-badge>
|
</ion-badge>
|
||||||
|
|
||||||
<ion-badge class="ion-text-wrap" color="danger" *ngIf="message.issystem && message.message == 'exit'">
|
<ion-badge class="ion-text-wrap" color="danger" *ngIf="message.issystem && message.message === 'exit'">
|
||||||
<span>
|
<span>
|
||||||
<ion-icon name="fas-right-from-bracket" aria-hidden="true"></ion-icon>
|
<ion-icon name="fas-right-from-bracket" aria-hidden="true"></ion-icon>
|
||||||
{{ message.timestamp * 1000 | coreFormatDate:"strftimetime" }}
|
{{ message.timestamp * 1000 | coreFormatDate:"strftimetime" }}
|
||||||
|
@ -37,7 +37,7 @@
|
||||||
</span>
|
</span>
|
||||||
</ion-badge>
|
</ion-badge>
|
||||||
|
|
||||||
<ion-badge class="ion-text-wrap" color="primary" *ngIf="message.beep == 'all'">
|
<ion-badge class="ion-text-wrap" color="primary" *ngIf="message.beep === 'all'">
|
||||||
<span>
|
<span>
|
||||||
<ion-icon name="fas-bell" aria-hidden="true"></ion-icon>
|
<ion-icon name="fas-bell" aria-hidden="true"></ion-icon>
|
||||||
{{ message.timestamp * 1000 | coreFormatDate:"strftimetime" }}
|
{{ message.timestamp * 1000 | coreFormatDate:"strftimetime" }}
|
||||||
|
@ -55,7 +55,7 @@
|
||||||
</ion-badge>
|
</ion-badge>
|
||||||
|
|
||||||
<ion-badge class="ion-text-wrap" color="light"
|
<ion-badge class="ion-text-wrap" color="light"
|
||||||
*ngIf="message.userid == currentUserId && message.beep && message.beep != 'all'">
|
*ngIf="message.userid === currentUserId && message.beep && message.beep !== 'all'">
|
||||||
<span>
|
<span>
|
||||||
<ion-icon name="fas-bell" aria-hidden="true"></ion-icon>
|
<ion-icon name="fas-bell" aria-hidden="true"></ion-icon>
|
||||||
{{ message.timestamp * 1000 | coreFormatDate:"strftimetime" }}
|
{{ message.timestamp * 1000 | coreFormatDate:"strftimetime" }}
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
@import "~theme/components/discussion.scss";
|
|
||||||
|
|
||||||
:host {
|
:host {
|
||||||
.addon-mod_chat-notice {
|
.addon-mod_chat-notice {
|
||||||
margin-top: 8px;
|
margin-top: 8px;
|
||||||
|
|
|
@ -14,7 +14,6 @@
|
||||||
|
|
||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { CoreUser } from '@features/user/services/user';
|
import { CoreUser } from '@features/user/services/user';
|
||||||
import { IonRefresher } from '@ionic/angular';
|
|
||||||
import { CoreNavigator } from '@services/navigator';
|
import { CoreNavigator } from '@services/navigator';
|
||||||
import { CoreSites } from '@services/sites';
|
import { CoreSites } from '@services/sites';
|
||||||
import { CoreDomUtils } from '@services/utils/dom';
|
import { CoreDomUtils } from '@services/utils/dom';
|
||||||
|
@ -31,7 +30,7 @@ import { CoreTime } from '@singletons/time';
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'page-addon-mod-chat-session-messages',
|
selector: 'page-addon-mod-chat-session-messages',
|
||||||
templateUrl: 'session-messages.html',
|
templateUrl: 'session-messages.html',
|
||||||
styleUrls: ['session-messages.scss'],
|
styleUrls: ['../../../../../theme/components/discussion.scss', 'session-messages.scss'],
|
||||||
})
|
})
|
||||||
export class AddonModChatSessionMessagesPage implements OnInit {
|
export class AddonModChatSessionMessagesPage implements OnInit {
|
||||||
|
|
||||||
|
@ -158,7 +157,7 @@ export class AddonModChatSessionMessagesPage implements OnInit {
|
||||||
*
|
*
|
||||||
* @param refresher Refresher.
|
* @param refresher Refresher.
|
||||||
*/
|
*/
|
||||||
async refreshMessages(refresher: IonRefresher): Promise<void> {
|
async refreshMessages(refresher: HTMLIonRefresherElement): Promise<void> {
|
||||||
try {
|
try {
|
||||||
await CoreUtils.ignoreErrors(AddonModChat.invalidateSessionMessages(this.chatId, this.sessionStart, this.groupId));
|
await CoreUtils.ignoreErrors(AddonModChat.invalidateSessionMessages(this.chatId, this.sessionStart, this.groupId));
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,6 @@ import { AfterViewInit, Component, OnDestroy, OnInit, ViewChild } from '@angular
|
||||||
import { CoreListItemsManager } from '@classes/items-management/list-items-manager';
|
import { CoreListItemsManager } from '@classes/items-management/list-items-manager';
|
||||||
import { CoreRoutedItemsManagerSourcesTracker } from '@classes/items-management/routed-items-manager-sources-tracker';
|
import { CoreRoutedItemsManagerSourcesTracker } from '@classes/items-management/routed-items-manager-sources-tracker';
|
||||||
import { CoreSplitViewComponent } from '@components/split-view/split-view';
|
import { CoreSplitViewComponent } from '@components/split-view/split-view';
|
||||||
import { IonRefresher } from '@ionic/angular';
|
|
||||||
import { CoreGroupInfo } from '@services/groups';
|
import { CoreGroupInfo } from '@services/groups';
|
||||||
import { CoreNavigator } from '@services/navigator';
|
import { CoreNavigator } from '@services/navigator';
|
||||||
import { CoreDomUtils } from '@services/utils/dom';
|
import { CoreDomUtils } from '@services/utils/dom';
|
||||||
|
@ -143,7 +142,7 @@ export class AddonModChatSessionsPage implements OnInit, AfterViewInit, OnDestro
|
||||||
*
|
*
|
||||||
* @param refresher Refresher.
|
* @param refresher Refresher.
|
||||||
*/
|
*/
|
||||||
async refreshSessions(refresher: IonRefresher): Promise<void> {
|
async refreshSessions(refresher: HTMLIonRefresherElement): Promise<void> {
|
||||||
try {
|
try {
|
||||||
this.sessions.getSource().setDirty(true);
|
this.sessions.getSource().setDirty(true);
|
||||||
|
|
||||||
|
|
|
@ -89,7 +89,7 @@
|
||||||
<ion-col *ngIf="choice.publish && results" size="12" size-lg="7">
|
<ion-col *ngIf="choice.publish && results" size="12" size-lg="7">
|
||||||
<ion-item-group *ngFor="let result of results">
|
<ion-item-group *ngFor="let result of results">
|
||||||
<ion-item [button]="result.numberofuser > 0" class="divider ion-text-wrap" (click)="toggle(result)"
|
<ion-item [button]="result.numberofuser > 0" class="divider ion-text-wrap" (click)="toggle(result)"
|
||||||
[attr.aria-label]="(result.expanded ? 'core.collapse' : 'core.expand') | translate" detail="false">
|
[attr.aria-label]="(result.expanded ? 'core.collapse' : 'core.expand') | translate" [detail]="false">
|
||||||
<ion-icon [name]="result.numberofuser > 0 ? 'fas-chevron-right' : ''" flip-rtl slot="start" aria-hidden="true"
|
<ion-icon [name]="result.numberofuser > 0 ? 'fas-chevron-right' : ''" flip-rtl slot="start" aria-hidden="true"
|
||||||
class="expandable-status-icon" [class.expandable-status-icon-expanded]="result.expanded">
|
class="expandable-status-icon" [class.expandable-status-icon-expanded]="result.expanded">
|
||||||
</ion-icon>
|
</ion-icon>
|
||||||
|
|
|
@ -301,7 +301,7 @@ export class AddonModChoiceIndexComponent extends CoreCourseModuleMainActivityCo
|
||||||
this.data = [];
|
this.data = [];
|
||||||
this.labels = [];
|
this.labels = [];
|
||||||
|
|
||||||
this.results = results.map((result: AddonModChoiceResultFormatted) => {
|
this.results = results.map<AddonModChoiceResultFormatted>((result) => {
|
||||||
if (result.numberofuser > 0) {
|
if (result.numberofuser > 0) {
|
||||||
hasVotes = true;
|
hasVotes = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
</ion-buttons>
|
</ion-buttons>
|
||||||
<ion-title>
|
<ion-title>
|
||||||
<h1>
|
<h1>
|
||||||
<core-format-text [text]="title" contextLevel="module" [contextInstanceId]="module?.id" [courseId]="courseId">
|
<core-format-text [text]="title" contextLevel="module" [contextInstanceId]="module.id" [courseId]="courseId">
|
||||||
</core-format-text>
|
</core-format-text>
|
||||||
</h1>
|
</h1>
|
||||||
</ion-title>
|
</ion-title>
|
||||||
|
|
|
@ -1,49 +1,49 @@
|
||||||
<ion-button size="small" *ngIf="action == 'actionsmenu'" fill="clear" (click)="actionsMenu($event)"
|
<ion-button size="small" *ngIf="action === 'actionsmenu'" fill="clear" (click)="actionsMenu($event)"
|
||||||
[attr.aria-label]="'addon.mod_data.actionsmenu' | translate">
|
[attr.aria-label]="'addon.mod_data.actionsmenu' | translate">
|
||||||
<ion-icon name="fas-ellipsis-vertical" slot="icon-only" aria-hidden="true"></ion-icon>
|
<ion-icon name="fas-ellipsis-vertical" slot="icon-only" aria-hidden="true"></ion-icon>
|
||||||
</ion-button>
|
</ion-button>
|
||||||
|
|
||||||
<ion-button size="small" *ngIf="action == 'more'" fill="clear" (click)="viewEntry()"
|
<ion-button size="small" *ngIf="action === 'more'" fill="clear" (click)="viewEntry()"
|
||||||
[attr.aria-label]="'addon.mod_data.showmore' | translate">
|
[attr.aria-label]="'addon.mod_data.showmore' | translate">
|
||||||
<ion-icon name="fas-magnifying-glass-plus" slot="icon-only" aria-hidden="true"></ion-icon>
|
<ion-icon name="fas-magnifying-glass-plus" slot="icon-only" aria-hidden="true"></ion-icon>
|
||||||
</ion-button>
|
</ion-button>
|
||||||
|
|
||||||
<ion-button size="small" *ngIf="action == 'edit'" fill="clear" (click)="editEntry()" [attr.aria-label]="'core.edit' | translate">
|
<ion-button size="small" *ngIf="action === 'edit'" fill="clear" (click)="editEntry()" [attr.aria-label]="'core.edit' | translate">
|
||||||
<ion-icon name="fas-pen" slot="icon-only" aria-hidden="true"></ion-icon>
|
<ion-icon name="fas-pen" slot="icon-only" aria-hidden="true"></ion-icon>
|
||||||
</ion-button>
|
</ion-button>
|
||||||
|
|
||||||
<ion-button size="small" *ngIf="action == 'delete' && !entry.deleted" fill="clear" color="danger" (click)="deleteEntry()"
|
<ion-button size="small" *ngIf="action === 'delete' && !entry.deleted" fill="clear" color="danger" (click)="deleteEntry()"
|
||||||
[attr.aria-label]="'core.delete' | translate">
|
[attr.aria-label]="'core.delete' | translate">
|
||||||
<ion-icon name="fas-trash" slot="icon-only" aria-hidden="true"></ion-icon>
|
<ion-icon name="fas-trash" slot="icon-only" aria-hidden="true"></ion-icon>
|
||||||
</ion-button>
|
</ion-button>
|
||||||
|
|
||||||
<ion-button size="small" *ngIf="action == 'delete' && entry.deleted" fill="clear" color="danger" (click)="undoDelete()"
|
<ion-button size="small" *ngIf="action === 'delete' && entry.deleted" fill="clear" color="danger" (click)="undoDelete()"
|
||||||
[attr.aria-label]="'core.restore' | translate">
|
[attr.aria-label]="'core.restore' | translate">
|
||||||
<ion-icon name="fas-rotate-left" slot="icon-only" aria-hidden="true"></ion-icon>
|
<ion-icon name="fas-rotate-left" slot="icon-only" aria-hidden="true"></ion-icon>
|
||||||
</ion-button>
|
</ion-button>
|
||||||
|
|
||||||
<ion-button size="small" *ngIf="action == 'approve'" fill="clear" (click)="approveEntry()"
|
<ion-button size="small" *ngIf="action === 'approve'" fill="clear" (click)="approveEntry()"
|
||||||
[attr.aria-label]="'addon.mod_data.approve' | translate">
|
[attr.aria-label]="'addon.mod_data.approve' | translate">
|
||||||
<ion-icon name="fas-thumbs-up" slot="icon-only" aria-hidden="true"></ion-icon>
|
<ion-icon name="fas-thumbs-up" slot="icon-only" aria-hidden="true"></ion-icon>
|
||||||
</ion-button>
|
</ion-button>
|
||||||
|
|
||||||
<ion-button size="small" *ngIf="action == 'disapprove'" fill="clear" (click)="disapproveEntry()"
|
<ion-button size="small" *ngIf="action === 'disapprove'" fill="clear" (click)="disapproveEntry()"
|
||||||
[attr.aria-label]="'addon.mod_data.disapprove' | translate">
|
[attr.aria-label]="'addon.mod_data.disapprove' | translate">
|
||||||
<ion-icon name="far-thumbs-down" slot="icon-only" aria-hidden="true"></ion-icon>
|
<ion-icon name="far-thumbs-down" slot="icon-only" aria-hidden="true"></ion-icon>
|
||||||
</ion-button>
|
</ion-button>
|
||||||
|
|
||||||
<core-comments *ngIf="action == 'comments' && mode == 'list'" contextLevel="module" [instanceId]="database.coursemodule"
|
<core-comments *ngIf="action === 'comments' && mode === 'list'" contextLevel="module" [instanceId]="database.coursemodule"
|
||||||
component="mod_data" [itemId]="entry.id" area="database_entry" [courseId]="database.course">
|
component="mod_data" [itemId]="entry.id" area="database_entry" [courseId]="database.course">
|
||||||
</core-comments>
|
</core-comments>
|
||||||
|
|
||||||
<span *ngIf="action == 'timeadded'">{{ entry.timecreated * 1000 | coreFormatDate }}</span>
|
<span *ngIf="action === 'timeadded'">{{ entry.timecreated * 1000 | coreFormatDate }}</span>
|
||||||
<span *ngIf="action == 'timemodified'">{{ entry.timemodified * 1000 | coreFormatDate }}</span>
|
<span *ngIf="action === 'timemodified'">{{ entry.timemodified * 1000 | coreFormatDate }}</span>
|
||||||
|
|
||||||
<core-user-avatar *ngIf="action == 'userpicture'" [user]="entry" slot="start" [courseId]="database.course" [userId]="entry.userid"
|
<core-user-avatar *ngIf="action === 'userpicture'" [user]="entry" slot="start" [courseId]="database.course" [userId]="entry.userid"
|
||||||
[profileUrl]="userPicture"></core-user-avatar>
|
[profileUrl]="userPicture"></core-user-avatar>
|
||||||
|
|
||||||
<a *ngIf="action == 'user' && entry" core-user-link [courseId]="database.course" [userId]="entry.userid" [title]="entry.fullname">
|
<a *ngIf="action === 'user' && entry" core-user-link [courseId]="database.course" [userId]="entry.userid" [title]="entry.fullname">
|
||||||
{{entry.fullname}}
|
{{entry.fullname}}
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<core-tag-list *ngIf="tagsEnabled && action == 'tags' && entry" [tags]="entry.tags"></core-tag-list>
|
<core-tag-list *ngIf="tagsEnabled && action === 'tags' && entry" [tags]="entry.tags"></core-tag-list>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<ion-content>
|
<ion-content>
|
||||||
<ion-list>
|
<ion-list>
|
||||||
<ion-item button class="ion-text-wrap" (click)="onItemClick(item)" *ngFor="let item of items" detail="false"
|
<ion-item button class="ion-text-wrap" (click)="onItemClick(item)" *ngFor="let item of items" [detail]="false"
|
||||||
[attr.aria-label]="item.text | translate">
|
[attr.aria-label]="item.text | translate">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<p class="item-heading">{{ item.text | translate }}</p>
|
<p class="item-heading">{{ item.text | translate }}</p>
|
||||||
|
|
|
@ -63,14 +63,14 @@
|
||||||
|
|
||||||
<!-- Reset search. -->
|
<!-- Reset search. -->
|
||||||
<ng-container *ngIf="search.searching && !isEmpty">
|
<ng-container *ngIf="search.searching && !isEmpty">
|
||||||
<ion-item (click)="searchReset($event)" button detail="false" *ngIf="!foundRecordsTranslationData">
|
<ion-item (click)="searchReset($event)" button [detail]="false" *ngIf="!foundRecordsTranslationData">
|
||||||
<ion-label color="info">
|
<ion-label color="info">
|
||||||
{{ 'addon.mod_data.resetsettings' | translate}}
|
{{ 'addon.mod_data.resetsettings' | translate}}
|
||||||
</ion-label>
|
</ion-label>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
|
|
||||||
<ion-card class="core-success-card" *ngIf="foundRecordsTranslationData">
|
<ion-card class="core-success-card" *ngIf="foundRecordsTranslationData">
|
||||||
<ion-item (click)="searchReset($event)" button detail="false">
|
<ion-item (click)="searchReset($event)" button [detail]="false">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<p [innerHTML]="'addon.mod_data.foundrecords' | translate:{$a: foundRecordsTranslationData}"></p>
|
<p [innerHTML]="'addon.mod_data.foundrecords' | translate:{$a: foundRecordsTranslationData}"></p>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue