Skip to content

Commit

Permalink
Merge pull request openvinotoolkit#1699 from yatarkan/yt/notebooks-li…
Browse files Browse the repository at this point in the history
…braries-tags

Enable ecosystem (libraries) tags in notebooks GitHub Pages app
  • Loading branch information
andrei-kochin authored Feb 13, 2024
2 parents 4d251af + 3cb5d3e commit 8128bdf
Show file tree
Hide file tree
Showing 8 changed files with 251 additions and 213 deletions.
79 changes: 60 additions & 19 deletions selector/src/components/FiltersPanel/FiltersPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { FilterSection } from '@/components/shared/FilterSection/FilterSection';
import { Search } from '@/components/shared/Search/Search';
import { ITabItem, Tabs } from '@/components/shared/Tabs/Tabs';
import { INotebookMetadata } from '@/shared/notebook-metadata';
import { CATEGORIES, TASKS, TASKS_VALUES } from '@/shared/notebook-tags';
import { CATEGORIES, LIBRARIES, LIBRARIES_VALUES, TASKS, TASKS_VALUES } from '@/shared/notebook-tags';
import { NotebooksContext } from '@/shared/notebooks-context';

interface IFilterGroup<T extends string = string> {
Expand All @@ -24,15 +24,55 @@ const filterGroups: IFilterGroup<FilterGroupKey>[] = [
tags: Object.values(CATEGORIES),
},
{ title: 'AI Tasks', group: 'tasks', tags: TASKS_VALUES },
{ title: 'Ecosystem', group: 'libraries', tags: LIBRARIES_VALUES },
];

