Merge pull request #58 from dakshesh14/feat/issue_view

feat: reset to default view, and create new default view
This commit is contained in:
Vihar Kurama 2022-12-20 18:33:31 +05:30 committed by GitHub
commit 78a1522b48
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 80 additions and 12 deletions

View File

@ -4,3 +4,4 @@ export const SET_ISSUE_VIEW = "SET_ISSUE_VIEW";
export const SET_GROUP_BY_PROPERTY = "SET_GROUP_BY_PROPERTY";
export const SET_ORDER_BY_PROPERTY = "SET_ORDER_BY_PROPERTY";
export const SET_FILTER_ISSUES = "SET_FILTER_ISSUES";
export const RESET_TO_DEFAULT = "RESET_TO_DEFAULT";

View File

@ -9,13 +9,14 @@ import {
SET_GROUP_BY_PROPERTY,
SET_ORDER_BY_PROPERTY,
SET_FILTER_ISSUES,
RESET_TO_DEFAULT,
} from "constants/theme.context.constants";
// components
import ToastAlert from "components/toast-alert";
// hooks
import useUser from "lib/hooks/useUser";
// constants
import { PROJECT_MEMBERS, USER_PROJECT_VIEW } from "constants/fetch-keys";
import { USER_PROJECT_VIEW } from "constants/fetch-keys";
// services
import projectService from "lib/services/project.service";
@ -31,7 +32,8 @@ type ReducerActionType = {
| typeof SET_ISSUE_VIEW
| typeof SET_ORDER_BY_PROPERTY
| typeof SET_FILTER_ISSUES
| typeof SET_GROUP_BY_PROPERTY;
| typeof SET_GROUP_BY_PROPERTY
| typeof RESET_TO_DEFAULT;
payload?: Partial<Theme>;
};
@ -46,6 +48,8 @@ type ContextType = {
setGroupByProperty: (property: NestedKeyOf<IIssue> | null) => void;
setOrderBy: (property: NestedKeyOf<IIssue> | null) => void;
setFilterIssue: (property: "activeIssue" | "backlogIssue" | null) => void;
resetFilterToDefault: () => void;
setNewFilterDefaultView: () => void;
};
type StateType = Theme;
@ -70,8 +74,7 @@ export const reducer: ReducerFunctionType = (state, action) => {
};
return newState;
case REHYDRATE_THEME: {
const newState = payload;
return { ...initialState, ...newState };
return { ...initialState, ...payload };
}
case SET_ISSUE_VIEW: {
const newState = {
@ -113,6 +116,12 @@ export const reducer: ReducerFunctionType = (state, action) => {
...newState,
};
}
case RESET_TO_DEFAULT: {
return {
...initialState,
...payload,
};
}
default: {
return state;
}
@ -120,18 +129,27 @@ export const reducer: ReducerFunctionType = (state, action) => {
};
const saveDataToServer = async (workspaceSlug: string, projectID: string, state: any) => {
await projectService.setProjectView(workspaceSlug, projectID, state);
await projectService.setProjectView(workspaceSlug, projectID, {
view_props: state,
});
};
const setNewDefault = async (workspaceSlug: string, projectID: string, state: any) => {
await projectService.setProjectView(workspaceSlug, projectID, {
view_props: state,
default_props: state,
});
};
export const ThemeContextProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
const [state, dispatch] = useReducer(reducer, initialState);
const { activeProject, activeWorkspace, user } = useUser();
const { activeProject, activeWorkspace } = useUser();
const { data: projectMember } = useSWR(
activeWorkspace && activeProject ? PROJECT_MEMBERS(activeProject.id) : null,
const { data: myViewProps, mutate: mutateMyViewProps } = useSWR(
activeWorkspace && activeProject ? USER_PROJECT_VIEW(activeProject.id) : null,
activeWorkspace && activeProject
? () => projectService.projectMembers(activeWorkspace.slug, activeProject.id)
? () => projectService.projectMemberMe(activeWorkspace.slug, activeProject.id)
: null
);
@ -191,6 +209,7 @@ export const ThemeContextProvider: React.FC<{ children: React.ReactNode }> = ({
},
[activeProject, activeWorkspace, state]
);
const setFilterIssue = useCallback(
(property: "activeIssue" | "backlogIssue" | null) => {
dispatch({
@ -209,12 +228,30 @@ export const ThemeContextProvider: React.FC<{ children: React.ReactNode }> = ({
[activeProject, activeWorkspace, state]
);
const setNewDefaultView = useCallback(() => {
if (!activeWorkspace || !activeProject) return;
setNewDefault(activeWorkspace.slug, activeProject.id, state);
}, [activeProject, activeWorkspace, state]);
const resetToDefault = useCallback(() => {
dispatch({
type: RESET_TO_DEFAULT,
payload: myViewProps?.default_props,
});
if (!activeWorkspace || !activeProject) return;
saveDataToServer(activeWorkspace.slug, activeProject.id, myViewProps?.default_props).then(
() => {
mutateMyViewProps();
}
);
}, [activeProject, activeWorkspace, myViewProps, mutateMyViewProps]);
useEffect(() => {
dispatch({
type: REHYDRATE_THEME,
payload: projectMember?.find((member) => member.member.id === user?.id)?.view_props,
payload: myViewProps?.view_props,
});
}, [projectMember, user]);
}, [myViewProps]);
return (
<themeContext.Provider
@ -229,6 +266,8 @@ export const ThemeContextProvider: React.FC<{ children: React.ReactNode }> = ({
setOrderBy,
filterIssue: state.filterIssue,
setFilterIssue,
resetFilterToDefault: resetToDefault,
setNewFilterDefaultView: setNewDefaultView,
}}
>
<ToastAlert />

View File

@ -17,6 +17,8 @@ const useIssuesFilter = (projectIssues: IIssue[]) => {
setOrderBy,
filterIssue,
setFilterIssue,
resetFilterToDefault,
setNewFilterDefaultView,
} = useTheme();
const { states } = useUser();
@ -95,6 +97,8 @@ const useIssuesFilter = (projectIssues: IIssue[]) => {
setOrderBy,
filterIssue,
setFilterIssue,
resetFilterToDefault,
setNewFilterDefaultView,
} as const;
};

View File

@ -230,7 +230,10 @@ class ProjectServices extends APIService {
async setProjectView(
workspacSlug: string,
projectId: string,
data: ProjectViewTheme
data: {
view_props?: ProjectViewTheme;
default_props?: ProjectViewTheme;
}
): Promise<any> {
await this.post(PROJECT_VIEW_ENDPOINT(workspacSlug, projectId), data)
.then((response) => {

View File

@ -142,6 +142,8 @@ const ProjectIssues: NextPage = () => {
setFilterIssue,
orderBy,
filterIssue,
resetFilterToDefault,
setNewFilterDefaultView,
} = useIssuesFilter(projectIssues?.results.filter((p) => p.parent === null) ?? []);
useEffect(() => {
@ -292,6 +294,23 @@ const ProjectIssues: NextPage = () => {
))}
</div>
</div>
<div className="border-b-2"></div>
<div className="relative flex justify-end gap-x-3">
<button
type="button"
className="text-xs"
onClick={() => resetFilterToDefault()}
>
Reset to default
</button>
<button
type="button"
className="text-xs font-medium text-theme"
onClick={() => setNewFilterDefaultView()}
>
Set as default
</button>
</div>
</div>
</Popover.Panel>
</Transition>

View File

@ -31,7 +31,9 @@ export interface IProjectMember {
workspace: IWorkspace;
comment: string;
role: 5 | 10 | 15 | 20;
view_props: ProjectViewTheme;
default_props: ProjectViewTheme;
created_at: Date;
updated_at: Date;