Merge branch 'main' into jade/uwu2000
This commit is contained in:
commit
d9c3f051b9
17 changed files with 528 additions and 141 deletions
|
|
@ -1,6 +1,8 @@
|
|||
import {
|
||||
exportPatterns,
|
||||
importPatterns,
|
||||
loadAndSetFeaturedPatterns,
|
||||
loadAndSetPublicPatterns,
|
||||
patternFilterName,
|
||||
useActivePattern,
|
||||
useViewingPatternData,
|
||||
|
|
@ -12,10 +14,10 @@ import { useExamplePatterns } from '../../useExamplePatterns.jsx';
|
|||
import { parseJSON, isUdels } from '../../util.mjs';
|
||||
import { ButtonGroup } from './Forms.jsx';
|
||||
import { settingsMap, useSettings } from '../../../settings.mjs';
|
||||
|
||||
function classNames(...classes) {
|
||||
return classes.filter(Boolean).join(' ');
|
||||
}
|
||||
import { Pagination } from '../pagination/Pagination.jsx';
|
||||
import { useState } from 'react';
|
||||
import { useDebounce } from '../usedebounce.jsx';
|
||||
import cx from '@src/cx.mjs';
|
||||
|
||||
export function PatternLabel({ pattern } /* : { pattern: Tables<'code'> } */) {
|
||||
const meta = useMemo(() => getMetadata(pattern.code), [pattern]);
|
||||
|
|
@ -33,13 +35,15 @@ export function PatternLabel({ pattern } /* : { pattern: Tables<'code'> } */) {
|
|||
if (title == null) {
|
||||
title = 'unnamed';
|
||||
}
|
||||
return <>{`${pattern.id}: ${title} by ${Array.isArray(meta.by) ? meta.by.join(',') : 'Anonymous'}`}</>;
|
||||
|
||||
const author = Array.isArray(meta.by) ? meta.by.join(',') : 'Anonymous';
|
||||
return <>{`${pattern.id}: ${title} by ${author.slice(0, 100)}`.slice(0, 60)}</>;
|
||||
}
|
||||
|
||||
function PatternButton({ showOutline, onClick, pattern, showHiglight }) {
|
||||
return (
|
||||
<a
|
||||
className={classNames(
|
||||
className={cx(
|
||||
'mr-4 hover:opacity-50 cursor-pointer block',
|
||||
showOutline && 'outline outline-1',
|
||||
showHiglight && 'bg-selection',
|
||||
|
|
@ -84,82 +88,72 @@ function ActionButton({ children, onClick, label, labelIsHidden }) {
|
|||
);
|
||||
}
|
||||
|
||||
export function PatternsTab({ context }) {
|
||||
const updateCodeWindow = (context, patternData, reset = false) => {
|
||||
context.handleUpdate(patternData, reset);
|
||||
};
|
||||
|
||||
const autoResetPatternOnChange = !isUdels();
|
||||
|
||||
function UserPatterns({ context }) {
|
||||
const activePattern = useActivePattern();
|
||||
const viewingPatternStore = useViewingPatternData();
|
||||
const viewingPatternData = parseJSON(viewingPatternStore);
|
||||
|
||||
const { userPatterns, patternFilter } = useSettings();
|
||||
|
||||
const examplePatterns = useExamplePatterns();
|
||||
const collections = examplePatterns.collections;
|
||||
|
||||
const updateCodeWindow = (patternData, reset = false) => {
|
||||
context.handleUpdate(patternData, reset);
|
||||
};
|
||||
const viewingPatternID = viewingPatternData?.id;
|
||||
|
||||
const autoResetPatternOnChange = !isUdels();
|
||||
|
||||
return (
|
||||
<div className="px-4 w-full text-foreground space-y-2 flex flex-col overflow-hidden max-h-full h-full">
|
||||
<ButtonGroup
|
||||
value={patternFilter}
|
||||
onChange={(value) => settingsMap.setKey('patternFilter', value)}
|
||||
items={patternFilterName}
|
||||
></ButtonGroup>
|
||||
{patternFilter === patternFilterName.user && (
|
||||
<div>
|
||||
<div className="pr-4 space-x-4 border-b border-foreground flex max-w-full overflow-x-auto">
|
||||
<ActionButton
|
||||
label="new"
|
||||
onClick={() => {
|
||||
const { data } = userPattern.createAndAddToDB();
|
||||
updateCodeWindow(data);
|
||||
}}
|
||||
/>
|
||||
<ActionButton
|
||||
label="duplicate"
|
||||
onClick={() => {
|
||||
const { data } = userPattern.duplicate(viewingPatternData);
|
||||
updateCodeWindow(data);
|
||||
}}
|
||||
/>
|
||||
<ActionButton
|
||||
label="delete"
|
||||
onClick={() => {
|
||||
const { data } = userPattern.delete(viewingPatternID);
|
||||
updateCodeWindow({ ...data, collection: userPattern.collection });
|
||||
}}
|
||||
/>
|
||||
<label className="hover:opacity-50 cursor-pointer">
|
||||
<input
|
||||
style={{ display: 'none' }}
|
||||
type="file"
|
||||
multiple
|
||||
accept="text/plain,application/json"
|
||||
onChange={(e) => importPatterns(e.target.files)}
|
||||
/>
|
||||
import
|
||||
</label>
|
||||
<ActionButton label="export" onClick={exportPatterns} />
|
||||
<div className="flex flex-col gap-2 flex-grow overflow-hidden h-full pb-2 ">
|
||||
<div className="pr-4 space-x-4 flex max-w-full overflow-x-auto">
|
||||
<ActionButton
|
||||
label="new"
|
||||
onClick={() => {
|
||||
const { data } = userPattern.createAndAddToDB();
|
||||
updateCodeWindow(context, data);
|
||||
}}
|
||||
/>
|
||||
<ActionButton
|
||||
label="duplicate"
|
||||
onClick={() => {
|
||||
const { data } = userPattern.duplicate(viewingPatternData);
|
||||
updateCodeWindow(context, data);
|
||||
}}
|
||||
/>
|
||||
<ActionButton
|
||||
label="delete"
|
||||
onClick={() => {
|
||||
const { data } = userPattern.delete(viewingPatternID);
|
||||
updateCodeWindow(context, { ...data, collection: userPattern.collection });
|
||||
}}
|
||||
/>
|
||||
<label className="hover:opacity-50 cursor-pointer">
|
||||
<input
|
||||
style={{ display: 'none' }}
|
||||
type="file"
|
||||
multiple
|
||||
accept="text/plain,application/json"
|
||||
onChange={(e) => importPatterns(e.target.files)}
|
||||
/>
|
||||
import
|
||||
</label>
|
||||
<ActionButton label="export" onClick={exportPatterns} />
|
||||
|
||||
<ActionButton
|
||||
label="delete-all"
|
||||
onClick={() => {
|
||||
const { data } = userPattern.clearAll();
|
||||
updateCodeWindow(data);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<ActionButton
|
||||
label="delete-all"
|
||||
onClick={() => {
|
||||
const { data } = userPattern.clearAll();
|
||||
updateCodeWindow(context, data);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<section className="flex overflow-y-auto max-h-full flex-grow flex-col">
|
||||
<div className="overflow-auto h-full bg-background p-2 rounded-md">
|
||||
{patternFilter === patternFilterName.user && (
|
||||
<PatternButtons
|
||||
onClick={(id) =>
|
||||
updateCodeWindow({ ...userPatterns[id], collection: userPattern.collection }, autoResetPatternOnChange)
|
||||
updateCodeWindow(
|
||||
context,
|
||||
{ ...userPatterns[id], collection: userPattern.collection },
|
||||
autoResetPatternOnChange,
|
||||
)
|
||||
}
|
||||
patterns={userPatterns}
|
||||
started={context.started}
|
||||
|
|
@ -167,23 +161,111 @@ export function PatternsTab({ context }) {
|
|||
viewingPatternID={viewingPatternID}
|
||||
/>
|
||||
)}
|
||||
{patternFilter !== patternFilterName.user &&
|
||||
Array.from(collections.keys()).map((collection) => {
|
||||
const patterns = collections.get(collection);
|
||||
return (
|
||||
<section key={collection} className="py-2">
|
||||
<h2 className="text-xl mb-2">{collection}</h2>
|
||||
|
||||
<PatternButtons
|
||||
onClick={(id) => updateCodeWindow({ ...patterns[id], collection }, autoResetPatternOnChange)}
|
||||
started={context.started}
|
||||
patterns={patterns}
|
||||
activePattern={activePattern}
|
||||
/>
|
||||
</section>
|
||||
);
|
||||
})}
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function PatternPageWithPagination({ patterns, patternOnClick, context, paginationOnChange, initialPage }) {
|
||||
const [page, setPage] = useState(initialPage);
|
||||
const debouncedPageChange = useDebounce(() => {
|
||||
paginationOnChange(page);
|
||||
});
|
||||
|
||||
const onPageChange = (pageNum) => {
|
||||
setPage(pageNum);
|
||||
debouncedPageChange();
|
||||
};
|
||||
|
||||
const activePattern = useActivePattern();
|
||||
return (
|
||||
<div className="flex flex-grow flex-col h-full overflow-hidden justify-between">
|
||||
<div className="overflow-auto flex flex-col flex-grow bg-background p-2 rounded-md ">
|
||||
<PatternButtons
|
||||
onClick={(id) => patternOnClick(id)}
|
||||
started={context.started}
|
||||
patterns={patterns}
|
||||
activePattern={activePattern}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex items-center gap-2 py-2">
|
||||
<label htmlFor="pattern pagination">Page</label>
|
||||
<Pagination id="pattern pagination" currPage={page} onPageChange={onPageChange} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
let featuredPageNum = 1;
|
||||
function FeaturedPatterns({ context }) {
|
||||
const examplePatterns = useExamplePatterns();
|
||||
const collections = examplePatterns.collections;
|
||||
const patterns = collections.get(patternFilterName.featured);
|
||||
return (
|
||||
<PatternPageWithPagination
|
||||
patterns={patterns}
|
||||
context={context}
|
||||
initialPage={featuredPageNum}
|
||||
patternOnClick={(id) => {
|
||||
updateCodeWindow(
|
||||
context,
|
||||
{ ...patterns[id], collection: patternFilterName.featured },
|
||||
autoResetPatternOnChange,
|
||||
);
|
||||
}}
|
||||
paginationOnChange={async (pageNum) => {
|
||||
await loadAndSetFeaturedPatterns(pageNum - 1);
|
||||
featuredPageNum = pageNum;
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
let latestPageNum = 1;
|
||||
function LatestPatterns({ context }) {
|
||||
const examplePatterns = useExamplePatterns();
|
||||
const collections = examplePatterns.collections;
|
||||
const patterns = collections.get(patternFilterName.public);
|
||||
return (
|
||||
<PatternPageWithPagination
|
||||
patterns={patterns}
|
||||
context={context}
|
||||
initialPage={latestPageNum}
|
||||
patternOnClick={(id) => {
|
||||
updateCodeWindow(context, { ...patterns[id], collection: patternFilterName.public }, autoResetPatternOnChange);
|
||||
}}
|
||||
paginationOnChange={async (pageNum) => {
|
||||
await loadAndSetPublicPatterns(pageNum - 1);
|
||||
latestPageNum = pageNum;
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function PublicPatterns({ context }) {
|
||||
const { patternFilter } = useSettings();
|
||||
if (patternFilter === patternFilterName.featured) {
|
||||
return <FeaturedPatterns context={context} />;
|
||||
}
|
||||
return <LatestPatterns context={context} />;
|
||||
}
|
||||
|
||||
export function PatternsTab({ context }) {
|
||||
const { patternFilter } = useSettings();
|
||||
|
||||
return (
|
||||
<div className="px-4 w-full text-foreground space-y-2 flex flex-col overflow-hidden max-h-full h-full">
|
||||
<ButtonGroup
|
||||
value={patternFilter}
|
||||
onChange={(value) => settingsMap.setKey('patternFilter', value)}
|
||||
items={patternFilterName}
|
||||
></ButtonGroup>
|
||||
|
||||
{patternFilter === patternFilterName.user ? (
|
||||
<UserPatterns context={context} />
|
||||
) : (
|
||||
<PublicPatterns context={context} />
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue