diff options
author | Thomas F. K. Jorna <[email protected]> | 2022-01-03 17:21:18 +0100 |
---|---|---|
committer | GitHub <[email protected]> | 2022-01-03 17:21:18 +0100 |
commit | dad03e3be5b0a7c1159e0207cce11540ca830359 (patch) | |
tree | 4ae4e0a40c578e12b6d4f11a3f785c8190865f8b /components/Tweaks/Filter | |
parent | 9ed0c5705a302a91fab2b8bcc777a12dcf9b3682 (diff) |
feat(filter): add option to filter by subdirectory (#190)
Diffstat (limited to 'components/Tweaks/Filter')
-rw-r--r-- | components/Tweaks/Filter/FilterPanel.tsx | 245 | ||||
-rw-r--r-- | components/Tweaks/Filter/TagColorPanel.tsx | 139 |
2 files changed, 384 insertions, 0 deletions
diff --git a/components/Tweaks/Filter/FilterPanel.tsx b/components/Tweaks/Filter/FilterPanel.tsx new file mode 100644 index 0000000..55ff3e5 --- /dev/null +++ b/components/Tweaks/Filter/FilterPanel.tsx @@ -0,0 +1,245 @@ +import { ChevronDownIcon } from '@chakra-ui/icons' +import { + Text, + Box, + Button, + Flex, + Menu, + MenuButton, + StackDivider, + VStack, + Portal, + MenuList, + MenuItem, + Switch, + Accordion, + AccordionItem, + AccordionButton, + AccordionIcon, + AccordionPanel, +} from '@chakra-ui/react' +import React, { useContext } from 'react' +import { OptionPanel } from '../OptionPanel' +import { initialFilter, initialLocal, TagColors } from '../../config' +import { TagColorPanel } from './TagColorPanel' +import { SliderWithInfo } from '../SliderWithInfo' +import { VariablesContext } from '../../../util/variablesContext' + +export interface FilterPanelProps { + filter: typeof initialFilter + setFilter: any + tagColors: TagColors + setTagColors: any + highlightColor: string + colorList: string[] + tags: string[] + local: typeof initialLocal + setLocal: any +} + +const FilterPanel = (props: FilterPanelProps) => { + const { + filter, + setFilter, + local, + setLocal, + tagColors, + setTagColors, + highlightColor, + colorList, + tags, + } = props + const { roamDir, subDirs } = useContext(VariablesContext) + return ( + <Box> + <VStack + spacing={2} + justifyContent="flex-start" + divider={<StackDivider borderColor="gray.500" />} + align="stretch" + paddingLeft={7} + color="gray.800" + > + <Flex alignItems="center" justifyContent="space-between"> + <Text>Link children to</Text> + <Menu isLazy placement="right"> + <MenuButton + as={Button} + rightIcon={<ChevronDownIcon />} + colorScheme="" + color="black" + size="sm" + > + {(() => { + switch (filter.parent) { + case 'parent': + return <Text>File</Text> + case 'heading': + return <Text>Heading</Text> + default: + return <Text>Nothing</Text> + } + })()} + </MenuButton> + <Portal> + <MenuList bgColor="gray.200" zIndex="popover"> + <MenuItem + onClick={() => + setFilter((curr: typeof initialFilter) => ({ ...curr, parent: '' })) + } + > + Nothing + </MenuItem> + <MenuItem + onClick={() => + setFilter((curr: typeof initialFilter) => ({ + ...curr, + parent: 'parent', + })) + } + > + Parent file node + </MenuItem> + <MenuItem + onClick={() => + setFilter((curr: typeof initialFilter) => ({ + ...curr, + parent: 'heading', + })) + } + > + Next highest heading node + </MenuItem> + </MenuList> + </Portal> + </Menu> + </Flex> + <Flex justifyContent="space-between"> + <Text>Orphans</Text> + <Switch + onChange={() => { + setFilter((curr: typeof initialFilter) => { + return { ...curr, orphans: !curr.orphans } + }) + }} + isChecked={filter.orphans} + ></Switch> + </Flex> + <Flex justifyContent="space-between"> + <Text>Dailies</Text> + <Switch + onChange={() => { + setFilter((curr: typeof initialFilter) => { + return { ...curr, dailies: !curr.dailies } + }) + }} + isChecked={filter.dailies} + ></Switch> + </Flex> + <Flex justifyContent="space-between"> + <Text>Org-noter pages</Text> + <Switch + onChange={() => { + setFilter((curr: typeof initialFilter) => { + return { ...curr, noter: !curr.noter } + }) + }} + isChecked={filter.noter} + ></Switch> + </Flex> + <Flex justifyContent="space-between"> + <Text>Citations without note files</Text> + <Switch + onChange={() => { + setFilter({ ...filter, filelessCites: !filter.filelessCites }) + }} + isChecked={filter.filelessCites} + ></Switch> + </Flex> + <Flex justifyContent="space-between"> + <Text>Non-existent nodes</Text> + <Switch + onChange={() => { + setTagColors({ ...tagColors, bad: 'white' }) + setFilter({ ...filter, bad: !filter.bad }) + }} + isChecked={filter.bad} + ></Switch> + </Flex> + <SliderWithInfo + label="Number of neighbors in local graph" + value={local.neighbors} + onChange={(v) => setLocal({ ...local, neighbors: v })} + min={1} + max={5} + step={1} + /> + </VStack> + <Accordion padding={0} allowToggle allowMultiple paddingLeft={3}> + <AccordionItem> + <AccordionButton> + Directory filters + <AccordionIcon /> + </AccordionButton> + <AccordionPanel pr={0} mr={0}> + <OptionPanel + filter={filter} + setFilter={setFilter} + options={subDirs} + displayName="directory blocklist" + listName="dirsBlocklist" + labelFilter={roamDir} + /> + <OptionPanel + filter={filter} + setFilter={setFilter} + options={subDirs} + displayName="directory allowlist" + listName="dirsAllowlist" + labelFilter={roamDir} + /> + </AccordionPanel> + </AccordionItem> + <AccordionItem> + <AccordionButton> + Tag filters + <AccordionIcon /> + </AccordionButton> + <AccordionPanel pr={0} mr={0}> + <OptionPanel + filter={filter} + setFilter={setFilter} + options={tags} + displayName="tag blocklist" + listName="tagsBlacklist" + /> + <OptionPanel + filter={filter} + setFilter={setFilter} + options={tags} + displayName="tag allowlist" + listName="tagsWhitelist" + /> + </AccordionPanel> + </AccordionItem> + <AccordionItem> + <AccordionButton> + Tag colors + <AccordionIcon /> + </AccordionButton> + <AccordionPanel pr={0} mr={0}> + <TagColorPanel + tags={tags} + colorList={colorList} + tagColors={tagColors} + setTagColors={setTagColors} + highlightColor={highlightColor} + /> + </AccordionPanel> + </AccordionItem> + </Accordion> + </Box> + ) +} + +export default FilterPanel diff --git a/components/Tweaks/Filter/TagColorPanel.tsx b/components/Tweaks/Filter/TagColorPanel.tsx new file mode 100644 index 0000000..eb458dc --- /dev/null +++ b/components/Tweaks/Filter/TagColorPanel.tsx @@ -0,0 +1,139 @@ +import { DeleteIcon } from '@chakra-ui/icons' +import { + Text, + Box, + Flex, + IconButton, + Menu, + MenuButton, + MenuItem, + MenuList, + Portal, + StackDivider, + VStack, + Button, +} from '@chakra-ui/react' +import { CUIAutoComplete } from 'chakra-ui-autocomplete' +import React, { useState } from 'react' +import { TagColors } from '../../config' + +export interface TagColorPanelProps { + tags: string[] + highlightColor: string + colorList: string[] + tagColors: TagColors + setTagColors: any +} +export const TagColorPanel = (props: TagColorPanelProps) => { + const { colorList, tagColors, setTagColors, highlightColor, tags } = props + const tagArray = tags.map((tag) => { + return { value: tag, label: tag } + }) + + const [selectedItems, setSelectedItems] = useState<typeof tagArray>( + Object.keys(tagColors).map((tag) => { + return { value: tag, label: tag } + }), + ) + + return ( + <Box> + <CUIAutoComplete + items={tagArray} + labelStyleProps={{ fontWeight: 300, fontSize: 14 }} + label="Add tag to color" + placeholder=" " + disableCreateItem={true} + selectedItems={selectedItems} + onSelectedItemsChange={(changes) => { + if (changes.selectedItems) { + setSelectedItems(Array.from(new Set(changes.selectedItems))) + setTagColors( + Object.fromEntries( + Array.from(new Set(changes.selectedItems)).map((item) => { + return [item.label, tagColors[item.label] ?? 'gray.600'] + }), + ), + ) + } + }} + listItemStyleProps={{ overflow: 'hidden' }} + highlightItemBg="gray.400" + toggleButtonStyleProps={{ variant: 'outline' }} + inputStyleProps={{ + height: 8, + focusBorderColor: highlightColor, + color: 'gray.800', + borderColor: 'gray.500', + }} + tagStyleProps={{ + display: 'none', + rounded: 'full', + bg: highlightColor, + height: 8, + paddingLeft: 4, + fontWeight: 'bold', + }} + hideToggleButton + itemRenderer={(selected) => selected.label} + /> + <VStack + spacing={2} + justifyContent="flex-start" + divider={<StackDivider borderColor="gray.500" />} + align="stretch" + color="gray.800" + > + {Object.keys(tagColors).map((tag) => { + return ( + <Flex key={tag} alignItems="center" justifyContent="space-between" width="100%" pl={2}> + <Box width="100%"> + <Text>{tag}</Text> + </Box> + <Menu isLazy placement="right"> + <MenuButton as={Button} colorScheme="" color="black"> + {<Box bgColor={tagColors[tag]} borderRadius="sm" height={6} width={6}></Box>} + </MenuButton> + <Portal> + <MenuList minW={10} zIndex="popover" bgColor="gray.200"> + {colorList.map((color: string) => ( + <MenuItem + key={color} + onClick={() => + setTagColors({ + ...tagColors, + [tag]: color, + }) + } + justifyContent="space-between" + alignItems="center" + display="flex" + > + <Box bgColor={color} borderRadius="sm" height={6} width={6}></Box> + </MenuItem> + ))} + </MenuList> + </Portal> + </Menu> + <IconButton + aria-label="Delete tag color" + variant="ghost" + icon={<DeleteIcon />} + onClick={() => { + setTagColors( + Object.fromEntries( + Array.from(new Set(selectedItems)).map((item) => { + return [item.label, tagColors[item.label] ?? 'gray.600'] + }), + ), + ) + setSelectedItems(selectedItems.filter((item) => item.value !== tag)) + }} + /> + </Flex> + ) + })} + </VStack> + </Box> + ) +} |