const taskSectionTitlesMap: Record<keyof typeof TASKS, string> = {
const tasksSectionsTitlesMap: Record<keyof typeof TASKS, string> = {
MULTIMODAL: 'Multimodal',
CV: 'Computer Vision',
NLP: 'Natural Language Processing',
AUDIO: 'Audio',
};

const librariesSectionsTitlesMap: Record<keyof typeof LIBRARIES, string> = {
OPENVINO: 'OpenVINO',
OTHER: 'Other Tools',
};

function getTagsFilterSections<T extends Record<string, Record<string, string>>>({
group,
tagsMap,
titlesMap,
selectedTags,
filterTags,
handleTagClick,
}: {
group: keyof INotebookMetadata['tags'];
tagsMap: T;
titlesMap: Record<keyof T, string>;
selectedTags: INotebookMetadata['tags'];
filterTags: (tags: string[]) => string[];
handleTagClick: (tag: string, group: FilterGroupKey) => void;
}): JSX.Element[] {
return Object.entries(tagsMap).map(([sectionKey, tagsMap]) => {
const title = titlesMap[sectionKey];
const filteredTags = filterTags(Object.values(tagsMap));
if (!filteredTags.length) {
return <></>;
}
return (
<FilterSection<typeof group>
key={`${group}-${sectionKey}`}
title={title}
group={group}
tags={filteredTags}
selectedTags={selectedTags[group]}
onTagClick={(tag, group) => handleTagClick(tag, group!)}
></FilterSection>
);
});
}

export const FiltersPanel = (): JSX.Element => {
const { selectedTags, setSelectedTags } = useContext(NotebooksContext);

Expand All @@ -56,23 +96,22 @@ export const FiltersPanel = (): JSX.Element => {
}
};

const tasksFilterSections = Object.entries(TASKS).map(([sectionKey, tagsMap]) => {
const group = 'tasks';
const title = taskSectionTitlesMap[sectionKey as keyof typeof TASKS];
const filteredTags = filterTags(Object.values(tagsMap));
if (!filteredTags.length) {
return <></>;
}
return (
<FilterSection<typeof group>
key={`${group}-${sectionKey}`}
title={title}
group={group}
tags={filteredTags}
selectedTags={selectedTags[group]}
onTagClick={(tag, group) => handleTagClick(tag, group!)}
></FilterSection>
);
const tasksFilterSections = getTagsFilterSections<typeof TASKS>({
group: 'tasks',
tagsMap: TASKS,
titlesMap: tasksSectionsTitlesMap,
selectedTags,
filterTags,
handleTagClick,
});

const librariesFilterSections = getTagsFilterSections<typeof LIBRARIES>({
group: 'libraries',
tagsMap: LIBRARIES,
titlesMap: librariesSectionsTitlesMap,
selectedTags,
filterTags,
handleTagClick,
});

const tabItems: ITabItem[] = filterGroups.map(({ title, group, tags }) => ({
Expand All @@ -90,6 +129,8 @@ export const FiltersPanel = (): JSX.Element => {
></Search>
{group === 'tasks' ? (
tasksFilterSections
) : group === 'libraries' ? (
librariesFilterSections
) : (
<FilterSection<FilterGroupKey>
group={group}
Expand Down
4 changes: 4 additions & 0 deletions selector/src/components/Header/Header.scss
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@
display: flex;
align-items: center;
justify-content: center;

img {
padding-top: 0.25rem;
}
}
}

Expand Down
23 changes: 0 additions & 23 deletions selector/src/models/notebook-metadata.ts

This file was deleted.

63 changes: 0 additions & 63 deletions selector/src/models/notebook-tags.js

This file was deleted.

112 changes: 112 additions & 0 deletions selector/src/notebook-metadata/notebook-content-reader.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
// @ts-check

import { existsSync, readFileSync } from 'fs';
import { basename, dirname, join } from 'path';
import { fileURLToPath } from 'url';

/** @typedef {import('../shared/notebook-metadata.ts').INotebookMetadata} INotebookMetadata */
/**
* @typedef {{
* metadata: { openvino_notebooks?: Partial<INotebookMetadata> };
* cells: Array<{ cell_type: 'markdown' | 'code'; source: string[]; }>
* }} INotebookJson
*/

const CURRENT_DIR_PATH = dirname(fileURLToPath(import.meta.url));

export const NOTEBOOKS_DIRECTORY_PATH = join(CURRENT_DIR_PATH, '..', '..', '..', 'notebooks');

export class NotebookContentReader {
/**
* @param {string} notebookFilePath
*/
constructor(notebookFilePath) {
/** @protected */
this._notebookFilePath = notebookFilePath;

this._checkFilesExist();
}

/**
* @private
*/
_checkFilesExist() {
if (!existsSync(this._absoluteNotebookPath)) {
throw Error(`Notebook file "${this._notebookFilePath}" does not exists.`);
}

if (!existsSync(this._readmeFilePath)) {
throw Error(`README.md file does not exists for notebook "${this._notebookFilePath}".`);
}
}

/**
* @private
* @returns {string}
*/
get _readmeFilePath() {
return join(NOTEBOOKS_DIRECTORY_PATH, dirname(this._notebookFilePath), 'README.md');
}

/**
* @protected
* @returns {string}
*/
get _absoluteNotebookPath() {
return join(NOTEBOOKS_DIRECTORY_PATH, this._notebookFilePath);
}

/**
* @protected
* @returns {string}
*/
get _notebookFileName() {
return basename(this._notebookFilePath);
}

/**
* @protected
* @returns {INotebookJson}
*/
_getNotebookJson() {
const notebookContent = readFileSync(this._absoluteNotebookPath, { encoding: 'utf8' });
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return JSON.parse(notebookContent);
}

/**
* @protected
* @returns {INotebookJson['cells']}
*/
_getCodeCells() {
return this._getNotebookJson().cells.filter(({ cell_type }) => cell_type === 'code');
}

/**
* @protected
* @returns {string}
*/
_getReadmeContent() {
return readFileSync(this._readmeFilePath, { encoding: 'utf8' });
}

/**
* @protected
* @template {keyof INotebookMetadata} K
* @param {K} key
* @returns {Partial<INotebookMetadata>[K] | null}
*/
_getMetadataFromNotebookFile(key) {
const { metadata } = this._getNotebookJson();
if (!metadata.openvino_notebooks) {
console.warn(`No "openvino_notebooks" metadata found in notebook "${this._notebookFilePath}".`);
return null;
}
const metadataPart = metadata.openvino_notebooks[key];
if (metadataPart === undefined) {
console.warn(`"${key}" is not found in "openvino_notebooks" metadata for notebook "${this._notebookFilePath}".`);
return null;
}
return metadataPart;
}
}
Loading

0 comments on commit 8128bdf

Please sign in to comment.