Added search/filter in patterns tab
Added pattern as dep to filter memo Format
This commit is contained in:
parent
0a2f2eaa3d
commit
6908ea38e4
2 changed files with 106 additions and 86 deletions
|
|
@ -1,4 +1,4 @@
|
||||||
const ALLOW_MANY = ['by', 'url', 'genre', 'license'];
|
const ALLOW_MANY = ['by', 'url', 'genre', 'license', 'tag'];
|
||||||
|
|
||||||
export function getMetadata(raw_code) {
|
export function getMetadata(raw_code) {
|
||||||
if (raw_code == null) {
|
if (raw_code == null) {
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ import { Pagination } from '../pagination/Pagination.jsx';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { useDebounce } from '../usedebounce.jsx';
|
import { useDebounce } from '../usedebounce.jsx';
|
||||||
import cx from '@src/cx.mjs';
|
import cx from '@src/cx.mjs';
|
||||||
|
import { Textbox } from '../textbox/Textbox.jsx';
|
||||||
|
|
||||||
export function PatternLabel({ pattern } /* : { pattern: Tables<'code'> } */) {
|
export function PatternLabel({ pattern } /* : { pattern: Tables<'code'> } */) {
|
||||||
const meta = useMemo(() => getMetadata(pattern.code), [pattern]);
|
const meta = useMemo(() => getMetadata(pattern.code), [pattern]);
|
||||||
|
|
@ -33,7 +34,7 @@ export function PatternLabel({ pattern } /* : { pattern: Tables<'code'> } */) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const author = 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)}</>;
|
return <>{`${title} by ${author.slice(0, 100)}`.slice(0, 60)}</>;
|
||||||
}
|
}
|
||||||
|
|
||||||
function PatternButton({ showOutline, onClick, pattern, showHiglight }) {
|
function PatternButton({ showOutline, onClick, pattern, showHiglight }) {
|
||||||
|
|
@ -79,73 +80,117 @@ const updateCodeWindow = (context, patternData, reset = false) => {
|
||||||
context.handleUpdate(patternData, reset);
|
context.handleUpdate(patternData, reset);
|
||||||
};
|
};
|
||||||
|
|
||||||
function UserPatterns({ context }) {
|
export function PatternsTab({ context }) {
|
||||||
|
const [search, setSearch] = useState('');
|
||||||
const activePattern = useActivePattern();
|
const activePattern = useActivePattern();
|
||||||
const viewingPatternStore = useViewingPatternData();
|
const viewingPatternStore = useViewingPatternData();
|
||||||
const viewingPatternData = parseJSON(viewingPatternStore);
|
const viewingPatternData = parseJSON(viewingPatternStore);
|
||||||
const { userPatterns, patternFilter, patternAutoStart } = useSettings();
|
const { userPatterns, patternAutoStart } = useSettings();
|
||||||
const viewingPatternID = viewingPatternData?.id;
|
const viewingPatternID = viewingPatternData?.id;
|
||||||
return (
|
|
||||||
<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,text/x-markdown,application/json"
|
|
||||||
onChange={(e) => importPatterns(e.target.files)}
|
|
||||||
/>
|
|
||||||
import
|
|
||||||
</label>
|
|
||||||
<ActionButton label="export" onClick={exportPatterns} />
|
|
||||||
|
|
||||||
<ActionButton
|
const visiblePatterns = useMemo(() => {
|
||||||
label="delete-all"
|
return Object.fromEntries(
|
||||||
onClick={() => {
|
Object.entries(userPatterns).filter(([_key, pattern]) => {
|
||||||
const { data } = userPattern.clearAll();
|
if (!search) {
|
||||||
updateCodeWindow(context, data);
|
return true;
|
||||||
}}
|
}
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="overflow-auto h-full bg-background p-2 rounded-md">
|
const meta = getMetadata(pattern.code);
|
||||||
{/* {patternFilter === patternFilterName.user && ( */}
|
|
||||||
<PatternButtons
|
|
||||||
onClick={(id) => {
|
|
||||||
updateCodeWindow(context, { ...userPatterns[id], collection: userPattern.collection }, patternAutoStart);
|
|
||||||
|
|
||||||
if (context.started && activePattern === id) {
|
// Search for specific meta keys
|
||||||
context.handleEvaluate();
|
const searchTrimmed = search.trim();
|
||||||
|
if (searchTrimmed.includes(':')) {
|
||||||
|
const [metaKey, metaSearch] = searchTrimmed.split(':');
|
||||||
|
if (metaKey !== undefined && metaSearch !== undefined && metaKey in meta) {
|
||||||
|
const metaValues = meta[metaKey];
|
||||||
|
if (Array.isArray(metaValues)) {
|
||||||
|
return metaValues.some((metaValue) => metaValue.toLowerCase().includes(metaSearch.trim().toLowerCase()));
|
||||||
|
} else if (typeof metaValues === 'string') {
|
||||||
|
return metaValues.toLowerCase().includes(metaSearch.trim().toLowerCase());
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}}
|
}
|
||||||
patterns={userPatterns}
|
}
|
||||||
started={context.started}
|
const title = meta.title ? meta.title : 'unnamed';
|
||||||
activePattern={activePattern}
|
const authors = meta.by ? meta.by : ['anonymous'];
|
||||||
viewingPatternID={viewingPatternID}
|
const tags = meta.tag ? meta.tag : [];
|
||||||
/>
|
const lowerCaseSearch = search.toLowerCase();
|
||||||
{/* )} */}
|
return (
|
||||||
|
title.toLowerCase().includes(lowerCaseSearch) ||
|
||||||
|
authors.some((author) => author.toLowerCase().includes(lowerCaseSearch)) ||
|
||||||
|
tags.some((tag) => tag.toLowerCase().includes(lowerCaseSearch))
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}, [search, viewingPatternStore]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="px-4 w-full text-foreground space-y-2 flex flex-col overflow-hidden max-h-full h-full">
|
||||||
|
<div class="w-full flex">
|
||||||
|
<Textbox className="w-full" placeholder="Search" value={search} onChange={setSearch} />
|
||||||
|
</div>
|
||||||
|
<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,text/x-markdown,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(context, data);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="overflow-auto h-full bg-background p-2 rounded-md">
|
||||||
|
{/* {patternFilter === patternFilterName.user && ( */}
|
||||||
|
<PatternButtons
|
||||||
|
onClick={(id) => {
|
||||||
|
updateCodeWindow(context, { ...userPatterns[id], collection: userPattern.collection }, patternAutoStart);
|
||||||
|
|
||||||
|
if (context.started && activePattern === id) {
|
||||||
|
context.handleEvaluate();
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
patterns={visiblePatterns}
|
||||||
|
started={context.started}
|
||||||
|
activePattern={activePattern}
|
||||||
|
viewingPatternID={viewingPatternID}
|
||||||
|
/>
|
||||||
|
{/* )} */}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
@ -232,28 +277,3 @@ function PublicPatterns({ context }) {
|
||||||
}
|
}
|
||||||
return <LatestPatterns 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">
|
|
||||||
<UserPatterns context={context} />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
/* 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