MOBILE-2768 policy: Adapt the UI of accept policy page
parent
d7ce967746
commit
c7262f715e
|
@ -2282,7 +2282,7 @@
|
||||||
"core.phone": "moodle",
|
"core.phone": "moodle",
|
||||||
"core.pictureof": "moodle",
|
"core.pictureof": "moodle",
|
||||||
"core.play": "local_moodlemobileapp",
|
"core.play": "local_moodlemobileapp",
|
||||||
"core.policy.policyaccept": "moodle",
|
"core.policy.havereadandagreepolicy": "local_moodlemobileapp",
|
||||||
"core.policy.policyacceptmandatory": "local_moodlemobileapp",
|
"core.policy.policyacceptmandatory": "local_moodlemobileapp",
|
||||||
"core.policy.policyagree": "moodle",
|
"core.policy.policyagree": "moodle",
|
||||||
"core.policy.policyagreement": "moodle",
|
"core.policy.policyagreement": "moodle",
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"policyaccept": "I understand and agree",
|
"havereadandagreepolicy": "I have read and agree to the {{policyname}}",
|
||||||
"policyacceptmandatory": "I understand and agree to the mandatory site policies",
|
"policyacceptmandatory": "I understand and agree to the mandatory site policies",
|
||||||
"policyagree": "You must agree to this policy to continue using this site. Do you agree?",
|
"policyagree": "You must agree to this policy to continue using this site. Do you agree?",
|
||||||
"policyagreement": "Site policy agreement",
|
"policyagreement": "Site policy agreement",
|
||||||
|
|
|
@ -4,35 +4,62 @@
|
||||||
<ion-back-button [text]="'core.back' | translate" />
|
<ion-back-button [text]="'core.back' | translate" />
|
||||||
</ion-buttons>
|
</ion-buttons>
|
||||||
|
|
||||||
<ion-title>
|
<ion-title *ngIf="siteName">
|
||||||
<h1>{{ 'core.policy.policyagreement' | translate }}</h1>
|
<h1><core-format-text [text]="siteName" contextLevel="system" [contextInstanceId]="0" /></h1>
|
||||||
</ion-title>
|
</ion-title>
|
||||||
|
|
||||||
|
<ion-buttons slot="end">
|
||||||
|
<ion-button fill="clear" (click)="cancel()" [attr.aria-label]="'core.cancel' | translate">
|
||||||
|
<ion-icon name="fas-xmark" slot="icon-only" aria-hidden=true />
|
||||||
|
</ion-button>
|
||||||
|
</ion-buttons>
|
||||||
</ion-toolbar>
|
</ion-toolbar>
|
||||||
</ion-header>
|
</ion-header>
|
||||||
<ion-content>
|
<ion-content class="limited-width">
|
||||||
<core-loading [hideUntil]="policyLoaded">
|
<core-loading [hideUntil]="policyLoaded">
|
||||||
<ion-list *ngIf="sitePolicy">
|
<form *ngIf="policyForm" [formGroup]="policyForm" (ngSubmit)="submitAcceptances($event)">
|
||||||
<ion-item class="ion-text-wrap">
|
<ion-item class="ion-text-wrap">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<p>{{ 'core.policy.policyagree' | translate }}</p>
|
<h2>{{ 'core.policy.policyagreement' | translate }}</h2>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
<ion-item class="ion-text-wrap">
|
<hr>
|
||||||
<ion-label>
|
<ng-container *ngIf="isPoliciesURL && sitePoliciesURL">
|
||||||
<p>
|
<ion-card class="core-info-card">
|
||||||
<a [href]="sitePolicy" core-link [capture]="false">{{ 'core.policy.policyagreementclick' | translate }}</a>
|
<ion-item class="ion-text-wrap">
|
||||||
</p>
|
<ion-icon name="fas-circle-info" slot="start" aria-hidden="true" />
|
||||||
</ion-label>
|
<ion-label>
|
||||||
</ion-item>
|
<p>{{ 'core.policy.policyagree' | translate }}</p>
|
||||||
<ion-card *ngIf="showInline" class="core-site-policy-iframe-container">
|
</ion-label>
|
||||||
<core-iframe [src]="sitePolicy" />
|
</ion-item>
|
||||||
</ion-card>
|
</ion-card>
|
||||||
<ion-button class="ion-text-wrap ion-margin-horizontal" expand="block" (click)="accept()">
|
<ion-item class="ion-text-wrap core-site-policy-link">
|
||||||
{{ 'core.policy.policyacceptmandatory' | translate }}
|
<ion-label>
|
||||||
</ion-button>
|
<p>
|
||||||
<ion-button class="ion-text-wrap ion-margin-horizontal ion-margin-bottom" expand="block" fill="outline" (click)="cancel()">
|
<a [href]="sitePoliciesURL" core-link [capture]="false">
|
||||||
{{ 'core.cancel' | translate }}
|
{{ 'core.policy.policyagreementclick' | translate }}<ion-icon name="fas-up-right-from-square"
|
||||||
</ion-button>
|
aria-hidden="true" />
|
||||||
</ion-list>
|
</a>
|
||||||
|
</p>
|
||||||
|
</ion-label>
|
||||||
|
</ion-item>
|
||||||
|
<div class="core-site-policy-iframe-container" [class.core-policy-has-iframe]="showInline">
|
||||||
|
<core-iframe *ngIf="showInline" [src]="sitePoliciesURL" />
|
||||||
|
</div>
|
||||||
|
<ion-item class="ion-text-wrap">
|
||||||
|
<ion-checkbox name="agreepolicy" formControlName="agreepolicy">
|
||||||
|
<span *ngIf="isManageAcceptancesAvailable" [core-mark-required]="true">
|
||||||
|
{{ 'core.policy.havereadandagreepolicy' | translate:{ policyname:'core.policy.policyagreement' | translate } }}
|
||||||
|
</span>
|
||||||
|
<span *ngIf="!isManageAcceptancesAvailable" [core-mark-required]="true">
|
||||||
|
{{ 'core.policy.policyacceptmandatory' | translate }}
|
||||||
|
</span>
|
||||||
|
</ion-checkbox>
|
||||||
|
</ion-item>
|
||||||
|
<ion-button type="submit" class="ion-text-wrap ion-margin-horizontal" expand="block" [disabled]="!policyForm.valid">
|
||||||
|
{{ 'core.continue' | translate }}
|
||||||
|
</ion-button>
|
||||||
|
</ng-container>
|
||||||
|
</form>
|
||||||
</core-loading>
|
</core-loading>
|
||||||
</ion-content>
|
</ion-content>
|
||||||
|
|
|
@ -1,20 +1,45 @@
|
||||||
|
@use "theme/globals" as *;
|
||||||
|
|
||||||
:host {
|
:host {
|
||||||
ion-list {
|
hr {
|
||||||
|
background: var(--black);
|
||||||
|
margin: 0 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
form {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
flex-grow: 1;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
||||||
ion-item {
|
ion-item, .core-info-card {
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.core-site-policy-iframe-container {
|
ion-item {
|
||||||
height: 100%;
|
--inner-border-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
core-iframe {
|
.core-site-policy-link {
|
||||||
height: 100%;
|
p {
|
||||||
width: 100%;
|
text-decoration: underline;
|
||||||
|
font-size: 1rem;
|
||||||
|
|
||||||
|
ion-icon {
|
||||||
|
font-size: 0.875rem;
|
||||||
|
@include margin-horizontal(4px, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.core-site-policy-iframe-container {
|
||||||
|
margin: 8px;
|
||||||
|
display: flex;
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ion-button[type="submit"] {
|
||||||
|
margin-bottom: 12px;;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@ import { CoreEvents } from '@singletons/events';
|
||||||
import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
|
import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
|
||||||
import { Translate } from '@singletons';
|
import { Translate } from '@singletons';
|
||||||
import { CorePolicy } from '@features/policy/services/policy';
|
import { CorePolicy } from '@features/policy/services/policy';
|
||||||
|
import { FormControl, FormGroup, Validators } from '@angular/forms';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Page to accept a site policy.
|
* Page to accept a site policy.
|
||||||
|
@ -35,20 +36,26 @@ import { CorePolicy } from '@features/policy/services/policy';
|
||||||
})
|
})
|
||||||
export class CorePolicySitePolicyPage implements OnInit {
|
export class CorePolicySitePolicyPage implements OnInit {
|
||||||
|
|
||||||
sitePolicy?: string;
|
siteName?: string;
|
||||||
|
isManageAcceptancesAvailable = false;
|
||||||
|
isPoliciesURL = false;
|
||||||
|
sitePoliciesURL?: string;
|
||||||
showInline?: boolean;
|
showInline?: boolean;
|
||||||
policyLoaded?: boolean;
|
policyLoaded?: boolean;
|
||||||
|
policyForm?: FormGroup;
|
||||||
|
|
||||||
protected siteId?: string;
|
protected siteId?: string;
|
||||||
protected currentSite!: CoreSite;
|
protected currentSite!: CoreSite;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @inheritdoc
|
* @inheritdoc
|
||||||
*/
|
*/
|
||||||
ngOnInit(): void {
|
async ngOnInit(): Promise<void> {
|
||||||
this.siteId = CoreNavigator.getRouteParam('siteId');
|
this.siteId = CoreNavigator.getRouteParam('siteId');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
this.currentSite = CoreSites.getRequiredCurrentSite();
|
this.currentSite = CoreSites.getRequiredCurrentSite();
|
||||||
|
this.siteName = (await CoreUtils.ignoreErrors(this.currentSite.getSiteName(), '')) || '';
|
||||||
} catch {
|
} catch {
|
||||||
// Not logged in, stop.
|
// Not logged in, stop.
|
||||||
this.cancel();
|
this.cancel();
|
||||||
|
@ -66,17 +73,36 @@ export class CorePolicySitePolicyPage implements OnInit {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.fetchSitePolicy();
|
this.isManageAcceptancesAvailable = await CorePolicy.isManageAcceptancesAvailable(this.siteId);
|
||||||
|
this.isPoliciesURL = this.isManageAcceptancesAvailable ?
|
||||||
|
(await this.currentSite.getConfig('sitepolicyhandler')) !== 'tool_policy' :
|
||||||
|
true; // Site doesn't support managing acceptances, just display it as a URL.
|
||||||
|
|
||||||
|
if (this.isPoliciesURL) {
|
||||||
|
this.initFormForPoliciesURL();
|
||||||
|
|
||||||
|
await this.fetchSitePoliciesURL();
|
||||||
|
} else {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
CoreAnalytics.logEvent({
|
||||||
|
type: CoreAnalyticsEventType.VIEW_ITEM,
|
||||||
|
ws: 'auth_email_get_signup_settings',
|
||||||
|
name: Translate.instant('core.policy.policyagreement'),
|
||||||
|
data: { category: 'policy' },
|
||||||
|
url: '/user/policy.php',
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetch the site policy URL.
|
* Fetch the site policies URL.
|
||||||
*
|
*
|
||||||
* @returns Promise resolved when done.
|
* @returns Promise resolved when done.
|
||||||
*/
|
*/
|
||||||
protected async fetchSitePolicy(): Promise<void> {
|
protected async fetchSitePoliciesURL(): Promise<void> {
|
||||||
try {
|
try {
|
||||||
this.sitePolicy = await CorePolicy.getSitePoliciesURL(this.siteId);
|
this.sitePoliciesURL = await CorePolicy.getSitePoliciesURL(this.siteId);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
CoreDomUtils.showErrorModalDefault(error, 'Error getting site policy.');
|
CoreDomUtils.showErrorModalDefault(error, 'Error getting site policy.');
|
||||||
this.cancel();
|
this.cancel();
|
||||||
|
@ -86,9 +112,9 @@ export class CorePolicySitePolicyPage implements OnInit {
|
||||||
|
|
||||||
// Try to get the mime type.
|
// Try to get the mime type.
|
||||||
try {
|
try {
|
||||||
const mimeType = await CoreUtils.getMimeTypeFromUrl(this.sitePolicy);
|
const mimeType = await CoreUtils.getMimeTypeFromUrl(this.sitePoliciesURL);
|
||||||
|
|
||||||
const extension = CoreMimetypeUtils.getExtension(mimeType, this.sitePolicy);
|
const extension = CoreMimetypeUtils.getExtension(mimeType, this.sitePoliciesURL);
|
||||||
this.showInline = extension == 'html' || extension == 'htm';
|
this.showInline = extension == 'html' || extension == 'htm';
|
||||||
} catch {
|
} catch {
|
||||||
// Unable to get mime type, assume it's not supported.
|
// Unable to get mime type, assume it's not supported.
|
||||||
|
@ -96,13 +122,17 @@ export class CorePolicySitePolicyPage implements OnInit {
|
||||||
} finally {
|
} finally {
|
||||||
this.policyLoaded = true;
|
this.policyLoaded = true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
CoreAnalytics.logEvent({
|
/**
|
||||||
type: CoreAnalyticsEventType.VIEW_ITEM,
|
* Init the form to accept the policies using a URL.
|
||||||
ws: 'auth_email_get_signup_settings',
|
*/
|
||||||
name: Translate.instant('core.policy.policyagreement'),
|
protected initFormForPoliciesURL(): void {
|
||||||
data: { category: 'policy' },
|
this.policyForm = new FormGroup({
|
||||||
url: '/user/policy.php',
|
agreepolicy: new FormControl(false, {
|
||||||
|
validators: Validators.requiredTrue,
|
||||||
|
nonNullable: true,
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,11 +148,19 @@ export class CorePolicySitePolicyPage implements OnInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Accept the site policy.
|
* Submit the acceptances to one or several policies.
|
||||||
*
|
*
|
||||||
|
* @param event Event.
|
||||||
* @returns Promise resolved when done.
|
* @returns Promise resolved when done.
|
||||||
*/
|
*/
|
||||||
async accept(): Promise<void> {
|
async submitAcceptances(event: Event): Promise<void> {
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
|
||||||
|
if (!this.policyForm?.valid) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const modal = await CoreDomUtils.showModalLoading('core.sending', true);
|
const modal = await CoreDomUtils.showModalLoading('core.sending', true);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -99,7 +99,9 @@ ion-item .in-item {
|
||||||
|
|
||||||
// Correctly inherit ion-text-wrap onto labels.
|
// Correctly inherit ion-text-wrap onto labels.
|
||||||
.item > ion-label,
|
.item > ion-label,
|
||||||
.fake-ion-item {
|
.fake-ion-item,
|
||||||
|
.item.ion-text-wrap > ion-checkbox::part(label),
|
||||||
|
ion-checkbox.ion-text-wrap::part(label) {
|
||||||
core-format-text,
|
core-format-text,
|
||||||
core-format-text > *:not(pre) {
|
core-format-text > *:not(pre) {
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
@ -110,7 +112,9 @@ ion-item .in-item {
|
||||||
|
|
||||||
.item.ion-text-wrap > ion-label,
|
.item.ion-text-wrap > ion-label,
|
||||||
ion-item > .in-item,
|
ion-item > .in-item,
|
||||||
.fake-ion-item.ion-text-wrap {
|
.fake-ion-item.ion-text-wrap,
|
||||||
|
.item.ion-text-wrap > ion-checkbox::part(label),
|
||||||
|
ion-checkbox.ion-text-wrap::part(label) {
|
||||||
core-format-text,
|
core-format-text,
|
||||||
core-format-text > *:not(pre) {
|
core-format-text > *:not(pre) {
|
||||||
white-space: normal;
|
white-space: normal;
|
||||||
|
@ -118,7 +122,9 @@ ion-item > .in-item,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.item.ion-text-wrap > ion-label {
|
.item.ion-text-wrap > ion-label,
|
||||||
|
.item.ion-text-wrap > ion-checkbox::part(label),
|
||||||
|
ion-checkbox.ion-text-wrap::part(label) {
|
||||||
white-space: normal !important;
|
white-space: normal !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue