From 7c29ae248b488abef4480063c78107c86c33960c Mon Sep 17 00:00:00 2001 From: Yuri Lysov Date: Sun, 3 May 2020 16:34:26 +0300 Subject: [PATCH] Task 2: - Added simple routing for compnonents - Changed the structure of components and modules in project - Added pipe for time transforming - Implemented markup + styles + logic for all project's components --- package-lock.json | 26 ++++++ package.json | 3 + src/app/core/commons/variables.less | 10 ++ src/app/core/mocks/mocked-data.ts | 58 ++++++++++-- src/app/core/models/course-item.interface.ts | 2 +- src/app/core/pipes/transform-minutes.pipe.ts | 34 +++++++ .../course-page/course-page.component.html | 1 + .../course-page/course-page.component.less | 0 .../course-page/course-page.component.spec.ts | 25 +++++ src/app/course-page/course-page.component.ts | 8 ++ src/app/course-page/course-page.module.ts | 10 ++ .../course-item/course-item.component.html | 39 ++++++++ .../course-item/course-item.component.less | 87 ++++++++++++++++++ .../course-item/course-item.component.spec.ts | 25 +++++ .../course-item/course-item.component.ts | 24 +++++ .../course-list/course-list.component.html | 29 +++--- .../course-list/course-list.component.less | 20 +++- .../course-list/course-list.component.ts | 5 +- src/app/home-page/home-page.component.html | 14 +-- src/app/home-page/home-page.component.less | 8 ++ src/app/home-page/home-page.component.ts | 10 +- src/app/home-page/home-page.module.ts | 12 ++- .../add-course/add-course.component.html | 9 +- .../add-course/add-course.component.less | 34 +++++++ .../add-course/add-course.component.ts | 6 +- .../toolbox/search/search.component.html | 11 ++- .../toolbox/search/search.component.less | 48 ++++++++++ .../toolbox/search/search.component.ts | 10 +- .../home-page/toolbox/toolbox.component.html | 5 +- .../home-page/toolbox/toolbox.component.ts | 2 +- src/app/root/app-routing.module.ts | 7 +- src/app/root/app.component.html | 15 +-- src/app/root/app.component.less | 16 +++- src/app/root/app.component.ts | 4 +- src/app/root/app.module.ts | 2 + src/app/shared/footer/footer.component.html | 4 +- src/app/shared/footer/footer.component.less | 12 +++ .../header-login/header-login.component.html | 22 ++++- .../header-login/header-login.component.less | 22 +++++ .../header-login/header-login.component.ts | 6 +- .../header-logo/header-logo.component.html | 4 +- .../header-logo/header-logo.component.less | 4 + src/app/shared/header/header.component.html | 10 +- src/app/shared/header/header.component.less | 10 +- src/app/shared/shared.module.ts | 4 +- src/assets/fonts/oswald-bold/Oswald-Bold.woff | Bin 0 -> 51904 bytes .../fonts/oswald-bold/Oswald-Bold.woff2 | Bin 0 -> 38576 bytes .../SourceSansPro-Light.woff | Bin 0 -> 122756 bytes .../SourceSansPro-Light.woff2 | Bin 0 -> 83756 bytes .../SourceSansPro-Regular.woff | Bin 0 -> 123748 bytes .../SourceSansPro-Regular.woff2 | Bin 0 -> 84716 bytes .../SourceSansPro-SemiBold.woff | Bin 0 -> 122880 bytes .../SourceSansPro-SemiBold.woff2 | Bin 0 -> 83976 bytes src/assets/img/play-logo.svg | 26 ++++++ src/assets/less/modules/_fonts.less | 31 +++++++ src/styles.less | 10 ++ 56 files changed, 709 insertions(+), 75 deletions(-) create mode 100644 src/app/core/commons/variables.less create mode 100644 src/app/core/pipes/transform-minutes.pipe.ts create mode 100644 src/app/course-page/course-page.component.html create mode 100644 src/app/course-page/course-page.component.less create mode 100644 src/app/course-page/course-page.component.spec.ts create mode 100644 src/app/course-page/course-page.component.ts create mode 100644 src/app/course-page/course-page.module.ts create mode 100644 src/app/home-page/course-list/course-item/course-item.component.html create mode 100644 src/app/home-page/course-list/course-item/course-item.component.less create mode 100644 src/app/home-page/course-list/course-item/course-item.component.spec.ts create mode 100644 src/app/home-page/course-list/course-item/course-item.component.ts create mode 100644 src/assets/fonts/oswald-bold/Oswald-Bold.woff create mode 100644 src/assets/fonts/oswald-bold/Oswald-Bold.woff2 create mode 100644 src/assets/fonts/sourse-sans-pro-light/SourceSansPro-Light.woff create mode 100644 src/assets/fonts/sourse-sans-pro-light/SourceSansPro-Light.woff2 create mode 100644 src/assets/fonts/sourse-sans-pro-regular/SourceSansPro-Regular.woff create mode 100644 src/assets/fonts/sourse-sans-pro-regular/SourceSansPro-Regular.woff2 create mode 100644 src/assets/fonts/sourse-sans-pro-semibold/SourceSansPro-SemiBold.woff create mode 100644 src/assets/fonts/sourse-sans-pro-semibold/SourceSansPro-SemiBold.woff2 create mode 100644 src/assets/img/play-logo.svg create mode 100644 src/assets/less/modules/_fonts.less diff --git a/package-lock.json b/package-lock.json index 6c79098..9439b71 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1455,6 +1455,32 @@ "to-fast-properties": "^2.0.0" } }, + "@fortawesome/angular-fontawesome": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/@fortawesome/angular-fontawesome/-/angular-fontawesome-0.6.1.tgz", + "integrity": "sha512-ARQjtRuT+ZskzJDJKPwuiGO3+7nS0iyNLU/uHVJHfG4LwGJxwVIGldwg1SU957sra0Z0OtWEajHMhiS4vB9LwQ==" + }, + "@fortawesome/fontawesome-common-types": { + "version": "0.2.28", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.2.28.tgz", + "integrity": "sha512-gtis2/5yLdfI6n0ia0jH7NJs5i/Z/8M/ZbQL6jXQhCthEOe5Cr5NcQPhgTvFxNOtURE03/ZqUcEskdn2M+QaBg==" + }, + "@fortawesome/fontawesome-svg-core": { + "version": "1.2.28", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-1.2.28.tgz", + "integrity": "sha512-4LeaNHWvrneoU0i8b5RTOJHKx7E+y7jYejplR7uSVB34+mp3Veg7cbKk7NBCLiI4TyoWS1wh9ZdoyLJR8wSAdg==", + "requires": { + "@fortawesome/fontawesome-common-types": "^0.2.28" + } + }, + "@fortawesome/free-solid-svg-icons": { + "version": "5.13.0", + "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-5.13.0.tgz", + "integrity": "sha512-IHUgDJdomv6YtG4p3zl1B5wWf9ffinHIvebqQOmV3U+3SLw4fC+LUCCgwfETkbTtjy5/Qws2VoVf6z/ETQpFpg==", + "requires": { + "@fortawesome/fontawesome-common-types": "^0.2.28" + } + }, "@istanbuljs/schema": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.2.tgz", diff --git a/package.json b/package.json index 1b40c82..9c8413a 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,9 @@ "@angular/platform-browser": "~9.1.3", "@angular/platform-browser-dynamic": "~9.1.3", "@angular/router": "~9.1.3", + "@fortawesome/angular-fontawesome": "^0.6.1", + "@fortawesome/fontawesome-svg-core": "^1.2.28", + "@fortawesome/free-solid-svg-icons": "^5.13.0", "rxjs": "~6.5.4", "tslib": "^1.10.0", "zone.js": "~0.10.2" diff --git a/src/app/core/commons/variables.less b/src/app/core/commons/variables.less new file mode 100644 index 0000000..d9bc831 --- /dev/null +++ b/src/app/core/commons/variables.less @@ -0,0 +1,10 @@ +@color-white: white; +@color-gray: #f2f3f7; +@color-gray1: #f2f3f7df; +@color-gray2: #d9dbe3; +@color-gray3: #979cac; +@color-black: #414452; +@color-green: #9bc837; +@color-green1: #8cc837; +@color-blue: #30b6dd; +@color-blue1: #64b6dd; diff --git a/src/app/core/mocks/mocked-data.ts b/src/app/core/mocks/mocked-data.ts index f831078..bfb19d2 100644 --- a/src/app/core/mocks/mocked-data.ts +++ b/src/app/core/mocks/mocked-data.ts @@ -5,21 +5,65 @@ export const fakeVideoList: CourseItemInfo[] = [ id: 1, title: 'video_1', createdAtDate: new Date, - durationTime: '120', - description: 'description of 1st video' - }, + durationTime: 120, + description: + `Lorem, ipsum dolor sit amet consectetur adipisicing elit. + Fuga at magni dignissimos accusamus asperiores enim corrupti nobis dolorem ducimus + nostrum dolor, consequuntur, quia laudantium tempore? Neque doloremque eos rerum nulla. + Fuga at magni dignissimos accusamus asperiores enim corrupti nobis dolorem ducimus + nostrum dolor, consequuntur, quia laudantium tempore? Neque doloremque eos rerum nulla. + ` + } , { id: 2, title: 'video_2', createdAtDate: new Date, - durationTime: '120', - description: 'description of 2nd video' + durationTime: 180, + description: + `Lorem, ipsum dolor sit amet consectetur adipisicing elit. + Fuga at magni dignissimos accusamus asperiores enim corrupti nobis dolorem ducimus + nostrum dolor, consequuntur, quia laudantium tempore? Neque doloremque eos rerum nulla. + Lorem, ipsum dolor sit amet consectetur adipisicing elit. + Fuga at magni dignissimos accusamus asperiores enim corrupti nobis dolorem ducimus + ` }, { id: 3, title: 'video_3', createdAtDate: new Date, - durationTime: '120', - description: 'description of 3st video' + durationTime: 180, + description: + `Lorem, ipsum dolor sit amet consectetur adipisicing elit. + Fuga at magni dignissimos accusamus asperiores enim corrupti nobis dolorem ducimus + nostrum dolor, consequuntur, quia laudantium tempore? Neque doloremque eos rerum nulla. + Lorem, ipsum dolor sit amet consectetur adipisicing elit. + Fuga at magni dignissimos accusamus asperiores enim corrupti nobis dolorem ducimus + ` + }, + { + id: 4, + title: 'video_4', + createdAtDate: new Date, + durationTime: 132, + description: + `Lorem, ipsum dolor sit amet consectetur adipisicing elit. + Fuga at magni dignissimos accusamus asperiores enim corrupti nobis dolorem ducimus + nostrum dolor, consequuntur, quia laudantium tempore? Neque doloremque eos rerum nulla. + Lorem, ipsum dolor sit amet consectetur adipisicing elit. + Fuga at magni dignissimos accusamus asperiores enim corrupti nobis dolorem ducimus + ` + }, + { + id: 5, + title: 'video_5', + createdAtDate: new Date, + durationTime: 120, + description: + `Lorem, ipsum dolor sit amet consectetur adipisicing elit. + Fuga at magni dignissimos accusamus asperiores enim corrupti nobis dolorem ducimus + nostrum dolor, consequuntur, quia laudantium tempore? Neque doloremque eos rerum nulla. + Lorem, ipsum dolor sit amet consectetur adipisicing elit. + Fuga at magni dignissimos accusamus asperiores enim corrupti nobis dolorem ducimus + ` } ]; diff --git a/src/app/core/models/course-item.interface.ts b/src/app/core/models/course-item.interface.ts index 5113956..a5361ca 100644 --- a/src/app/core/models/course-item.interface.ts +++ b/src/app/core/models/course-item.interface.ts @@ -3,6 +3,6 @@ export interface CourseItemInfo { id: number; title: string; createdAtDate: Date; - durationTime: string; + durationTime: number; description: string; } diff --git a/src/app/core/pipes/transform-minutes.pipe.ts b/src/app/core/pipes/transform-minutes.pipe.ts new file mode 100644 index 0000000..6fb81e3 --- /dev/null +++ b/src/app/core/pipes/transform-minutes.pipe.ts @@ -0,0 +1,34 @@ +import { Pipe, PipeTransform } from '@angular/core'; +/* + * Transform time in hh:mm format + * Usage: + * time | transformMinutesToHours + * Example: + * {{ 120 | transformMinutesToHours }} + * formats to: 2h + * + * {{ 16 | transformMinutesToHours }} + * formats to: 16min + * + * {{ 61 | transformMinutesToHours }} + * formats to: 1h 1min +*/ +const MINUTE_IN_SEC: number = 60; +@Pipe({name: 'transformMinutesToHours'}) + +export class TransformMinutesToHoursPipe implements PipeTransform { + public transform(time: number): string { + if (time < MINUTE_IN_SEC) { + return `${time}min`; + } + + if (time % MINUTE_IN_SEC === 0) { + return `${Math.floor(time / MINUTE_IN_SEC)}h`; + } + + const hours: number = Math.floor(time / MINUTE_IN_SEC); + const minutes: number = time % MINUTE_IN_SEC; + + return `${hours}h ${minutes}min`; + } +} diff --git a/src/app/course-page/course-page.component.html b/src/app/course-page/course-page.component.html new file mode 100644 index 0000000..b9d1c81 --- /dev/null +++ b/src/app/course-page/course-page.component.html @@ -0,0 +1 @@ +

