forked from CIT/Vmeda.Online
		
	
						commit
						c1ea233092
					
				| @ -11,7 +11,7 @@ | |||||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | ||||||
| // See the License for the specific language governing permissions and
 | // See the License for the specific language governing permissions and
 | ||||||
| // limitations under the License.
 | // limitations under the License.
 | ||||||
| import { Input, OnInit, OnChanges, SimpleChange } from '@angular/core'; | import { Input, Output, OnInit, OnChanges, SimpleChange, EventEmitter } from '@angular/core'; | ||||||
| import { FormGroup, FormBuilder, Validators } from '@angular/forms'; | import { FormGroup, FormBuilder, Validators } from '@angular/forms'; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
| @ -23,11 +23,13 @@ export class AddonModDataFieldPluginComponent implements OnInit, OnChanges { | |||||||
|     @Input() value?: any; // The value of the field.
 |     @Input() value?: any; // The value of the field.
 | ||||||
|     @Input() database?: any; // Database object.
 |     @Input() database?: any; // Database object.
 | ||||||
|     @Input() error?: string; // Error when editing.
 |     @Input() error?: string; // Error when editing.
 | ||||||
|     @Input() viewAction?: string; // Action to perform.
 |     @Output() gotoEntry?: EventEmitter<number>; // Action to perform.
 | ||||||
|     @Input() form?: FormGroup; // Form where to add the form control. Just required for edit and search modes.
 |     @Input() form?: FormGroup; // Form where to add the form control. Just required for edit and search modes.
 | ||||||
|     @Input() search?: any; // The search value of all fields.
 |     @Input() search?: any; // The search value of all fields.
 | ||||||
| 
 | 
 | ||||||
|     constructor(protected fb: FormBuilder) { } |     constructor(protected fb: FormBuilder) { | ||||||
|  |         this.gotoEntry = new EventEmitter(); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|      * Add the form control for the search mode. |      * Add the form control for the search mode. | ||||||
|  | |||||||
| @ -28,7 +28,7 @@ | |||||||
| <span *ngIf="action == 'timemodified'">{{ entry.timemodified * 1000 |  coreFormatDate:"dffulldate" }}</span> | <span *ngIf="action == 'timemodified'">{{ entry.timemodified * 1000 |  coreFormatDate:"dffulldate" }}</span> | ||||||
| 
 | 
 | ||||||
| <a *ngIf="action == 'userpicture'" core-user-link [courseId]="database.courseid" [userId]="entry.userid" [title]="entry.fullname"> | <a *ngIf="action == 'userpicture'" core-user-link [courseId]="database.courseid" [userId]="entry.userid" [title]="entry.fullname"> | ||||||
|     <img class="avatar-round" [src]="userPicture" [alt]="'core.pictureof' | translate:{$a: user.fullname}" core-external-content onError="this.src='assets/img/user-avatar.png'" role="presentation"> |     <img class="avatar-round" [src]="userPicture" [alt]="'core.pictureof' | translate:{$a: entry.fullname}" core-external-content onError="this.src='assets/img/user-avatar.png'" role="presentation"> | ||||||
| </a> | </a> | ||||||
| 
 | 
 | ||||||
| <a *ngIf="action == 'user'" core-user-link [courseId]="database.courseid" [userId]="entry.userid" [title]="entry.fullname">{{entry.fullname}}</a> | <a *ngIf="action == 'user' && entry" core-user-link [courseId]="database.courseid" [userId]="entry.userid" [title]="entry.fullname">{{entry.fullname}}</a> | ||||||
|  | |||||||
| @ -11,7 +11,7 @@ | |||||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | ||||||
| // See the License for the specific language governing permissions and
 | // See the License for the specific language governing permissions and
 | ||||||
| // limitations under the License.
 | // limitations under the License.
 | ||||||
| import { Component, Input, OnInit, Injector, ViewChild, OnChanges, SimpleChange } from '@angular/core'; | import { Component, Input, Output, OnInit, Injector, ViewChild, OnChanges, SimpleChange, EventEmitter } from '@angular/core'; | ||||||
| import { FormGroup } from '@angular/forms'; | import { FormGroup } from '@angular/forms'; | ||||||
| import { AddonModDataProvider } from '../../providers/data'; | import { AddonModDataProvider } from '../../providers/data'; | ||||||
| import { AddonModDataFieldsDelegate } from '../../providers/fields-delegate'; | import { AddonModDataFieldsDelegate } from '../../providers/fields-delegate'; | ||||||
| @ -32,7 +32,7 @@ export class AddonModDataFieldPluginComponent implements OnInit, OnChanges { | |||||||
|     @Input() value?: any; // The value of the field.
 |     @Input() value?: any; // The value of the field.
 | ||||||
|     @Input() database?: any; // Database object.
 |     @Input() database?: any; // Database object.
 | ||||||
|     @Input() error?: string; // Error when editing.
 |     @Input() error?: string; // Error when editing.
 | ||||||
|     @Input() viewAction: string; // Action to perform.
 |     @Output() gotoEntry: EventEmitter<number>; // Action to perform.
 | ||||||
|     @Input() form?: FormGroup; // Form where to add the form control. Just required for edit and search modes.
 |     @Input() form?: FormGroup; // Form where to add the form control. Just required for edit and search modes.
 | ||||||
|     @Input() search?: any; // The search value of all fields.
 |     @Input() search?: any; // The search value of all fields.
 | ||||||
| 
 | 
 | ||||||
| @ -42,6 +42,7 @@ export class AddonModDataFieldPluginComponent implements OnInit, OnChanges { | |||||||
| 
 | 
 | ||||||
|     constructor(protected injector: Injector, protected dataDelegate: AddonModDataFieldsDelegate, |     constructor(protected injector: Injector, protected dataDelegate: AddonModDataFieldsDelegate, | ||||||
|             protected dataProvider: AddonModDataProvider) { |             protected dataProvider: AddonModDataProvider) { | ||||||
|  |         this.gotoEntry = new EventEmitter(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
| @ -66,7 +67,7 @@ export class AddonModDataFieldPluginComponent implements OnInit, OnChanges { | |||||||
|                     value: this.value, |                     value: this.value, | ||||||
|                     database: this.database, |                     database: this.database, | ||||||
|                     error: this.error, |                     error: this.error, | ||||||
|                     viewAction: this.viewAction, |                     gotoEntry: this.gotoEntry, | ||||||
|                     form: this.form, |                     form: this.form, | ||||||
|                     search: this.search |                     search: this.search | ||||||
|                 }; |                 }; | ||||||
|  | |||||||
| @ -329,7 +329,8 @@ export class AddonModDataIndexComponent extends CoreCourseModuleMainActivityComp | |||||||
|                     this.jsData = { |                     this.jsData = { | ||||||
|                         fields: this.fields, |                         fields: this.fields, | ||||||
|                         entries: this.entries, |                         entries: this.entries, | ||||||
|                         data: this.data |                         data: this.data, | ||||||
|  |                         gotoEntry: this.gotoEntry.bind(this) | ||||||
|                     }; |                     }; | ||||||
|                 }); |                 }); | ||||||
|             } else if (!this.search.searching) { |             } else if (!this.search.searching) { | ||||||
|  | |||||||
| @ -11,6 +11,6 @@ | |||||||
|     <ion-input type="text" [formControlName]="'f_'+field.id" [placeholder]="field.name"></ion-input> |     <ion-input type="text" [formControlName]="'f_'+field.id" [placeholder]="field.name"></ion-input> | ||||||
| </span> | </span> | ||||||
| 
 | 
 | ||||||
| <span *ngIf="mode == 'list' && imageUrl" (click)="viewAction()"><img [src]="imageUrl" [alt]="title" [title]="title" class="core-media-adapt-width list_picture" core-external-content/></span> | <span *ngIf="mode == 'list' && imageUrl" (click)="gotoEntry.emit(entryId)"><img [src]="imageUrl" [alt]="title" [title]="title" class="core-media-adapt-width list_picture" core-external-content/></span> | ||||||
| 
 | 
 | ||||||
| <img *ngIf="mode == 'show' && imageUrl" [src]="imageUrl" [alt]="title" [title]="title" class="core-media-adapt-width list_picture" [width]="width" [height]="height" core-external-content/> | <img *ngIf="mode == 'show' && imageUrl" [src]="imageUrl" [alt]="title" [title]="title" class="core-media-adapt-width list_picture" [attr.width]="width" [attr.height]="height" core-external-content/> | ||||||
|  | |||||||
| @ -13,8 +13,9 @@ | |||||||
| // limitations under the License.
 | // limitations under the License.
 | ||||||
| import { Component } from '@angular/core'; | import { Component } from '@angular/core'; | ||||||
| import { FormBuilder } from '@angular/forms'; | import { FormBuilder } from '@angular/forms'; | ||||||
| import { AddonModDataFieldPluginComponent } from '../../../classes/field-plugin-component'; |  | ||||||
| import { CoreFileSessionProvider } from '@providers/file-session'; | import { CoreFileSessionProvider } from '@providers/file-session'; | ||||||
|  | import { CoreDomUtilsProvider } from '@providers/utils/dom'; | ||||||
|  | import { AddonModDataFieldPluginComponent } from '../../../classes/field-plugin-component'; | ||||||
| import { AddonModDataProvider } from '../../../providers/data'; | import { AddonModDataProvider } from '../../../providers/data'; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
| @ -38,7 +39,8 @@ export class AddonModDataFieldPictureComponent extends AddonModDataFieldPluginCo | |||||||
|     width: string; |     width: string; | ||||||
|     height: string; |     height: string; | ||||||
| 
 | 
 | ||||||
|     constructor(protected fb: FormBuilder, private fileSessionprovider: CoreFileSessionProvider) { |     constructor(protected fb: FormBuilder, private fileSessionprovider: CoreFileSessionProvider, | ||||||
|  |             private domUtils: CoreDomUtilsProvider) { | ||||||
|         super(fb); |         super(fb); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -129,8 +131,8 @@ export class AddonModDataFieldPictureComponent extends AddonModDataFieldPluginCo | |||||||
|                     this.imageUrl = (this.image && this.image.fileurl) || null; |                     this.imageUrl = (this.image && this.image.fileurl) || null; | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             this.width  = this.field.param1 || ''; |             this.width  = this.domUtils.formatPixelsSize(this.field.param1); | ||||||
|             this.height = this.field.param2 || ''; |             this.height = this.domUtils.formatPixelsSize(this.field.param2); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -2,8 +2,8 @@ | |||||||
|     <ion-navbar> |     <ion-navbar> | ||||||
|         <ion-title><core-format-text [text]="title"></core-format-text></ion-title> |         <ion-title><core-format-text [text]="title"></core-format-text></ion-title> | ||||||
|         <ion-buttons end> |         <ion-buttons end> | ||||||
|             <button ion-button icon-only (click)="save()" [attr.aria-label]="'core.save' | translate"> |             <button ion-button clear (click)="save()" [attr.aria-label]="'core.save' | translate"> | ||||||
|                 <ion-icon name="send"></ion-icon> |                 {{ 'core.save' | translate }} | ||||||
|             </button> |             </button> | ||||||
|         </ion-buttons> |         </ion-buttons> | ||||||
|     </ion-navbar> |     </ion-navbar> | ||||||
|  | |||||||
| @ -253,12 +253,14 @@ export class AddonModDataEditPage { | |||||||
|                     }); |                     }); | ||||||
|                 } else { |                 } else { | ||||||
|                     this.errors = {}; |                     this.errors = {}; | ||||||
|  |                     if (result.fieldnotifications) { | ||||||
|                         result.fieldnotifications.forEach((fieldNotif) => { |                         result.fieldnotifications.forEach((fieldNotif) => { | ||||||
|                             const field = this.fieldsArray.find((field) => field.name == fieldNotif.fieldname); |                             const field = this.fieldsArray.find((field) => field.name == fieldNotif.fieldname); | ||||||
|                             if (field) { |                             if (field) { | ||||||
|                                 this.errors[field.id] = fieldNotif.notification; |                                 this.errors[field.id] = fieldNotif.notification; | ||||||
|                             } |                             } | ||||||
|                         }); |                         }); | ||||||
|  |                     } | ||||||
|                     this.jsData['errors'] = this.errors; |                     this.jsData['errors'] = this.errors; | ||||||
| 
 | 
 | ||||||
|                     setTimeout(() => { |                     setTimeout(() => { | ||||||
|  | |||||||
| @ -62,7 +62,7 @@ export class AddonModDataProvider { | |||||||
|                     .then((entry) => { |                     .then((entry) => { | ||||||
|                 return { |                 return { | ||||||
|                     // Return provissional entry Id.
 |                     // Return provissional entry Id.
 | ||||||
|                     newentryid: entry[1] |                     newentryid: entry | ||||||
|                 }; |                 }; | ||||||
|             }); |             }); | ||||||
|         }; |         }; | ||||||
| @ -194,8 +194,9 @@ export class AddonModDataProvider { | |||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
|         // App is offline, check required fields.
 |         // App is offline, check required fields.
 | ||||||
|         fields.forEach((field) => { |         Object.keys(fields).forEach((key) => { | ||||||
|             const notification = this.fieldsDelegate.getFieldsNotifications(field, contentsIndexed[field.id]); |             const field = fields[key], | ||||||
|  |                 notification = this.fieldsDelegate.getFieldsNotifications(field, contentsIndexed[field.id]); | ||||||
|             if (notification) { |             if (notification) { | ||||||
|                 notifications.push({ |                 notifications.push({ | ||||||
|                     fieldname: field.name, |                     fieldname: field.name, | ||||||
|  | |||||||
| @ -119,7 +119,7 @@ export class AddonModDataHelperProvider { | |||||||
| 
 | 
 | ||||||
|             // Replace field by a generic directive.
 |             // Replace field by a generic directive.
 | ||||||
|             render = '<addon-mod-data-field-plugin [field]="fields[' + field.id + ']" [value]="entries[' + entry.id + |             render = '<addon-mod-data-field-plugin [field]="fields[' + field.id + ']" [value]="entries[' + entry.id + | ||||||
|                     '].contents[' + field.id + ']" mode="' + mode + '" [database]="data" (viewAction)="gotoEntry(' + entry.id + |                     '].contents[' + field.id + ']" mode="' + mode + '" [database]="data" (gotoEntry)="gotoEntry(' + entry.id + | ||||||
|                     ')"></addon-mod-data-field-plugin>'; |                     ')"></addon-mod-data-field-plugin>'; | ||||||
|             template = template.replace(replace, render); |             template = template.replace(replace, render); | ||||||
|         }); |         }); | ||||||
|  | |||||||
| @ -46,6 +46,7 @@ import { Subscription } from 'rxjs'; | |||||||
| export class CoreRichTextEditorComponent implements AfterContentInit, OnDestroy { | export class CoreRichTextEditorComponent implements AfterContentInit, OnDestroy { | ||||||
|     // Based on: https://github.com/judgewest2000/Ionic3RichText/
 |     // Based on: https://github.com/judgewest2000/Ionic3RichText/
 | ||||||
|     // @todo: Anchor button, fullscreen...
 |     // @todo: Anchor button, fullscreen...
 | ||||||
|  |     // @todo: Textarea height is not being updated when editor is resized. Height is calculated if any css is changed.
 | ||||||
| 
 | 
 | ||||||
|     @Input() placeholder = ''; // Placeholder to set in textarea.
 |     @Input() placeholder = ''; // Placeholder to set in textarea.
 | ||||||
|     @Input() control: FormControl; // Form control.
 |     @Input() control: FormControl; // Form control.
 | ||||||
| @ -154,14 +155,21 @@ export class CoreRichTextEditorComponent implements AfterContentInit, OnDestroy | |||||||
|      */ |      */ | ||||||
|     protected maximizeEditorSize(): Promise<number> { |     protected maximizeEditorSize(): Promise<number> { | ||||||
|         this.content.resize(); |         this.content.resize(); | ||||||
|  |         const contentVisibleHeight = this.content.contentHeight; | ||||||
| 
 | 
 | ||||||
|         const deferred = this.utils.promiseDefer(); |         const deferred = this.utils.promiseDefer(); | ||||||
| 
 | 
 | ||||||
|         setTimeout(() => { |         setTimeout(() => { | ||||||
|             const contentVisibleHeight = this.content.contentHeight; |             const contentVisibleHeight = this.content.contentHeight; | ||||||
| 
 | 
 | ||||||
|  |             if (contentVisibleHeight <= 0) { | ||||||
|  |                 deferred.resolve(0); | ||||||
|  | 
 | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             setTimeout(() => { | ||||||
|                 // Editor is ready, adjust Height if needed.
 |                 // Editor is ready, adjust Height if needed.
 | ||||||
|             if (contentVisibleHeight > 0) { |  | ||||||
|                 const height = this.getSurroundingHeight(this.element); |                 const height = this.getSurroundingHeight(this.element); | ||||||
|                 if (contentVisibleHeight > height) { |                 if (contentVisibleHeight > height) { | ||||||
|                     this.element.style.height = this.domUtils.formatPixelsSize(contentVisibleHeight - height); |                     this.element.style.height = this.domUtils.formatPixelsSize(contentVisibleHeight - height); | ||||||
| @ -170,11 +178,7 @@ export class CoreRichTextEditorComponent implements AfterContentInit, OnDestroy | |||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|                 deferred.resolve(contentVisibleHeight - height); |                 deferred.resolve(contentVisibleHeight - height); | ||||||
| 
 |             }, 100); | ||||||
|                 return; |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             deferred.resolve(0); |  | ||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
|         return deferred.promise; |         return deferred.promise; | ||||||
| @ -206,6 +210,13 @@ export class CoreRichTextEditorComponent implements AfterContentInit, OnDestroy | |||||||
|         height += this.domUtils.getComputedStyleMeasure(cs, 'paddingTop') + |         height += this.domUtils.getComputedStyleMeasure(cs, 'paddingTop') + | ||||||
|             this.domUtils.getComputedStyleMeasure(cs, 'paddingBottom'); |             this.domUtils.getComputedStyleMeasure(cs, 'paddingBottom'); | ||||||
| 
 | 
 | ||||||
|  |         if (element && element.parentNode && element.parentNode.tagName == 'ION-CONTENT') { | ||||||
|  |             const cs2 = getComputedStyle(element); | ||||||
|  | 
 | ||||||
|  |             height -= this.domUtils.getComputedStyleMeasure(cs2, 'paddingTop') + | ||||||
|  |                 this.domUtils.getComputedStyleMeasure(cs2, 'paddingBottom'); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         return height; |         return height; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -487,7 +498,6 @@ export class CoreRichTextEditorComponent implements AfterContentInit, OnDestroy | |||||||
|      */ |      */ | ||||||
|     ngOnDestroy(): void { |     ngOnDestroy(): void { | ||||||
|         this.valueChangeSubscription && this.valueChangeSubscription.unsubscribe(); |         this.valueChangeSubscription && this.valueChangeSubscription.unsubscribe(); | ||||||
|         this.keyboardObs && this.keyboardObs.off(); |  | ||||||
|         window.removeEventListener('resize', this.resizeFunction); |         window.removeEventListener('resize', this.resizeFunction); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -7,4 +7,10 @@ page-core-mainmenu { | |||||||
|         @extend .fa-graduation-cap; |         @extend .fa-graduation-cap; | ||||||
|         @extend .fa; |         @extend .fa; | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     .ion-ios-fa-graduation-cap-outline { | ||||||
|  |         color: transparent; | ||||||
|  |         -webkit-text-stroke-width: 0.8px; | ||||||
|  |         -webkit-text-stroke-color: $tabs-tab-color-inactive; | ||||||
|  |     } | ||||||
| } | } | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user