Skip to content

Commit

Permalink
Copy over changes from studiorack-app
Browse files Browse the repository at this point in the history
  • Loading branch information
kmturley committed Sep 22, 2024
1 parent 093c481 commit 925bc33
Show file tree
Hide file tree
Showing 13 changed files with 377 additions and 31 deletions.
31 changes: 14 additions & 17 deletions components/card.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,25 @@
import styles from '../styles/components/card.module.css';
import Link from 'next/link';
import { getBasePath } from '../lib/path';
import { imageError } from '../lib/image';
import { pluginFileUrl } from '@studiorack/core';

type CardProps = {
section: string;
plugin: any;
pluginIndex: number;
item: any;
index: number;
};

const Card = ({ section, plugin, pluginIndex }: CardProps) => (
<Link href={`/${section}/[userId]/[pluginId]`} as={`/${section}/${plugin.id}`} className={styles.cardLink}>
const Card = ({ section, item, index }: CardProps) => (
<Link
href={`/${section}/[userId]/[${section === 'projects' ? 'projectId' : 'pluginId'}]`}
as={`/${section}/${item.id}`}
className={styles.cardLink}
>
<div className={styles.card}>
<div className={styles.cardDetails}>
<div className={styles.cardHead}>
<h4 className={styles.cardTitle}>
{plugin.name} <span className={styles.cardVersion}>v{plugin.version}</span>
{item.name} <span className={styles.cardVersion}>v{item.version}</span>
</h4>
<span className={styles.cardButton}>
<img
Expand All @@ -29,22 +32,16 @@ const Card = ({ section, plugin, pluginIndex }: CardProps) => (
</div>
<ul className={styles.cardTags}>
<img className={styles.cardIcon} src={`${getBasePath()}/images/icon-tag.svg`} alt="Tags" loading="lazy" />
{plugin.tags.map((tag: string, tagIndex: number) => (
<li className={styles.cardTag} key={`${tag}-${tagIndex}-${pluginIndex}`}>
{item.tags.map((tag: string, tagIndex: number) => (
<li className={styles.cardTag} key={`${tag}-${tagIndex}-${index}`}>
{tag}
{tagIndex !== plugin.tags.length - 1 ? ',' : ''}
{tagIndex !== item.tags.length - 1 ? ',' : ''}
</li>
))}
</ul>
</div>
{plugin.files.image ? (
<img
className={styles.cardImage}
src={pluginFileUrl(plugin, 'image')}
alt={plugin.name}
onError={imageError}
loading="lazy"
/>
{item.files.image ? (
<img className={styles.cardImage} src={pluginFileUrl(item, 'image')} alt={item.name} loading="lazy" />
) : (
''
)}
Expand Down
2 changes: 1 addition & 1 deletion components/filters.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ type FiltersProps = {

const Filters = ({ section }: FiltersProps) => {
const router = useRouter();
const search: string = router.query['search'] as string;
const search: string = (router.query['search'] as string) || '';

const onSearch = (event: ChangeEvent) => {
const el: HTMLInputElement = event.target as HTMLInputElement;
Expand Down
28 changes: 19 additions & 9 deletions components/list.tsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,38 @@
import styles from '../styles/components/list.module.css';
import { PluginVersion, PluginVersionLocal, ProjectVersion, ProjectVersionLocal } from '@studiorack/core';
import {
PluginVersion,
PluginVersionLocal,
PluginTypes,
ProjectTypes,
ProjectVersion,
ProjectVersionLocal,
} from '@studiorack/core';
import Header from './header';
import Card from './card';
import Filters from './filters';
import Crumb from './crumb';
import Tabs from './tabs';

type ListProps = {
filters?: boolean;
plugins: PluginVersion[] | PluginVersionLocal[] | ProjectVersion[] | ProjectVersionLocal[];
items: ListItem[];
type: string;
tabs?: PluginTypes | ProjectTypes;
title: string;
};

const List = ({ filters = true, plugins, type, title }: ListProps) => (
type ListItem = PluginVersion | PluginVersionLocal | ProjectVersion | ProjectVersionLocal;

const List = ({ filters = true, items, type, tabs, title }: ListProps) => (
<section className={styles.list}>
<Crumb items={[type]}></Crumb>
<Header title={title} count={plugins.length} />
<Header title={title} count={items.length} />
{filters ? <Filters section={type} /> : ''}
{tabs ? <Tabs items={tabs} /> : ''}
<div className={styles.listGrid}>
{plugins.map(
(plugin: PluginVersion | PluginVersionLocal | ProjectVersion | ProjectVersionLocal, pluginIndex: number) => (
<Card section={type} plugin={plugin} pluginIndex={pluginIndex} key={`${plugin.id}-${pluginIndex}`}></Card>
),
)}
{items.map((item: ListItem, index: number) => (
<Card section={type} item={item} index={index} key={`${item.id}-${index}`}></Card>
))}
</div>
</section>
);
Expand Down
71 changes: 71 additions & 0 deletions components/tabs.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import styles from '../styles/components/tabs.module.css';
import { PluginType, PluginTypes, ProjectType, ProjectTypes } from '@studiorack/core';
import { useRouter } from 'next/router';
import { ChangeEvent } from 'react';

type TabsProps = {
items: PluginTypes | ProjectTypes;
};

type TabsItem = PluginType | ProjectType;
type TabsKey = keyof PluginTypes & keyof ProjectTypes;

const Tabs = ({ items }: TabsProps) => {
const router = useRouter();
let category: string = (router.query['category'] as string) || 'all';
const search: string = (router.query['search'] as string) || '';

const isSelected = (path: string) => {
return category === path ? 'selected' : '';
};

const onSearch = (event: ChangeEvent) => {
const el: HTMLInputElement = event.target as HTMLInputElement;
router.query['search'] = el.value ? el.value.toLowerCase() : '';
router.push({
pathname: router.pathname,
query: router.query,
});
};

const selectCategory = (event: any) => {
category = (event.target as HTMLTextAreaElement).getAttribute('data-category') || '';
router.query['category'] = category || '';
router.push({
pathname: router.pathname,
query: router.query,
});
};

return (
<div className={styles.tabs}>
<ul className={styles.tabsCategory}>
<li>
<a data-category="all" onClick={selectCategory} className={isSelected('all')}>
All
</a>
</li>
{Object.keys(items).map((key: string, index: number) => (
<li key={`${key}-${index}`}>
<a data-category={key} onClick={selectCategory} className={isSelected(key)}>
{(items[key as TabsKey] as TabsItem).name}
</a>
</li>
))}
<li>
<input
className={styles.tabsSearch}
placeholder="Keyword"
type="search"
id="search"
name="search"
value={search}
onChange={onSearch}
/>
</li>
</ul>
</div>
);
};

export default Tabs;
19 changes: 19 additions & 0 deletions lib/project.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { ProjectTypes, ProjectVersion } from '@studiorack/core';
import { NextRouter } from 'next/router';

export function filterProjects(projectTypes: ProjectTypes, projects: ProjectVersion[], router: NextRouter) {
const category: string = (router.query['category'] as string) || 'all';
const search: string = router.query['search'] as string;
return projects.filter((project: ProjectVersion) => {
if (category !== 'all' && project.type?.ext !== projectTypes[category as keyof ProjectTypes]?.ext) return false;
if (
search &&
project.id?.toLowerCase().indexOf(search.toLowerCase()) === -1 &&
project.name?.toLowerCase().indexOf(search.toLowerCase()) === -1 &&
project.description?.toLowerCase().indexOf(search.toLowerCase()) === -1 &&
project.tags?.indexOf(search.toLowerCase()) === -1
)
return false;
return project;
});
}
2 changes: 1 addition & 1 deletion pages/effects/[userId]/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class PluginList extends Component<
<Head>
<title>{pageTitle(['Effects', this.state.userId])}</title>
</Head>
<List filters={false} plugins={this.state.pluginsFiltered} type="effects" title={this.state.userId} />
<List items={this.state.pluginsFiltered} type="effects" title={this.state.userId} filters={false} />
</Layout>
);
}
Expand Down
2 changes: 1 addition & 1 deletion pages/effects/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const Effects = ({ plugins }: EffectsProps) => {
<Head>
<title>{pageTitle(['Effects'])}</title>
</Head>
<List plugins={pluginsFiltered} type="effects" title="Effects" />
<List items={pluginsFiltered} type="effects" title="Effects" />
</Layout>
);
};
Expand Down
2 changes: 1 addition & 1 deletion pages/instruments/[userId]/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class PluginList extends Component<
<Head>
<title>{pageTitle(['Instruments', this.state.userId])}</title>
</Head>
<List filters={false} plugins={this.state.pluginsFiltered} type="instruments" title={this.state.userId} />
<List items={this.state.pluginsFiltered} type="instruments" title={this.state.userId} filters={false} />
</Layout>
);
}
Expand Down
2 changes: 1 addition & 1 deletion pages/instruments/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const Instruments = ({ plugins }: InstrumentsProps) => {
<Head>
<title>{pageTitle(['Instruments'])}</title>
</Head>
<List plugins={pluginsFiltered} type="instruments" title="Instruments" />
<List items={pluginsFiltered} type="instruments" title="Instruments" />
</Layout>
);
};
Expand Down
40 changes: 40 additions & 0 deletions pages/projects/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { configDefaults, ConfigList, projectsGetLocal, ProjectVersion, ProjectVersionLocal } from '@studiorack/core';
import { useRouter } from 'next/router';
import Layout from '../../components/layout';
import Head from 'next/head';
import { GetStaticProps } from 'next';
import { pageTitle } from '../../lib/utils';
import List from '../../components/list';
import { filterProjects } from '../../lib/project';

type ProjectsProps = {
projects: ProjectVersion[];
};

const Projects = ({ projects }: ProjectsProps) => {
const router = useRouter();
const projectTypes = configDefaults('appFolder', 'pluginFolder', 'presetFolder', 'projectFolder').projectTypes;
const projectsFiltered: ProjectVersion[] = filterProjects(projectTypes, projects, router);
return (
<Layout>
<Head>
<title>{pageTitle(['Projects'])}</title>
</Head>
<List items={projectsFiltered} type="projects" title="Projects" filters={false} tabs={projectTypes} />
</Layout>
);
};

export default Projects;

export const getStaticProps: GetStaticProps = async () => {
let projects = await projectsGetLocal();
projects = projects.sort(function (a: ProjectVersionLocal, b: ProjectVersionLocal) {
return a.name.localeCompare(b.name);
});
return {
props: {
projects,
},
};
};
88 changes: 88 additions & 0 deletions styles/components/grid-item.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
.pluginLink,
.pluginLink:hover {
border-bottom: none;
padding-bottom: 0;
transition: none;
}

.plugin {
background-color: #111;
border-radius: 0.5rem;
cursor: pointer;
max-height: 200px;
overflow: hidden;
padding: 1.5rem 1.5rem 0 1.5rem;
margin-bottom: 1rem;
transition: background-color 0.25s ease-out;
}

.plugin:hover {
background-color: #222;
}

.pluginDetails {
margin-bottom: 1.5rem;
}

.pluginHead {
display: flex;
justify-content: space-between;
}

.pluginTitle {
flex-shrink: 1;
margin: 0;
}

.pluginButton,
.pluginButtonInstalled {
background-color: #0d51ff;
border-radius: 4px;
display: flex;
flex-shrink: 0;
height: 15px;
justify-content: center;
margin-left: 0.5rem;
padding: 8px;
width: 15px;
}

.pluginButtonIcon,
.projectButtonIcon {
max-width: 100%;
}

.pluginButtonInstalled {
background-color: #48ad6a;
}

.projectButton {
margin-left: 0.5rem;
width: 30px;
}

.pluginVersion {
color: #666;
font-size: 0.75rem;
}

.pluginTags {
display: flex;
list-style: none;
margin: 0;
padding: 0;
}

.pluginIcon {
margin-right: 0.5rem;
width: 15px;
}

.pluginTag {
margin-right: 0.25rem;
}

.pluginImage {
display: cover;
width: 100%;
}
Loading

0 comments on commit 925bc33

Please sign in to comment.