course-page works!

diff --git a/src/app/course-page/course-page.component.less b/src/app/course-page/course-page.component.less new file mode 100644 index 0000000..e69de29 diff --git a/src/app/course-page/course-page.component.spec.ts b/src/app/course-page/course-page.component.spec.ts new file mode 100644 index 0000000..c795e29 --- /dev/null +++ b/src/app/course-page/course-page.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CoursePageComponent } from './course-page.component'; + +describe('CoursePageComponent', () => { + let component: CoursePageComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ CoursePageComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(CoursePageComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/course-page/course-page.component.ts b/src/app/course-page/course-page.component.ts new file mode 100644 index 0000000..550e833 --- /dev/null +++ b/src/app/course-page/course-page.component.ts @@ -0,0 +1,8 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'app-course-page', + templateUrl: './course-page.component.html', + styleUrls: ['./course-page.component.less'] +}) +export class CoursePageComponent { } diff --git a/src/app/course-page/course-page.module.ts b/src/app/course-page/course-page.module.ts new file mode 100644 index 0000000..abd3368 --- /dev/null +++ b/src/app/course-page/course-page.module.ts @@ -0,0 +1,10 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { CoursePageComponent } from './course-page.component'; + +@NgModule({ + declarations: [CoursePageComponent], + exports: [CoursePageComponent], + imports: [CommonModule] +}) +export class CoursePageModule { } diff --git a/src/app/home-page/course-list/course-item/course-item.component.html b/src/app/home-page/course-list/course-item/course-item.component.html new file mode 100644 index 0000000..d3b6d33 --- /dev/null +++ b/src/app/home-page/course-list/course-item/course-item.component.html @@ -0,0 +1,39 @@ +
  • +
    +
    + + + +
    +

    + + {{item.durationTime | transformMinutesToHours}} +

    +

    + + {{item.createdAtDate | date}} +

    +
    + +
    + +
    + {{item.description}} +
    +
    + +
    + + +
    +
  • \ No newline at end of file diff --git a/src/app/home-page/course-list/course-item/course-item.component.less b/src/app/home-page/course-list/course-item/course-item.component.less new file mode 100644 index 0000000..e54ca20 --- /dev/null +++ b/src/app/home-page/course-list/course-item/course-item.component.less @@ -0,0 +1,87 @@ +@import '../../../core/commons/variables'; + +.course-list-item { + display: flex; + flex-wrap: nowrap; + padding: 20px; + border: 1px solid @color-gray; + background-color: @color-white; + border-radius: 6px; + box-shadow: 5px 5px 18px @color-gray2; + margin-bottom: 20px; + + &-data { + width: 80%; + padding-right: 50px; + font-family: 'SourseSansPro Regular'; + + &-header { + align-items: center; + display: flex; + justify-content: space-between; + + &-info { + display: flex; + color: @color-gray2; + + p:first-child { + margin-right: 20px; + } + } + + &-title { + display: flex; + a { + font-size: 30px; + text-decoration: none; + text-transform: uppercase; + + &:hover { + text-decoration: underline; + } + } + } + } + + &-text { + line-height: 2; + } + } + + &-actions { + display: flex; + align-items: center; + justify-content: center; + width: 20%; + + button { + height: 25px; + width: 200px; + margin-right: 8px; + margin-left: 8px; + background-color: @color-blue; + color: @color-white; + border-radius: 3px; + border: none; + font-size: 12px; + font-family: 'SourseSansPro Semibold'; + cursor: pointer; + outline: none; + &:hover { + background-color: @color-blue1; + } + } + } + + &-loadmore { + margin-top: 15px; + display: flex; + justify-content: center; + align-items: center; + height: 50px; + border: 1px solid @color-gray; + box-shadow: 5px 5px 18px @color-gray2; + background-color: @color-white; + border-radius: 6px; + } +} \ No newline at end of file diff --git a/src/app/home-page/course-list/course-item/course-item.component.spec.ts b/src/app/home-page/course-list/course-item/course-item.component.spec.ts new file mode 100644 index 0000000..699fc04 --- /dev/null +++ b/src/app/home-page/course-list/course-item/course-item.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CourseItemComponent } from './course-item.component'; + +describe('CourseItemComponent', () => { + let component: CourseItemComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ CourseItemComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(CourseItemComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/home-page/course-list/course-item/course-item.component.ts b/src/app/home-page/course-list/course-item/course-item.component.ts new file mode 100644 index 0000000..91fed04 --- /dev/null +++ b/src/app/home-page/course-list/course-item/course-item.component.ts @@ -0,0 +1,24 @@ +import { Component, Input, Output, EventEmitter } from '@angular/core'; +import { IconDefinition, faEdit, faTrash, faClock, faCalendar } from '@fortawesome/free-solid-svg-icons'; +import { CourseItemInfo } from 'src/app/core/models'; +import { Router } from '@angular/router'; + +@Component({ + selector: 'app-course-item', + templateUrl: './course-item.component.html', + styleUrls: ['./course-item.component.less'] +}) +export class CourseItemComponent { + @Input() public item: CourseItemInfo; + @Input() public routerLink: Router; + @Output() public onDeleteCourse: EventEmitter = new EventEmitter(); + + public editButtonIcon: IconDefinition = faEdit; + public trashButtonIcon: IconDefinition = faTrash; + public clockButtonIcon: IconDefinition = faClock; + public calendarButtonIcon: IconDefinition = faCalendar; + + public onDeleteCourseEmit(id: number): void { + return this.onDeleteCourse.emit(id); + } +} diff --git a/src/app/home-page/course-list/course-list.component.html b/src/app/home-page/course-list/course-list.component.html index 500bef8..7833452 100644 --- a/src/app/home-page/course-list/course-list.component.html +++ b/src/app/home-page/course-list/course-list.component.html @@ -1,19 +1,12 @@ -

    course-list works!

    -