Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue 1616/user home page #1647

Closed
wants to merge 44 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
9ef9184
Remove redirects for Activist Portal URIs
richardolsson Nov 10, 2023
987eeee
Create boilerplate for activist portal pages
richardolsson Nov 10, 2023
9ebd037
Add my home page with header and tabs
Jrende Nov 11, 2023
fb9d013
Add compoents per page
Jrende Nov 11, 2023
455a8a9
Change icons and tab colour on my home screen
KraftKatten Nov 11, 2023
7baa9eb
Merge branch 'issue-1616/user-home-page' of https://github.com/zetkin…
KraftKatten Nov 11, 2023
ee6146f
Fix syntax errors
Jrende Nov 11, 2023
2831cdd
Merge branch 'issue-1616/user-home-page' of https://github.com/zetkin…
KraftKatten Nov 11, 2023
5b7fefb
Add organizations list
Jrende Nov 11, 2023
087119d
Add user call assignments list
Jrende Nov 11, 2023
9e43335
Redirect from "/my" to "/my/home"
Jrende Nov 11, 2023
d70397f
Added task list to my todo
KraftKatten Nov 11, 2023
128267b
Merge branch 'issue-1616/user-home-page' of https://github.com/zetkin…
KraftKatten Nov 11, 2023
c32f904
Change titles on my todo
KraftKatten Nov 11, 2023
d21ada7
Improve look of call assignment list
Jrende Nov 11, 2023
a6576cf
Added to-dos for my home
KraftKatten Nov 11, 2023
8086a1b
Merge branch 'issue-1616/user-home-page' of https://github.com/zetkin…
KraftKatten Nov 11, 2023
bd285ff
Smaller table
Jrende Nov 11, 2023
f2634e9
Added icons to my todo
KraftKatten Nov 11, 2023
7f3245d
Merge branch 'issue-1616/user-home-page' of https://github.com/zetkin…
KraftKatten Nov 11, 2023
dbeef0a
Add link to organization home page
Jrende Nov 11, 2023
ecc0043
Moved icons to front of text on my todo
KraftKatten Nov 11, 2023
1ed13ca
Merge branch 'issue-1616/user-home-page' of https://github.com/zetkin…
KraftKatten Nov 11, 2023
4b0e0f0
Use data grid instead of list
Jrende Nov 12, 2023
28da72a
Changes to my organization page
KraftKatten Nov 12, 2023
7bf03cc
Merge branch 'issue-1616/user-home-page' of https://github.com/zetkin…
KraftKatten Nov 12, 2023
d5f9d8b
Create reusable event list for sign-up (activist portal)
richardolsson Nov 12, 2023
19e2d47
Merge pull request #1640 from zetkin/epic-1615/common-event-list
richardolsson Nov 12, 2023
9bb4db9
Fetch events for current user
Jrende Nov 12, 2023
1e161bb
Merge remote-tracking branch 'origin/epic-1615/activist-portal-base' …
Jrende Nov 12, 2023
ece355a
Added secondary text to my organization page
KraftKatten Nov 12, 2023
2741004
Merge branch 'issue-1616/user-home-page' of https://github.com/zetkin…
KraftKatten Nov 12, 2023
b0012be
Use event list component
Jrende Nov 12, 2023
8b6c1bb
Add user events to todo page
Jrende Nov 12, 2023
66aa8f3
Added scroll-to functionality for my home buttons
KraftKatten Nov 12, 2023
9b81317
Merge branch 'issue-1616/user-home-page' of https://github.com/zetkin…
KraftKatten Nov 12, 2023
001b04d
Added dividers to org list
KraftKatten Nov 12, 2023
ee9661c
Fixed margins on headers on my home
KraftKatten Nov 12, 2023
224bc4c
Added hardcoded Next up to my home
KraftKatten Nov 12, 2023
0729f66
Pagination for events
Jrende Nov 12, 2023
6eefa0f
Changed margins on my tasks
KraftKatten Nov 12, 2023
eb6d9a2
Merge branch 'issue-1616/user-home-page' of https://github.com/zetkin…
KraftKatten Nov 12, 2023
75cef16
Show only 5 events
Jrende Nov 12, 2023
89caebf
More linting
Jrende Nov 12, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 0 additions & 16 deletions next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,22 +58,6 @@ module.exports = {
destination: '/legacy?path=/campaign/action%3A:eventId&orgId=:orgId',
permanent: false,
},
// all paths with /o redirected to Gen2
{
source: '/o/:path*',
destination: 'https://zetk.in/o/:path*',
permanent: false,
},
{
source: '/organize/:orgId/campaigns/:path*',
destination: '/organize/:orgId/projects/:path*',
permanent: false,
},
{
source: '/organize/:orgId/people/views/:path*',
destination: '/organize/:orgId/people/lists/:path*',
permanent: false,
}
];
},
};
64 changes: 64 additions & 0 deletions src/features/events/components/EventSignUpCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { FC } from 'react';
import {
Button,
Card,
CardActions,
CardContent,
CardMedia,
Typography,
useTheme,
} from '@mui/material';

