|
@ -153,7 +153,7 @@ jobs:
|
|||
|
||||
- name: Initialise moodle-plugin-ci
|
||||
run: |
|
||||
composer create-project -n --no-dev --prefer-dist moodlehq/moodle-plugin-ci ci ^4.4
|
||||
composer create-project -n --no-dev --prefer-dist moodlehq/moodle-plugin-ci ci ^4.5
|
||||
echo $(cd ci/bin; pwd) >> $GITHUB_PATH
|
||||
echo $(cd ci/vendor/bin; pwd) >> $GITHUB_PATH
|
||||
sudo locale-gen en_AU.UTF-8
|
||||
|
|
|
@ -69,7 +69,8 @@ jobs:
|
|||
cat circular-dependencies
|
||||
lines=$(cat circular-dependencies | wc -l)
|
||||
echo "Total circular dependencies: $lines"
|
||||
test $lines -le 185
|
||||
test $lines -ge 138
|
||||
test $lines -le 148
|
||||
- name: JavaScript code compatibility
|
||||
run: |
|
||||
npx check-es-compat www/*.js --polyfills="\{Array,String,TypedArray\}.prototype.at,Object.hasOwn"
|
||||
|
|
|
@ -3,8 +3,7 @@
|
|||
|
||||
<ion-list>
|
||||
<ion-item>
|
||||
<ion-label position="floating">What is the answer to the Ultimate Question of Life, The Universe, and Everything?</ion-label>
|
||||
<ion-input [(ngModel)]="CONTENT_OTHERDATA.answer"></ion-input>
|
||||
<ion-input labelPlacement="floating" [(ngModel)]="CONTENT_OTHERDATA.answer" label="What is the answer to the Ultimate Question of Life, The Universe, and Everything?"></ion-input>
|
||||
</ion-item>
|
||||
<ion-item *ngIf="CONTENT_OTHERDATA.answer === '42'">
|
||||
<ion-label>That is correct!</ion-label>
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
"@awesome-cordova-plugins/sqlite": "^6.7.0",
|
||||
"@awesome-cordova-plugins/status-bar": "^6.7.0",
|
||||
"@awesome-cordova-plugins/web-intent": "^6.7.0",
|
||||
"@ionic/angular": "^7.8.6",
|
||||
"@ionic/angular": "^8.2.5",
|
||||
"@ionic/cordova-builders": "^11.0.0",
|
||||
"@moodlehq/cordova-plugin-advanced-http": "3.3.1-moodle.1",
|
||||
"@moodlehq/cordova-plugin-camera": "7.0.0-moodle.1",
|
||||
|
@ -107,7 +107,7 @@
|
|||
"@angular/cli": "^17.3.6",
|
||||
"@angular/compiler-cli": "^17.3.7",
|
||||
"@angular/language-service": "^17.3.7",
|
||||
"@ionic/angular-toolkit": "^10.1.1",
|
||||
"@ionic/angular-toolkit": "^11.0.1",
|
||||
"@ionic/cli": "^7.2.0",
|
||||
"@jsdevtools/coverage-istanbul-loader": "^3.0.5",
|
||||
"@types/faker": "^5.5.9",
|
||||
|
@ -3646,123 +3646,32 @@
|
|||
"dev": true
|
||||
},
|
||||
"node_modules/@ionic/angular": {
|
||||
"version": "7.8.6",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/angular/-/angular-7.8.6.tgz",
|
||||
"integrity": "sha512-3Qe53hXpyjtx6fFcxt/NTAlauIawsGmCZJPauV5sAnSKVuX8C82C1zMAZTeJt6m2dnd71wythc98BXUXsx/UxQ==",
|
||||
"version": "8.2.5",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/angular/-/angular-8.2.5.tgz",
|
||||
"integrity": "sha512-vvL5TIN8YbrkW5IZ4TYw2zVa4/+boITe19nElPz1Bu7O15lEEzLe+9RqcIMDERwzgqzsBXLh1CUJk+1TXkMhJg==",
|
||||
"dependencies": {
|
||||
"@ionic/core": "7.8.6",
|
||||
"@ionic/core": "8.2.5",
|
||||
"ionicons": "^7.0.0",
|
||||
"jsonc-parser": "^3.0.0",
|
||||
"tslib": "^2.3.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@angular/core": ">=14.0.0",
|
||||
"@angular/forms": ">=14.0.0",
|
||||
"@angular/router": ">=14.0.0",
|
||||
"@angular/core": ">=16.0.0",
|
||||
"@angular/forms": ">=16.0.0",
|
||||
"@angular/router": ">=16.0.0",
|
||||
"rxjs": ">=7.5.0",
|
||||
"zone.js": ">=0.11.0"
|
||||
"zone.js": ">=0.13.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@ionic/angular-toolkit": {
|
||||
"version": "10.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/angular-toolkit/-/angular-toolkit-10.1.1.tgz",
|
||||
"integrity": "sha512-idLaBUY14M7JQmvxAGeDZvk7WcamWEHo1OHGRuLRAn+7uWrKeGxfWbnbZJhvRCLQndr8j7q3WV3Z+0APkPuKaQ==",
|
||||
"version": "11.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/angular-toolkit/-/angular-toolkit-11.0.1.tgz",
|
||||
"integrity": "sha512-dxx2RDbxDYM2nWRPIirKMJySHtqJ1u02T25PGbNb99W2Wlcmu1cza3+2/PQ8ga18yMz/dQqaGyEmPDf3ZSVO0w==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@angular-devkit/core": "^16.0.0",
|
||||
"@angular-devkit/schematics": "^16.0.0",
|
||||
"@schematics/angular": "^16.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@ionic/angular-toolkit/node_modules/@angular-devkit/core": {
|
||||
"version": "16.2.14",
|
||||
"resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-16.2.14.tgz",
|
||||
"integrity": "sha512-Ui14/d2+p7lnmXlK/AX2ieQEGInBV75lonNtPQgwrYgskF8ufCuN0DyVZQUy9fJDkC+xQxbJyYrby/BS0R0e7w==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"ajv": "8.12.0",
|
||||
"ajv-formats": "2.1.1",
|
||||
"jsonc-parser": "3.2.0",
|
||||
"picomatch": "2.3.1",
|
||||
"rxjs": "7.8.1",
|
||||
"source-map": "0.7.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^16.14.0 || >=18.10.0",
|
||||
"npm": "^6.11.0 || ^7.5.6 || >=8.0.0",
|
||||
"yarn": ">= 1.13.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"chokidar": "^3.5.2"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"chokidar": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@ionic/angular-toolkit/node_modules/@angular-devkit/schematics": {
|
||||
"version": "16.2.14",
|
||||
"resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-16.2.14.tgz",
|
||||
"integrity": "sha512-B6LQKInCT8w5zx5Pbroext5eFFRTCJdTwHN8GhcVS8IeKCnkeqVTQLjB4lBUg7LEm8Y7UHXwzrVxmk+f+MBXhw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@angular-devkit/core": "16.2.14",
|
||||
"jsonc-parser": "3.2.0",
|
||||
"magic-string": "0.30.1",
|
||||
"ora": "5.4.1",
|
||||
"rxjs": "7.8.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^16.14.0 || >=18.10.0",
|
||||
"npm": "^6.11.0 || ^7.5.6 || >=8.0.0",
|
||||
"yarn": ">= 1.13.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@ionic/angular-toolkit/node_modules/@schematics/angular": {
|
||||
"version": "16.2.14",
|
||||
"resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-16.2.14.tgz",
|
||||
"integrity": "sha512-YqIv727l9Qze8/OL6H9mBHc2jVXzAGRNBYnxYWqWhLbfvuVbbldo6NNIIjgv6lrl2LJSdPAAMNOD5m/f6210ug==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@angular-devkit/core": "16.2.14",
|
||||
"@angular-devkit/schematics": "16.2.14",
|
||||
"jsonc-parser": "3.2.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^16.14.0 || >=18.10.0",
|
||||
"npm": "^6.11.0 || ^7.5.6 || >=8.0.0",
|
||||
"yarn": ">= 1.13.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@ionic/angular-toolkit/node_modules/jsonc-parser": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz",
|
||||
"integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@ionic/angular-toolkit/node_modules/magic-string": {
|
||||
"version": "0.30.1",
|
||||
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.1.tgz",
|
||||
"integrity": "sha512-mbVKXPmS0z0G4XqFDCTllmDQ6coZzn94aMlb0o/A4HEHJCKcanlDZwYJgwnkmgD3jyWhUgj9VsPrfd972yPffA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@jridgewell/sourcemap-codec": "^1.4.15"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@ionic/angular-toolkit/node_modules/picomatch": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
|
||||
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=8.6"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/jonschlinkert"
|
||||
"@angular-devkit/core": "^17.0.0",
|
||||
"@angular-devkit/schematics": "^17.0.0",
|
||||
"@schematics/angular": "^17.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@ionic/angular/node_modules/jsonc-parser": {
|
||||
|
@ -4291,11 +4200,11 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@ionic/core": {
|
||||
"version": "7.8.6",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-7.8.6.tgz",
|
||||
"integrity": "sha512-HAYZdEmeJgOdo2kDlZkcCGHb+zs/vjU6iv4skbVBL7y+OnSv/oC2u83Yee8S3/aY0YAxkyBgu7hLTYH13Zc2Aw==",
|
||||
"version": "8.2.5",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-8.2.5.tgz",
|
||||
"integrity": "sha512-NhK5KfP5NL5NITibj8sOUlfI/ARNCF5rBu5HdIEfFe25MJkd0IYBQWjVaESFhSk7aB8pXEP8DIx1AHbT9e3Sog==",
|
||||
"dependencies": {
|
||||
"@stencil/core": "^4.12.2",
|
||||
"@stencil/core": "^4.19.2",
|
||||
"ionicons": "^7.2.2",
|
||||
"tslib": "^2.1.0"
|
||||
}
|
||||
|
|
|
@ -72,7 +72,7 @@
|
|||
"@awesome-cordova-plugins/sqlite": "^6.7.0",
|
||||
"@awesome-cordova-plugins/status-bar": "^6.7.0",
|
||||
"@awesome-cordova-plugins/web-intent": "^6.7.0",
|
||||
"@ionic/angular": "^7.8.6",
|
||||
"@ionic/angular": "^8.2.5",
|
||||
"@ionic/cordova-builders": "^11.0.0",
|
||||
"@moodlehq/cordova-plugin-advanced-http": "3.3.1-moodle.1",
|
||||
"@moodlehq/cordova-plugin-camera": "7.0.0-moodle.1",
|
||||
|
@ -141,7 +141,7 @@
|
|||
"@angular/cli": "^17.3.6",
|
||||
"@angular/compiler-cli": "^17.3.7",
|
||||
"@angular/language-service": "^17.3.7",
|
||||
"@ionic/angular-toolkit": "^10.1.1",
|
||||
"@ionic/angular-toolkit": "^11.0.1",
|
||||
"@ionic/cli": "^7.2.0",
|
||||
"@jsdevtools/coverage-istanbul-loader": "^3.0.5",
|
||||
"@types/faker": "^5.5.9",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
diff --git a/node_modules/@ionic/core/components/popover.js b/node_modules/@ionic/core/components/popover.js
|
||||
index 21fb3e3..52ea4a6 100644
|
||||
index 19b79c4..67289f4 100644
|
||||
--- a/node_modules/@ionic/core/components/popover.js
|
||||
+++ b/node_modules/@ionic/core/components/popover.js
|
||||
@@ -763,8 +763,10 @@ const iosEnterAnimation = (baseEl, opts) => {
|
||||
|
@ -29,10 +29,10 @@ index 21fb3e3..52ea4a6 100644
|
|||
const contentEl = root.querySelector('.popover-content');
|
||||
const referenceSizeEl = trigger || ((_a = ev === null || ev === void 0 ? void 0 : ev.detail) === null || _a === void 0 ? void 0 : _a.ionShadowTarget) || (ev === null || ev === void 0 ? void 0 : ev.target);
|
||||
diff --git a/node_modules/@ionic/core/dist/cjs/ion-popover.cjs.entry.js b/node_modules/@ionic/core/dist/cjs/ion-popover.cjs.entry.js
|
||||
index 68a908b..050e544 100644
|
||||
index 2dcf484..54aeac9 100644
|
||||
--- a/node_modules/@ionic/core/dist/cjs/ion-popover.cjs.entry.js
|
||||
+++ b/node_modules/@ionic/core/dist/cjs/ion-popover.cjs.entry.js
|
||||
@@ -768,8 +768,10 @@ const iosEnterAnimation = (baseEl, opts) => {
|
||||
@@ -769,8 +769,10 @@ const iosEnterAnimation = (baseEl, opts) => {
|
||||
const { event: ev, size, trigger, reference, side, align } = opts;
|
||||
const doc = baseEl.ownerDocument;
|
||||
const isRTL = doc.dir === 'rtl';
|
||||
|
@ -45,7 +45,7 @@ index 68a908b..050e544 100644
|
|||
const root = helpers.getElementRoot(baseEl);
|
||||
const contentEl = root.querySelector('.popover-content');
|
||||
const arrowEl = root.querySelector('.popover-arrow');
|
||||
@@ -889,8 +891,10 @@ const mdEnterAnimation = (baseEl, opts) => {
|
||||
@@ -890,8 +892,10 @@ const mdEnterAnimation = (baseEl, opts) => {
|
||||
const { event: ev, size, trigger, reference, side, align } = opts;
|
||||
const doc = baseEl.ownerDocument;
|
||||
const isRTL = doc.dir === 'rtl';
|
||||
|
@ -93,10 +93,10 @@ index 603923a..ff10a25 100644
|
|||
const contentEl = root.querySelector('.popover-content');
|
||||
const referenceSizeEl = trigger || ((_a = ev === null || ev === void 0 ? void 0 : ev.detail) === null || _a === void 0 ? void 0 : _a.ionShadowTarget) || (ev === null || ev === void 0 ? void 0 : ev.target);
|
||||
diff --git a/node_modules/@ionic/core/dist/esm/ion-popover.entry.js b/node_modules/@ionic/core/dist/esm/ion-popover.entry.js
|
||||
index 839e91c..abcd28f 100644
|
||||
index 8ca76cf..c5b990a 100644
|
||||
--- a/node_modules/@ionic/core/dist/esm/ion-popover.entry.js
|
||||
+++ b/node_modules/@ionic/core/dist/esm/ion-popover.entry.js
|
||||
@@ -764,8 +764,10 @@ const iosEnterAnimation = (baseEl, opts) => {
|
||||
@@ -765,8 +765,10 @@ const iosEnterAnimation = (baseEl, opts) => {
|
||||
const { event: ev, size, trigger, reference, side, align } = opts;
|
||||
const doc = baseEl.ownerDocument;
|
||||
const isRTL = doc.dir === 'rtl';
|
||||
|
@ -109,7 +109,7 @@ index 839e91c..abcd28f 100644
|
|||
const root = getElementRoot(baseEl);
|
||||
const contentEl = root.querySelector('.popover-content');
|
||||
const arrowEl = root.querySelector('.popover-arrow');
|
||||
@@ -885,8 +887,10 @@ const mdEnterAnimation = (baseEl, opts) => {
|
||||
@@ -886,8 +888,10 @@ const mdEnterAnimation = (baseEl, opts) => {
|
||||
const { event: ev, size, trigger, reference, side, align } = opts;
|
||||
const doc = baseEl.ownerDocument;
|
||||
const isRTL = doc.dir === 'rtl';
|
||||
|
@ -123,10 +123,10 @@ index 839e91c..abcd28f 100644
|
|||
const contentEl = root.querySelector('.popover-content');
|
||||
const referenceSizeEl = trigger || ((_a = ev === null || ev === void 0 ? void 0 : ev.detail) === null || _a === void 0 ? void 0 : _a.ionShadowTarget) || (ev === null || ev === void 0 ? void 0 : ev.target);
|
||||
diff --git a/node_modules/@ionic/core/hydrate/index.js b/node_modules/@ionic/core/hydrate/index.js
|
||||
index 7f898c7..a3a7669 100644
|
||||
index 5a50b98..884e2ce 100644
|
||||
--- a/node_modules/@ionic/core/hydrate/index.js
|
||||
+++ b/node_modules/@ionic/core/hydrate/index.js
|
||||
@@ -29254,8 +29254,10 @@ const iosEnterAnimation$1 = (baseEl, opts) => {
|
||||
@@ -23702,8 +23702,10 @@ const iosEnterAnimation$1 = (baseEl, opts) => {
|
||||
const { event: ev, size, trigger, reference, side, align } = opts;
|
||||
const doc = baseEl.ownerDocument;
|
||||
const isRTL = doc.dir === 'rtl';
|
||||
|
@ -139,7 +139,7 @@ index 7f898c7..a3a7669 100644
|
|||
const root = getElementRoot(baseEl);
|
||||
const contentEl = root.querySelector('.popover-content');
|
||||
const arrowEl = root.querySelector('.popover-arrow');
|
||||
@@ -29375,8 +29377,10 @@ const mdEnterAnimation$1 = (baseEl, opts) => {
|
||||
@@ -23823,8 +23825,10 @@ const mdEnterAnimation$1 = (baseEl, opts) => {
|
||||
const { event: ev, size, trigger, reference, side, align } = opts;
|
||||
const doc = baseEl.ownerDocument;
|
||||
const isRTL = doc.dir === 'rtl';
|
|
@ -150,6 +150,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
:host-context(html.dark) {
|
||||
:host-context(:root.dark) {
|
||||
--addon-calendar-blank-day-background-color: var(--gray-900);
|
||||
}
|
||||
|
|
|
@ -294,27 +294,6 @@ export class AddonCalendarHelperProvider {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Format reminders, adding calculated data.
|
||||
*
|
||||
* @param reminders Reminders.
|
||||
* @param timestart Event timestart.
|
||||
* @param siteId Site ID.
|
||||
* @returns Formatted reminders.
|
||||
* @deprecated since 4.1 Use AddonCalendarHelper.getEventReminders.
|
||||
*/
|
||||
async formatReminders(
|
||||
reminders: { eventid: number }[],
|
||||
timestart: number,
|
||||
siteId?: string,
|
||||
): Promise<AddonCalendarEventReminder[]> {
|
||||
if (!reminders.length) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return AddonCalendarHelper.getEventReminders(reminders[0].eventid, timestart, siteId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Format reminders, adding calculated data.
|
||||
*
|
||||
|
|
|
@ -45,10 +45,7 @@ import {
|
|||
CoreReminders,
|
||||
CoreRemindersPushNotificationData,
|
||||
CoreRemindersService,
|
||||
CoreRemindersUnits,
|
||||
CoreReminderValueAndUnit,
|
||||
} from '@features/reminders/services/reminders';
|
||||
import { CoreReminderDBRecord } from '@features/reminders/services/database/reminders';
|
||||
import { CoreEvents } from '@singletons/events';
|
||||
import { CoreSiteWSPreSets } from '@classes/sites/authenticated-site';
|
||||
import { ADDON_CALENDAR_COMPONENT } from '../constants';
|
||||
|
@ -66,18 +63,6 @@ export enum AddonCalendarEventType {
|
|||
USER = 'user',
|
||||
}
|
||||
|
||||
/**
|
||||
* Units to set a reminder.
|
||||
*
|
||||
* @deprecated since 4.1 Use CoreReminderUnits instead.
|
||||
*/
|
||||
export enum AddonCalendarReminderUnits {
|
||||
MINUTE = CoreConstants.SECONDS_MINUTE,
|
||||
HOUR = CoreConstants.SECONDS_HOUR,
|
||||
DAY = CoreConstants.SECONDS_DAY,
|
||||
WEEK = CoreConstants.SECONDS_WEEK,
|
||||
}
|
||||
|
||||
declare module '@singletons/events' {
|
||||
|
||||
/**
|
||||
|
@ -178,17 +163,6 @@ export class AddonCalendarProvider {
|
|||
return !!site?.isVersionGreaterEqualThan('3.7.1');
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a number of seconds, convert it to a unit&value format compatible with reminders.
|
||||
*
|
||||
* @param seconds Number of seconds.
|
||||
* @returns Value and unit.
|
||||
* @deprecated since 4.1 Use CoreRemindersService.convertSecondsToValueAndUnit instead.
|
||||
*/
|
||||
static convertSecondsToValueAndUnit(seconds: number): CoreReminderValueAndUnit {
|
||||
return CoreRemindersService.convertSecondsToValueAndUnit(seconds);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete an event.
|
||||
*
|
||||
|
@ -592,17 +566,6 @@ export class AddonCalendarProvider {
|
|||
return CoreTimeUtils.userDate(time, 'core.strftimedayshort');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the configured default notification time.
|
||||
*
|
||||
* @param siteId ID of the site. If not defined, use current site.
|
||||
* @returns Promise resolved with the default time (in seconds).
|
||||
* @deprecated since 4.1 Use CoreReminders.getDefaultNotificationTime instead.
|
||||
*/
|
||||
async getDefaultNotificationTime(siteId?: string): Promise<number> {
|
||||
return CoreReminders.getDefaultNotificationTime(siteId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a calendar event. If the server request fails and data is not cached, try to get it from local DB.
|
||||
*
|
||||
|
@ -780,18 +743,6 @@ export class AddonCalendarProvider {
|
|||
return event.eventtype;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an event reminder and cancel the notification.
|
||||
*
|
||||
* @param id Reminder ID.
|
||||
* @param siteId ID of the site the event belongs to. If not defined, use current site.
|
||||
* @returns Promise resolved when the notification is updated.
|
||||
* @deprecated since 4.1. Use CoreReminders.removeReminder instead.
|
||||
*/
|
||||
async deleteEventReminder(id: number, siteId?: string): Promise<void> {
|
||||
await CoreReminders.removeReminder(id, siteId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get calendar events for a certain day.
|
||||
*
|
||||
|
@ -876,21 +827,6 @@ export class AddonCalendarProvider {
|
|||
(categoryId ? categoryId : '');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a calendar reminders from local Db.
|
||||
*
|
||||
* @param eventId Event ID.
|
||||
* @param siteId ID of the site the event belongs to. If not defined, use current site.
|
||||
* @returns Promise resolved when the event data is retrieved.
|
||||
* @deprecated since 4.1. Use CoreReminders.getReminders instead.
|
||||
*/
|
||||
async getEventReminders(eventId: number, siteId?: string): Promise<CoreReminderDBRecord[]> {
|
||||
return CoreReminders.getReminders({
|
||||
instanceId: eventId,
|
||||
component: ADDON_CALENDAR_COMPONENT,
|
||||
}, siteId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the events in a certain period. The period is calculated like this:
|
||||
* start time: now + daysToStart
|
||||
|
@ -1089,19 +1025,6 @@ export class AddonCalendarProvider {
|
|||
(categoryId ? categoryId : '');
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a value and a unit, return the translated label.
|
||||
*
|
||||
* @param value Value.
|
||||
* @param unit Unit.
|
||||
* @param addDefaultLabel Whether to add the "Default" text.
|
||||
* @returns Translated label.
|
||||
* @deprecated since 4.1 Use CoreReminders.getUnitValueLabel instead.
|
||||
*/
|
||||
getUnitValueLabel(value: number, unit: CoreRemindersUnits, addDefaultLabel = false): string {
|
||||
return CoreReminders.getUnitValueLabel(value, unit, addDefaultLabel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get upcoming calendar events.
|
||||
*
|
||||
|
@ -1378,16 +1301,6 @@ export class AddonCalendarProvider {
|
|||
return this.isCalendarDisabledInSite(site);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the next events for all the sites and schedules their notifications.
|
||||
*
|
||||
* @returns Promise resolved when done.
|
||||
* @deprecated since 4.1 Use AddonCalendar.updateAllSitesEventReminders.
|
||||
*/
|
||||
async scheduleAllSitesEventsNotifications(): Promise<void> {
|
||||
await AddonCalendar.updateAllSitesEventReminders();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the next events for all the sites and updates their reminders.
|
||||
*/
|
||||
|
@ -1415,21 +1328,6 @@ export class AddonCalendarProvider {
|
|||
await this.getEventsList(undefined, undefined, undefined, siteId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the next events for all the sites and schedules their notifications.
|
||||
*
|
||||
* @returns Promise resolved when done.
|
||||
* @deprecated since 4.1. No replacement for that function.
|
||||
*/
|
||||
async scheduleEventsNotifications(
|
||||
events: ({ id: number; timestart: number; timeduration: number; name: string})[],
|
||||
siteId?: string,
|
||||
): Promise<void> {
|
||||
siteId = siteId || CoreSites.getCurrentSiteId();
|
||||
|
||||
await AddonCalendar.updateEventsReminders(events, siteId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedules the notifications for a list of events.
|
||||
* If an event notification time is 0, cancel its scheduled notification (if any).
|
||||
|
@ -1470,18 +1368,6 @@ export class AddonCalendarProvider {
|
|||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default notification time.
|
||||
*
|
||||
* @param time New default time.
|
||||
* @param siteId ID of the site. If not defined, use current site.
|
||||
* @returns Promise resolved when stored.
|
||||
* @deprecated since 4.1 Use CoreReminders.setDefaultNotificationTime.
|
||||
*/
|
||||
async setDefaultNotificationTime(time: number, siteId?: string): Promise<void> {
|
||||
await CoreReminders.setDefaultNotificationTime(time, siteId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store an event in local DB as it is.
|
||||
*
|
||||
|
@ -2203,13 +2089,6 @@ export type AddonCalendarUpdatedEventEvent = {
|
|||
sent?: boolean;
|
||||
};
|
||||
|
||||
/**
|
||||
* Value and unit for reminders.
|
||||
*
|
||||
* @deprecated since 4.1, use CoreReminderValueAndUnit instead.
|
||||
*/
|
||||
export type AddonCalendarValueAndUnit = CoreReminderValueAndUnit;
|
||||
|
||||
/**
|
||||
* Options to pass to submit event.
|
||||
*/
|
||||
|
|
|
@ -77,7 +77,7 @@
|
|||
{{ message.timecreated | coreFormatDate: "strftimedayshort" }}
|
||||
</h3>
|
||||
|
||||
<ion-chip class="addon-messages-unreadfrom" *ngIf="unreadMessageFrom > 0 && message.id === unreadMessageFrom" color="light">
|
||||
<ion-chip class="addon-messages-unreadfrom" *ngIf="unreadMessageFrom > 0 && message.id === unreadMessageFrom">
|
||||
<ion-label>{{ 'addon.messages.newmessages' | translate }}</ion-label>
|
||||
<ion-icon name="fas-arrow-down" aria-hidden="true" />
|
||||
</ion-chip>
|
||||
|
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
|
@ -40,7 +40,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
:host-context(html.dark) ::ng-deep {
|
||||
:host-context(:root.dark) ::ng-deep {
|
||||
ion-item.submissioneditable p {
|
||||
color: var(--danger-tint);
|
||||
}
|
||||
|
|
|
@ -449,7 +449,7 @@ export class AddonModAssignSubmissionComponent implements OnInit, OnDestroy, Can
|
|||
this.feedback,
|
||||
this.submitId,
|
||||
);
|
||||
} catch (error) {
|
||||
} catch {
|
||||
// Error ocurred, consider there are no changes.
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
</ion-toolbar>
|
||||
|
||||
<core-navbar-buttons slot="end">
|
||||
<ion-button [hidden]="!canSaveGrades" fill="clear" (click)="submitGrade()">
|
||||
<ion-button [class.hidden]="!canSaveGrades" fill="clear" (click)="submitGrade()">
|
||||
{{ 'core.done' | translate }}
|
||||
</ion-button>
|
||||
</core-navbar-buttons>
|
||||
|
|
|
@ -100,6 +100,7 @@ Feature: Test marking workflow in assignment activity in app
|
|||
And I press "Grade" in the app
|
||||
When I set the field "Grade out of 100" to "60" in the app
|
||||
And I press "Done" in the app
|
||||
And I wait loading to finish in the app
|
||||
And I press "Student1" in the app
|
||||
And I press "Grade" in the app
|
||||
Then I should find "60 / 100" within "Current grade in assignment" "ion-item" in the app
|
||||
|
@ -112,6 +113,7 @@ Feature: Test marking workflow in assignment activity in app
|
|||
And I press "Grade" in the app
|
||||
When I set the field "Grade out of 100" to "80" in the app
|
||||
And I press "Done" in the app
|
||||
And I wait loading to finish in the app
|
||||
And I press "Student3" in the app
|
||||
And I press "Grade" in the app
|
||||
Then I should find "80" within "Current grade in gradebook" "ion-item" in the app
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
:host-context(html.dark) {
|
||||
:host-context(:root.dark) {
|
||||
--recording-details-background: var(--gray-800);
|
||||
--recording-details-border: var(--gray-500);
|
||||
}
|
||||
|
|
|
@ -49,6 +49,8 @@ Feature: Test basic usage of BBB activity in app
|
|||
And I should be able to press "Join session" in the app
|
||||
|
||||
When I press "Join session" in the app
|
||||
# TODO: This step will make behat github actions work but we should find a better way to wait for the room to start.
|
||||
And I wait "3" seconds
|
||||
And I wait for the BigBlueButton room to start
|
||||
And I switch back to the app
|
||||
Then I should find "The session is in progress." in the app
|
||||
|
@ -68,6 +70,8 @@ Feature: Test basic usage of BBB activity in app
|
|||
And I should be able to press "Join session" in the app
|
||||
|
||||
When I press "Join session" in the app
|
||||
# TODO: This step will make behat github actions work but we should find a better way to wait for the room to start.
|
||||
And I wait "3" seconds
|
||||
And I wait for the BigBlueButton room to start
|
||||
And I switch back to the app
|
||||
Then I should find "The session is in progress." in the app
|
||||
|
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
|
@ -35,7 +35,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
:host-context(html.dark) {
|
||||
:host-context(:root.dark) {
|
||||
.addon-mod_h5pactivity-result-table-row.item:nth-child(even) {
|
||||
--background: var(--gray-900);
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
<ion-input labelPlacement="stacked" name="password" type="password"
|
||||
placeholder="{{ 'core.login.password' | translate }}" core-auto-focus #passwordinput [clearOnEdit]="false"
|
||||
[label]="'addon.mod_lesson.enterpassword' | translate">
|
||||
<core-show-password slot="end" />
|
||||
<ion-input-password-toggle slot="end" showIcon="fas-eye" hideIcon="fas-eye-slash" />
|
||||
</ion-input>
|
||||
</ion-item>
|
||||
<ion-button expand="block" type="submit">
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
--background-odd: var(--light);
|
||||
}
|
||||
|
||||
:host-context(html.dark) {
|
||||
:host-context(:root.dark) {
|
||||
--background-odd: var(--medium);
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,6 @@
|
|||
<ion-input id="addon-mod_quiz-accessrule-password-input" name="quizpassword" type="password"
|
||||
placeholder="{{ 'addon.mod_quiz.quizpassword' | translate }}" [formControlName]="'quizpassword'" [clearOnEdit]="false"
|
||||
[attr.aria-label]="'addon.mod_quiz.quizpassword' | translate">
|
||||
<core-show-password slot="end" />
|
||||
<ion-input-password-toggle slot="end" showIcon="fas-eye" hideIcon="fas-eye-slash" />
|
||||
</ion-input>
|
||||
</ion-item>
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
</ion-title>
|
||||
|
||||
<ion-buttons slot="end">
|
||||
<ion-button fill="clear" id="addon-mod_quiz-connection-error-button" [hidden]="!autoSaveError"
|
||||
<ion-button fill="clear" id="addon-mod_quiz-connection-error-button" [class.hidden]="!autoSaveError"
|
||||
(click)="showConnectionError($event)" [ariaLabel]="'addon.mod_quiz.connectionerror' | translate" aria-haspopup="dialog">
|
||||
<ion-icon name="fas-circle-exclamation" slot="icon-only" aria-hidden="true" />
|
||||
</ion-button>
|
||||
|
|
|
@ -167,12 +167,16 @@ Feature: Attempt a quiz in app
|
|||
And I press "Three" in the app
|
||||
And I set the field "Answer" to "Berlin" in the app
|
||||
And I press "Next" in the app
|
||||
And I wait loading to finish in the app
|
||||
And I set the field "Answer" to "testing" in the app
|
||||
And I press "Next" in the app
|
||||
And I wait loading to finish in the app
|
||||
And I set the field "Answer" to "5" in the app
|
||||
And I press "Next" in the app
|
||||
And I wait loading to finish in the app
|
||||
And I set the field "Answer" to "Testing an essay" in the app
|
||||
And I press "Next" "ion-button" in the app
|
||||
And I wait loading to finish in the app
|
||||
And I press "quick" ".drag" in the app
|
||||
And I click on ".place1.drop" "css"
|
||||
And I press "fox" ".drag" in the app
|
||||
|
@ -180,26 +184,33 @@ Feature: Attempt a quiz in app
|
|||
And I press "lazy" ".drag" in the app
|
||||
And I click on ".place3.drop" "css"
|
||||
And I press "Next" in the app
|
||||
And I wait loading to finish in the app
|
||||
And I press "True" in the app
|
||||
And I press "Next" in the app
|
||||
And I wait loading to finish in the app
|
||||
And I set the field "frog" to "amphibian" in the app
|
||||
And I set the field "newt" to "insect" in the app
|
||||
And I set the field "cat" to "mammal" in the app
|
||||
And I press "Next" in the app
|
||||
And I wait loading to finish in the app
|
||||
Then I should find "Text of the eighth question" in the app
|
||||
|
||||
When I press "Next" in the app
|
||||
And I wait loading to finish in the app
|
||||
And I set the field "Blank 1" to "cat" in the app
|
||||
And I set the field "Blank 2" to "mat" in the app
|
||||
And I press "Next" in the app
|
||||
And I wait loading to finish in the app
|
||||
And I press "abyssal" ".drag" in the app
|
||||
And I click on ".place6.dropzone" "css"
|
||||
And I press "trench" ".drag" in the app
|
||||
And I click on ".place3.dropzone" "css"
|
||||
And I press "Next" in the app
|
||||
And I wait loading to finish in the app
|
||||
And I press "Railway station" ".marker" in the app
|
||||
And I click on "img.dropbackground" "css"
|
||||
And I press "Submit" in the app
|
||||
And I wait loading to finish in the app
|
||||
Then I should find "Answer saved" in the app
|
||||
And I should find "Incomplete answer" within "10" "ion-item" in the app
|
||||
But I should not find "Not yet answered" in the app
|
||||
|
@ -224,8 +235,10 @@ Feature: Attempt a quiz in app
|
|||
|
||||
When I press "True" in the app
|
||||
And I press "Next" in the app
|
||||
And I wait loading to finish in the app
|
||||
And I press "False" in the app
|
||||
And I press "Submit" in the app
|
||||
And I wait loading to finish in the app
|
||||
And I press "Submit all and finish" in the app
|
||||
Then I should find "Once you submit" in the app
|
||||
But I should not find "Questions without a response" in the app
|
||||
|
|
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 37 KiB |
|
@ -25,7 +25,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
:host-context(html.dark) {
|
||||
:host-context(:root.dark) {
|
||||
--grid-background: var(--gray-900);
|
||||
--even-background: var(--medium);
|
||||
}
|
||||
|
|
|
@ -56,7 +56,7 @@ $addon-mod-wiki-toc-level-padding: 12px !default;
|
|||
}
|
||||
}
|
||||
|
||||
:host-context(html.dark) {
|
||||
:host-context(:root.dark) {
|
||||
--addon-mod-wiki-newentry-link-color: var(--danger-tint);
|
||||
--addon-mod-wiki-toc-background-color: var(--medium);
|
||||
}
|
||||
|
|
|
@ -10,8 +10,7 @@
|
|||
</h1>
|
||||
</ion-title>
|
||||
<ion-buttons slot="end" [hidden]="!loaded">
|
||||
<ion-button *ngIf="assessmentId && access.assessingallowed" fill="clear" (click)="saveAssessment()"
|
||||
[ariaLabel]="'core.save' | translate">
|
||||
<ion-button *ngIf="assessmentId && access.assessingallowed" fill="clear" (click)="saveAssessment()">
|
||||
{{ 'core.save' | translate }}
|
||||
</ion-button>
|
||||
<ion-button *ngIf="canAddFeedback" fill="clear" (click)="saveEvaluation()">
|
||||
|
|
|
@ -11,7 +11,8 @@
|
|||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<core-navbar-buttons slot="end">
|
||||
<ion-button [hidden]="!canDeleteNotes" slot="end" fill="clear" (click)="toggleDelete()" [ariaLabel]="'core.toggledelete' | translate">
|
||||
<ion-button [class.hidden]="!canDeleteNotes" slot="end" fill="clear" (click)="toggleDelete()"
|
||||
[ariaLabel]="'core.toggledelete' | translate">
|
||||
<ion-icon name="fas-pen" slot="icon-only" aria-hidden="true" />
|
||||
</ion-button>
|
||||
<core-context-menu>
|
||||
|
|
|
@ -209,72 +209,6 @@ export class AddonNotificationsProvider {
|
|||
return ROOT_CACHE_KEY + 'list';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get some notifications.
|
||||
*
|
||||
* @param notifications Current list of loaded notifications. It's used to calculate the offset.
|
||||
* @param options Other options.
|
||||
* @returns Promise resolved with notifications and if can load more.
|
||||
* @deprecated since 4.1. Use getNotificationsWithStatus instead.
|
||||
*/
|
||||
async getNotifications(
|
||||
notifications: AddonNotificationsNotificationMessageFormatted[],
|
||||
options?: AddonNotificationsGetNotificationsOptions,
|
||||
): Promise<{notifications: AddonNotificationsNotificationMessageFormatted[]; canLoadMore: boolean}> {
|
||||
|
||||
notifications = notifications || [];
|
||||
options = options || {};
|
||||
options.limit = options.limit || AddonNotificationsProvider.LIST_LIMIT;
|
||||
options.siteId = options.siteId || CoreSites.getCurrentSiteId();
|
||||
let newNotifications: AddonNotificationsNotificationMessageFormatted[];
|
||||
|
||||
// Request 1 more notification so we can know if there are more notifications.
|
||||
const originalLimit = options.limit;
|
||||
options.limit = options.limit + 1;
|
||||
|
||||
const site = await CoreSites.getSite(options.siteId);
|
||||
|
||||
if (site.isVersionGreaterEqualThan('4.0')) {
|
||||
// In 4.0 the app can request read and unread at the same time.
|
||||
options.offset = notifications.length;
|
||||
newNotifications = await this.getNotificationsWithStatus(
|
||||
AddonNotificationsGetReadType.BOTH,
|
||||
options,
|
||||
);
|
||||
} else {
|
||||
// We need 2 calls, one for read and the other one for unread.
|
||||
options.offset = notifications.reduce((total, current) => total + (current.read ? 0 : 1), 0);
|
||||
|
||||
const unread = await this.getNotificationsWithStatus(AddonNotificationsGetReadType.UNREAD, options);
|
||||
|
||||
newNotifications = unread;
|
||||
|
||||
if (unread.length < options.limit) {
|
||||
// Limit not reached. Get read notifications until reach the limit.
|
||||
const readOptions = {
|
||||
...options,
|
||||
offset: notifications.length - options.offset,
|
||||
limit: options.limit - unread.length,
|
||||
};
|
||||
|
||||
try {
|
||||
const read = await this.getNotificationsWithStatus(AddonNotificationsGetReadType.READ, readOptions);
|
||||
|
||||
newNotifications = unread.concat(read);
|
||||
} catch (error) {
|
||||
if (unread.length <= 0) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
notifications: newNotifications.slice(0, originalLimit),
|
||||
canLoadMore: newNotifications.length > originalLimit,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get notifications from site.
|
||||
*
|
||||
|
|
|
@ -31,7 +31,7 @@ export class CoreSiteError extends CoreError {
|
|||
}
|
||||
|
||||
/**
|
||||
* @deprecated This getter should not be called directly, but it's defined for backwards compatibility with many
|
||||
* @deprecated since 4.4. This getter should not be called directly, but it's defined for backwards compatibility with many
|
||||
* parts of the code that type errors as any and use it. We cannot rename those because the errors could also be
|
||||
* CoreWSError instances which do have an "errorcode" property.
|
||||
*
|
||||
|
|
|
@ -55,14 +55,6 @@ export class CorePromisedValue<T = unknown> extends CorePromise<T> {
|
|||
this.rejectPromise = rejectPromise;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns Promise.
|
||||
* @deprecated since 4.1. The instance can be directly used as a promise.
|
||||
*/
|
||||
get promise(): Promise<T> {
|
||||
return this;
|
||||
}
|
||||
|
||||
get value(): T | null {
|
||||
return this.resolvedValue ?? null;
|
||||
}
|
||||
|
|
|
@ -475,23 +475,6 @@ export class CoreSite extends CoreAuthenticatedSite {
|
|||
await this.openWithAutoLogin(false, url, options, alertMessage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Open a URL in browser using auto-login in the Moodle site if available and the URL belongs to the site.
|
||||
*
|
||||
* @param url The URL to open.
|
||||
* @param alertMessage If defined, an alert will be shown before opening the browser.
|
||||
* @param options Other options.
|
||||
* @returns Promise resolved when done, rejected otherwise.
|
||||
* @deprecated since 4.1. Use openInBrowserWithAutoLogin instead, now it always checks that URL belongs to same site.
|
||||
*/
|
||||
async openInBrowserWithAutoLoginIfSameSite(
|
||||
url: string,
|
||||
alertMessage?: string,
|
||||
options: CoreUtilsOpenInBrowserOptions = {},
|
||||
): Promise<void> {
|
||||
return this.openInBrowserWithAutoLogin(url, alertMessage, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Open a URL in inappbrowser using auto-login in the Moodle site if available.
|
||||
*
|
||||
|
@ -506,23 +489,6 @@ export class CoreSite extends CoreAuthenticatedSite {
|
|||
return iabInstance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Open a URL in inappbrowser using auto-login in the Moodle site if available and the URL belongs to the site.
|
||||
*
|
||||
* @param url The URL to open.
|
||||
* @param options Override default options passed to inappbrowser.
|
||||
* @param alertMessage If defined, an alert will be shown before opening the inappbrowser.
|
||||
* @returns Promise resolved when done.
|
||||
* @deprecated since 4.1. Use openInAppWithAutoLogin instead, now it always checks that URL belongs to same site.
|
||||
*/
|
||||
async openInAppWithAutoLoginIfSameSite(
|
||||
url: string,
|
||||
options?: InAppBrowserOptions,
|
||||
alertMessage?: string,
|
||||
): Promise<InAppBrowserObject> {
|
||||
return this.openInAppWithAutoLogin(url, options, alertMessage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Open a URL in browser or InAppBrowser using auto-login in the Moodle site if available.
|
||||
*
|
||||
|
@ -575,25 +541,6 @@ export class CoreSite extends CoreAuthenticatedSite {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Open a URL in browser or InAppBrowser using auto-login in the Moodle site if available and the URL belongs to the site.
|
||||
*
|
||||
* @param inApp True to open it in InAppBrowser, false to open in browser.
|
||||
* @param url The URL to open.
|
||||
* @param options Override default options passed to inappbrowser.
|
||||
* @param alertMessage If defined, an alert will be shown before opening the browser/inappbrowser.
|
||||
* @returns Promise resolved when done. Resolve param is returned only if inApp=true.
|
||||
* @deprecated since 4.1. Use openWithAutoLogin instead, now it always checks that URL belongs to same site.
|
||||
*/
|
||||
async openWithAutoLoginIfSameSite(
|
||||
inApp: boolean,
|
||||
url: string,
|
||||
options: InAppBrowserOptions & CoreUtilsOpenInBrowserOptions = {},
|
||||
alertMessage?: string,
|
||||
): Promise<InAppBrowserObject | void> {
|
||||
return this.openWithAutoLogin(inApp, url, options, alertMessage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the config of this site.
|
||||
* It is recommended to use getStoredConfig instead since it's faster and doesn't use network.
|
||||
|
|
|
@ -146,7 +146,7 @@
|
|||
}
|
||||
|
||||
.select-icon {
|
||||
color: var(--ion-color-step-500, gray);
|
||||
color: var(--ion-text-color-step-500, gray);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -97,7 +97,7 @@ import { CoreSitesListComponent } from './sites-list/sites-list';
|
|||
CoreProgressBarComponent,
|
||||
CoreRecaptchaComponent,
|
||||
CoreSendMessageFormComponent,
|
||||
CoreShowPasswordComponent,
|
||||
CoreShowPasswordComponent, // eslint-disable-line deprecation/deprecation
|
||||
CoreSitePickerComponent,
|
||||
CoreSplitViewComponent,
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
|
@ -153,7 +153,7 @@ import { CoreSitesListComponent } from './sites-list/sites-list';
|
|||
CoreProgressBarComponent,
|
||||
CoreRecaptchaComponent,
|
||||
CoreSendMessageFormComponent,
|
||||
CoreShowPasswordComponent,
|
||||
CoreShowPasswordComponent, // eslint-disable-line deprecation/deprecation
|
||||
CoreSitePickerComponent,
|
||||
CoreSplitViewComponent,
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<ion-button [hidden]="hideMenu" fill="clear" [ariaLabel]="ariaLabel" (click)="showContextMenu($event)" aria-haspopup="true"
|
||||
<ion-button [class.hidden]="hideMenu" fill="clear" [ariaLabel]="ariaLabel" (click)="showContextMenu($event)" aria-haspopup="true"
|
||||
[attr.aria-controls]="uniqueId">
|
||||
<ion-icon [name]="icon" slot="icon-only" aria-hidden="true" />
|
||||
</ion-button>
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
:host-context(html.dark) {
|
||||
:host-context(:root.dark) {
|
||||
&.dimmed {
|
||||
--text-color: var(--gray-300);
|
||||
}
|
||||
|
|
|
@ -78,7 +78,7 @@
|
|||
--margin-end: 12px;
|
||||
}
|
||||
|
||||
:host-context(html.dark) {
|
||||
:host-context(:root.dark) {
|
||||
&.version_40:not(.colorize),
|
||||
&.version_current {
|
||||
background-color: var(--white);
|
||||
|
|
|
@ -40,12 +40,12 @@ const BUTTON_HIDDEN_CLASS = 'core-navbar-button-hidden';
|
|||
*
|
||||
* You can use the [hidden] input to hide all the inner buttons if a certain condition is met.
|
||||
*
|
||||
* IMPORTANT: Do not use *ngIf in the buttons inside this component, it can cause problems. Please use [hidden] instead.
|
||||
* IMPORTANT: Do not use *ngIf in the buttons inside this component, it can cause problems. Please use [class.hidden] instead.
|
||||
*
|
||||
* Example usage:
|
||||
*
|
||||
* <core-navbar-buttons slot="end">
|
||||
* <ion-button [hidden]="!buttonShown" [attr.aria-label]="Do something" (click)="action()">
|
||||
* <ion-button [class.hidden]="!buttonShown" [ariaLabel]="Do something" (click)="action()">
|
||||
* <ion-icon name="funnel" slot="icon-only" aria-hidden="true"></ion-icon>
|
||||
* </ion-button>
|
||||
* </core-navbar-buttons>
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
<ion-input [ariaLabel]="placeholder | translate" class="ion-text-wrap core-ioninput-password" name="password"
|
||||
type="password" placeholder="{{ placeholder | translate }}" [(ngModel)]="password" core-auto-focus
|
||||
[clearOnEdit]="false">
|
||||
<core-show-password slot="end" />
|
||||
<ion-input-password-toggle slot="end" showIcon="fas-eye" hideIcon="fas-eye-slash" />
|
||||
</ion-input>
|
||||
</ion-item>
|
||||
<ion-item *ngIf="error" class="ion-text-wrap ion-padding-top text-danger">
|
||||
|
|
|
@ -1,5 +1,2 @@
|
|||
<ng-content />
|
||||
<ion-button fill="clear" [ariaLabel]="(shown ? 'core.hide' : 'core.show') | translate" core-suppress-events (onClick)="toggle($event)"
|
||||
(mousedown)="doNotBlur($event)" (keydown)="doNotBlur($event)" (keyup)="toggle($event)">
|
||||
<ion-icon [name]="shown ? 'fas-eye-slash' : 'fas-eye'" slot="icon-only" aria-hidden="true" />
|
||||
</ion-button>
|
||||
<ion-input-password-toggle slot="end" showIcon="fas-eye" hideIcon="fas-eye-slash" *ngIf="!this.ionInput" />
|
||||
|
|
|
@ -1,31 +0,0 @@
|
|||
@use "theme/globals" as *;
|
||||
|
||||
:host {
|
||||
display: contents;
|
||||
|
||||
// Only applies to deprecated way (surrounding).
|
||||
::ng-deep ion-input + ion-button {
|
||||
background: transparent;
|
||||
padding: 0 var(--inner-padding-end) 0 4px;
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
position: absolute;
|
||||
@include safe-area-position(null, 0px, null, null);
|
||||
top: 0;
|
||||
}
|
||||
|
||||
// Only applies to deprecated way (surrounding).
|
||||
::ng-deep ion-input {
|
||||
--padding-end: 56px !important;
|
||||
}
|
||||
|
||||
::ng-deep ion-input.input-label-placement-stacked + ion-button {
|
||||
top: 14px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ion-button {
|
||||
z-index: 5;
|
||||
pointer-events: visible;
|
||||
}
|
|
@ -12,173 +12,80 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { Component, OnInit, AfterViewInit, Input, ElementRef, ContentChild } from '@angular/core';
|
||||
import { Component, AfterViewInit, Input, ContentChild, ViewEncapsulation } from '@angular/core';
|
||||
import { IonInput } from '@ionic/angular';
|
||||
|
||||
import { CorePlatform } from '@services/platform';
|
||||
import { CoreDomUtils } from '@services/utils/dom';
|
||||
|
||||
import { CoreUtils } from '@services/utils/utils';
|
||||
import { CoreLogger } from '@singletons/logger';
|
||||
|
||||
/**
|
||||
* This component allows to show/hide a password.
|
||||
* It's meant to be used with ion-input.
|
||||
* It's recommended to use it as a slot of the input.
|
||||
* It's meant to be used with ion-input as a slot of the input.
|
||||
*
|
||||
* @description
|
||||
*
|
||||
* There are 2 ways to use ths component:
|
||||
* - Slot it to start or end on the ion-input element.
|
||||
* - Surround the ion-input with the password with this component. This is deprecated.
|
||||
*
|
||||
* In order to help finding the input you can specify the name of the input or the ion-input element.
|
||||
*
|
||||
* - Surround the ion-input with the password with this component. Not recommended.
|
||||
*
|
||||
* Example of new usage:
|
||||
*
|
||||
* <ion-input type="password" name="password">
|
||||
* <ion-input type="password">
|
||||
* <core-show-password slot="end" />
|
||||
* </ion-input>
|
||||
*
|
||||
* Example deprecated usage:
|
||||
* Example surrounding usage:
|
||||
*
|
||||
* <core-show-password>
|
||||
* <ion-input type="password" name="password"></ion-input>
|
||||
* <ion-input type="password" />
|
||||
* </core-show-password>
|
||||
*
|
||||
* @deprecated since 4.5. Use <ion-input-password-toggle slot="end" showIcon="fas-eye" hideIcon="fas-eye-slash" /> instead.
|
||||
*/
|
||||
@Component({
|
||||
selector: 'core-show-password',
|
||||
templateUrl: 'core-show-password.html',
|
||||
styleUrls: ['show-password.scss'],
|
||||
styles: 'core-show-password { display: contents; }',
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
})
|
||||
export class CoreShowPasswordComponent implements OnInit, AfterViewInit {
|
||||
|
||||
@Input() initialShown?: boolean | string; // Whether the password should be shown at start.
|
||||
|
||||
@Input() name = ''; // Deprecated. Not used anymore.
|
||||
@ContentChild(IonInput) ionInput?: IonInput | HTMLIonInputElement; // Deprecated. Use slot instead.
|
||||
|
||||
protected input?: HTMLInputElement;
|
||||
protected hostElement: HTMLElement;
|
||||
protected logger: CoreLogger;
|
||||
|
||||
constructor(element: ElementRef) {
|
||||
this.hostElement = element.nativeElement;
|
||||
this.logger = CoreLogger.getInstance('CoreShowPasswordComponent');
|
||||
}
|
||||
|
||||
get shown(): boolean {
|
||||
return this.input?.type === 'text';
|
||||
}
|
||||
|
||||
set shown(shown: boolean) {
|
||||
if (!this.input) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.input.type = shown ? 'text' : 'password';
|
||||
}
|
||||
export class CoreShowPasswordComponent implements AfterViewInit {
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
* @deprecated since 4.5. Not used anymore.
|
||||
*/
|
||||
ngOnInit(): void {
|
||||
this.shown = CoreUtils.isTrueOrOne(this.initialShown);
|
||||
}
|
||||
@Input() initialShown = '';
|
||||
|
||||
/**
|
||||
* @deprecated since 4.4. Not used anymore.
|
||||
*/
|
||||
@Input() name = '';
|
||||
|
||||
/**
|
||||
* @deprecated since 4.4. Use slotted solution instead.
|
||||
*/
|
||||
@ContentChild(IonInput) ionInput?: IonInput | HTMLIonInputElement;
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
async ngAfterViewInit(): Promise<void> {
|
||||
await this.setInputElement();
|
||||
|
||||
if (!this.input) {
|
||||
return;
|
||||
}
|
||||
|
||||
// By default, don't autocapitalize and autocorrect.
|
||||
if (!this.input.getAttribute('autocorrect')) {
|
||||
this.input.setAttribute('autocorrect', 'off');
|
||||
}
|
||||
if (!this.input.getAttribute('autocapitalize')) {
|
||||
this.input.setAttribute('autocapitalize', 'none');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the input element to affect.
|
||||
*/
|
||||
protected async setInputElement(): Promise<void> {
|
||||
if (!this.ionInput) {
|
||||
this.ionInput = this.hostElement.closest('ion-input') ?? undefined;
|
||||
|
||||
this.hostElement.setAttribute('slot', 'end');
|
||||
} else {
|
||||
// It's outside ion-input, warn devs.
|
||||
this.logger.warn('Deprecated CoreShowPasswordComponent usage, it\'s not needed to surround ion-input anymore.');
|
||||
}
|
||||
CoreLogger.getInstance('CoreShowPasswordComponent')
|
||||
.warn('Deprecated component, use <ion-input-password-toggle /> instead.');
|
||||
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
if (!this.ionInput) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
this.input = await this.ionInput.getInputElement();
|
||||
} catch {
|
||||
// This should never fail, but it does in some testing environment because Ionic elements are not
|
||||
// rendered properly. So in case this fails it will try to find through the name and ignore the error.
|
||||
const name = this.ionInput.name;
|
||||
if (!name) {
|
||||
return;
|
||||
}
|
||||
this.input = this.hostElement.querySelector<HTMLInputElement>('input[name="' + name + '"]') ?? undefined;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle show/hide password.
|
||||
*
|
||||
* @param event The mouse event.
|
||||
*/
|
||||
toggle(event: Event): void {
|
||||
if (event.type === 'keyup' && !this.isValidKeyboardKey(<KeyboardEvent>event)) {
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
const input = await CoreUtils.ignoreErrors(this.ionInput.getInputElement());
|
||||
if (!input) {
|
||||
return;
|
||||
}
|
||||
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
const isFocused = document.activeElement === this.input;
|
||||
this.shown = !this.shown;
|
||||
|
||||
// In Android, the keyboard is closed when the input type changes. Focus it again.
|
||||
if (this.input && isFocused && CorePlatform.isAndroid()) {
|
||||
CoreDomUtils.focusElement(this.input);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Do not loose focus.
|
||||
*
|
||||
* @param event The mouse event.
|
||||
*/
|
||||
doNotBlur(event: Event): void {
|
||||
if (event.type === 'keydown' && !this.isValidKeyboardKey(<KeyboardEvent>event)) {
|
||||
return;
|
||||
}
|
||||
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if Space or Enter have been pressed.
|
||||
*
|
||||
* @param event Keyboard Event.
|
||||
* @returns Wether space or enter have been pressed.
|
||||
*/
|
||||
protected isValidKeyboardKey(event: KeyboardEvent): boolean {
|
||||
return event.key === ' ' || event.key === 'Enter';
|
||||
const toggle = CoreDomUtils.convertToElement('<ion-input-password-toggle slot="end" />');
|
||||
input.parentElement?.appendChild(toggle.children[0]);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -77,7 +77,6 @@ import { Md5 } from 'ts-md5/dist/md5';
|
|||
// Import core classes that can be useful for site plugins.
|
||||
import { CoreSyncBaseProvider } from '@classes/base-sync';
|
||||
import { CoreArray } from '@singletons/array';
|
||||
import { CoreComponentsRegistry } from '@singletons/components-registry';
|
||||
import { CoreDirectivesRegistry } from '@singletons/directives-registry';
|
||||
import { CoreDom } from '@singletons/dom';
|
||||
import { CoreForms } from '@singletons/form';
|
||||
|
@ -295,12 +294,13 @@ export class CoreCompileProvider {
|
|||
instance['CoreLoggerProvider'] = CoreLogger;
|
||||
instance['moment'] = moment;
|
||||
instance['Md5'] = Md5;
|
||||
instance['Network'] = CoreNetwork.instance; // @deprecated since 4.1, plugins should use CoreNetwork instead.
|
||||
instance['Platform'] = CorePlatform.instance; // @deprecated since 4.1, plugins should use CorePlatform instead.
|
||||
/**
|
||||
* @deprecated since 4.1, plugins should use CoreNetwork instead.
|
||||
* Keeping this a bit more to avoid plugins breaking.
|
||||
*/
|
||||
instance['Network'] = CoreNetwork.instance;
|
||||
instance['CoreSyncBaseProvider'] = CoreSyncBaseProvider;
|
||||
instance['CoreArray'] = CoreArray;
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
instance['CoreComponentsRegistry'] = CoreComponentsRegistry;
|
||||
instance['CoreDirectivesRegistry'] = CoreDirectivesRegistry;
|
||||
instance['CoreNetwork'] = CoreNetwork.instance;
|
||||
instance['CorePlatform'] = CorePlatform.instance;
|
||||
|
|
|
@ -31,7 +31,8 @@ import { Component, HostBinding, Input } from '@angular/core';
|
|||
*
|
||||
* <core-course-module-description [description]="myDescription"></core-course-module-description>
|
||||
*
|
||||
* @deprecated since 4.0 use core-course-module-info
|
||||
* @deprecated since 4.0 use core-course-module-info instead.
|
||||
* Keeping this a bit more to avoid plugins breaking.
|
||||
*/
|
||||
@Component({
|
||||
selector: 'core-course-module-description',
|
||||
|
|
|
@ -50,6 +50,6 @@
|
|||
height: 0 !important;
|
||||
}
|
||||
|
||||
:host-context(html.dark) {
|
||||
:host-context(:root.dark) {
|
||||
--button-color: var(--gray-100);
|
||||
}
|
||||
|
|
|
@ -198,7 +198,7 @@
|
|||
}
|
||||
|
||||
|
||||
:host-context(html.dark) {
|
||||
:host-context(:root.dark) {
|
||||
.activity-description-availabilityinfo {
|
||||
.core-module-availabilityinfo {
|
||||
background: var(--gray-800);
|
||||
|
|
|
@ -16,14 +16,11 @@ import { NgModule } from '@angular/core';
|
|||
|
||||
import { CoreSharedModule } from '@/core/shared.module';
|
||||
import { CoreCoursesCourseListItemComponent } from './course-list-item/course-list-item';
|
||||
import { CoreCoursesCourseProgressComponent } from './course-progress/course-progress';
|
||||
import { CoreCoursesCourseOptionsMenuComponent } from './course-options-menu/course-options-menu';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
CoreCoursesCourseListItemComponent,
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
CoreCoursesCourseProgressComponent,
|
||||
CoreCoursesCourseOptionsMenuComponent,
|
||||
],
|
||||
imports: [
|
||||
|
@ -31,8 +28,6 @@ import { CoreCoursesCourseOptionsMenuComponent } from './course-options-menu/cou
|
|||
],
|
||||
exports: [
|
||||
CoreCoursesCourseListItemComponent,
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
CoreCoursesCourseProgressComponent,
|
||||
CoreCoursesCourseOptionsMenuComponent,
|
||||
],
|
||||
})
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
}
|
||||
|
||||
|
||||
:host-context(html.dark) {
|
||||
:host-context(:root.dark) {
|
||||
--button-background: rgb(0 0 0 / 30%);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
<core-courses-course-list-item [course]="course" class="core-course-progress" [showDownload]="showDownload"
|
||||
[layout]="showAll ? 'card' : 'summarycard'" />
|
|
@ -1,42 +0,0 @@
|
|||
// (C) Copyright 2015 Moodle Pty Ltd.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { Component, HostBinding, Input } from '@angular/core';
|
||||
import { CoreCourseListItem } from '@features/courses/services/courses';
|
||||
|
||||
/**
|
||||
* This component is meant to display a course for a list of courses with progress.
|
||||
*
|
||||
* Example usage:
|
||||
*
|
||||
* <core-courses-course-progress [course]="course">
|
||||
* </core-courses-course-progress>
|
||||
*
|
||||
* @deprecated since 4.0. Use core-courses-course-list-item instead.
|
||||
*/
|
||||
@Component({
|
||||
selector: 'core-courses-course-progress',
|
||||
templateUrl: 'core-courses-course-progress.html',
|
||||
})
|
||||
export class CoreCoursesCourseProgressComponent {
|
||||
|
||||
@Input() course!: CoreCourseListItem; // The course to render.
|
||||
@Input() showAll = false; // If true, will show all actions, options, star and progress.
|
||||
@Input() showDownload = true; // If true, will show download button. Only works if the options menu is not shown.
|
||||
|
||||
@HostBinding('class.deprecated') get isDeprecated(): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -27,7 +27,7 @@
|
|||
<!-- Download all courses. -->
|
||||
<div *ngIf="downloadCoursesEnabled && myOverviewBlock && myOverviewBlock.filteredCourses.length > 0"
|
||||
class="core-button-spinner">
|
||||
<ion-button *ngIf="!myOverviewBlock.prefetchCoursesData.loading" fill="clear"
|
||||
<ion-button *ngIf="!myOverviewBlock.prefetchCoursesData.loading" fill="clear" size="default"
|
||||
(click)="myOverviewBlock.prefetchCourses()"
|
||||
[attr.aria-label]="myOverviewBlock.prefetchCoursesData.statusTranslatable | translate">
|
||||
<ion-icon [name]="myOverviewBlock.prefetchCoursesData.icon" slot="icon-only" aria-hidden="true" />
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
--background: var(--rte-editor-background);
|
||||
}
|
||||
|
||||
:host-context(html.dark) {
|
||||
:host-context(:root.dark) {
|
||||
--color: var(--white);
|
||||
--button-color: var(--gray-200);
|
||||
--button-active-color: var(--gray-500);
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
--core-table-border-color: var(--stroke);
|
||||
}
|
||||
|
||||
:host-context(html.dark) {
|
||||
:host-context(:root.dark) {
|
||||
--icon-color: var(--gray-200);
|
||||
}
|
||||
|
||||
|
|
|
@ -166,7 +166,7 @@
|
|||
|
||||
}
|
||||
|
||||
:host-context(html.dark) {
|
||||
:host-context(:root.dark) {
|
||||
@if ($core-login-button-outline-dark) {
|
||||
form ion-button {
|
||||
--background: white;
|
||||
|
|
|
@ -53,7 +53,7 @@
|
|||
<ion-input name="password" type="password" placeholder="{{ 'core.login.password' | translate }}"
|
||||
formControlName="password" [clearOnEdit]="false" autocomplete="current-password" enterkeyhint="go"
|
||||
required="true" [attr.aria-label]="'core.login.password' | translate ">
|
||||
<core-show-password slot="end" />
|
||||
<ion-input-password-toggle slot="end" showIcon="fas-eye" hideIcon="fas-eye-slash" />
|
||||
</ion-input>
|
||||
</ion-item>
|
||||
<ion-button expand="block" type="submit" [disabled]="!credForm.valid"
|
||||
|
|
|
@ -103,7 +103,7 @@
|
|||
placeholder="{{ 'core.login.password' | translate }}" formControlName="password" [clearOnEdit]="false"
|
||||
autocomplete="new-password" required="true">
|
||||
<div slot="label" [core-mark-required]="true">{{ 'core.login.password' | translate }}</div>
|
||||
<core-show-password slot="end" />
|
||||
<ion-input-password-toggle slot="end" showIcon="fas-eye" hideIcon="fas-eye-slash" />
|
||||
</ion-input>
|
||||
<p *ngIf="settings.passwordpolicy" class="core-input-footnote">
|
||||
{{settings.passwordpolicy}}
|
||||
|
|
|
@ -65,7 +65,7 @@
|
|||
placeholder="{{ 'core.login.password' | translate }}" formControlName="password" [clearOnEdit]="false"
|
||||
autocomplete="current-password" enterkeyhint="go" required="true"
|
||||
[attr.aria-label]="'core.login.password' | translate">
|
||||
<core-show-password slot="end" />
|
||||
<ion-input-password-toggle slot="end" showIcon="fas-eye" hideIcon="fas-eye-slash" />
|
||||
</ion-input>
|
||||
</ion-item>
|
||||
<ion-button type="submit" expand="block" [disabled]="!credForm.valid"
|
||||
|
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 32 KiB |
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
|
@ -11,6 +11,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
:host-context(html.dark) {
|
||||
:host-context(:root.dark) {
|
||||
--heading-text-color: var(--gray-400);
|
||||
}
|
||||
|
|
|
@ -91,7 +91,7 @@
|
|||
|
||||
}
|
||||
|
||||
:host-context(html.dark) ion-item {
|
||||
:host-context(:root.dark) ion-item {
|
||||
--core-global-search-result-content-color: var(--gray-400);
|
||||
--core-global-search-result-context-color: var(--gray-500);
|
||||
}
|
||||
|
|
|
@ -437,7 +437,7 @@ export class CoreSettingsHelperProvider {
|
|||
const isDark = CoreDomUtils.hasModeClass('dark');
|
||||
|
||||
if (isDark !== enable) {
|
||||
CoreDomUtils.toggleModeClass('dark', enable, { includeLegacy: true });
|
||||
CoreDomUtils.toggleModeClass('dark', enable);
|
||||
this.darkModeObservable.next(enable);
|
||||
|
||||
CoreApp.setSystemUIColors();
|
||||
|
|
|
@ -61,6 +61,6 @@
|
|||
|
||||
}
|
||||
|
||||
:host-context(html.dark) {
|
||||
:host-context(:root.dark) {
|
||||
--popover-background: var(--gray-700);
|
||||
}
|
||||
|
|
|
@ -30,9 +30,9 @@ import { CoreDatabaseTable } from '@classes/database/database-table';
|
|||
import { CorePromisedValue } from '@classes/promised-value';
|
||||
import { Subscription } from 'rxjs';
|
||||
import { CorePlatform } from '@services/platform';
|
||||
import { CoreNetwork, CoreNetworkConnection } from '@services/network';
|
||||
import { CoreMainMenuProvider } from '@features/mainmenu/services/mainmenu';
|
||||
import { CoreKeyboard } from '@singletons/keyboard';
|
||||
import { CoreNetwork } from './network';
|
||||
|
||||
/**
|
||||
* Factory to provide some global functionalities, like access to the global app database.
|
||||
|
@ -210,36 +210,6 @@ export class CoreAppProvider {
|
|||
return storesConfig.default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get platform major version number.
|
||||
*
|
||||
* @returns The platform major number.
|
||||
* @deprecated since 4.1.1. Use CorePlatform.getPlatformMajorVersion instead.
|
||||
*/
|
||||
getPlatformMajorVersion(): number {
|
||||
return CorePlatform.getPlatformMajorVersion();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the app is running in an Android mobile or tablet device.
|
||||
*
|
||||
* @returns Whether the app is running in an Android mobile or tablet device.
|
||||
* @deprecated since 4.1.1. Use CorePlatform.isAndroid instead.
|
||||
*/
|
||||
isAndroid(): boolean {
|
||||
return CorePlatform.isAndroid();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the app is running in an iOS mobile or tablet device.
|
||||
*
|
||||
* @returns Whether the app is running in an iOS mobile or tablet device.
|
||||
* @deprecated since 4.1.1. Use CorePlatform.isIOS instead.
|
||||
*/
|
||||
isIOS(): boolean {
|
||||
return CorePlatform.isIOS();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the keyboard is closing.
|
||||
*
|
||||
|
@ -270,16 +240,6 @@ export class CoreAppProvider {
|
|||
return CoreKeyboard.isKeyboardVisible();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the app is running in a mobile or tablet device (Cordova).
|
||||
*
|
||||
* @returns Whether the app is running in a mobile or tablet device.
|
||||
* @deprecated since 4.1. Use CorePlatform instead.
|
||||
*/
|
||||
isMobile(): boolean {
|
||||
return CorePlatform.isMobile();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the current window is wider than a mobile.
|
||||
*
|
||||
|
@ -294,31 +254,12 @@ export class CoreAppProvider {
|
|||
*
|
||||
* @returns Whether the app is online.
|
||||
* @deprecated since 4.1. Use CoreNetwork instead.
|
||||
* Keeping this a bit more to avoid plugins breaking.
|
||||
*/
|
||||
isOnline(): boolean {
|
||||
return CoreNetwork.isOnline();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if device uses a limited connection.
|
||||
*
|
||||
* @returns Whether the device uses a limited connection.
|
||||
* @deprecated since 4.1. Use CoreNetwork instead.
|
||||
*/
|
||||
isNetworkAccessLimited(): boolean {
|
||||
return CoreNetwork.isNetworkAccessLimited();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if device uses a wifi connection.
|
||||
*
|
||||
* @returns Whether the device uses a wifi connection.
|
||||
* @deprecated since 4.1. Use CoreNetwork instead.
|
||||
*/
|
||||
isWifi(): boolean {
|
||||
return CoreNetwork.isWifi();
|
||||
}
|
||||
|
||||
/**
|
||||
* Open the keyboard.
|
||||
*
|
||||
|
@ -561,16 +502,6 @@ export class CoreAppProvider {
|
|||
StatusBar.backgroundColorByHexString(color);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set value of forceOffline flag. If true, the app will think the device is offline.
|
||||
*
|
||||
* @param value Value to set.
|
||||
* @deprecated since 4.1. Use CoreNetwork.setForceConnectionMode instead.
|
||||
*/
|
||||
setForceOffline(value: boolean): void {
|
||||
CoreNetwork.setForceConnectionMode(value ? CoreNetworkConnection.NONE : CoreNetworkConnection.WIFI);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the installed version for the given schema.
|
||||
*
|
||||
|
|
|
@ -1015,17 +1015,6 @@ export class CoreFileProvider {
|
|||
return promise.then((entry) => this.getMetadata(entry));
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the starting slash of a path if it's there. E.g. '/sites/filepool' -> 'sites/filepool'.
|
||||
*
|
||||
* @param path Path.
|
||||
* @returns Path without a slash in the first position.
|
||||
* @deprecated since 4.1. Use CoreText.removeStartingSlash instead.
|
||||
*/
|
||||
removeStartingSlash(path: string): string {
|
||||
return CoreText.removeStartingSlash(path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience function to copy or move an external file.
|
||||
*
|
||||
|
|
|
@ -429,16 +429,6 @@ export class CoreLocalNotificationsProvider {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether local notifications are available.
|
||||
*
|
||||
* @returns Whether local notifications are available.
|
||||
* @deprecated since 4.1. It will always return true.
|
||||
*/
|
||||
isAvailable(): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether local notifications plugin is available.
|
||||
*
|
||||
|
|
|
@ -111,22 +111,22 @@ export class CoreNetworkService extends Network {
|
|||
|
||||
const hadOfflineMessage = CoreDomUtils.hasModeClass('core-offline');
|
||||
|
||||
CoreDomUtils.toggleModeClass('core-offline', !isOnline, { includeLegacy: true });
|
||||
CoreDomUtils.toggleModeClass('core-offline', !isOnline);
|
||||
|
||||
if (isOnline && hadOfflineMessage) {
|
||||
CoreDomUtils.toggleModeClass('core-online', true, { includeLegacy: true });
|
||||
CoreDomUtils.toggleModeClass('core-online', true);
|
||||
|
||||
setTimeout(() => {
|
||||
CoreDomUtils.toggleModeClass('core-online', false, { includeLegacy: true });
|
||||
CoreDomUtils.toggleModeClass('core-online', false);
|
||||
}, 3000);
|
||||
} else if (!isOnline) {
|
||||
CoreDomUtils.toggleModeClass('core-online', false, { includeLegacy: true });
|
||||
CoreDomUtils.toggleModeClass('core-online', false);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
const isOnline = this.isOnline();
|
||||
CoreDomUtils.toggleModeClass('core-offline', !isOnline, { includeLegacy: true });
|
||||
CoreDomUtils.toggleModeClass('core-offline', !isOnline);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -51,7 +51,7 @@ describe('CoreSitesProvider', () => {
|
|||
CoreHTMLClasses.initialize();
|
||||
CoreSites.initialize();
|
||||
|
||||
expect(document.documentElement.classList.contains('ionic7')).toBe(true);
|
||||
expect(document.documentElement.classList.contains('ionic8')).toBe(true);
|
||||
|
||||
const site = mock(new CoreSite('42', siteUrl, 'token', { info: {
|
||||
sitename: 'Example Campus',
|
||||
|
|
|
@ -1790,17 +1790,12 @@ export class CoreDomUtilsProvider {
|
|||
*
|
||||
* @param className Class name.
|
||||
* @param enable Whether to add or remove the class.
|
||||
* @param options Legacy options, deprecated since 4.1.
|
||||
*/
|
||||
toggleModeClass(
|
||||
className: string,
|
||||
enable = false,
|
||||
options: { includeLegacy: boolean } = { includeLegacy: false },
|
||||
): void {
|
||||
document.documentElement.classList.toggle(className, enable);
|
||||
|
||||
// @deprecated since 4.1.
|
||||
document.body.classList.toggle(className, enable && options.includeLegacy);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -215,19 +215,6 @@ export class CoreTimeUtilsProvider {
|
|||
return isoString.substring(0, isoString.indexOf('.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a text into user timezone timestamp.
|
||||
*
|
||||
* @param date To convert to timestamp.
|
||||
* @param applyOffset Whether to apply offset to date or not.
|
||||
* @returns Converted timestamp.
|
||||
* @deprecated since 4.1. Use moment(date).unix() instead.
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
convertToTimestamp(date: string, applyOffset?: boolean): number {
|
||||
return moment(date).unix();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the localized ISO format (i.e DDMMYY) from the localized moment format. Useful for translations.
|
||||
* DO NOT USE this function for ion-datetime format. Moment escapes characters with [], but ion-datetime doesn't support it.
|
||||
|
|
|
@ -1185,7 +1185,7 @@ export class CoreUtilsProvider {
|
|||
if (options.showBrowserWarning || options.showBrowserWarning === undefined) {
|
||||
try {
|
||||
await CoreWindow.confirmOpenBrowserIfNeeded(originaUrl);
|
||||
} catch (error) {
|
||||
} catch {
|
||||
return; // Cancelled, stop.
|
||||
}
|
||||
}
|
||||
|
@ -1409,16 +1409,6 @@ export class CoreUtilsProvider {
|
|||
return Object.keys(enumeration).filter(k => Number.isNaN(+k)) as K[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a deferred promise that can be resolved or rejected explicitly.
|
||||
*
|
||||
* @returns The deferred promise.
|
||||
* @deprecated since 4.1. Use CorePromisedValue instead.
|
||||
*/
|
||||
promiseDefer<T>(): CorePromisedValue<T> {
|
||||
return new CorePromisedValue<T>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a promise, returns true if it's rejected or false if it's resolved.
|
||||
*
|
||||
|
|
|
@ -17,21 +17,6 @@
|
|||
*/
|
||||
export class CoreArray {
|
||||
|
||||
/**
|
||||
* Check whether an array contains an item.
|
||||
*
|
||||
* @param arr Array.
|
||||
* @param item Item.
|
||||
* @returns Whether item is within the array.
|
||||
* @deprecated since 4.1. Use arr.includes() instead.
|
||||
*/
|
||||
static contains<T>(arr: T[], item: T): boolean {
|
||||
// eslint-disable-next-line no-console
|
||||
console.warn('CoreArray.contains is deprecated and will be removed soon. Please use array \'includes\' instead.');
|
||||
|
||||
return arr.indexOf(item) !== -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flatten the first dimension of a multi-dimensional array.
|
||||
*
|
||||
|
|
|
@ -1,94 +0,0 @@
|
|||
// (C) Copyright 2015 Moodle Pty Ltd.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { Component } from '@angular/core';
|
||||
import { AsyncDirective } from '@classes/async-directive';
|
||||
import { CoreDirectivesRegistry } from '@singletons/directives-registry';
|
||||
|
||||
/**
|
||||
* Registry to keep track of component instances.
|
||||
*
|
||||
* @deprecated since 4.1.1. Use CoreDirectivesRegistry instead.
|
||||
*/
|
||||
export class CoreComponentsRegistry {
|
||||
|
||||
/**
|
||||
* Register a component instance.
|
||||
*
|
||||
* @param element Root element.
|
||||
* @param instance Component instance.
|
||||
*/
|
||||
static register(element: Element, instance: unknown): void {
|
||||
CoreDirectivesRegistry.register(element, instance);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve a component instance.
|
||||
*
|
||||
* @param element Root element.
|
||||
* @param componentClass Component class.
|
||||
* @returns Component instance.
|
||||
*/
|
||||
static resolve<T>(element?: Element | null, componentClass?: ComponentConstructor<T>): T | null {
|
||||
return CoreDirectivesRegistry.resolve(element, componentClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a component instances and fail if it cannot be resolved.
|
||||
*
|
||||
* @param element Root element.
|
||||
* @param componentClass Component class.
|
||||
* @returns Component instance.
|
||||
*/
|
||||
static require<T>(element: Element, componentClass?: ComponentConstructor<T>): T {
|
||||
return CoreDirectivesRegistry.require(element, componentClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a component instances and wait to be ready.
|
||||
*
|
||||
* @param element Root element.
|
||||
* @param componentClass Component class.
|
||||
* @returns Promise resolved when done.
|
||||
*/
|
||||
static async waitComponentReady<T extends AsyncDirective>(
|
||||
element: Element | null,
|
||||
componentClass?: ComponentConstructor<T>,
|
||||
): Promise<void> {
|
||||
return CoreDirectivesRegistry.waitDirectiveReady(element, componentClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits all elements matching to be ready.
|
||||
*
|
||||
* @param element Element where to search.
|
||||
* @param selector Selector to search on parent.
|
||||
* @param componentClass Component class.
|
||||
* @returns Promise resolved when done.
|
||||
*/
|
||||
static async waitComponentsReady<T extends AsyncDirective>(
|
||||
element: Element,
|
||||
selector: string,
|
||||
componentClass?: ComponentConstructor<T>,
|
||||
): Promise<void> {
|
||||
return CoreDirectivesRegistry.waitDirectivesReady(element, selector, componentClass);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Component constructor.
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export type ComponentConstructor<T = Component> = { new(...args: any[]): T };
|
|
@ -535,20 +535,6 @@ export class CoreDom {
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Listen to click and Enter/Space keys in an element.
|
||||
*
|
||||
* @param element Element to listen to events.
|
||||
* @param callback Callback to call when clicked or the key is pressed.
|
||||
* @deprecated since 4.1.1: Use initializeClickableElementA11y instead.
|
||||
*/
|
||||
static onActivate(
|
||||
element: HTMLElement & {disabled?: boolean},
|
||||
callback: (event: MouseEvent | KeyboardEvent) => void,
|
||||
): void {
|
||||
this.initializeClickableElementA11y(element, callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes a clickable element a11y calling the click action when pressed enter or space
|
||||
* and adding tabindex and role if needed.
|
||||
|
|
|
@ -34,7 +34,7 @@ export class CoreHTMLClasses {
|
|||
* Initialize HTML classes.
|
||||
*/
|
||||
static initialize(): void {
|
||||
CoreDomUtils.toggleModeClass('ionic7', true);
|
||||
CoreDomUtils.toggleModeClass('ionic8', true);
|
||||
CoreDomUtils.toggleModeClass('development', CoreConstants.BUILD.isDevelopment);
|
||||
CoreHTMLClasses.addVersionClass(MOODLEAPP_VERSION_PREFIX, CoreConstants.CONFIG.versionname.replace('-dev', ''));
|
||||
|
||||
|
@ -72,9 +72,9 @@ export class CoreHTMLClasses {
|
|||
parts[1] = parts[1] || '0';
|
||||
parts[2] = parts[2] || '0';
|
||||
|
||||
CoreDomUtils.toggleModeClass(prefix + parts[0], true, { includeLegacy: true });
|
||||
CoreDomUtils.toggleModeClass(prefix + parts[0] + '-' + parts[1], true, { includeLegacy: true });
|
||||
CoreDomUtils.toggleModeClass(prefix + parts[0] + '-' + parts[1] + '-' + parts[2], true, { includeLegacy: true });
|
||||
CoreDomUtils.toggleModeClass(prefix + parts[0], true);
|
||||
CoreDomUtils.toggleModeClass(prefix + parts[0] + '-' + parts[1], true);
|
||||
CoreDomUtils.toggleModeClass(prefix + parts[0] + '-' + parts[1] + '-' + parts[2], true);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -88,7 +88,7 @@ export class CoreHTMLClasses {
|
|||
continue;
|
||||
}
|
||||
|
||||
CoreDomUtils.toggleModeClass(modeClass, false, { includeLegacy: true });
|
||||
CoreDomUtils.toggleModeClass(modeClass, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,8 +12,6 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { CorePath } from './path';
|
||||
|
||||
/**
|
||||
* Singleton with helper functions for text manipulation.
|
||||
*/
|
||||
|
@ -70,16 +68,4 @@ export class CoreText {
|
|||
return text.substring(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Concatenate two paths, adding a slash between them if needed.
|
||||
*
|
||||
* @param leftPath Left path.
|
||||
* @param rightPath Right path.
|
||||
* @returns Concatenated path.
|
||||
* @deprecated since 4.1. Use CorePath.concatenatePaths instead.
|
||||
*/
|
||||
static concatenatePaths(leftPath: string, rightPath: string): string {
|
||||
return CorePath.concatenatePaths(leftPath, rightPath);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -196,10 +196,13 @@ export class TestingBehatBlockingService {
|
|||
await CoreUtils.nextTick();
|
||||
|
||||
const blockingElements = Array.from(
|
||||
document.querySelectorAll<HTMLElement>('div.core-loading-container, ion-loading, .click-block-active'),
|
||||
document.querySelectorAll<HTMLElement>('div.core-loading-container, ion-loading'),
|
||||
);
|
||||
|
||||
const isBlocked = blockingElements.some(element => {
|
||||
// @TODO Fix ion-loading present check with CoreDom.isElementVisible.
|
||||
// ion-loading never has offsetParent since position is fixed.
|
||||
// Using isElementVisible solve the problem but will block behats (like BBB).
|
||||
if (!element.offsetParent) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -159,11 +159,19 @@ export class TestingBehatRuntimeService {
|
|||
*/
|
||||
async waitLoadingToFinish(): Promise<void> {
|
||||
await NgZone.run(async () => {
|
||||
const elements = Array.from(document.body.querySelectorAll<HTMLElement>('core-loading'))
|
||||
.filter((element) => CoreDom.isElementVisible(element));
|
||||
const coreLoadingsPromises: Promise<unknown>[] =
|
||||
Array.from(document.body.querySelectorAll<HTMLElement>('core-loading'))
|
||||
.filter((element) => CoreDom.isElementVisible(element))
|
||||
.map(element => CoreDirectivesRegistry.waitDirectiveReady(element, CoreLoadingComponent));
|
||||
|
||||
await Promise.all(elements.map(element =>
|
||||
CoreDirectivesRegistry.waitDirectiveReady(element, CoreLoadingComponent)));
|
||||
const ionLoadingsPromises: Promise<unknown>[] =
|
||||
Array.from(document.body.querySelectorAll<HTMLIonLoadingElement>('ion-loading'))
|
||||
.filter((element) => CoreDom.isElementVisible(element))
|
||||
.map(element => element.onDidDismiss());
|
||||
|
||||
const promises = coreLoadingsPromises.concat(ionLoadingsPromises);
|
||||
|
||||
await Promise.all(promises);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -143,6 +143,6 @@
|
|||
|
||||
}
|
||||
|
||||
html.dark .core-error-accordion {
|
||||
:root.dark .core-error-accordion {
|
||||
--background-color: var(--gray-700);
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ core-format-text {
|
|||
--core-format-text-viewer-icon-background: rgb(255 255 255 / 50%);
|
||||
}
|
||||
|
||||
html.dark core-format-text {
|
||||
:root.dark core-format-text {
|
||||
--core-format-text-viewer-icon-background: rgb(0 0 0 / 50%);
|
||||
}
|
||||
|
||||
|
@ -378,7 +378,7 @@ ion-header.ios h1 core-format-text {
|
|||
}
|
||||
}
|
||||
|
||||
html.dark core-format-text select,
|
||||
html.dark core-rich-text-editor .core-rte-editor select {
|
||||
:root.dark core-format-text select,
|
||||
:root.dark core-rich-text-editor .core-rte-editor select {
|
||||
background-image: url('data:image/svg+xml;charset=US-ASCII,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22292.4%22%20height%3D%22292.4%22%3E%3Cpath%20fill%3D%22%23FFFFFF%22%20d%3D%22M287%2069.4a17.6%2017.6%200%200%200-13-5.4H18.4c-5%200-9.3%201.8-12.9%205.4A17.6%2017.6%200%200%200%200%2082.2c0%205%201.8%209.3%205.4%2012.9l128%20127.9c3.6%203.6%207.8%205.4%2012.8%205.4s9.2-1.8%2012.8-5.4L287%2095c3.5-3.5%205.4-7.8%205.4-12.8%200-5-1.9-9.2-5.5-12.8z%22%2F%3E%3C%2Fsvg%3E');
|
||||
}
|
||||
|
|
|
@ -6,25 +6,6 @@ ion-fab[core-fab] {
|
|||
}
|
||||
}
|
||||
|
||||
// The following 4 selectors can probably be removed after Ionic migration to 7+
|
||||
ion-fab.fab-horizontal-start {
|
||||
left: calc(10px + var(--ion-safe-area-right, 0px));
|
||||
}
|
||||
|
||||
&[dir=rtl] ion-fab.fab-horizontal-start {
|
||||
right: calc(10px + var(--ion-safe-area-right, 0px));
|
||||
left: unset
|
||||
}
|
||||
|
||||
ion-fab.fab-horizontal-end {
|
||||
right: calc(10px + var(--ion-safe-area-right, 0px));
|
||||
}
|
||||
|
||||
&[dir=rtl] ion-fab.fab-horizontal-end {
|
||||
left: calc(10px + var(--ion-safe-area-right, 0px));
|
||||
right: unset
|
||||
}
|
||||
|
||||
ion-content.has-collapsible-footer ion-fab {
|
||||
bottom: calc(var(--core-collapsible-footer-height, 0px) + 10px);
|
||||
@include core-transition(all, 200ms);
|
||||
|
|
|
@ -2,6 +2,10 @@ ion-input {
|
|||
&.input-disabled.md, &.input-disabled.ios {
|
||||
opacity: var(--mdl-input-disabled-opacity);
|
||||
}
|
||||
|
||||
ion-input-password-toggle {
|
||||
--ion-color-primary: var(--text-color);
|
||||
}
|
||||
}
|
||||
|
||||
input[disabled],
|
||||
|
|
|
@ -15,10 +15,6 @@ ion-select {
|
|||
}
|
||||
|
||||
ion-select-popover {
|
||||
ion-list ion-radio-group ion-item.select-interface-option ion-radio.hydrated::part(container) {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
ion-item {
|
||||
font-size: var(--text-size);
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
@import "../globals.scss";
|
||||
|
||||
ion-toast {
|
||||
--color: var(--ion-color-step-50);
|
||||
--color: var(--ion-text-color-step-950);
|
||||
--button-color: var(--primary);
|
||||
--background: var(--ion-color-step-800);
|
||||
--background: var(--ion-background-color-step-800);
|
||||
|
||||
@include media-breakpoint-down(sm) {
|
||||
&::part(container) {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
swiper-container {
|
||||
--swiper-theme-color: var(--ion-color-primary, #3880ff);
|
||||
--swiper-pagination-bullet-inactive-color: var(--ion-color-step-200, #cccccc);
|
||||
--swiper-pagination-bullet-inactive-color: var(--ion-text-color-step-800, #cccccc);
|
||||
--swiper-pagination-color: var(--swiper-theme-color);
|
||||
--swiper-pagination-progressbar-bg-color: rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.25);
|
||||
--swiper-scrollbar-bg-color: rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.1);
|
||||
|
|
|
@ -297,7 +297,7 @@
|
|||
@mixin darkmode() {
|
||||
$root: #{&};
|
||||
|
||||
@at-root #{add-root-selector($root, "html.dark")} {
|
||||
@at-root #{add-root-selector($root, ":root.dark")} {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
@import "./globals.scss";
|
||||
|
||||
html.force-safe-area-margins {
|
||||
:root.force-safe-area-margins {
|
||||
--ion-safe-area-left: 40px;
|
||||
--ion-safe-area-right: 40px;
|
||||
--ion-safe-area-top: 40px;
|
||||
--ion-safe-area-bottom: 40px;
|
||||
}
|
||||
|
||||
html {
|
||||
:root {
|
||||
--zoom-level: 100%;
|
||||
zoom: var(--zoom-level);
|
||||
|
||||
|
@ -21,7 +21,7 @@ a {
|
|||
cursor: pointer;
|
||||
}
|
||||
|
||||
html[dir=rtl] {
|
||||
:root[dir=rtl] {
|
||||
--rotate-expandable: rotate(-90deg);
|
||||
}
|
||||
|
||||
|
@ -488,7 +488,7 @@ video::-webkit-media-text-track-display {
|
|||
/**
|
||||
* https://github.com/ionic-team/ionic-framework/blob/6ffbdbb3b2b69290cf25753d535bc7483bd7c6e8/BREAKING.md#css-utilities
|
||||
*/
|
||||
[hidden] {
|
||||
[hidden], .hidden {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
* Light Theme
|
||||
* -------------------------------------------
|
||||
*/
|
||||
html {
|
||||
:root {
|
||||
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,6 @@ html {
|
|||
* Dark Theme
|
||||
* -------------------------------------------
|
||||
*/
|
||||
html.dark {
|
||||
:root.dark {
|
||||
|
||||
}
|
||||
|
|
|
@ -5,171 +5,198 @@
|
|||
* http://ionicframework.com/docs/theming/
|
||||
*/
|
||||
|
||||
html.dark {
|
||||
@mixin dark-palette() {
|
||||
& {
|
||||
// Ionic shades, defined for ionic internal use.
|
||||
--ion-background-color-step-0: var(--black);
|
||||
--ion-background-color-step-50: var(--gray-900);
|
||||
--ion-background-color-step-100: var(--gray-900);
|
||||
--ion-background-color-step-150: var(--gray-800);
|
||||
--ion-background-color-step-200: var(--gray-800);
|
||||
--ion-background-color-step-250: var(--gray-700);
|
||||
--ion-background-color-step-300: var(--gray-700);
|
||||
--ion-background-color-step-350: var(--gray-600);
|
||||
--ion-background-color-step-400: var(--gray-600);
|
||||
--ion-background-color-step-450: var(--gray-500);
|
||||
--ion-background-color-step-500: var(--gray-500);
|
||||
--ion-background-color-step-550: var(--gray-400);
|
||||
--ion-background-color-step-600: var(--gray-400);
|
||||
--ion-background-color-step-650: var(--gray-300);
|
||||
--ion-background-color-step-700: var(--gray-300);
|
||||
--ion-background-color-step-750: var(--gray-200);
|
||||
--ion-background-color-step-800: var(--gray-200);
|
||||
--ion-background-color-step-850: var(--gray-100);
|
||||
--ion-background-color-step-900: var(--gray-100);
|
||||
--ion-background-color-step-950: var(--gray-100);
|
||||
--ion-background-color-step-1000: var(--white);
|
||||
|
||||
// Ionic shades, defined for ionic internal use.
|
||||
--ion-color-step-0: var(--black);
|
||||
--ion-color-step-50: var(--gray-900);
|
||||
--ion-color-step-100: var(--gray-900);
|
||||
--ion-color-step-150: var(--gray-800);
|
||||
--ion-color-step-200: var(--gray-800);
|
||||
--ion-color-step-250: var(--gray-700);
|
||||
--ion-color-step-300: var(--gray-700);
|
||||
--ion-color-step-350: var(--gray-600);
|
||||
--ion-color-step-400: var(--gray-600);
|
||||
--ion-color-step-450: var(--gray-500);
|
||||
--ion-color-step-500: var(--gray-500);
|
||||
--ion-color-step-550: var(--gray-400);
|
||||
--ion-color-step-600: var(--gray-400);
|
||||
--ion-color-step-650: var(--gray-300);
|
||||
--ion-color-step-700: var(--gray-300);
|
||||
--ion-color-step-750: var(--gray-200);
|
||||
--ion-color-step-800: var(--gray-200);
|
||||
--ion-color-step-850: var(--gray-100);
|
||||
--ion-color-step-900: var(--gray-100);
|
||||
--ion-color-step-950: var(--gray-100);
|
||||
--ion-color-step-1000: var(--white);
|
||||
--ion-text-color-step-0: var(--white);
|
||||
--ion-text-color-step-50: var(--gray-100);
|
||||
--ion-text-color-step-100: var(--gray-100);
|
||||
--ion-text-color-step-150: var(--gray-200);
|
||||
--ion-text-color-step-200: var(--gray-200);
|
||||
--ion-text-color-step-250: var(--gray-300);
|
||||
--ion-text-color-step-300: var(--gray-300);
|
||||
--ion-text-color-step-350: var(--gray-400);
|
||||
--ion-text-color-step-400: var(--gray-400);
|
||||
--ion-text-color-step-450: var(--gray-500);
|
||||
--ion-text-color-step-500: var(--gray-500);
|
||||
--ion-text-color-step-550: var(--gray-600);
|
||||
--ion-text-color-step-600: var(--gray-600);
|
||||
--ion-text-color-step-650: var(--gray-700);
|
||||
--ion-text-color-step-700: var(--gray-700);
|
||||
--ion-text-color-step-750: var(--gray-800);
|
||||
--ion-text-color-step-800: var(--gray-800);
|
||||
--ion-text-color-step-850: var(--gray-900);
|
||||
--ion-text-color-step-900: var(--gray-900);
|
||||
--ion-text-color-step-950: var(--gray-900);
|
||||
--ion-text-color-step-1000: var(--black);
|
||||
|
||||
@each $color-name, $unused in $colors {
|
||||
@include generate-color($color-name, $colors, 'dark');
|
||||
}
|
||||
|
||||
--ion-background-color: #{$background-color-dark};
|
||||
--ion-background-color-rgb: #{$background-color-dark-rgb};
|
||||
|
||||
--text-color: #{$text-color-dark};
|
||||
--ion-text-color: var(--text-color);
|
||||
--ion-text-color-rgb: #{$text-color-dark-rgb};
|
||||
--subdued-text-color: var(--medium);
|
||||
--stroke: var(--gray-700);
|
||||
|
||||
--contrast-background: var(--gray-900);
|
||||
|
||||
--loader-shine: 90 90 90;
|
||||
|
||||
--drop-shadow-top: 0px 2px 5px rgb(var(--mdl-shadow-boxShadowColor) / 1);
|
||||
--drop-shadow-bottom: 0px -2px 5px rgb(var(--mdl-shadow-boxShadowColor) / 1);
|
||||
|
||||
--ion-card-color: var(--text-color);
|
||||
--ion-card-background: var(--ion-item-background);
|
||||
--ion-card-border-color: var(--stroke);
|
||||
|
||||
--ion-border-color: var(--stroke);
|
||||
--ion-item-border-color: var(--stroke);
|
||||
|
||||
--core-input-stroke: var(--gray-600);
|
||||
--core-input-text: var(--dark);
|
||||
--core-input-background: var(--gray-900);
|
||||
|
||||
ion-content {
|
||||
--background: var(--ion-background-color);
|
||||
--background-alternative: var(--gray-900);
|
||||
}
|
||||
|
||||
--core-bottom-tabs-badge-text-color: var(--primary-contrast);
|
||||
--core-bottom-tabs-background: var(--gray-900);
|
||||
--core-bottom-tabs-color: var(--gray-200);
|
||||
|
||||
ion-action-sheet {
|
||||
.action-sheet-cancel {
|
||||
--button-color: var(--danger-tint);
|
||||
@each $color-name, $unused in $colors {
|
||||
@include generate-color($color-name, $colors, 'dark');
|
||||
}
|
||||
|
||||
--ion-background-color: #{$background-color-dark};
|
||||
--ion-background-color-rgb: #{$background-color-dark-rgb};
|
||||
|
||||
--text-color: #{$text-color-dark};
|
||||
--ion-text-color: var(--text-color);
|
||||
--ion-text-color-rgb: #{$text-color-dark-rgb};
|
||||
--subdued-text-color: var(--medium);
|
||||
--stroke: var(--gray-700);
|
||||
|
||||
--contrast-background: var(--gray-900);
|
||||
|
||||
--loader-shine: 90 90 90;
|
||||
|
||||
--drop-shadow-top: 0px 2px 5px rgb(var(--mdl-shadow-boxShadowColor) / 1);
|
||||
--drop-shadow-bottom: 0px -2px 5px rgb(var(--mdl-shadow-boxShadowColor) / 1);
|
||||
|
||||
--ion-card-color: var(--text-color);
|
||||
--ion-card-background: var(--ion-item-background);
|
||||
--ion-card-border-color: var(--stroke);
|
||||
|
||||
--ion-border-color: var(--stroke);
|
||||
--ion-item-border-color: var(--stroke);
|
||||
|
||||
--core-input-stroke: var(--gray-600);
|
||||
--core-input-text: var(--dark);
|
||||
--core-input-background: var(--gray-900);
|
||||
|
||||
ion-content {
|
||||
--background: var(--ion-background-color);
|
||||
--background-alternative: var(--gray-900);
|
||||
}
|
||||
|
||||
--core-bottom-tabs-badge-text-color: var(--primary-contrast);
|
||||
--core-bottom-tabs-background: var(--gray-900);
|
||||
--core-bottom-tabs-color: var(--gray-200);
|
||||
|
||||
ion-action-sheet {
|
||||
.action-sheet-cancel {
|
||||
--button-color: var(--danger-tint);
|
||||
}
|
||||
}
|
||||
|
||||
ion-popover,
|
||||
ion-popover ion-content {
|
||||
--background: var(--gray-800);
|
||||
--ion-item-background: var(--background);
|
||||
--ion-background-color: var(--background);
|
||||
}
|
||||
|
||||
--core-link-color: var(--info-tint);
|
||||
|
||||
--core-header-toolbar-background: var(--gray-900);
|
||||
--core-header-toolbar-color: var(--text-color);
|
||||
--core-header-toolbar-border-color: var(--stroke);
|
||||
|
||||
--core-tabs-background: var(--gray-900);
|
||||
--core-tab-background: var(--core-tabs-background);
|
||||
--core-tab-color: var(--subdued-text-color);
|
||||
--core-tab-border-color: var(--gray-200);
|
||||
--core-tab-color-active: var(--dark);
|
||||
|
||||
--core-progressbar-text-color: var(--gray-100);
|
||||
|
||||
--core-empty-box-icon-color: var(--gray-700);
|
||||
|
||||
--ion-item-background: #{$ion-item-background-dark};
|
||||
--ion-item-icon-color: var(--medium);
|
||||
--ion-item-detail-icon-color: var(--dark);
|
||||
--core-more-icon: var(--ion-item-icon-color);
|
||||
|
||||
--item-divider-background: var(--ion-item-background);
|
||||
--item-divider-color: var(--text-color);
|
||||
--spacer-background: var(--gray-700);
|
||||
|
||||
|
||||
--ion-searchbar-background: var(--ion-background-color);
|
||||
--ion-searchbar-border-color: var(--core-input-stroke);
|
||||
--ion-searchbar-color: var(--text-color);
|
||||
--ion-searchbar-icon-color: var(--core-input-stroke);
|
||||
|
||||
--core-search-box-background: var(--ion-background-color);
|
||||
--core-search-box-border-color: var(--core-input-stroke);
|
||||
--core-search-box-color: var(--core-input-text);
|
||||
|
||||
--core-combobox-background: var(--core-input-background);
|
||||
--core-combobox-color: var(--text-color);
|
||||
--core-combobox-border-color: var(--core-input-stroke);
|
||||
|
||||
--collapsible-toggle-text: var(--medium);
|
||||
|
||||
--background-gradient-rgb: #{$ion-item-background-dark-rgb};
|
||||
|
||||
--core-login-background: var(--gray-900);
|
||||
--core-login-text-color: var(--white);
|
||||
--core-login-input-background: var(--core-login-background);
|
||||
--core-login-input-color: var(--core-login-text-color);
|
||||
|
||||
--core-question-correct-color: var(--success-tint);
|
||||
--core-question-correct-color-bg: var(--success-shade);
|
||||
--core-question-incorrect-color: var(--danger);
|
||||
--core-question-incorrect-color-bg: var(--danger-shade);
|
||||
--core-question-partial-color: var(--warning-tint);
|
||||
--core-question-partial-color-bg: var(--warning-shade);
|
||||
--core-question-feedback-color: var(--warning-tint);
|
||||
--core-question-feedback-color-bg: var(--warning-shade);
|
||||
--core-question-warning-color: var(--danger);
|
||||
--core-question-saved-color-bg: var(--gray-500);
|
||||
|
||||
--core-question-feedback-color: var(--warning-tint);
|
||||
--core-question-feedback-background-color: var(--warning-shade);
|
||||
|
||||
--core-dd-question-selected-shadow: 2px 2px 4px var(--gray-200);
|
||||
--core-dd-question-border: var(--gray-200);
|
||||
|
||||
--core-send-message-input-background: var(--gray-900);
|
||||
--core-send-message-input-color: var(--white);
|
||||
|
||||
--core-navigation-background: var(--contrast-background);
|
||||
|
||||
--core-collapsible-footer-background: var(--contrast-background);
|
||||
|
||||
--core-messages-message-bg: var(--gray-800);
|
||||
--core-messages-message-activated-bg: var(--gray-700);
|
||||
--core-messages-message-note-text: var(--subdued-text-color);
|
||||
--core-messages-message-mine-bg: var(--gray-700);
|
||||
--core-messages-message-mine-activated-bg: var(--gray-600);
|
||||
--core-messages-discussion-badge: var(--primary);
|
||||
--core-messages-discussion-badge-text: var(--gray-100);
|
||||
|
||||
--addon-forum-border-color: var(--gray-500);
|
||||
--addon-forum-highlight-color: var(--gray-800);
|
||||
|
||||
--core-table-header-background: var(--gray-900);
|
||||
--core-table-odd-cell-background: var(--gray-800);
|
||||
--core-table-odd-cell-hover: var(--gray-600);
|
||||
--core-table-even-cell-background: var(--gray-900);
|
||||
--core-table-even-cell-hover: var(--gray-700);
|
||||
|
||||
}
|
||||
|
||||
ion-popover,
|
||||
ion-popover ion-content {
|
||||
--background: var(--gray-800);
|
||||
--ion-item-background: var(--background);
|
||||
--ion-background-color: var(--background);
|
||||
}
|
||||
|
||||
--core-link-color: var(--info-tint);
|
||||
|
||||
--core-header-toolbar-background: var(--gray-900);
|
||||
--core-header-toolbar-color: var(--text-color);
|
||||
--core-header-toolbar-border-color: var(--stroke);
|
||||
|
||||
--core-tabs-background: var(--gray-900);
|
||||
--core-tab-background: var(--core-tabs-background);
|
||||
--core-tab-color: var(--subdued-text-color);
|
||||
--core-tab-border-color: var(--gray-200);
|
||||
--core-tab-color-active: var(--dark);
|
||||
|
||||
--core-progressbar-text-color: var(--gray-100);
|
||||
|
||||
--core-empty-box-icon-color: var(--gray-700);
|
||||
|
||||
--ion-item-background: #{$ion-item-background-dark};
|
||||
--ion-item-icon-color: var(--medium);
|
||||
--ion-item-detail-icon-color: var(--dark);
|
||||
--core-more-icon: var(--ion-item-icon-color);
|
||||
|
||||
--item-divider-background: var(--ion-item-background);
|
||||
--item-divider-color: var(--text-color);
|
||||
--spacer-background: var(--gray-700);
|
||||
|
||||
|
||||
--ion-searchbar-background: var(--ion-background-color);
|
||||
--ion-searchbar-border-color: var(--core-input-stroke);
|
||||
--ion-searchbar-color: var(--text-color);
|
||||
--ion-searchbar-icon-color: var(--core-input-stroke);
|
||||
|
||||
--core-search-box-background: var(--ion-background-color);
|
||||
--core-search-box-border-color: var(--core-input-stroke);
|
||||
--core-search-box-color: var(--core-input-text);
|
||||
|
||||
--core-combobox-background: var(--core-input-background);
|
||||
--core-combobox-color: var(--text-color);
|
||||
--core-combobox-border-color: var(--core-input-stroke);
|
||||
|
||||
--collapsible-toggle-text: var(--medium);
|
||||
|
||||
--background-gradient-rgb: #{$ion-item-background-dark-rgb};
|
||||
|
||||
--core-login-background: var(--gray-900);
|
||||
--core-login-text-color: var(--white);
|
||||
--core-login-input-background: var(--core-login-background);
|
||||
--core-login-input-color: var(--core-login-text-color);
|
||||
|
||||
--core-question-correct-color: var(--success-tint);
|
||||
--core-question-correct-color-bg: var(--success-shade);
|
||||
--core-question-incorrect-color: var(--danger);
|
||||
--core-question-incorrect-color-bg: var(--danger-shade);
|
||||
--core-question-partial-color: var(--warning-tint);
|
||||
--core-question-partial-color-bg: var(--warning-shade);
|
||||
--core-question-feedback-color: var(--warning-tint);
|
||||
--core-question-feedback-color-bg: var(--warning-shade);
|
||||
--core-question-warning-color: var(--danger);
|
||||
--core-question-saved-color-bg: var(--gray-500);
|
||||
|
||||
--core-question-feedback-color: var(--warning-tint);
|
||||
--core-question-feedback-background-color: var(--warning-shade);
|
||||
|
||||
--core-dd-question-selected-shadow: 2px 2px 4px var(--gray-200);
|
||||
--core-dd-question-border: var(--gray-200);
|
||||
|
||||
--core-send-message-input-background: var(--gray-900);
|
||||
--core-send-message-input-color: var(--white);
|
||||
|
||||
--core-navigation-background: var(--contrast-background);
|
||||
|
||||
--core-collapsible-footer-background: var(--contrast-background);
|
||||
|
||||
--core-messages-message-bg: var(--gray-800);
|
||||
--core-messages-message-activated-bg: var(--gray-700);
|
||||
--core-messages-message-note-text: var(--subdued-text-color);
|
||||
--core-messages-message-mine-bg: var(--gray-700);
|
||||
--core-messages-message-mine-activated-bg: var(--gray-600);
|
||||
--core-messages-discussion-badge: var(--primary);
|
||||
--core-messages-discussion-badge-text: var(--gray-100);
|
||||
|
||||
--addon-forum-border-color: var(--gray-500);
|
||||
--addon-forum-highlight-color: var(--gray-800);
|
||||
|
||||
--core-table-header-background: var(--gray-900);
|
||||
--core-table-odd-cell-background: var(--gray-800);
|
||||
--core-table-odd-cell-hover: var(--gray-600);
|
||||
--core-table-even-cell-background: var(--gray-900);
|
||||
--core-table-even-cell-hover: var(--gray-700);
|
||||
|
||||
}
|
||||
|
||||
:root.dark {
|
||||
@include dark-palette();
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
@import "theme.light.scss";
|
||||
@import "theme.dark.scss";
|
||||
|
||||
html {
|
||||
:root {
|
||||
// Add serif fallback font for km language in some devices.
|
||||
--ion-font-family: var(--ion-default-font), serif;
|
||||
|
||||
|
@ -243,7 +243,7 @@ html {
|
|||
}
|
||||
|
||||
/** @deprecated since 4.3 **/
|
||||
html {
|
||||
:root {
|
||||
--small-radius: var(--mdl-shape-borderRadius-xs);
|
||||
--medium-radius: var(--mdl-shape-borderRadius-sm);
|
||||
--big-radius: var(--mdl-shape-borderRadius-lg);
|
||||
|
@ -251,7 +251,7 @@ html {
|
|||
}
|
||||
|
||||
/** @deprecated since 4.4 **/
|
||||
html {
|
||||
:root {
|
||||
--font-size-normal: var(--mdl-typography-fontSize-md);
|
||||
--a11y-min-target-size: var(--a11y-sizing-minTargetSize);
|
||||
--a11y-focus-width: var(--a11y-shadow-focus-boxShadowSpread);
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* http://ionicframework.com/docs/theming/
|
||||
*/
|
||||
|
||||
html {
|
||||
:root {
|
||||
|
||||
// Color palette
|
||||
--black: #{$black};
|
||||
|
@ -21,27 +21,49 @@ html {
|
|||
--white: #{$white};
|
||||
|
||||
// Ionic shades, defined for ionic internal use.
|
||||
--ion-color-step-0: var(--white);
|
||||
--ion-color-step-50: var(--gray-100);
|
||||
--ion-color-step-100: var(--gray-100);
|
||||
--ion-color-step-150: var(--gray-200);
|
||||
--ion-color-step-200: var(--gray-200);
|
||||
--ion-color-step-250: var(--gray-300);
|
||||
--ion-color-step-300: var(--gray-300);
|
||||
--ion-color-step-350: var(--gray-400);
|
||||
--ion-color-step-400: var(--gray-400);
|
||||
--ion-color-step-450: var(--gray-500);
|
||||
--ion-color-step-500: var(--gray-500);
|
||||
--ion-color-step-550: var(--gray-600);
|
||||
--ion-color-step-600: var(--gray-600);
|
||||
--ion-color-step-650: var(--gray-700);
|
||||
--ion-color-step-700: var(--gray-700);
|
||||
--ion-color-step-750: var(--gray-800);
|
||||
--ion-color-step-800: var(--gray-800);
|
||||
--ion-color-step-850: var(--gray-900);
|
||||
--ion-color-step-900: var(--gray-900);
|
||||
--ion-color-step-950: var(--gray-900);
|
||||
--ion-color-step-1000: var(--black);
|
||||
--ion-background-color-step-0: var(--white);
|
||||
--ion-background-color-step-50: var(--gray-100);
|
||||
--ion-background-color-step-100: var(--gray-100);
|
||||
--ion-background-color-step-150: var(--gray-200);
|
||||
--ion-background-color-step-200: var(--gray-200);
|
||||
--ion-background-color-step-250: var(--gray-300);
|
||||
--ion-background-color-step-300: var(--gray-300);
|
||||
--ion-background-color-step-350: var(--gray-400);
|
||||
--ion-background-color-step-400: var(--gray-400);
|
||||
--ion-background-color-step-450: var(--gray-500);
|
||||
--ion-background-color-step-500: var(--gray-500);
|
||||
--ion-background-color-step-550: var(--gray-600);
|
||||
--ion-background-color-step-600: var(--gray-600);
|
||||
--ion-background-color-step-650: var(--gray-700);
|
||||
--ion-background-color-step-700: var(--gray-700);
|
||||
--ion-background-color-step-750: var(--gray-800);
|
||||
--ion-background-color-step-800: var(--gray-800);
|
||||
--ion-background-color-step-850: var(--gray-900);
|
||||
--ion-background-color-step-900: var(--gray-900);
|
||||
--ion-background-color-step-950: var(--gray-900);
|
||||
--ion-background-color-step-1000: var(--black);
|
||||
|
||||
--ion-text-color-step-0: var(--black);
|
||||
--ion-text-color-step-50: var(--gray-900);
|
||||
--ion-text-color-step-100: var(--gray-900);
|
||||
--ion-text-color-step-150: var(--gray-800);
|
||||
--ion-text-color-step-200: var(--gray-800);
|
||||
--ion-text-color-step-250: var(--gray-700);
|
||||
--ion-text-color-step-300: var(--gray-700);
|
||||
--ion-text-color-step-350: var(--gray-600);
|
||||
--ion-text-color-step-400: var(--gray-600);
|
||||
--ion-text-color-step-450: var(--gray-500);
|
||||
--ion-text-color-step-500: var(--gray-500);
|
||||
--ion-text-color-step-550: var(--gray-400);
|
||||
--ion-text-color-step-600: var(--gray-400);
|
||||
--ion-text-color-step-650: var(--gray-300);
|
||||
--ion-text-color-step-700: var(--gray-300);
|
||||
--ion-text-color-step-750: var(--gray-200);
|
||||
--ion-text-color-step-800: var(--gray-200);
|
||||
--ion-text-color-step-850: var(--gray-100);
|
||||
--ion-text-color-step-900: var(--gray-100);
|
||||
--ion-text-color-step-950: var(--gray-100);
|
||||
--ion-text-color-step-1000: var(--white);
|
||||
|
||||
@each $color-name, $unused in $colors {
|
||||
@include generate-color($color-name, $colors, 'light');
|
||||
|
|
|
@ -29,36 +29,34 @@
|
|||
@import "components/videojs.scss";
|
||||
|
||||
/* Ionic components overrides */
|
||||
html {
|
||||
@import "components/ion-accordion.scss";
|
||||
@import "components/ion-action-sheet.scss";
|
||||
@import "components/ion-alert.scss";
|
||||
@import "components/ion-avatar.scss";
|
||||
@import "components/ion-back-button.scss";
|
||||
@import "components/ion-badge.scss";
|
||||
@import "components/ion-button.scss";
|
||||
@import "components/ion-card.scss";
|
||||
@import "components/ion-checkbox.scss";
|
||||
@import "components/ion-chip.scss";
|
||||
@import "components/ion-content.scss";
|
||||
@import "components/ion-datetime.scss";
|
||||
@import "components/ion-fab.scss";
|
||||
@import "components/ion-header.scss";
|
||||
@import "components/ion-icon.scss";
|
||||
@import "components/ion-input.scss";
|
||||
@import "components/ion-item.scss";
|
||||
@import "components/ion-item-divider.scss";
|
||||
@import "components/ion-modal.scss";
|
||||
@import "components/ion-loading.scss";
|
||||
@import "components/ion-note.scss";
|
||||
@import "components/ion-popover.scss";
|
||||
@import "components/ion-radio.scss";
|
||||
@import "components/ion-searchbar.scss";
|
||||
@import "components/ion-select.scss";
|
||||
@import "components/ion-spinner.scss";
|
||||
@import "components/ion-toast.scss";
|
||||
@import "components/swiper.scss";
|
||||
}
|
||||
@import "components/ion-accordion.scss";
|
||||
@import "components/ion-action-sheet.scss";
|
||||
@import "components/ion-alert.scss";
|
||||
@import "components/ion-avatar.scss";
|
||||
@import "components/ion-back-button.scss";
|
||||
@import "components/ion-badge.scss";
|
||||
@import "components/ion-button.scss";
|
||||
@import "components/ion-card.scss";
|
||||
@import "components/ion-checkbox.scss";
|
||||
@import "components/ion-chip.scss";
|
||||
@import "components/ion-content.scss";
|
||||
@import "components/ion-datetime.scss";
|
||||
@import "components/ion-fab.scss";
|
||||
@import "components/ion-header.scss";
|
||||
@import "components/ion-icon.scss";
|
||||
@import "components/ion-input.scss";
|
||||
@import "components/ion-item.scss";
|
||||
@import "components/ion-item-divider.scss";
|
||||
@import "components/ion-modal.scss";
|
||||
@import "components/ion-loading.scss";
|
||||
@import "components/ion-note.scss";
|
||||
@import "components/ion-popover.scss";
|
||||
@import "components/ion-radio.scss";
|
||||
@import "components/ion-searchbar.scss";
|
||||
@import "components/ion-select.scss";
|
||||
@import "components/ion-spinner.scss";
|
||||
@import "components/ion-toast.scss";
|
||||
@import "components/swiper.scss";
|
||||
|
||||
/* Some styles from 3rd party libraries. */
|
||||
@import "components/bootstrap/utilities/screenreaders.scss";
|
||||
|
@ -67,14 +65,26 @@ html {
|
|||
@import "@ionic/angular/css/core.css";
|
||||
|
||||
/* Basic CSS for apps built with Ionic */
|
||||
@import "@ionic/angular/css/normalize.css";
|
||||
@import "@ionic/angular/css/structure.css";
|
||||
@import "@ionic/angular/css/typography.css";
|
||||
@import "@ionic/angular/css/display.css";
|
||||
@import '@ionic/angular/css/normalize.css';
|
||||
@import '@ionic/angular/css/structure.css';
|
||||
@import '@ionic/angular/css/typography.css';
|
||||
|
||||
/* Optional CSS utils that can be commented out */
|
||||
@import "@ionic/angular/css/padding.css";
|
||||
@import "@ionic/angular/css/float-elements.css";
|
||||
@import "@ionic/angular/css/text-alignment.css";
|
||||
@import "@ionic/angular/css/text-transformation.css";
|
||||
@import "@ionic/angular/css/flex-utils.css";
|
||||
@import '@ionic/angular/css/padding.css';
|
||||
@import '@ionic/angular/css/float-elements.css';
|
||||
@import '@ionic/angular/css/text-alignment.css';
|
||||
@import '@ionic/angular/css/text-transformation.css';
|
||||
@import '@ionic/angular/css/flex-utils.css';
|
||||
@import '@ionic/angular/css/display.css';
|
||||
|
||||
|
||||
/**
|
||||
* Ionic Dark Palette
|
||||
* -----------------------------------------------------
|
||||
* For more information, please see:
|
||||
* https://ionicframework.com/docs/theming/dark-mode
|
||||
*/
|
||||
|
||||
/* @import '@ionic/angular/css/palettes/dark.always.css'; */
|
||||
/* @import '@ionic/angular/css/palettes/dark.class.css'; */
|
||||
/* @import '@ionic/angular/css/palettes/dark.system.css'; */
|
||||
|
|
|
@ -2,8 +2,15 @@ This file describes API changes in the Moodle App that affect site plugins, info
|
|||
|
||||
For more information about upgrading, read the official documentation: https://moodledev.io/general/app/upgrading/
|
||||
|
||||
=== 4.5.0 ===
|
||||
|
||||
- Ionic has been upgraded to major version 8. See breaking changes and upgrade guide here: https://ionicframework.com/docs/updating/8-0
|
||||
- core-show-password has been deprecated in favor of ion-input-password-toggle
|
||||
|
||||
|
||||
=== 4.4.0 ===
|
||||
|
||||
- Ionic has been upgraded to major version 7. See breaking changes and upgrade guide here: https://ionicframework.com/docs/updating/7-0 and https://ionicframework.com/docs/updating/6-0
|
||||
- Starting with this release, this file will only document breaking changes for APIs exposed to site plugins. Internal changes will no longer be documented.
|
||||
- CoreCache has been deprecated, use plain object as in-memory stores instead.
|
||||
- Renamed CoreLoginSitesComponent to CoreLoginSitesModalComponent to make it clear that it's a modal and to avoid confusing it with the new CoreSitesListComponent.
|
||||
|
|