From f87de9b1c64a3afeec59d7ecafcce772b8ffc5d9 Mon Sep 17 00:00:00 2001 From: leofvo Date: Wed, 15 Feb 2023 16:17:21 +0100 Subject: [PATCH 1/3] build(fixture): mock server for modules and improved courses --- packages/mock-server/fixtures/course.ts | 41 +++++--- packages/mock-server/fixtures/generic.ts | 7 ++ packages/mock-server/fixtures/module.ts | 115 +++++++++++++++++++++++ packages/mock-server/fixtures/video.ts | 9 +- packages/mock-server/index.ts | 4 +- 5 files changed, 154 insertions(+), 22 deletions(-) create mode 100644 packages/mock-server/fixtures/module.ts diff --git a/packages/mock-server/fixtures/course.ts b/packages/mock-server/fixtures/course.ts index 07493b78..2049fa45 100644 --- a/packages/mock-server/fixtures/course.ts +++ b/packages/mock-server/fixtures/course.ts @@ -7,19 +7,10 @@ import { FactoryDefinition, ModelDefinition, } from "miragejs/-types"; +import { BaseModel } from "./generic"; +import { Module, readableModule } from "./module"; -export interface Watchtime { - videoId: string; - userId?: string; - watchedSeconds: number; - watchedPercent: number; - isWatched: boolean; -} - -export interface Course { - id: string; - createdAt?: string; - updatedAt?: string; +export interface Course extends BaseModel { visibility?: string; draft?: boolean; name: string; @@ -27,7 +18,9 @@ export interface Course { description: string; content: string; user?: User; - modules?: any[]; // TODO + userId?: string; + __v?: number; + modules?: Module[]; // TODO } export class CourseMock implements Mock { @@ -47,8 +40,8 @@ export class CourseMock implements Mock { }; }); - server.get("courses/:id", (schema) => { - return schema.first("course"); + server.get("courses/:id", (schema, request) => { + return readableCourse; }); } @@ -98,3 +91,21 @@ export class CourseMock implements Mock { return Model.extend({}); } } + +const readableCourse: Course = { + id: "a3497139-5174-4a62-83be-06d22bfa8486", + createdAt: "2022-06-09T13:11:05.062Z", + updatedAt: "2022-06-09T13:11:05.062Z", + description: + "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras finibus mauris vitae risus vestibulum fermentum. Aliquam erat volutpat. Etiam aliquam congue nulla, ac efficitur elit iaculis id. Proin aliquet magna non nulla lacinia sagittis. Donec sed mi bibendum, convallis elit sed, accumsan erat. Vivamus a dolor sit amet eros ultricies ullamcorper. Sed nec sem ac nunc egestas malesuada nec id diam. Nunc aliquam, sem et interdum rhoncus, lacus est imperdiet velit, vitae mollis nunc elit sed nibh. Cras mollis semper justo, vel fermentum diam. Praesent eget nisl et lorem suscipit tristique. Vestibulum bibendum odio a sapien scelerisque tincidunt. Fusce consequat interdum mauris, eu placerat massa laoreet nec. Vivamus id orci porttitor, ultrices arcu quis, vestibulum erat. Cras condimentum nibh et ante facilisis, a laoreet nulla porta. Donec blandit nibh sagittis ligula tempor, id pharetra justo placerat. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Cras sed nisl vitae elit suscipit maximus. Cras semper, risus nec vestibulum finibus, lorem felis fermentum quam, ac tincidunt nisi dolor id nisl. Praesent nunc sem, ultricies nec bibendum sit amet, viverra vel lectus.", + draft: false, + visibility: "public", + modules: [readableModule, readableModule, readableModule], + name: "PolyCloud", + slug: "polycloud-dlv9vg", + user: BaseUsers[1], + userId: BaseUsers[1].id, + content: + "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras finibus mauris vitae risus vestibulum fermentum. Aliquam erat volutpat. Etiam aliquam congue nulla, ac efficitur elit iaculis id. Proin aliquet magna non nulla lacinia sagittis. Donec sed mi bibendum, convallis elit sed, accumsan erat. Vivamus a dolor sit amet eros ultricies ullamcorper. Sed nec sem ac nunc egestas malesuada nec id diam. Nunc aliquam, sem et interdum rhoncus, lacus est imperdiet velit, vitae mollis nunc elit sed nibh. Cras mollis semper justo, vel fermentum diam. \nPraesent eget nisl et lorem suscipit tristique. Vestibulum bibendum odio a sapien scelerisque tincidunt. Fusce consequat interdum mauris, eu placerat massa laoreet nec. Vivamus id orci porttitor, ultrices arcu quis, vestibulum erat. Cras condimentum nibh et ante facilisis, a laoreet nulla porta. Donec blandit nibh sagittis ligula tempor, id pharetra justo placerat. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Cras sed nisl vitae elit suscipit maximus. Cras semper, risus nec vestibulum finibus, lorem felis fermentum quam, ac tincidunt nisi dolor id nisl. Praesent nunc sem, ultricies nec bibendum sit amet, viverra vel lectus. \nSed fermentum tempus sollicitudin. Nulla at augue efficitur, dapibus quam nec, consectetur nunc. Sed aliquet dictum efficitur. Morbi ut auctor sem. Phasellus rutrum, massa nec viverra luctus, eros purus pharetra sem, nec vulputate mi tellus sed sem. Vestibulum vitae mollis nunc. Nam gravida fermentum nisl, at porttitor eros sollicitudin id. Proin quis finibus dui. Maecenas ultricies diam tempus nibh egestas, sit amet euismod dui commodo. Fusce vitae nibh ultricies, vulputate urna et, vestibulum arcu. Cras dictum blandit eleifend. Etiam magna metus, scelerisque et tempus non, feugiat ut est. Donec molestie magna at diam dictum interdum. Morbi accumsan semper lacus at consequat.\n Donec nulla magna, rhoncus nec auctor a, feugiat a mi. Sed a mauris nec justo sodales suscipit. Nam semper non sapien eget iaculis. Aenean suscipit posuere tincidunt. Sed tristique mauris urna, ut vulputate metus iaculis et. Maecenas fermentum leo at est euismod vulputate. Nulla sapien felis, finibus eu purus nec, cursus vulputate ipsum. Nullam vulputate leo enim, a semper dolor ullamcorper tempus. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Pellentesque ut massa commodo, euismod nulla malesuada, posuere felis.\n Donec tempor tincidunt ex et facilisis. Donec massa magna, eleifend sed cursus ac, efficitur vitae arcu. Nulla et nunc euismod, ultricies velit vel, varius urna. Maecenas sit amet nisi sagittis, cursus risus non, tincidunt nulla. Sed fringilla, tortor vitae ornare pharetra, ante nulla vestibulum massa, nec fermentum libero nunc eget dolor. Proin tincidunt dui nisi, congue fringilla lectus lacinia et. Donec sodales mattis ante, quis lobortis nisi fringilla ac. Curabitur sed convallis sapien, pulvinar convallis libero.", + __v: 1, +}; diff --git a/packages/mock-server/fixtures/generic.ts b/packages/mock-server/fixtures/generic.ts index 5031f4cc..16e5d80f 100644 --- a/packages/mock-server/fixtures/generic.ts +++ b/packages/mock-server/fixtures/generic.ts @@ -1,6 +1,13 @@ import { Server } from "miragejs"; import { FactoryDefinition, ModelDefinition } from "miragejs/-types"; +export interface BaseModel { + id: string; + createdAt?: string; + updatedAt?: string; + __v?: number; +} + export interface Mock { name(): string; /** diff --git a/packages/mock-server/fixtures/module.ts b/packages/mock-server/fixtures/module.ts new file mode 100644 index 00000000..28fb4e72 --- /dev/null +++ b/packages/mock-server/fixtures/module.ts @@ -0,0 +1,115 @@ +import { Mock } from "./generic"; +import { BaseUsers, User } from "./user"; +import { faker } from "@faker-js/faker"; +import { Factory, Model, Server } from "miragejs"; +import { + AnyRegistry, + FactoryDefinition, + ModelDefinition, +} from "miragejs/-types"; +import { BaseModel } from "./generic"; +import { readableVideo, Video } from "./video"; + +export interface Module extends BaseModel { + description: string; + name: string; + slug: string; + elements?: Element[]; + passwords?: string[]; + user?: User; + userId?: string; + visibility?: string; + draft?: boolean; +} + +export interface Element extends Video { + type: string; + order: number; + name: string; +} + +export class ModuleMock implements Mock { + name(): string { + return "course"; + } + + routes(server: Server): void { + server.timing = 1000; + + server.get("modules", (schema, request) => { + const { pageSize } = request.queryParams; + const { models } = (schema as any).courses.all(); + return { + data: models.slice(0, pageSize ?? 100), + total: models.length, + }; + }); + + server.get("modules/:slug", (schema, request) => { + return readableModule; + }); + } + + factory(): FactoryDefinition<{}> { + return Factory.extend({ + id() { + return faker.datatype.uuid(); + }, + slug() { + return faker.datatype.uuid(); + }, + name() { + return faker.name.jobTitle(); + }, + description() { + return faker.lorem.lines(5); + }, + user() { + return BaseUsers[0]; + }, + visibility() { + return Math.random() > 0.2 ? "public" : "private"; + }, + draft() { + return Math.random() < 0.4; + }, + createdAt() { + return faker.date.past(2); + }, + updatedAt() { + return faker.date.recent(1); + }, + }); + } + + seeds(server: Server): void { + server.createList(this.name(), 20); + } + + model(): ModelDefinition { + return Model.extend({}); + } +} + +export const readableModule: Module = { + createdAt: "2022-06-12T20:53:51.581Z", + description: "TODO", + draft: false, + elements: [ + { order: 0, type: "video", name: readableVideo.title, ...readableVideo }, + { order: 0, type: "quizz", name: readableVideo.title, ...readableVideo }, + { order: 0, type: "quizz", name: readableVideo.title, ...readableVideo }, + { order: 0, type: "video", name: readableVideo.title, ...readableVideo }, + { order: 0, type: "video", name: readableVideo.title, ...readableVideo }, + { order: 0, type: "video", name: readableVideo.title, ...readableVideo }, + ], + id: "644bcb05-5978-4fc9-93bf-6dfc2c0c9e77", + name: "Polycloud - Amphithéâtre Peytavin", + passwords: [], + slug: "polycloud-amphitheatre-peytavin--z5ubit", + updatedAt: "2022-06-12T20:53:51.581Z", + user: BaseUsers[0], + userId: BaseUsers[0].id, + visibility: "public", + __v: 1, +}; diff --git a/packages/mock-server/fixtures/video.ts b/packages/mock-server/fixtures/video.ts index 38f54127..02a3dd15 100644 --- a/packages/mock-server/fixtures/video.ts +++ b/packages/mock-server/fixtures/video.ts @@ -1,4 +1,4 @@ -import { Mock } from "./generic"; +import { BaseModel, Mock } from "./generic"; import { BaseUsers, User } from "./user"; import { faker } from "@faker-js/faker"; import { Factory, Model, Server } from "miragejs"; @@ -16,8 +16,7 @@ export interface Watchtime { isWatched: boolean; } -export interface Video { - id: string; +export interface Video extends BaseModel { slug: string; title: string; description: string; @@ -29,8 +28,6 @@ export interface Video { source: string; visibility?: string; draft?: boolean; - createdAt?: string; - updatedAt?: string; isLiked?: boolean; watchtime?: Watchtime | undefined; } @@ -124,7 +121,7 @@ export class VideoMock implements Mock { } } -const readableVideo: Video = { +export const readableVideo: Video = { id: "50d4ec43-4e66-48ff-9149-d6678243815c", slug: "angular-in-100-seconds", title: "Angular in 100 seconds", diff --git a/packages/mock-server/index.ts b/packages/mock-server/index.ts index c3fc38e3..2aaa1a76 100644 --- a/packages/mock-server/index.ts +++ b/packages/mock-server/index.ts @@ -2,6 +2,7 @@ import { createServer } from "miragejs"; import { FactoryDefinition, ModelDefinition } from "miragejs/-types"; import { CourseMock } from "./fixtures/course"; import { Mock } from "./fixtures/generic"; +import { ModuleMock } from "./fixtures/module"; import { SearchMock } from "./fixtures/search"; import { UserMock } from "./fixtures/user"; import { VideoMock } from "./fixtures/video"; @@ -13,6 +14,7 @@ const mocks: Mock[] = [ new VideoMock(), new SearchMock(), new CourseMock(), + new ModuleMock(), ]; function initModels(): { [key: string]: ModelDefinition } { @@ -40,7 +42,7 @@ export function initMockServer() { mocks.forEach((mock) => mock.seeds(server)); }, routes() { - this.urlPrefix = 'http://localhost:4000'; + this.urlPrefix = "http://localhost:4000"; mocks.forEach((mock) => mock.routes(this)); }, }); From a8b69222b3a93257205d1ad7d681663687d770c5 Mon Sep 17 00:00:00 2001 From: leofvo Date: Wed, 15 Feb 2023 16:34:35 +0100 Subject: [PATCH 2/3] chore: improve course ui --- apps/polyflix/public/locales/en/courses.json | 1 + apps/polyflix/public/locales/fr/courses.json | 1 + .../ItemCollectionTimeline.component.tsx | 10 ++++++++-- .../polyflix/src/modules/courses/pages/[slug].page.tsx | 4 +++- 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/apps/polyflix/public/locales/en/courses.json b/apps/polyflix/public/locales/en/courses.json index 167fa607..a8861049 100644 --- a/apps/polyflix/public/locales/en/courses.json +++ b/apps/polyflix/public/locales/en/courses.json @@ -8,6 +8,7 @@ } }, "collections": "Modules", + "collectionNumber": "Module {{number}}", "introduction": "Getting started", "courseCard": { "footerElements": "{{count}} module(s) in this course", diff --git a/apps/polyflix/public/locales/fr/courses.json b/apps/polyflix/public/locales/fr/courses.json index 549f1723..4bdb3744 100644 --- a/apps/polyflix/public/locales/fr/courses.json +++ b/apps/polyflix/public/locales/fr/courses.json @@ -8,6 +8,7 @@ } }, "collections": "Modules", + "collectionNumber": "Module {{number}}", "introduction": "Présentation", "courseCard": { "footerElements": "{{count}} module(s) dans ce cours", diff --git a/apps/polyflix/src/modules/collections/components/CollectionTimeline/ItemCollectionTimeline.component.tsx b/apps/polyflix/src/modules/collections/components/CollectionTimeline/ItemCollectionTimeline.component.tsx index a4206d4f..242dc16d 100644 --- a/apps/polyflix/src/modules/collections/components/CollectionTimeline/ItemCollectionTimeline.component.tsx +++ b/apps/polyflix/src/modules/collections/components/CollectionTimeline/ItemCollectionTimeline.component.tsx @@ -102,6 +102,7 @@ export const ItemCollectionTimeline = ({ @@ -116,8 +117,12 @@ export const ItemCollectionTimeline = ({ variant="body1" sx={{ textDecoration: isHover ? 'underline' : 'none', - color: 'black', }} + color={(theme) => + +query.get('index')! === index + ? theme.palette.primary.main + : theme.palette.grey[500] + } > {element.name} @@ -125,8 +130,9 @@ export const ItemCollectionTimeline = ({ variant="caption" sx={{ textTransform: 'capitalize', - color: 'black', + opacity: 0.7, }} + color={(theme) => theme.palette.grey[500]} > {element.type} diff --git a/apps/polyflix/src/modules/courses/pages/[slug].page.tsx b/apps/polyflix/src/modules/courses/pages/[slug].page.tsx index c3957a77..f3a407c5 100644 --- a/apps/polyflix/src/modules/courses/pages/[slug].page.tsx +++ b/apps/polyflix/src/modules/courses/pages/[slug].page.tsx @@ -217,7 +217,7 @@ export const CourseSlugPage = () => { <> {t('collections')} - {course?.modules?.map((module) => ( + {course?.modules?.map((module, index) => ( <> {module.visibility === 'private' && user?.id != module.user?.id && @@ -230,6 +230,7 @@ export const CourseSlugPage = () => { width: 'auto', }} > + {t('collectionNumber', { number: index + 1 })} -{' '} {module.name} @@ -251,6 +252,7 @@ export const CourseSlugPage = () => { width: 'auto', }} > + {t('collectionNumber', { number: index + 1 })} -{' '} {module.name} From c10a8bc7465324e3fc0ebb958d390b9ba53548cf Mon Sep 17 00:00:00 2001 From: leofvo Date: Wed, 15 Feb 2023 16:47:54 +0100 Subject: [PATCH 3/3] style(navbar): fix background color --- .../core/components/Dashboard/Navbar/Navbar.component.tsx | 3 --- 1 file changed, 3 deletions(-) diff --git a/apps/polyflix/src/modules/core/components/Dashboard/Navbar/Navbar.component.tsx b/apps/polyflix/src/modules/core/components/Dashboard/Navbar/Navbar.component.tsx index 5f5d6760..7219734c 100644 --- a/apps/polyflix/src/modules/core/components/Dashboard/Navbar/Navbar.component.tsx +++ b/apps/polyflix/src/modules/core/components/Dashboard/Navbar/Navbar.component.tsx @@ -54,11 +54,8 @@ export const DashboardNavbar: React.FC> = () => { return } if (window.scrollY > 0) { - toolBarRef.current.style.backgroundColor = - theme.palette.background.default toolBarContainerRef.current.style.border = 'none' } else { - toolBarRef.current.style.backgroundColor = 'transparent' toolBarContainerRef.current.style.borderBottom = `1px solid ${theme.palette.grey[400]}` } }