import { ZetkinEvent } from 'utils/types/zetkin';

type EventSignUpCardProps = {
event: ZetkinEvent;
};

const EventSignUpCard: FC<EventSignUpCardProps> = ({ event }) => {
const theme = useTheme();
// TODO: Instead of always using the en-US .toLocaleString, update to match the user settings.
const startTime = new Date(event.start_time).toLocaleString('sv-SE', {
hour: 'numeric',
minute: 'numeric',
});

return (
<Card sx={{ marginTop: '2rem' }}>
<CardMedia
alt={event.title || undefined}
component="img"
height="140"
image="https://zetkin.org/assets/img/hero.jpg"
/>
<CardContent>
<Typography component="div" gutterBottom variant="h5">
{event.title}
</Typography>
<Typography
component="p"
gutterBottom
sx={{ color: theme.palette.secondary.main, fontSize: '.7rem' }}
>
{startTime} - {event.location?.title}
</Typography>
<Typography color={theme.palette.secondary.main} variant="body2">
{event.info_text}
</Typography>
</CardContent>
<CardActions sx={{ justifyContent: 'space-between' }}>
<Button
href={`/o/${event.organization.id}/projects/${event.id}`}
size="small"
>
Read more
</Button>
<Button size="small" variant="contained">
Count me in!
</Button>
</CardActions>
</Card>
);
};

export default EventSignUpCard;
21 changes: 21 additions & 0 deletions src/features/events/components/EventSignUpList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { Box } from '@mui/material';
import { FC } from 'react';

import EventSignUpCard from './EventSignUpCard';
import { ZetkinEvent } from 'utils/types/zetkin';

type EventSignUpListProps = {
events: ZetkinEvent[];
};

const EventSignUpList: FC<EventSignUpListProps> = ({ events }) => {
return (
<Box>
{events.map((event) => {
return <EventSignUpCard key={event.id} event={event} />;
})}
</Box>
);
};

export default EventSignUpList;
25 changes: 25 additions & 0 deletions src/features/user/hooks/useCurrentUserCallAssigments.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { CallAssignmentData } from '../../callAssignments/apiTypes';
import { IFuture } from 'core/caching/futures';
import { loadListIfNecessary } from 'core/caching/cacheUtils';
import {
callAssignmentsLoad,
callAssignmentsLoaded,
} from '../../callAssignments/store';
import { useApiClient, useAppDispatch, useAppSelector } from 'core/hooks';

export default function useCurrentUserCallAssignments(): IFuture<
CallAssignmentData[]
> {
const apiClient = useApiClient();
const dispatch = useAppDispatch();
const assignmentList = useAppSelector(
(state) => state.callAssignments.assignmentList
);

return loadListIfNecessary(assignmentList, dispatch, {
actionOnLoad: () => callAssignmentsLoad(),
actionOnSuccess: (data) => callAssignmentsLoaded(data),
loader: () =>
apiClient.get<CallAssignmentData[]>(`/api/users/me/call_assignments`),
});
}
19 changes: 19 additions & 0 deletions src/features/user/hooks/useCurrentUserEvents.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { IFuture } from 'core/caching/futures';
import { loadListIfNecessary } from 'core/caching/cacheUtils';
import { ZetkinEvent } from 'utils/types/zetkin';
import { eventsLoad, eventsLoaded } from '../../events/store';
import { useApiClient, useAppDispatch, useAppSelector } from 'core/hooks';

export default function useCurrentUserEvents(): IFuture<ZetkinEvent[]> {
const apiClient = useApiClient();
const dispatch = useAppDispatch();
const events = useAppSelector((state) => state.events.eventList);

const eventFuture = loadListIfNecessary(events, dispatch, {
actionOnLoad: () => eventsLoad(),
actionOnSuccess: (events) => eventsLoaded(events),
loader: () => apiClient.get<ZetkinEvent[]>(`/api/users/me/actions`),
});

return eventFuture;
}
46 changes: 46 additions & 0 deletions src/pages/my/home/CallAssignmentList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { Box } from '@mui/system';
import { FC } from 'react';
import { scaffold } from 'utils/next';
import { ZetkinCallAssignment } from 'utils/types/zetkin';
import { DataGrid, GridColDef } from '@mui/x-data-grid';

