diff --git a/services/web/frontend/js/features/project-list/components/sidebar/sidebar-filters.tsx b/services/web/frontend/js/features/project-list/components/sidebar/sidebar-filters.tsx index e350bcd6e5..9345e8362b 100644 --- a/services/web/frontend/js/features/project-list/components/sidebar/sidebar-filters.tsx +++ b/services/web/frontend/js/features/project-list/components/sidebar/sidebar-filters.tsx @@ -15,13 +15,13 @@ function SidebarFilter({ filter, text }: SidebarFilterProps) { const { filter: activeFilter, selectFilter, - selectedTag, + selectedTagId, } = useProjectListContext() return (
  • diff --git a/services/web/frontend/js/features/project-list/components/sidebar/tags-list.tsx b/services/web/frontend/js/features/project-list/components/sidebar/tags-list.tsx index f15a47a17a..0987ef94c3 100644 --- a/services/web/frontend/js/features/project-list/components/sidebar/tags-list.tsx +++ b/services/web/frontend/js/features/project-list/components/sidebar/tags-list.tsx @@ -5,7 +5,10 @@ import { useTranslation } from 'react-i18next' import { Tag } from '../../../../../../app/src/Features/Tags/types' import ColorManager from '../../../../ide/colors/ColorManager' import Icon from '../../../../shared/components/icon' -import { useProjectListContext } from '../../context/project-list-context' +import { + UNCATEGORIZED_KEY, + useProjectListContext, +} from '../../context/project-list-context' import CreateTagModal from './create-tag-modal' import DeleteTagModal from './delete-tag-modal' import RenameTagModal from './rename-tag-modal' @@ -15,7 +18,7 @@ export default function TagsList() { const { tags, untaggedProjectsCount, - selectedTag, + selectedTagId, selectTag, addTag, renameTag, @@ -98,7 +101,7 @@ export default function TagsList() { {_.sortBy(tags, ['name']).map((tag, index) => { return (
  • ) })} -
  • - diff --git a/services/web/frontend/js/features/project-list/context/project-list-context.tsx b/services/web/frontend/js/features/project-list/context/project-list-context.tsx index 2d76bee714..fbd9bebbea 100644 --- a/services/web/frontend/js/features/project-list/context/project-list-context.tsx +++ b/services/web/frontend/js/features/project-list/context/project-list-context.tsx @@ -14,6 +14,7 @@ import { Project, Sort, } from '../../../../../types/project/dashboard/api' +import usePersistedState from '../../../shared/hooks/use-persisted-state' import getMeta from '../../../utils/meta' import useAsync from '../../../shared/hooks/use-async' import { getProjects } from '../util/api' @@ -46,6 +47,8 @@ const filters: FilterMap = { }, } +export const UNCATEGORIZED_KEY = 'uncategorized' + type ProjectListContextValue = { visibleProjects: Project[] setVisibleProjects: React.Dispatch> @@ -59,8 +62,8 @@ type ProjectListContextValue = { untaggedProjectsCount: number filter: Filter selectFilter: (filter: Filter) => void - selectedTag?: string | null - selectTag: (tagName: string | null) => void + selectedTagId?: string | undefined + selectTag: (tagId: string) => void addTag: (tag: Tag) => void renameTag: (tagId: string, newTagName: string) => void deleteTag: (tagId: string) => void @@ -86,9 +89,14 @@ export function ProjectListProvider({ children }: ProjectListProviderProps) { by: 'lastUpdated', order: 'desc', }) - const [filter, setFilter] = useState('all') - const [selectedTag, setSelectedTag] = useState() - const [tags, setTags] = useState([]) + const [filter, setFilter] = usePersistedState( + 'project-list-filter', + 'all' + ) + const [selectedTagId, setSelectedTagId] = usePersistedState< + string | undefined + >('project-list-selected-tag-id', undefined) + const [tags, setTags] = useState(getMeta('ol-tags', []) as Tag[]) const [searchText, setSearchText] = useState('') const { isLoading: loading, @@ -98,8 +106,6 @@ export function ProjectListProvider({ children }: ProjectListProviderProps) { } = useAsync() const isLoading = isIdle ? true : loading - useEffect(() => setTags(getMeta('ol-tags', []) as Tag[]), []) - useEffect(() => { setLoadProgress(40) runAsync(getProjects({ by: 'lastUpdated', order: 'desc' })) @@ -122,8 +128,8 @@ export function ProjectListProvider({ children }: ProjectListProviderProps) { ) } - if (selectedTag !== undefined) { - if (selectedTag === null) { + if (selectedTagId !== undefined) { + if (selectedTagId === UNCATEGORIZED_KEY) { const taggedProjectIds = _.uniq( _.flatten(tags.map(tag => tag.project_ids)) ) @@ -134,17 +140,30 @@ export function ProjectListProvider({ children }: ProjectListProviderProps) { !taggedProjectIds.includes(project.id) ) } else { - const tag = _.find(tags, tag => tag._id === selectedTag) - filteredProjects = filteredProjects.filter(project => - tag?.project_ids?.includes(project.id) - ) + const tag = _.find(tags, tag => tag._id === selectedTagId) + if (tag) { + filteredProjects = filteredProjects.filter(project => + tag?.project_ids?.includes(project.id) + ) + } else { + setFilter('all') + setSelectedTagId(undefined) + } } } else { filteredProjects = _.filter(filteredProjects, filters[filter]) } setVisibleProjects(filteredProjects) - }, [loadedProjects, tags, filter, selectedTag, searchText]) + }, [ + loadedProjects, + tags, + filter, + setFilter, + selectedTagId, + setSelectedTagId, + searchText, + ]) const untaggedProjectsCount = useMemo(() => { const taggedProjectIds = _.uniq(_.flatten(tags.map(tag => tag.project_ids))) @@ -156,14 +175,20 @@ export function ProjectListProvider({ children }: ProjectListProviderProps) { ).length }, [tags, loadedProjects]) - const selectFilter = useCallback((filter: Filter) => { - setFilter(filter) - setSelectedTag(undefined) - }, []) + const selectFilter = useCallback( + (filter: Filter) => { + setFilter(filter) + setSelectedTagId(undefined) + }, + [setFilter, setSelectedTagId] + ) - const selectTag = useCallback((tagId: string | null) => { - setSelectedTag(tagId) - }, []) + const selectTag = useCallback( + (tagId: string) => { + setSelectedTagId(tagId) + }, + [setSelectedTagId] + ) const addTag = useCallback((tag: Tag) => { setTags(tags => _.uniqBy(_.concat(tags, [tag]), '_id')) @@ -219,7 +244,7 @@ export function ProjectListProvider({ children }: ProjectListProviderProps) { isLoading, loadProgress, renameTag, - selectedTag, + selectedTagId, selectFilter, selectTag, setSearchText, @@ -241,7 +266,7 @@ export function ProjectListProvider({ children }: ProjectListProviderProps) { isLoading, loadProgress, renameTag, - selectedTag, + selectedTagId, selectFilter, selectTag, setSearchText,