diff --git a/assets/js/dashboard/components/dropdown.tsx b/assets/js/dashboard/components/dropdown.tsx index 308720f52000..e9d25dbcff64 100644 --- a/assets/js/dashboard/components/dropdown.tsx +++ b/assets/js/dashboard/components/dropdown.tsx @@ -18,32 +18,57 @@ import { export const ToggleDropdownButton = forwardRef< HTMLDivElement, { + variant?: 'ghost' | 'button' + className?: string currentOption: ReactNode children: ReactNode onClick: () => void dropdownContainerProps: AriaAttributes } ->(({ currentOption, children, onClick, dropdownContainerProps }, ref) => { - return ( -
- - {children} -
- ) -}) +>( + ( + { + className, + currentOption, + children, + onClick, + dropdownContainerProps, + ...props + }, + ref + ) => { + const { variant } = { variant: 'button', ...props } + const wrapperClass = { ghost: '', button: 'min-w-32 md:w-48 md:relative' }[ + variant + ] + const sharedButtonClass = + 'flex items-center rounded text-xs md:text-sm leading-tight px-2 py-2 md:px-3' + const buttonClass = { + ghost: + 'text-gray-500 hover:text-gray-800 hover:bg-gray-200 dark:hover:text-gray-200 dark:hover:bg-gray-900', + button: + 'w-full justify-between bg-white dark:bg-gray-800 shadow text-gray-800 dark:text-gray-200 hover:bg-gray-200 dark:hover:bg-gray-900' + }[variant] + + return ( +
+ + {children} +
+ ) + } +) export const DropdownMenuWrapper = forwardRef< HTMLDivElement, diff --git a/assets/js/dashboard/filters.js b/assets/js/dashboard/filters.js deleted file mode 100644 index 455d760222c6..000000000000 --- a/assets/js/dashboard/filters.js +++ /dev/null @@ -1,373 +0,0 @@ -/** @format */ - -import React, { Fragment, useEffect, useState } from 'react' -import { useQueryContext } from './query-context' -import { useSiteContext } from './site-context' -import { filterRoute } from './router' -import { - AppNavigationLink, - useAppNavigate -} from './navigation/use-app-navigate' -import { - AdjustmentsVerticalIcon, - MagnifyingGlassIcon, - XMarkIcon, - PencilSquareIcon -} from '@heroicons/react/20/solid' -import classNames from 'classnames' -import { Menu, Transition } from '@headlessui/react' - -import { - FILTER_GROUP_TO_MODAL_TYPE, - cleanLabels, - FILTER_MODAL_TO_FILTER_GROUP, - formatFilterGroup, - EVENT_PROPS_PREFIX, - plainFilterText, - styledFilterText -} from './util/filters' - -const WRAPSTATE = { unwrapped: 0, waiting: 1, wrapped: 2 } - -function removeFilter(filterIndex, navigate, query) { - const newFilters = query.filters.filter( - (_filter, index) => filterIndex != index - ) - const newLabels = cleanLabels(newFilters, query.labels) - - navigate({ - search: (search) => ({ - ...search, - filters: newFilters, - labels: newLabels - }) - }) -} - -function clearAllFilters(navigate) { - navigate({ - search: (search) => ({ - ...search, - filters: null, - labels: null - }) - }) -} - -function AppliedFilterPillVertical({ filterIndex, filter }) { - const { query } = useQueryContext() - const navigate = useAppNavigate() - const [_operation, filterKey, _clauses] = filter - - const type = filterKey.startsWith(EVENT_PROPS_PREFIX) ? 'props' : filterKey - - return ( - -
- search} - className="group flex w-full justify-between items-center" - style={{ width: 'calc(100% - 1.5rem)' }} - > - - {styledFilterText(query, filter)} - - - - removeFilter(filterIndex, navigate, query)} - > - - -
-
- ) -} - -function OpenFilterGroupOptionsButton({ option }) { - return ( - - {({ active }) => ( - search} - className={classNames( - active - ? 'bg-gray-100 dark:bg-gray-900 text-gray-900 dark:text-gray-100' - : 'text-gray-800 dark:text-gray-300', - 'block px-4 py-2 text-sm font-medium' - )} - > - {formatFilterGroup(option)} - - )} - - ) -} - -function DropdownContent({ wrapped }) { - const navigate = useAppNavigate() - const site = useSiteContext() - const { query } = useQueryContext() - const [addingFilter, setAddingFilter] = useState(false) - - if (wrapped === WRAPSTATE.unwrapped || addingFilter) { - let filterModals = { ...FILTER_MODAL_TO_FILTER_GROUP } - if (!site.propsAvailable) delete filterModals.props - - return ( - <> - {Object.keys(filterModals).map((option) => ( - - ))} - - ) - } - - return ( - <> -
setAddingFilter(true)} - > - + Add filter -
- {query.filters.map((filter, index) => ( - - ))} - -
clearAllFilters(navigate)} - > - Clear All Filters -
-
- - ) -} - -function Filters() { - const navigate = useAppNavigate() - const { query } = useQueryContext() - - const [wrapped, setWrapped] = useState(WRAPSTATE.waiting) - const [viewport, setViewport] = useState(1080) - - useEffect(() => { - handleResize() - - window.addEventListener('resize', handleResize, false) - - return () => { - window.removeEventListener('resize', handleResize, false) - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []) - - useEffect(() => { - setWrapped(WRAPSTATE.waiting) - }, [query, viewport]) - - useEffect(() => { - if (wrapped === WRAPSTATE.waiting) { - updateDisplayMode() - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [wrapped]) - - function handleResize() { - setViewport(window.innerWidth || 639) - } - - // Checks if the filter container is wrapping items - function updateDisplayMode() { - const container = document.getElementById('filters') - const children = (container && [...container.childNodes]) || [] - - // Always wrap on mobile - if (query.filters.length > 0 && viewport <= 768) { - setWrapped(WRAPSTATE.wrapped) - return - } - - setWrapped(WRAPSTATE.unwrapped) - - // Check for different y value between all child nodes - this indicates a wrap - children.forEach((child) => { - const currentChildY = child.getBoundingClientRect().top - const firstChildY = children[0].getBoundingClientRect().top - if (currentChildY !== firstChildY) { - setWrapped(WRAPSTATE.wrapped) - } - }) - } - - function AppliedFilterPillHorizontal({ filterIndex, filter }) { - const { query } = useQueryContext() - const [_operation, filterKey, _clauses] = filter - const type = filterKey.startsWith(EVENT_PROPS_PREFIX) ? 'props' : filterKey - return ( - - search} - > - - {styledFilterText(query, filter)} - - - removeFilter(filterIndex, navigate, query)} - > - - - - ) - } - - function renderDropdownButton() { - if (wrapped === false) { - const filterCount = query.filters.length - return ( - <> -