diff --git a/src/components/components.module.ts b/src/components/components.module.ts index 33b38d327..30ee33409 100644 --- a/src/components/components.module.ts +++ b/src/components/components.module.ts @@ -21,6 +21,7 @@ import { CoreMarkRequiredComponent } from './mark-required/mark-required'; import { CoreInputErrorsComponent } from './input-errors/input-errors'; import { CoreShowPasswordComponent } from './show-password/show-password'; import { CoreIframeComponent } from './iframe/iframe'; +import { CoreProgressBarComponent } from './progress-bar/progress-bar'; @NgModule({ declarations: [ @@ -28,7 +29,8 @@ import { CoreIframeComponent } from './iframe/iframe'; CoreMarkRequiredComponent, CoreInputErrorsComponent, CoreShowPasswordComponent, - CoreIframeComponent + CoreIframeComponent, + CoreProgressBarComponent ], imports: [ IonicModule, @@ -40,7 +42,8 @@ import { CoreIframeComponent } from './iframe/iframe'; CoreMarkRequiredComponent, CoreInputErrorsComponent, CoreShowPasswordComponent, - CoreIframeComponent + CoreIframeComponent, + CoreProgressBarComponent ] }) export class CoreComponentsModule {} diff --git a/src/components/progress-bar/progress-bar.html b/src/components/progress-bar/progress-bar.html new file mode 100644 index 000000000..3cc2055b0 --- /dev/null +++ b/src/components/progress-bar/progress-bar.html @@ -0,0 +1,8 @@ +
+ +
+ +
+
+ {{ 'core.percentagenumber' | translate: {$a: text} }} +
diff --git a/src/components/progress-bar/progress-bar.scss b/src/components/progress-bar/progress-bar.scss new file mode 100644 index 000000000..a1d8ec63d --- /dev/null +++ b/src/components/progress-bar/progress-bar.scss @@ -0,0 +1,53 @@ +$mm-progress-bar-height: 5px !default; + +core-progress-bar { + padding-right: 55px; + position: relative; + display: block; + // @extend .clearfix; + + .mm-progress-text { + margin-left: 10px; + line-height: 35px; + color: $gray-darker; + right: 0; + top: 0; + color: #626262; + position: absolute; + } + + progress { + -webkit-appearance: none; + appearance: none; + height: $mm-progress-bar-height; + margin: 15px 0; + padding: 0; + display: block; + width: 100%; + + .progress-bar-fallback, + &[value]::-webkit-progress-bar { + background-color: $gray-light; + border-radius: 2px; + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1) inset; + } + + .progress-bar-fallback span, + &[value]::-webkit-progress-value { + background-color: $mm-color-light; + border-radius: 2px; + } + + .progress-bar-fallback { + width: 100%; + height: $mm-progress-bar-height; + display: block; + position: relative; + + span { + height: $mm-progress-bar-height; + display: block; + } + } + } +} diff --git a/src/components/progress-bar/progress-bar.ts b/src/components/progress-bar/progress-bar.ts new file mode 100644 index 000000000..a77e70291 --- /dev/null +++ b/src/components/progress-bar/progress-bar.ts @@ -0,0 +1,60 @@ +// (C) Copyright 2015 Martin Dougiamas +// +// 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, Input, OnChanges, SimpleChange, ChangeDetectionStrategy } from '@angular/core'; +import { DomSanitizer, SafeStyle } from '@angular/platform-browser'; + +/** + * Component to show a progress bar and its value. + * + * Example usage: + * + */ +@Component({ + selector: 'core-progress-bar', + templateUrl: 'progress-bar.html', + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class CoreProgressBarComponent implements OnChanges { + @Input() progress: number|string; // Percentage from 0 to 100. + @Input() text?: string; // Percentage in text to be shown at the right. If not defined, progress will be used. + width: SafeStyle; + protected textSupplied = false; + + constructor(private sanitizer: DomSanitizer) {} + + /** + * Detect changes on input properties. + */ + ngOnChanges(changes: {[name: string]: SimpleChange}) { + if (changes.text && typeof changes.text.currentValue != 'undefined') { + // User provided a custom text, don't use default. + this.textSupplied = true; + } + + if (changes.progress) { + // Progress has changed. + this.width = this.sanitizer.bypassSecurityTrustStyle(this.progress + '%'); + if (typeof this.progress == 'string') { + this.progress = parseInt(this.progress, 10); + } + + if (this.progress < 0 || isNaN(this.progress)) { + this.progress = -1; + } else if (!this.textSupplied) { + this.text = String(this.progress); + } + } + } +} diff --git a/src/core/courses/components/course-progress/course-progress.html b/src/core/courses/components/course-progress/course-progress.html new file mode 100644 index 000000000..34c96b8d0 --- /dev/null +++ b/src/core/courses/components/course-progress/course-progress.html @@ -0,0 +1,35 @@ + + +
+
+
{{course.progress}}%
+
+ + + {{course.progress}}% + + + +
+
+
+ +
+
+

+ + + + + +
+ +

+

+ + +

+
+ +
diff --git a/src/core/courses/components/course-progress/course-progress.scss b/src/core/courses/components/course-progress/course-progress.scss new file mode 100644 index 000000000..e24e0ae82 --- /dev/null +++ b/src/core/courses/components/course-progress/course-progress.scss @@ -0,0 +1,2 @@ +core-courses-course-progress { +} diff --git a/src/core/courses/components/course-progress/course-progress.ts b/src/core/courses/components/course-progress/course-progress.ts new file mode 100644 index 000000000..54b5771eb --- /dev/null +++ b/src/core/courses/components/course-progress/course-progress.ts @@ -0,0 +1,72 @@ +// (C) Copyright 2015 Martin Dougiamas +// +// 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, Input, OnInit } from '@angular/core'; +import { NavController } from 'ionic-angular'; +import { TranslateService } from '@ngx-translate/core'; +import { CoreUtilsProvider } from '../../../../providers/utils/utils'; + +/** + * This component is meant to display a course for a list of courses with progress. + * + * Example usage: + * + * + * + */ +@Component({ + selector: 'core-courses-course-progress', + templateUrl: 'course-progress.html' +}) +export class CoreCoursesCourseProgressComponent implements OnInit { + @Input() course: any; // The course to render. + @Input() roundProgress?: boolean|string; // Whether to show the progress. + @Input() showSummary?: boolean|string; // Whether to show the summary. + + actionsLoaded = true; + prefetchCourseIcon: string; + + protected obsStatus; + protected downloadText; + protected downloadingText; + protected downloadButton = { + isDownload: true, + className: 'mm-download-course', + priority: 1000 + }; + protected buttons; + + constructor(private navCtrl: NavController, private translate: TranslateService, private utils: CoreUtilsProvider) { + this.downloadText = this.translate.instant('core.course.downloadcourse'); + this.downloadingText = this.translate.instant('core.downloading'); + } + + /** + * Component being initialized. + */ + ngOnInit() { + // @todo: Handle course prefetch. + // @todo: Handle course handlers (participants, etc.). + this.roundProgress = this.utils.isTrueOrOne(this.roundProgress); + this.showSummary = this.utils.isTrueOrOne(this.showSummary); + } + + /** + * Open a course. + */ + openCourse(course) { + this.navCtrl.push('CoreCourseSectionPage', {course: course}); + } + +} diff --git a/src/core/courses/courses.module.ts b/src/core/courses/courses.module.ts index 96e18c1ec..19beec0fe 100644 --- a/src/core/courses/courses.module.ts +++ b/src/core/courses/courses.module.ts @@ -14,14 +14,19 @@ import { NgModule } from '@angular/core'; import { CoreCoursesProvider } from './providers/courses'; +import { CoreCoursesCourseProgressComponent } from './components/course-progress/course-progress'; @NgModule({ declarations: [ + CoreCoursesCourseProgressComponent ], imports: [ ], providers: [ CoreCoursesProvider + ], + exports: [ + CoreCoursesCourseProgressComponent ] }) export class CoreCoursesModule {} diff --git a/src/directives/format-text.ts b/src/directives/format-text.ts index bf034f643..64b3485b0 100644 --- a/src/directives/format-text.ts +++ b/src/directives/format-text.ts @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { Directive, ElementRef, Input, OnInit, Output, EventEmitter } from '@angular/core'; +import { Directive, ElementRef, Input, Output, EventEmitter, OnChanges, SimpleChange } from '@angular/core'; import { Platform } from 'ionic-angular'; import { TranslateService } from '@ngx-translate/core'; import { CoreAppProvider } from '../providers/app'; @@ -38,7 +38,7 @@ import { CoreExternalContentDirective } from '../directives/external-content'; @Directive({ selector: 'core-format-text' }) -export class CoreFormatTextDirective implements OnInit { +export class CoreFormatTextDirective implements OnChanges { @Input() text: string; // The text to format. @Input() siteId?: string; // Site ID to use. @Input() component?: string; // Component for CoreExternalContentDirective. @@ -68,10 +68,12 @@ export class CoreFormatTextDirective implements OnInit { } /** - * Function executed when the directive is initialized. + * Detect changes on input properties. */ - ngOnInit() : void { - this.formatAndRenderContents(); + ngOnChanges(changes: {[name: string]: SimpleChange}) { + if (changes.text) { + this.formatAndRenderContents(); + } } /**