summaryrefslogtreecommitdiff
path: root/components/Tweaks/Filter
diff options
context:
space:
mode:
authorThomas F. K. Jorna <[email protected]>2022-01-03 17:21:18 +0100
committerGitHub <[email protected]>2022-01-03 17:21:18 +0100
commitdad03e3be5b0a7c1159e0207cce11540ca830359 (patch)
tree4ae4e0a40c578e12b6d4f11a3f785c8190865f8b /components/Tweaks/Filter
parent9ed0c5705a302a91fab2b8bcc777a12dcf9b3682 (diff)
feat(filter): add option to filter by subdirectory (#190)
Diffstat (limited to 'components/Tweaks/Filter')
-rw-r--r--components/Tweaks/Filter/FilterPanel.tsx245
-rw-r--r--components/Tweaks/Filter/TagColorPanel.tsx139
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>
+ )
+}