first commit
This commit is contained in:
146
admin/static/sections-autocomplete/SectionRow.tsx
Normal file
146
admin/static/sections-autocomplete/SectionRow.tsx
Normal file
@@ -0,0 +1,146 @@
|
||||
import { useQuery, useWidgetProps } from './utils';
|
||||
import { useEffect, useState, type KeyboardEvent } from 'react';
|
||||
|
||||
export type Section = {
|
||||
name: string;
|
||||
id: number;
|
||||
has_subsections: 0 | 1;
|
||||
}
|
||||
|
||||
type SectionRowProps = {
|
||||
section: { name: string; id: number; full_path?: string };
|
||||
depth?: number;
|
||||
hasSubsections?: boolean;
|
||||
};
|
||||
|
||||
function getEndpoint(sectionId: number) {
|
||||
return `/admin/autocomplete/sections/${sectionId}`;
|
||||
}
|
||||
|
||||
export function SectionRow({ section, hasSubsections, depth = 0 }: SectionRowProps) {
|
||||
const [showChildren, setShowChildren] = useState(false);
|
||||
const [shouldFetchChildren, setShouldFetchChildren] = useState(false);
|
||||
const { data } = useQuery<Section[]>(shouldFetchChildren ? getEndpoint(section.id): undefined);
|
||||
const { onAddSection, onAddWithSubsections, onSelect, hide, shouldHideAfterSelect } = useWidgetProps();
|
||||
|
||||
useEffect(() => {
|
||||
if (!shouldFetchChildren) {
|
||||
setShouldFetchChildren(showChildren);
|
||||
}
|
||||
}, [showChildren]);
|
||||
|
||||
function handleKeyboardNav(ev: KeyboardEvent<HTMLDivElement>) {
|
||||
switch (ev.key) {
|
||||
case 'ArrowLeft':
|
||||
setShowChildren(false);
|
||||
break;
|
||||
|
||||
case 'ArrowRight':
|
||||
setShowChildren(true);
|
||||
break;
|
||||
|
||||
case 'Enter':
|
||||
if (ev.ctrlKey) {
|
||||
if (onAddWithSubsections) {
|
||||
onAddWithSubsections(section.id);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (onAddSection) {
|
||||
onAddSection(section.id);
|
||||
}
|
||||
|
||||
if (onSelect) {
|
||||
onSelect(section.id);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
tabIndex={-1}
|
||||
className={`section-row${depth > 0 ? ' subsection' : ''}`}
|
||||
style={{ paddingLeft: `${depth * 28}px` }}
|
||||
onKeyUp={handleKeyboardNav}
|
||||
>
|
||||
<div
|
||||
className="SectionRow__content"
|
||||
onClick={ev => {
|
||||
if (onSelect) {
|
||||
ev.stopPropagation();
|
||||
if (shouldHideAfterSelect) {
|
||||
hide();
|
||||
}
|
||||
|
||||
onSelect(section.id);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<div className="SectionRow__left">
|
||||
{!!hasSubsections && (
|
||||
<div className="SectionRow__unwrap-button">
|
||||
<span
|
||||
onClick={ev => {
|
||||
ev.stopPropagation();
|
||||
setShowChildren(prev => !prev);
|
||||
}}
|
||||
className={`bi bi-dash-circle opener ${showChildren ? 'minus' : 'plus'}`}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<div className="SectionRow__name">
|
||||
<strong>
|
||||
{section.name}
|
||||
</strong>
|
||||
{!!section.full_path && (
|
||||
<span className="SectionRow__full-path">{section.full_path}</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="SectionRow__buttons">
|
||||
{!!onAddSection && (
|
||||
<button
|
||||
key="btn-add"
|
||||
type="button"
|
||||
className="btn btn-sm btn-primary"
|
||||
onClick={ev => {
|
||||
ev.stopPropagation();
|
||||
onAddSection(section.id);
|
||||
}}
|
||||
>
|
||||
<span className="bi bi-plus-lg m-r-1"></span> Přidat
|
||||
</button>
|
||||
)}
|
||||
{!!onAddWithSubsections && (
|
||||
<button
|
||||
type="button"
|
||||
key="btn-add-all"
|
||||
className="btn btn-sm btn-secondary"
|
||||
disabled={!hasSubsections}
|
||||
onClick={ev => {
|
||||
ev.stopPropagation();
|
||||
onAddWithSubsections(section.id);
|
||||
}}
|
||||
>
|
||||
<span className="bi bi-plus-lg m-r-1"></span> Včetně podsekcí
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{showChildren && data?.map((child, i) => (
|
||||
<SectionRow
|
||||
section={child}
|
||||
key={`c${section.id}-${child.id}-${i}`}
|
||||
depth={depth + 1}
|
||||
hasSubsections={child.has_subsections === 1}
|
||||
/>
|
||||
))}
|
||||
</>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user