const scaffoldOptions = {
allowNonOfficials: true,
authLevelRequired: 1,
};

const columns: GridColDef[] = [
{
disableColumnMenu: true,
field: 'title',
flex: 1,
headerName: 'Title',
},
];

export const getServerSideProps = scaffold(async () => {
return {
props: {},
};
}, scaffoldOptions);

type PageProps = { callAssignments: ZetkinCallAssignment[] };

const Page: FC<PageProps> = ({ callAssignments }) => {
return (
<Box>
<DataGrid
columns={columns}
disableRowSelectionOnClick
initialState={{
pagination: { paginationModel: { pageSize: 5 } },
}}
pageSizeOptions={[10]}
pagination
rows={callAssignments}
/>
</Box>
);
};

export default Page;
52 changes: 52 additions & 0 deletions src/pages/my/home/CallAssignments.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { Box } from '@mui/system';
import CallAssignmentList from './CallAssignmentList';
import { FC } from 'react';
import { HeadsetMic } from '@mui/icons-material';
import { scaffold } from 'utils/next';
import useCurrentUserCallAssignments from 'features/user/hooks/useCurrentUserCallAssigments';
import ZUIFuture from 'zui/ZUIFuture';

const scaffoldOptions = {
allowNonOfficials: true,
authLevelRequired: 1,
};

export const getServerSideProps = scaffold(async () => {
return {
props: {},
};
}, scaffoldOptions);

type PageProps = void;

const Page: FC<PageProps> = () => {
const callAssignments = useCurrentUserCallAssignments();
return (
<Box>
<Box
sx={{
alignItems: 'center',
display: 'flex',
gap: '5px',
pl: '0',
pt: '1em',
}}
>
<HeadsetMic />
<h2
style={{
marginBottom: 0,
marginTop: 0,
}}
>
Call Assignments
</h2>
</Box>
<ZUIFuture future={callAssignments}>
{(data) => <CallAssignmentList callAssignments={data} />}
</ZUIFuture>
</Box>
);
};

export default Page;
59 changes: 59 additions & 0 deletions src/pages/my/home/EventsFilterList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import Box from '@mui/material/Box';
import { Button } from '@mui/material';
import EventSignUpList from 'features/events/components/EventSignUpList';
import { scaffold } from 'utils/next';
import { ZetkinEvent } from 'utils/types/zetkin';
import { FC, useEffect, useState } from 'react';

const scaffoldOptions = {
allowNonOfficials: true,
authLevelRequired: 1,
};

export const getServerSideProps = scaffold(async () => {
return {
props: {},
};
}, scaffoldOptions);

type PageProps = { events: ZetkinEvent[] };

const pageSize = 5;
const Page: FC<PageProps> = ({ events }) => {
const [page, setPage] = useState(0);
const [eventsView, setEventsView] = useState<ZetkinEvent[]>([]);
const length = events.length;
useEffect(() => {
setEventsView(events.slice(page * pageSize, (page + 1) * pageSize));
}, [events, page]);

function changePage(incr: number) {
setPage((prev) => prev + incr);
}
const pagesAmount =
Math.floor(length / pageSize) + (length % pageSize != 0 ? 1 : 0);

return (
<Box>
{length >= pageSize && (
<Box sx={{ alignItems: 'baseline', display: 'flex', margin: 0 }}>
<Button disabled={page === 0} onClick={() => changePage(-1)}>
Prev
</Button>
<p>
Page {page + 1} of {pagesAmount}
</p>
<Button
disabled={page >= pagesAmount - 1}
onClick={() => changePage(1)}
>
Next
</Button>
</Box>
)}
<EventSignUpList events={eventsView} />
</Box>
);
};

export default Page;
36 changes: 36 additions & 0 deletions src/pages/my/home/EventsPage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { Box } from '@mui/system';
import { FC } from 'react';
import { scaffold } from 'utils/next';

const scaffoldOptions = {
allowNonOfficials: true,
authLevelRequired: 1,
};

export const getServerSideProps = scaffold(async () => {
return {
props: {},
};
}, scaffoldOptions);

type PageProps = void;

const Page: FC<PageProps> = () => {
return (
<Box
id="events"
sx={{
pl: '1em',
pr: '1em',
}}
>
<p>Sign up for more events here.</p>
<p>
TODO: Add events here, and a button for filtering between event type and
project, (and organization?)
</p>
</Box>
);
};

export default Page;
Loading