Skip to content

Commit

Permalink
Merge pull request #1558 from zetkin/issue-1542/refactor-tags-hook
Browse files Browse the repository at this point in the history
Issue 1542/refactor tags hook
  • Loading branch information
rebecarubio authored Sep 28, 2023
2 parents 6b7398b + a4e7110 commit fcf7956
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 52 deletions.
30 changes: 30 additions & 0 deletions src/features/tags/hooks/useTag.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { useSelector } from 'react-redux';

import { IFuture } from 'core/caching/futures';
import { loadItemIfNecessary } from 'core/caching/cacheUtils';
import { RootState } from 'core/store';
import { ZetkinTag } from 'utils/types/zetkin';
import { tagLoad, tagLoaded } from '../store';
import { useApiClient, useEnv } from 'core/hooks';

interface UseTagReturn {
tagFuture: IFuture<ZetkinTag>;
}
export default function useTag(orgId: number, tagId: number): UseTagReturn {
const apiClient = useApiClient();
const tags = useSelector((state: RootState) => state.tags);
const env = useEnv();

const item = tags.tagList.items.find((item) => item.id == tagId);

const tagFuture = loadItemIfNecessary(item, env.store, {
actionOnLoad: () => tagLoad(tagId),
actionOnSuccess: (tag) => tagLoaded(tag),
loader: () =>
apiClient.get<ZetkinTag>(`/api/orgs/${orgId}/people/tags/${tagId}`),
});

return {
tagFuture,
};
}
39 changes: 39 additions & 0 deletions src/features/tags/hooks/useTagMutation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { useStore } from 'react-redux';

import { useApiClient } from 'core/hooks';
import { ZetkinTag } from 'utils/types/zetkin';
import { tagAssigned, tagUnassigned } from '../store';

interface UseTagMutationReturn {
assignToPerson: (personId: number, value?: string) => void;
removeFromPerson: (personId: number) => Promise<void>;
}
export default function useTagMutation(
orgId: number,
tagId: number
): UseTagMutationReturn {
const apiClient = useApiClient();

const store = useStore();

const assignToPerson = async (personId: number, value?: string) => {
const data = value ? { value } : undefined;
const tag = await apiClient.put<ZetkinTag>(
`/api/orgs/${orgId}/people/${personId}/tags/${tagId}`,
data
);
store.dispatch(tagAssigned([personId, tag]));
};

const removeFromPerson = async (personId: number) => {
await apiClient.delete(
`/api/orgs/${orgId}/people/${personId}/tags/${tagId}`
);
store.dispatch(tagUnassigned([personId, tagId]));
};

return {
assignToPerson,
removeFromPerson,
};
}
30 changes: 0 additions & 30 deletions src/features/tags/models/TagModel.ts

This file was deleted.

18 changes: 2 additions & 16 deletions src/features/tags/repos/TagsRepo.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import Environment from 'core/env/Environment';
import IApiClient from 'core/api/client/IApiClient';
import { IFuture } from 'core/caching/futures';
import { loadItemIfNecessary } from 'core/caching/cacheUtils';

import { Store } from 'core/store';
import { ZetkinTag } from 'utils/types/zetkin';
import { tagAssigned, tagLoad, tagLoaded, tagUnassigned } from '../store';
import { tagAssigned, tagUnassigned } from '../store';

export default class TagsRepo {
private _apiClient: IApiClient;
Expand All @@ -29,19 +28,6 @@ export default class TagsRepo {
this._apiClient = env.apiClient;
}

getTag(orgId: number, tagId: number): IFuture<ZetkinTag> {
const state = this._store.getState();
const item = state.tags.tagList.items.find((item) => item.id == tagId);
return loadItemIfNecessary(item, this._store, {
actionOnLoad: () => tagLoad(tagId),
actionOnSuccess: (tag) => tagLoaded(tag),
loader: () =>
this._apiClient.get<ZetkinTag>(
`/api/orgs/${orgId}/people/tags/${tagId}`
),
});
}

async removeTagFromPerson(orgId: number, personId: number, tagId: number) {
await this._apiClient.delete(
`/api/orgs/${orgId}/people/${personId}/tags/${tagId}`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ import {

import { IColumnType } from '.';
import TagChip from 'features/tags/components/TagManager/components/TagChip';
import TagModel from 'features/tags/models/TagModel';
import useAccessLevel from 'features/views/hooks/useAccessLevel';
import useModel from 'core/useModel';
import useTag from 'features/tags/hooks/useTag';
import useTagMutation from 'features/tags/hooks/useTagMutation';
import ViewDataModel from 'features/views/models/ViewDataModel';
import { ZetkinObjectAccess } from 'core/api/types';
import { ZetkinTag } from 'utils/types/zetkin';
Expand Down Expand Up @@ -123,7 +123,9 @@ const Cell: FC<{
// TODO: Find a way to share a model between cells in a column
const query = useRouter().query;
const orgId = parseInt(query.orgId as string);
const model = useModel((env) => new TagModel(env, orgId, tagId));
const { tagFuture } = useTag(orgId, tagId);
const { assignToPerson, removeFromPerson } = useTagMutation(orgId, tagId);

const styles = useStyles();

const [isRestricted] = useAccessLevel();
Expand All @@ -134,7 +136,7 @@ const Cell: FC<{
return (
<TagChip
onDelete={() => {
model.removeFromPerson(personId);
removeFromPerson(personId);
}}
tag={cell}
/>
Expand All @@ -145,12 +147,12 @@ const Cell: FC<{
// likely that a user in restricted mode will not have access to assign
// (or even retrieve) the tag.
return (
<ZUIFuture future={model.getTag()}>
<ZUIFuture future={tagFuture}>
{(tag) => (
<Box
className={styles.ghostContainer}
onClick={() => {
model.assignToPerson(personId);
assignToPerson(personId);
}}
>
<Box className={styles.ghost}>
Expand Down

0 comments on commit fcf7956

Please sign in to comment.