forked from CIT/Vmeda.Online
		
	
						commit
						9a291e4fed
					
				| @ -1608,6 +1608,7 @@ | |||||||
|   "core.remove": "moodle", |   "core.remove": "moodle", | ||||||
|   "core.required": "moodle", |   "core.required": "moodle", | ||||||
|   "core.requireduserdatamissing": "local_moodlemobileapp", |   "core.requireduserdatamissing": "local_moodlemobileapp", | ||||||
|  |   "core.resourcedisplayopen": "moodle", | ||||||
|   "core.resources": "moodle", |   "core.resources": "moodle", | ||||||
|   "core.restore": "moodle", |   "core.restore": "moodle", | ||||||
|   "core.retry": "local_moodlemobileapp", |   "core.retry": "local_moodlemobileapp", | ||||||
|  | |||||||
| @ -36,6 +36,7 @@ export class AddonModFeedbackIndexComponent extends CoreCourseModuleMainActivity | |||||||
|     @Input() tab = 'overview'; |     @Input() tab = 'overview'; | ||||||
|     @Input() group = 0; |     @Input() group = 0; | ||||||
| 
 | 
 | ||||||
|  |     component = AddonModFeedbackProvider.COMPONENT; | ||||||
|     moduleName = 'feedback'; |     moduleName = 'feedback'; | ||||||
| 
 | 
 | ||||||
