Spaces:
Runtime error
Runtime error
| import { NOTEBOOKS_METADATA_FILE_NAME, NOTEBOOKS_STATUS_FILE_NAME } from './constants'; | |
| import { INotebookMetadata } from './notebook-metadata'; | |
| import { INotebookStatus } from './notebook-status'; | |
| export const SORT_OPTIONS = { | |
| RECENTLY_ADDED: 'Recently Added', | |
| RECENTLY_UPDATED: 'Recently Updated', | |
| NAME_ASCENDING: 'Name (A-Z)', | |
| NAME_DESCENDING: 'Name (Z-A)', | |
| } as const; | |
| export type SortValues = (typeof SORT_OPTIONS)[keyof typeof SORT_OPTIONS]; | |
| interface INotebooksFilters { | |
| tags: INotebookMetadata['tags']; | |
| searchValue: string; | |
| sort: SortValues; | |
| offset: number; | |
| limit: number; | |
| } | |
| type NotebooksMap = Record<string, INotebookMetadata & { status?: INotebookStatus['status'] }>; | |
| export type NotebookItem = NotebooksMap[string]; | |
| class NotebooksService { | |
| private _notebooksMap: NotebooksMap | null = null; | |
| private async _getNotebooksMap(): Promise<NotebooksMap> { | |
| if (!this._notebooksMap) { | |
| const { BASE_URL } = import.meta.env; | |
| const notebooksMetadataMap = (await fetch(`${BASE_URL}${NOTEBOOKS_METADATA_FILE_NAME}`).then((response) => | |
| response.json() | |
| )) as Record<string, INotebookMetadata>; | |
| const notebooksStatusMap = (await fetch(`${BASE_URL}${NOTEBOOKS_STATUS_FILE_NAME}`).then((response) => | |
| response.ok ? response.json() : {} | |
| )) as Record<string, INotebookStatus>; | |
| this._notebooksMap = this._getNotebooksMapWithStatuses(notebooksMetadataMap, notebooksStatusMap); | |
| } | |
| return this._notebooksMap; | |
| } | |
| async getNotebooks({ | |
| tags, | |
| searchValue, | |
| sort, | |
| offset, | |
| limit, | |
| }: INotebooksFilters): Promise<[INotebookMetadata[], number, number]> { | |
| const notebooks = Object.values(await this._getNotebooksMap()); | |
| const filteredNotebooks = notebooks | |
| .filter((notebook) => { | |
| const flatNotebookTags = Object.values(notebook.tags).flat(); | |
| const flatSelectedTags = Object.values(tags).flat(); | |
| return flatSelectedTags.every((tag) => flatNotebookTags.includes(tag)); | |
| }) | |
| .filter(({ title }) => title.toLowerCase().includes(searchValue.toLowerCase())); | |
| const sortedPaginatedNotebooks = filteredNotebooks.sort(this._getCompareFn(sort)).slice(offset, offset + limit); | |
| return [sortedPaginatedNotebooks, filteredNotebooks.length, notebooks.length]; | |
| } | |
| async getOtherTags(): Promise<string[]> { | |
| const notebooks = Object.values(await this._getNotebooksMap()); | |
| return notebooks | |
| .reduce((acc, { tags }) => { | |
| for (const tag of tags.other) { | |
| if (!acc.includes(tag)) { | |
| acc.push(tag); | |
| } | |
| } | |
| return acc; | |
| }, [] as string[]) | |
| .sort((a, b) => a.toUpperCase().localeCompare(b.toUpperCase())); | |
| } | |
| private _getCompareFn(sort: SortValues): Parameters<Array<INotebookMetadata>['sort']>[0] { | |
| if (sort === SORT_OPTIONS.RECENTLY_ADDED) { | |
| return (a: INotebookMetadata, b: INotebookMetadata) => | |
| new Date(b.createdDate).getTime() - new Date(a.createdDate).getTime(); | |
| } | |
| if (sort === SORT_OPTIONS.RECENTLY_UPDATED) { | |
| return (a: INotebookMetadata, b: INotebookMetadata) => | |
| new Date(b.modifiedDate).getTime() - new Date(a.modifiedDate).getTime(); | |
| } | |
| if (sort === SORT_OPTIONS.NAME_ASCENDING) { | |
| return (a: INotebookMetadata, b: INotebookMetadata) => a.title.toUpperCase().localeCompare(b.title.toUpperCase()); | |
| } | |
| if (sort === SORT_OPTIONS.NAME_DESCENDING) { | |
| return (a: INotebookMetadata, b: INotebookMetadata) => b.title.toUpperCase().localeCompare(a.title.toUpperCase()); | |
| } | |
| } | |
| private _getNotebooksMapWithStatuses( | |
| metadataMap: Record<string, INotebookMetadata>, | |
| statusMap: Record<string, INotebookStatus> | |
| ): NotebooksMap { | |
| const result = { ...metadataMap } as NotebooksMap; | |
| for (const [notebookPath, { status }] of Object.entries(statusMap)) { | |
| if (!result[notebookPath]) { | |
| console.warn(`Unknown notebook "${notebookPath}" found in status report.`); | |
| continue; | |
| } | |
| if (result[notebookPath].status) { | |
| console.warn(`Status of the notebook "${notebookPath}" already exists and will be overrided.`); | |
| } | |
| result[notebookPath].status = status; | |
| } | |
| return result; | |
| } | |
| } | |
| export const notebooksService = new NotebooksService(); | |