|     access = { |     access = { | ||||||
| @ -67,6 +68,7 @@ export class AddonModFeedbackIndexComponent extends CoreCourseModuleMainActivity | |||||||
|     firstSelectedTab: number; |     firstSelectedTab: number; | ||||||
| 
 | 
 | ||||||
|     protected submitObserver: any; |     protected submitObserver: any; | ||||||
|  |     protected syncEventName = AddonModFeedbackSyncProvider.AUTO_SYNCED; | ||||||
| 
 | 
 | ||||||
|     constructor(injector: Injector, private feedbackProvider: AddonModFeedbackProvider, @Optional() content: Content, |     constructor(injector: Injector, private feedbackProvider: AddonModFeedbackProvider, @Optional() content: Content, | ||||||
|             private feedbackOffline: AddonModFeedbackOfflineProvider, private groupsProvider: CoreGroupsProvider, |             private feedbackOffline: AddonModFeedbackOfflineProvider, private groupsProvider: CoreGroupsProvider, | ||||||
|  | |||||||
| @ -357,7 +357,7 @@ export class AddonModForumDiscussionPage implements OnDestroy { | |||||||
|     protected syncDiscussion(showErrors: boolean): Promise<any> { |     protected syncDiscussion(showErrors: boolean): Promise<any> { | ||||||
|         const promises = []; |         const promises = []; | ||||||
| 
 | 
 | ||||||
|         promises.push(this.forumSync.syncDiscussionReplies(this.forumId, this.discussionId).then((result) => { |         promises.push(this.forumSync.syncDiscussionReplies(this.discussionId).then((result) => { | ||||||
|             if (result.warnings && result.warnings.length) { |             if (result.warnings && result.warnings.length) { | ||||||
|                 this.domUtils.showErrorModal(result.warnings[0]); |                 this.domUtils.showErrorModal(result.warnings[0]); | ||||||
|             } |             } | ||||||
|  | |||||||
| @ -51,53 +51,64 @@ | |||||||
|                 </ion-card> |                 </ion-card> | ||||||
| 
 | 
 | ||||||
|                 <core-loading [hideUntil]="!showSpinner"> |                 <core-loading [hideUntil]="!showSpinner"> | ||||||
|                     <ion-list *ngIf="lesson && (!preventMessages || !preventMessages.length)"> | 
 | ||||||
|  |                     <ion-list *ngIf="(lesson && (!preventMessages || !preventMessages.length)) || retakeToReview"> | ||||||
|                         <ion-item text-wrap *ngIf="retakeToReview"> |                         <ion-item text-wrap *ngIf="retakeToReview"> | ||||||
|                             <!-- A retake was finished in a synchronization, allow reviewing it. --> |                             <!-- A retake was finished in a synchronization, allow reviewing it. --> | ||||||
|                             <p>{{ 'addon.mod_lesson.retakefinishedinsync' | translate }}</p> |                             <p padding-bottom>{{ 'addon.mod_lesson.retakefinishedinsync' | translate }}</p> | ||||||
|                             <a ion-button block (click)="review()">{{ 'addon.mod_lesson.review' | translate }}</a> |                             <a ion-button block (click)="review()">{{ 'addon.mod_lesson.review' | translate }}</a> | ||||||
|                         </ion-item> |                         </ion-item> | ||||||
| 
 | 
 | ||||||
|                         <ion-item text-wrap *ngIf="leftDuringTimed && !lesson.timelimit"> |                         <ng-container *ngIf="lesson && (!preventMessages || !preventMessages.length)"> | ||||||
|                             <!-- User left during the session and there is no time limit, ask to continue. --> |                             <ion-item text-wrap *ngIf="leftDuringTimed && !lesson.timelimit && !finishedOffline"> | ||||||
|                             <p [innerHTML]="'addon.mod_lesson.youhaveseen' | translate"></p> |                                 <!-- User left during the session and there is no time limit, ask to continue. --> | ||||||
|                             <ion-grid> |                                 <p [innerHTML]="'addon.mod_lesson.youhaveseen' | translate"></p> | ||||||
|                                 <ion-row> |                                 <ion-grid> | ||||||
|                                     <ion-col> |                                     <ion-row> | ||||||
|                                         <a ion-button block color="light" (click)="start(false)">{{ 'core.no' | translate }}</a> |                                         <ion-col> | ||||||
|                                     </ion-col> |                                             <a ion-button block color="light" (click)="start(false)">{{ 'core.no' | translate }}</a> | ||||||
|                                     <ion-col> |                                         </ion-col> | ||||||
|                                         <a ion-button block (click)="start(true)">{{ 'core.yes' | translate }}</a> |                                         <ion-col> | ||||||
|                                     </ion-col> |                                             <a ion-button block (click)="start(true)">{{ 'core.yes' | translate }}</a> | ||||||
|                                 </ion-row> |                                         </ion-col> | ||||||
|                             </ion-grid> |                                     </ion-row> | ||||||
|                         </ion-item> |                                 </ion-grid> | ||||||
|  |                             </ion-item> | ||||||
| 
 | 
 | ||||||
|                         <ion-item text-wrap *ngIf="leftDuringTimed && lesson.timelimit && lesson.retake"> |                             <ion-item text-wrap *ngIf="leftDuringTimed && lesson.timelimit && lesson.retake && !finishedOffline"> | ||||||
|                             <!-- User left during the session with time limit and retakes allowed, ask to continue. --> |                                 <!-- User left during the session with time limit and retakes allowed, ask to continue. --> | ||||||
|                             <p [innerHTML]="'addon.mod_lesson.leftduringtimed' | translate"></p> |                                 <p [innerHTML]="'addon.mod_lesson.leftduringtimed' | translate"></p> | ||||||
|                             <a ion-button block icon-end (click)="start(false)"> |                                 <a ion-button block icon-end (click)="start(false)"> | ||||||
|                                 {{ 'addon.mod_lesson.continue' | translate }} |                                     {{ 'addon.mod_lesson.continue' | translate }} | ||||||
|                                 <ion-icon name="arrow-forward" md="ios-arrow-forward"></ion-icon> |                                     <ion-icon name="arrow-forward" md="ios-arrow-forward"></ion-icon> | ||||||
|                             </a> |                                 </a> | ||||||
|                         </ion-item> |                             </ion-item> | ||||||
| 
 | 
 | ||||||
|                         <ion-item text-wrap *ngIf="leftDuringTimed && lesson.timelimit && !lesson.retake"> |                             <ion-item text-wrap *ngIf="leftDuringTimed && lesson.timelimit && !lesson.retake"> | ||||||
|                             <!-- User left during the session with time limit and retakes not allowed. This should be handled by preventMessages --> |                                 <!-- User left during the session with time limit and retakes not allowed. This should be handled by preventMessages --> | ||||||
|                             <p [innerHTML]="'addon.mod_lesson.leftduringtimednoretake' | translate"></p> |                                 <p [innerHTML]="'addon.mod_lesson.leftduringtimednoretake' | translate"></p> | ||||||
|                         </ion-item> |                             </ion-item> | ||||||
| 
 | 
 | ||||||
|                         <ion-item text-wrap *ngIf="!leftDuringTimed"> |                             <ion-item text-wrap *ngIf="!leftDuringTimed && !finishedOffline"> | ||||||
|                             <!-- User hasn't left during the session, show a start button. --> |                                 <!-- User hasn't left during the session, show a start button. --> | ||||||
|                             <a ion-button block *ngIf="!canManage" icon-end (click)="start(false)"> |                                 <a ion-button block *ngIf="!canManage" icon-end (click)="start(false)"> | ||||||
|                                 {{ 'core.start' | translate }} |                                     {{ 'core.start' | translate }} | ||||||
|                                 <ion-icon name="arrow-forward" md="ios-arrow-forward"></ion-icon> |                                     <ion-icon name="arrow-forward" md="ios-arrow-forward"></ion-icon> | ||||||
|                             </a> |                                 </a> | ||||||
|                             <a ion-button block *ngIf="canManage" icon-end (click)="start(false)"> |                                 <a ion-button block *ngIf="canManage" icon-end (click)="start(false)"> | ||||||
|                                 {{ 'addon.mod_lesson.preview' | translate }} |                                     {{ 'addon.mod_lesson.preview' | translate }} | ||||||
|                                 <ion-icon name="search"></ion-icon> |                                     <ion-icon name="search"></ion-icon> | ||||||
|                             </a> |                                 </a> | ||||||
|                         </ion-item> |                             </ion-item> | ||||||
|  | 
 | ||||||
|  |                             <ion-item text-wrap *ngIf="finishedOffline"> | ||||||
|  |                                 <!-- There's an attempt finished in offline. Let the user continue, showing the end of lesson. --> | ||||||
|  |                                 <a ion-button block icon-end (click)="start(true)"> | ||||||
|  |                                     {{ 'addon.mod_lesson.continue' | translate }} | ||||||
|  |                                     <ion-icon name="arrow-forward" md="ios-arrow-forward"></ion-icon> | ||||||
|  |                                 </a> | ||||||
|  |                             </ion-item> | ||||||
|  |                         </ng-container> | ||||||
|                     </ion-list> |                     </ion-list> | ||||||
|                 </core-loading> |                 </core-loading> | ||||||
|             </ng-template> |             </ng-template> | ||||||
|  | |||||||
| @ -56,6 +56,7 @@ export class AddonModLessonIndexComponent extends CoreCourseModuleMainActivityCo | |||||||
|     reportLoaded: boolean; // Whether the report data has been loaded.
 |     reportLoaded: boolean; // Whether the report data has been loaded.
 | ||||||
|     selectedGroupName: string; // The name of the selected group.
 |     selectedGroupName: string; // The name of the selected group.
 | ||||||
|     overview: any; // Reports overview data.
 |     overview: any; // Reports overview data.
 | ||||||
|  |     finishedOffline: boolean; // Whether a retake was finished in offline.
 | ||||||
| 
 | 
 | ||||||
|     protected syncEventName = AddonModLessonSyncProvider.AUTO_SYNCED; |     protected syncEventName = AddonModLessonSyncProvider.AUTO_SYNCED; | ||||||
|     protected accessInfo: any; // Lesson access info.
 |     protected accessInfo: any; // Lesson access info.
 | ||||||
| @ -159,6 +160,11 @@ export class AddonModLessonIndexComponent extends CoreCourseModuleMainActivityCo | |||||||
|                     } |                     } | ||||||
|                 })); |                 })); | ||||||
| 
 | 
 | ||||||
|  |                 // Check if the ser has a finished retake in offline.
 | ||||||
|  |                 promises.push(this.lessonOffline.hasFinishedRetake(this.lesson.id).then((finished) => { | ||||||
|  |                     this.finishedOffline = finished; | ||||||
|  |                 })); | ||||||
|  | 
 | ||||||
|                 // Update the list of content pages viewed and question attempts.
 |                 // Update the list of content pages viewed and question attempts.
 | ||||||
|                 promises.push(this.lessonProvider.getContentPagesViewedOnline(this.lesson.id, info.attemptscount)); |                 promises.push(this.lessonProvider.getContentPagesViewedOnline(this.lesson.id, info.attemptscount)); | ||||||
|                 promises.push(this.lessonProvider.getQuestionsAttemptsOnline(this.lesson.id, info.attemptscount)); |                 promises.push(this.lessonProvider.getQuestionsAttemptsOnline(this.lesson.id, info.attemptscount)); | ||||||
|  | |||||||
| @ -32,14 +32,14 @@ | |||||||
|             <!-- Page content. --> |             <!-- Page content. --> | ||||||
|             <ion-card *ngIf="!eolData && !processData"> |             <ion-card *ngIf="!eolData && !processData"> | ||||||
|                 <!-- Content page. --> |                 <!-- Content page. --> | ||||||
|                 <ion-item text-wrap *ngIf="!question"> |                 <ion-item text-wrap *ngIf="!question && pageContent"> | ||||||
|                     <core-format-text [component]="component" [componentId]="lesson.coursemodule" [text]="pageContent"></core-format-text> |                     <core-format-text [component]="component" [componentId]="lesson.coursemodule" [text]="pageContent"></core-format-text> | ||||||
|                 </ion-item> |                 </ion-item> | ||||||
| 
 | 
 | ||||||
|                 <!-- Question page. --> |                 <!-- Question page. --> | ||||||
|                 <!-- We need to set ngIf loaded to make formGroup directive restart every time a page changes, see MOBILE-2540. --> |                 <!-- We need to set ngIf loaded to make formGroup directive restart every time a page changes, see MOBILE-2540. --> | ||||||
|                 <form *ngIf="question && loaded" ion-list [formGroup]="questionForm"> |                 <form *ngIf="question && loaded" ion-list [formGroup]="questionForm"> | ||||||
|                     <ion-item-divider text-wrap> |                     <ion-item-divider text-wrap *ngIf="pageContent"> | ||||||
|                         <core-format-text [component]="component" [componentId]="lesson.coursemodule" [text]="pageContent"></core-format-text> |                         <core-format-text [component]="component" [componentId]="lesson.coursemodule" [text]="pageContent"></core-format-text> | ||||||
|                     </ion-item-divider> |                     </ion-item-divider> | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -27,7 +27,8 @@ import { AddonModLessonProvider } from './lesson'; | |||||||
| export class AddonModLessonHelperProvider { | export class AddonModLessonHelperProvider { | ||||||
| 
 | 
 | ||||||
|     constructor(private domUtils: CoreDomUtilsProvider, private fb: FormBuilder, private translate: TranslateService, |     constructor(private domUtils: CoreDomUtilsProvider, private fb: FormBuilder, private translate: TranslateService, | ||||||
|             private textUtils: CoreTextUtilsProvider, private timeUtils: CoreTimeUtilsProvider) { } |             private textUtils: CoreTextUtilsProvider, private timeUtils: CoreTimeUtilsProvider, | ||||||
|  |             private lessonProvider: AddonModLessonProvider) { } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|      * Given the HTML of next activity link, format it to extract the href and the text. |      * Given the HTML of next activity link, format it to extract the href and the text. | ||||||
| @ -149,8 +150,15 @@ export class AddonModLessonHelperProvider { | |||||||
|             return contents.innerHTML.trim(); |             return contents.innerHTML.trim(); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         // Cannot find contents element, return the page.contents (some elements like videos might not work).
 |         // Cannot find contents element.
 | ||||||
|         return data.page.contents; |         if (this.lessonProvider.isQuestionPage(data.page.type) || | ||||||
|  |                 data.page.qtype == AddonModLessonProvider.LESSON_PAGE_BRANCHTABLE) { | ||||||
|  |             // Return page.contents to prevent having duplicated elements (some elements like videos might not work).
 | ||||||
|  |             return data.page.contents; | ||||||
|  |         } else { | ||||||
|  |             // It's an end of cluster, end of branch, etc. Return the whole pagecontent to match what's displayed in web.
 | ||||||
|  |             return data.pagecontent; | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|  | |||||||
| @ -32,6 +32,7 @@ import { AddonModWorkshopOfflineProvider } from '../../providers/offline'; | |||||||
| export class AddonModWorkshopIndexComponent extends CoreCourseModuleMainActivityComponent { | export class AddonModWorkshopIndexComponent extends CoreCourseModuleMainActivityComponent { | ||||||
|     @Input() group = 0; |     @Input() group = 0; | ||||||
| 
 | 
 | ||||||
|  |     component = AddonModWorkshopProvider.COMPONENT; | ||||||
|     moduleName = 'workshop'; |     moduleName = 'workshop'; | ||||||
|     workshop: any; |     workshop: any; | ||||||
|     page = 0; |     page = 0; | ||||||
| @ -64,6 +65,7 @@ export class AddonModWorkshopIndexComponent extends CoreCourseModuleMainActivity | |||||||
|     protected obsAssessmentSaved: any; |     protected obsAssessmentSaved: any; | ||||||
|     protected appResumeSubscription: any; |     protected appResumeSubscription: any; | ||||||
|     protected syncObserver: any; |     protected syncObserver: any; | ||||||
|  |     protected syncEventName = AddonModWorkshopSyncProvider.AUTO_SYNCED; | ||||||
| 
 | 
 | ||||||
|     constructor(injector: Injector, private workshopProvider: AddonModWorkshopProvider, @Optional() content: Content, |     constructor(injector: Injector, private workshopProvider: AddonModWorkshopProvider, @Optional() content: Content, | ||||||
|             private workshopOffline: AddonModWorkshopOfflineProvider, private groupsProvider: CoreGroupsProvider, |             private workshopOffline: AddonModWorkshopOfflineProvider, private groupsProvider: CoreGroupsProvider, | ||||||
|  | |||||||
| @ -1608,6 +1608,7 @@ | |||||||
|     "core.remove": "Remove", |     "core.remove": "Remove", | ||||||
|     "core.required": "Required", |     "core.required": "Required", | ||||||
|     "core.requireduserdatamissing": "This user lacks some required profile data. Please enter the data in your site and try again.<br>{{$a}}", |     "core.requireduserdatamissing": "This user lacks some required profile data. Please enter the data in your site and try again.<br>{{$a}}", | ||||||
|  |     "core.resourcedisplayopen": "Open", | ||||||
|     "core.resources": "Resources", |     "core.resources": "Resources", | ||||||
|     "core.restore": "Restore", |     "core.restore": "Restore", | ||||||
|     "core.retry": "Retry", |     "core.retry": "Retry", | ||||||
|  | |||||||
| @ -605,7 +605,7 @@ export class CoreSite { | |||||||
| 
 | 
 | ||||||
|                     // Session expired, trigger event.
 |                     // Session expired, trigger event.
 | ||||||
|                     this.eventsProvider.trigger(CoreEventsProvider.SESSION_EXPIRED, {}, this.id); |                     this.eventsProvider.trigger(CoreEventsProvider.SESSION_EXPIRED, {}, this.id); | ||||||
|                     // Change error message. We'll try to get data from cache.
 |                     // Change error message. Try to get data from cache, the event will handle the error.
 | ||||||
|                     error.message = this.translate.instant('core.lostconnection'); |                     error.message = this.translate.instant('core.lostconnection'); | ||||||
|                 } else if (error.errorcode === 'userdeleted') { |                 } else if (error.errorcode === 'userdeleted') { | ||||||
|                     // User deleted, trigger event.
 |                     // User deleted, trigger event.
 | ||||||
| @ -614,17 +614,15 @@ export class CoreSite { | |||||||
| 
 | 
 | ||||||
|                     return Promise.reject(error); |                     return Promise.reject(error); | ||||||
|                 } else if (error.errorcode === 'forcepasswordchangenotice') { |                 } else if (error.errorcode === 'forcepasswordchangenotice') { | ||||||
|                     // Password Change Forced, trigger event.
 |                     // Password Change Forced, trigger event. Try to get data from cache, the event will handle the error.
 | ||||||
|                     this.eventsProvider.trigger(CoreEventsProvider.PASSWORD_CHANGE_FORCED, {}, this.id); |                     this.eventsProvider.trigger(CoreEventsProvider.PASSWORD_CHANGE_FORCED, {}, this.id); | ||||||
|                     error.message = this.translate.instant('core.forcepasswordchangenotice'); |                     error.message = this.translate.instant('core.forcepasswordchangenotice'); | ||||||
| 
 | 
 | ||||||
|                     return Promise.reject(error); |  | ||||||
|                 } else if (error.errorcode === 'usernotfullysetup') { |                 } else if (error.errorcode === 'usernotfullysetup') { | ||||||
|                     // User not fully setup, trigger event.
 |                     // User not fully setup, trigger event. Try to get data from cache, the event will handle the error.
 | ||||||
|                     this.eventsProvider.trigger(CoreEventsProvider.USER_NOT_FULLY_SETUP, {}, this.id); |                     this.eventsProvider.trigger(CoreEventsProvider.USER_NOT_FULLY_SETUP, {}, this.id); | ||||||
|                     error.message = this.translate.instant('core.usernotfullysetup'); |                     error.message = this.translate.instant('core.usernotfullysetup'); | ||||||
| 
 | 
 | ||||||
|                     return Promise.reject(error); |  | ||||||
|                 } else if (error.errorcode === 'sitepolicynotagreed') { |                 } else if (error.errorcode === 'sitepolicynotagreed') { | ||||||
|                     // Site policy not agreed, trigger event.
 |                     // Site policy not agreed, trigger event.
 | ||||||
|                     this.eventsProvider.trigger(CoreEventsProvider.SITE_POLICY_NOT_AGREED, {}, this.id); |                     this.eventsProvider.trigger(CoreEventsProvider.SITE_POLICY_NOT_AGREED, {}, this.id); | ||||||
|  | |||||||
| @ -62,13 +62,6 @@ export class CoreLocalFileComponent implements OnInit { | |||||||
|     ngOnInit(): void { |     ngOnInit(): void { | ||||||
|         this.manage = this.utils.isTrueOrOne(this.manage); |         this.manage = this.utils.isTrueOrOne(this.manage); | ||||||
| 
 | 
 | ||||||
|         // Let's calculate the relative path for the file.
 |  | ||||||
|         this.relativePath = this.fileProvider.removeBasePath(this.file.toURL()); |  | ||||||
|         if (!this.relativePath) { |  | ||||||
|             // Didn't find basePath, use fullPath but if the user tries to manage the file it'll probably fail.
 |  | ||||||
|             this.relativePath = this.file.fullPath; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         this.loadFileBasicData(); |         this.loadFileBasicData(); | ||||||
| 
 | 
 | ||||||
|         // Get the size and timemodified.
 |         // Get the size and timemodified.
 | ||||||
| @ -88,6 +81,13 @@ export class CoreLocalFileComponent implements OnInit { | |||||||
|         this.fileName = this.file.name; |         this.fileName = this.file.name; | ||||||
|         this.fileIcon = this.mimeUtils.getFileIcon(this.file.name); |         this.fileIcon = this.mimeUtils.getFileIcon(this.file.name); | ||||||
|         this.fileExtension = this.mimeUtils.getFileExtension(this.file.name); |         this.fileExtension = this.mimeUtils.getFileExtension(this.file.name); | ||||||
|  | 
 | ||||||
|  |         // Let's calculate the relative path for the file.
 | ||||||
|  |         this.relativePath = this.fileProvider.removeBasePath(this.file.toURL()); | ||||||
|  |         if (!this.relativePath) { | ||||||
|  |             // Didn't find basePath, use fullPath but if the user tries to manage the file it'll probably fail.
 | ||||||
|  |             this.relativePath = this.file.fullPath; | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|  | |||||||
| @ -2,7 +2,7 @@ | |||||||
| <div *ngIf="publicKey"> | <div *ngIf="publicKey"> | ||||||
|     <!-- A button to open the recaptcha modal. --> |     <!-- A button to open the recaptcha modal. --> | ||||||
|     <!-- Use anchor instead of button to prevent marking form as submitted. --> |     <!-- Use anchor instead of button to prevent marking form as submitted. --> | ||||||
|     <button ion-button block *ngIf="!model[modelValueName]" (click)="answerRecaptcha()" type="button">{{ 'core.answer' | translate }}</button> |     <button ion-button block *ngIf="!model[modelValueName]" (click)="answerRecaptcha()" type="button">{{ 'core.resourcedisplayopen' | translate }}</button> | ||||||
|     <p *ngIf="model[modelValueName]" class="text-success">{{ 'core.answered' | translate }}</p> |     <p *ngIf="model[modelValueName]" class="text-success">{{ 'core.answered' | translate }}</p> | ||||||
|     <p *ngIf="expired" class="text-danger">{{ 'core.login.recaptchaexpired' | translate }}</p> |     <p *ngIf="expired" class="text-danger">{{ 'core.login.recaptchaexpired' | translate }}</p> | ||||||
| </div> | </div> | ||||||
|  | |||||||
| @ -49,7 +49,7 @@ export class CoreSplitViewComponent implements OnInit, OnDestroy { | |||||||
|     @ViewChild('menu') menu: Menu; |     @ViewChild('menu') menu: Menu; | ||||||
|     @Input() when?: string | boolean = 'md'; |     @Input() when?: string | boolean = 'md'; | ||||||
| 
 | 
 | ||||||
|     protected isEnabled = false; |     protected isEnabled; | ||||||
|     protected masterPageName = ''; |     protected masterPageName = ''; | ||||||
|     protected masterPageIndex = 0; |     protected masterPageIndex = 0; | ||||||
|     protected loadDetailPage: any = false; |     protected loadDetailPage: any = false; | ||||||
| @ -174,7 +174,7 @@ export class CoreSplitViewComponent implements OnInit, OnDestroy { | |||||||
|      * @return {boolean} If split view is enabled. |      * @return {boolean} If split view is enabled. | ||||||
|      */ |      */ | ||||||
|     isOn(): boolean { |     isOn(): boolean { | ||||||
|         return this.isEnabled; |         return !!this.isEnabled; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
| @ -182,16 +182,24 @@ export class CoreSplitViewComponent implements OnInit, OnDestroy { | |||||||
|      * |      * | ||||||
|      * @param {any} page   The component class or deeplink name you want to push onto the navigation stack. |      * @param {any} page   The component class or deeplink name you want to push onto the navigation stack. | ||||||
|      * @param {any} params Any NavParams you want to pass along to the next view. |      * @param {any} params Any NavParams you want to pass along to the next view. | ||||||
|  |      * @param {boolean} [retrying] Whether it's retrying. | ||||||
|      */ |      */ | ||||||
|     push(page: any, params?: any): void { |     push(page: any, params?: any, retrying?: boolean): void { | ||||||
|         if (this.isEnabled) { |         if (typeof this.isEnabled == 'undefined' && !retrying) { | ||||||
|             this.detailNav.setRoot(page, params); |             // Hasn't calculated if it's enabled yet. Wait a bit and try again.
 | ||||||
|  |             setTimeout(() => { | ||||||
|  |                 this.push(page, params, true); | ||||||
|  |             }, 200); | ||||||
|         } else { |         } else { | ||||||
|             this.loadDetailPage = { |             if (this.isEnabled) { | ||||||
|                 component: page, |                 this.detailNav.setRoot(page, params); | ||||||
|                 data: params |             } else { | ||||||
|             }; |                 this.loadDetailPage = { | ||||||
|             this.masterNav.push(page, params); |                     component: page, | ||||||
|  |                     data: params | ||||||
|  |                 }; | ||||||
|  |                 this.masterNav.push(page, params); | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -294,10 +294,6 @@ export class LocalNotificationsMock extends LocalNotifications { | |||||||
|             notification.timeoutAfter = this.parseToInt('timeoutAfter', notification); |             notification.timeoutAfter = this.parseToInt('timeoutAfter', notification); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         if (typeof notification.data == 'object') { |  | ||||||
|             notification.data = JSON.stringify(notification.data); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         this.convertPriority(notification); |         this.convertPriority(notification); | ||||||
|         this.convertTrigger(notification); |         this.convertTrigger(notification); | ||||||
|         this.convertActions(notification); |         this.convertActions(notification); | ||||||
|  | |||||||
| @ -115,7 +115,7 @@ | |||||||
| 
 | 
 | ||||||
|             <!-- ReCAPTCHA --> |             <!-- ReCAPTCHA --> | ||||||
|             <ng-container *ngIf="settings.recaptchapublickey"> |             <ng-container *ngIf="settings.recaptchapublickey"> | ||||||
|                 <ion-item-divider text-wrap>{{ 'core.login.security_question' | translate }}</ion-item-divider> |                 <ion-item-divider text-wrap><span [core-mark-required]="true">{{ 'core.login.security_question' | translate }}</span></ion-item-divider> | ||||||
|                 <ion-item text-wrap> |                 <ion-item text-wrap> | ||||||
|                     <core-recaptcha [publicKey]="settings.recaptchapublickey" [model]="captcha" [siteUrl]="siteUrl"></core-recaptcha> |                     <core-recaptcha [publicKey]="settings.recaptchapublickey" [model]="captcha" [siteUrl]="siteUrl"></core-recaptcha> | ||||||
|                 </ion-item> |                 </ion-item> | ||||||
|  | |||||||
| @ -261,25 +261,25 @@ export class CoreLoginEmailSignupPage { | |||||||
|                 (fieldsData) => { |                 (fieldsData) => { | ||||||
|                     params.customprofilefields = fieldsData; |                     params.customprofilefields = fieldsData; | ||||||
| 
 | 
 | ||||||
|                     this.wsProvider.callAjax('auth_email_signup_user', params, { siteUrl: this.siteUrl }).then((result) => { |                     return this.wsProvider.callAjax('auth_email_signup_user', params, { siteUrl: this.siteUrl }); | ||||||
|                         if (result.success) { |                 }).then((result) => { | ||||||
|                             // Show alert and ho back.
 |                     if (result.success) { | ||||||
|                             const message = this.translate.instant('core.login.emailconfirmsent', { $a: params.email }); |                         // Show alert and ho back.
 | ||||||
|                             this.domUtils.showAlert(this.translate.instant('core.success'), message); |                         const message = this.translate.instant('core.login.emailconfirmsent', { $a: params.email }); | ||||||
|                             this.navCtrl.pop(); |                         this.domUtils.showAlert(this.translate.instant('core.success'), message); | ||||||
|                         } else { |                         this.navCtrl.pop(); | ||||||
|                             if (result.warnings && result.warnings.length) { |                     } else { | ||||||
|                                 let error = result.warnings[0].message; |                         if (result.warnings && result.warnings.length) { | ||||||
|                                 if (error == 'incorrect-captcha-sol') { |                             let error = result.warnings[0].message; | ||||||
|                                     error = this.translate.instant('core.login.recaptchaincorrect'); |                             if (error == 'incorrect-captcha-sol') { | ||||||
|                                 } |                                 error = this.translate.instant('core.login.recaptchaincorrect'); | ||||||
| 
 |  | ||||||
|                                 this.domUtils.showErrorModal(error); |  | ||||||
|                             } else { |  | ||||||
|                                 this.domUtils.showErrorModal('core.login.usernotaddederror', true); |  | ||||||
|                             } |                             } | ||||||
|  | 
 | ||||||
|  |                             this.domUtils.showErrorModal(error); | ||||||
|  |                         } else { | ||||||
|  |                             this.domUtils.showErrorModal('core.login.usernotaddederror', true); | ||||||
|                         } |                         } | ||||||
|                     }); |                     } | ||||||
|                 }).catch((error) => { |                 }).catch((error) => { | ||||||
|                     this.domUtils.showErrorModalDefault(error, 'core.login.usernotaddederror', true); |                     this.domUtils.showErrorModalDefault(error, 'core.login.usernotaddederror', true); | ||||||
|                 }).finally(() => { |                 }).finally(() => { | ||||||
|  | |||||||
| @ -44,15 +44,27 @@ export class CoreSharedFilesModule { | |||||||
|         delegate.registerHandler(handler); |         delegate.registerHandler(handler); | ||||||
| 
 | 
 | ||||||
|         if (platform.is('ios')) { |         if (platform.is('ios')) { | ||||||
|  |             let lastCheck = 0; | ||||||
|  | 
 | ||||||
|             // Check if there are new files at app start and when the app is resumed.
 |             // Check if there are new files at app start and when the app is resumed.
 | ||||||
|             helper.searchIOSNewSharedFiles(); |             helper.searchIOSNewSharedFiles(); | ||||||
|             platform.resume.subscribe(() => { |             platform.resume.subscribe(() => { | ||||||
|                 helper.searchIOSNewSharedFiles(); |                 // Wait a bit to make sure that APP_LAUNCHED_URL is treated before this callback.
 | ||||||
|  |                 setTimeout(() => { | ||||||
|  |                     if (Date.now() - lastCheck < 1000) { | ||||||
|  |                         // Last check less than 1s ago, don't do anything.
 | ||||||
|  |                         return; | ||||||
|  |                     } | ||||||
|  | 
 | ||||||
|  |                     lastCheck = Date.now(); | ||||||
|  |                     helper.searchIOSNewSharedFiles(); | ||||||
|  |                 }, 200); | ||||||
|             }); |             }); | ||||||
| 
 | 
 | ||||||
|             eventsProvider.on(CoreEventsProvider.APP_LAUNCHED_URL, (url) => { |             eventsProvider.on(CoreEventsProvider.APP_LAUNCHED_URL, (url) => { | ||||||
|                 if (url && url.indexOf('file://') === 0) { |                 if (url && url.indexOf('file://') === 0) { | ||||||
|                     // We received a file in iOS, it's probably a shared file. Treat it.
 |                     // We received a file in iOS, it's probably a shared file. Treat it.
 | ||||||
|  |                     lastCheck = Date.now(); | ||||||
|                     helper.searchIOSNewSharedFiles(url); |                     helper.searchIOSNewSharedFiles(url); | ||||||
|                 } |                 } | ||||||
|             }); |             }); | ||||||
|  | |||||||
| @ -196,6 +196,7 @@ | |||||||
|     "remove": "Remove", |     "remove": "Remove", | ||||||
|     "required": "Required", |     "required": "Required", | ||||||
|     "requireduserdatamissing": "This user lacks some required profile data. Please enter the data in your site and try again.<br>{{$a}}", |     "requireduserdatamissing": "This user lacks some required profile data. Please enter the data in your site and try again.<br>{{$a}}", | ||||||
|  |     "resourcedisplayopen": "Open", | ||||||
|     "resources": "Resources", |     "resources": "Resources", | ||||||
|     "restore": "Restore", |     "restore": "Restore", | ||||||
|     "retry": "Retry", |     "retry": "Retry", | ||||||
|  | |||||||
| @ -324,7 +324,16 @@ export class CoreFileProvider { | |||||||
|             path = this.removeStartingSlash(path.replace(this.basePath, '')); |             path = this.removeStartingSlash(path.replace(this.basePath, '')); | ||||||
|             this.logger.debug('Remove file: ' + path); |             this.logger.debug('Remove file: ' + path); | ||||||
| 
 | 
 | ||||||
|             return this.file.removeFile(this.basePath, path); |             return this.file.removeFile(this.basePath, path).catch((error) => { | ||||||
|  |                 // The delete can fail if the path has encoded characters. Try again if that's the case.
 | ||||||
|  |                 const decodedPath = decodeURI(path); | ||||||
|  | 
 | ||||||
|  |                 if (decodedPath != path) { | ||||||
|  |                     return this.file.removeFile(this.basePath, decodedPath); | ||||||
|  |                 } else { | ||||||
|  |                     return Promise.reject(error); | ||||||
|  |                 } | ||||||
|  |             }); | ||||||
|         }); |         }); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user