Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
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
101 changes: 101 additions & 0 deletions components/Activity/AgendaList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import { Agenda } from '@open-source-bazaar/activityhub-service';
import { computed } from 'mobx';
import { observer } from 'mobx-react';
import { ObservedComponent } from 'mobx-react-helper';
import { Column, RestTable } from 'mobx-restful-table';
import { Badge } from 'react-bootstrap';

import { AgendaModel } from '../../models/Agenda';
import placeStore from '../../models/Place';
import { i18n, I18nContext } from '../../models/Translation';
import userStore from '../../models/User';
import { renderTagInput } from '../Tag';

export interface AgendaListProps {
activityId: number;
isOrganizer?: boolean;
userId?: number;
}

@observer
export class AgendaList extends ObservedComponent<AgendaListProps, typeof i18n> {
static contextType = I18nContext;

agendaStore = new AgendaModel(this.props.activityId);

@computed
get columns(): Column<Agenda>[] {
const { t } = this.observedContext;
const { isOrganizer = false } = this.observedProps;

return [
{
renderHead: t('title'),
renderBody: ({ forum }) => forum?.title || t('unknown'),
required: true,
invalidMessage: t('field_required'),
},
{
renderHead: t('summary'),
renderBody: ({ forum }) => forum?.summary || '-',
type: 'textarea',
rows: 3,
},
{
renderHead: t('start_time'),
renderBody: ({ forum }) => forum?.startTime ? new Date(forum.startTime).toLocaleString() : '-',
type: 'datetime-local',
},
{
renderHead: t('end_time'),
renderBody: ({ forum }) => forum?.endTime ? new Date(forum.endTime).toLocaleString() : '-',
type: 'datetime-local',
},
{
renderHead: t('place'),
renderBody: ({ forum }) => forum?.place?.name || t('unknown'),
renderInput: renderTagInput(placeStore),
required: true,
invalidMessage: t('field_required'),
},
{
key: 'mentors',
renderHead: t('mentors'),
renderBody: ({ mentors }) =>
mentors?.map(mentor => mentor.name).join(', ') || '-',
renderInput: renderTagInput(userStore),
required: true,
invalidMessage: t('field_required'),
},
{
key: 'adopted',
renderHead: t('status'),
renderBody: ({ adopted }) => (
<Badge bg={adopted ? 'success' : 'warning'}>
{adopted ? t('approved') : t('pending_review')}
</Badge>
),
type: 'checkbox',
readOnly: !isOrganizer,
},
];
}

render() {
const { activityId, userId } = this.props;

return (
<RestTable
className="h-100 text-center"
striped
hover
editable
deletable
columns={this.columns}
store={this.agendaStore}
{...({ filter: { activity: activityId, createdBy: userId } } as any)}
translator={this.observedContext}
/>
);
}
}
2 changes: 2 additions & 0 deletions components/Activity/menu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@ export const organizerMenu = ({ t }: typeof i18n, activityId: number): MenuItem[
{ href: `/activity/${activityId}/editor`, title: t('edit_activity') },
{ href: `/activity/${activityId}/forum`, title: t('forum_list') },
{ href: `/activity/${activityId}/cooperation`, title: t('cooperation_management') },
{ href: `/activity/${activityId}/agenda`, title: t('agenda_management') },
];

export const userMenu = ({ t }: typeof i18n): MenuItem[] => [
{ href: '/user/organization', title: t('organization_list') },
{ href: '/user/activity', title: t('activity_list') },
{ href: '/user/session', title: t('session_list') },
{ href: '/user/agenda', title: t('agenda_management') },
];
87 changes: 87 additions & 0 deletions components/Session/List.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import { Session } from '@open-source-bazaar/activityhub-service';
import { computed } from 'mobx';
import { observer } from 'mobx-react';
import { ObservedComponent } from 'mobx-react-helper';
import { Column, RestTable } from 'mobx-restful-table';
import { Button } from 'react-bootstrap';

import sessionStore from '../../models/Session';
import { i18n, I18nContext } from '../../models/Translation';

export interface SessionListProps {
showActions?: boolean;
}

@observer
export class SessionList extends ObservedComponent<SessionListProps, typeof i18n> {
static contextType = I18nContext;

@computed
get columns(): Column<Session>[] {
const { t } = this.observedContext;
const { showActions = true } = this.observedProps;

const baseColumns: Column<Session>[] = [
{
key: 'title',
renderHead: t('title'),
renderBody: ({ title }) => title || t('unknown'),
required: true,
invalidMessage: t('field_required'),
},
{
key: 'summary',
renderHead: t('summary'),
renderBody: ({ summary }) => summary || '-',
type: 'textarea',
rows: 3,
},
{
key: 'durationMinute',
renderHead: t('duration_minutes'),
renderBody: ({ durationMinute }) => `${durationMinute || 0} ${t('minutes')}`,
type: 'number',
min: 1,
required: true,
invalidMessage: t('field_required'),
},
{
key: 'peopleCapacity',
renderHead: t('people_capacity'),
renderBody: ({ peopleCapacity }) => peopleCapacity || '-',
type: 'number',
min: 1,
},
];

if (showActions) {
baseColumns.push({
renderHead: t('actions'),
renderBody: () => (
<Button variant="outline-success" size="sm" href="/user/agenda">
{t('submit_to_activity')}
</Button>
),
});
}

return baseColumns;
}

render() {
const { showActions = true } = this.observedProps;

return (
<RestTable
className="h-100 text-center"
striped
hover
editable={showActions}
deletable={showActions}
columns={this.columns}
store={sessionStore}
translator={this.observedContext}
/>
);
}
}
14 changes: 14 additions & 0 deletions models/Agenda.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { Agenda } from '@open-source-bazaar/activityhub-service';

import { TableModel } from './Base';
import userStore from './User';

export class AgendaModel extends TableModel<Agenda> {
baseURI = '';
client = userStore.client;

constructor(activityId: number) {
super();
this.baseURI = `activity/${activityId}/agenda`;
}
}
11 changes: 11 additions & 0 deletions models/Session.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { Session } from '@open-source-bazaar/activityhub-service';

import { TableModel } from './Base';
import userStore from './User';

export class SessionModel extends TableModel<Session> {
baseURI = 'session';
client = userStore.client;
}

export default new SessionModel();
32 changes: 32 additions & 0 deletions pages/activity/[id]/agenda/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { User } from '@open-source-bazaar/activityhub-service';
import { observer } from 'mobx-react';
import { useRouter } from 'next/router';
import { compose, JWTProps, jwtVerifier } from 'next-ssr-middleware';
import { FC, useContext } from 'react';

import { AgendaList } from '../../../../components/Activity/AgendaList';
import { organizerMenu } from '../../../../components/Activity/menu';
import { SessionBox } from '../../../../components/User/SessionBox';
import { I18nContext } from '../../../../models/Translation';

interface AgendaListPageProps extends JWTProps<User> {}

export const getServerSideProps = compose<{ id: string }, AgendaListPageProps>(
jwtVerifier(),
);

const AgendaListPage: FC<AgendaListPageProps> = observer(({ jwtPayload }) => {
const { asPath, query } = useRouter(),
i18n = useContext(I18nContext);

const activityId = +(query.id as string);
const title = i18n.t('agenda_management');

return (
<SessionBox {...{ title, jwtPayload }} path={asPath} menu={organizerMenu(i18n, activityId)}>
<AgendaList activityId={activityId} isOrganizer />
</SessionBox>
);
});

export default AgendaListPage;
29 changes: 29 additions & 0 deletions pages/user/agenda.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { User } from '@open-source-bazaar/activityhub-service';
import { observer } from 'mobx-react';
import { useRouter } from 'next/router';
import { JWTProps, jwtVerifier } from 'next-ssr-middleware';
import { FC, useContext } from 'react';

import { AgendaList } from '../../components/Activity/AgendaList';
import { userMenu } from '../../components/Activity/menu';
import { SessionBox } from '../../components/User/SessionBox';
import { I18nContext } from '../../models/Translation';

interface UserAgendaPageProps extends JWTProps<User> {}

export const getServerSideProps = jwtVerifier<UserAgendaPageProps>();

const UserAgendaPage: FC<UserAgendaPageProps> = observer(({ jwtPayload }) => {
const { asPath } = useRouter(),
i18n = useContext(I18nContext);

const title = i18n.t('agenda_management');

return (
<SessionBox {...{ title, jwtPayload }} path={asPath} menu={userMenu(i18n)}>
<AgendaList userId={jwtPayload?.id} />
</SessionBox>
);
});

export default UserAgendaPage;
36 changes: 36 additions & 0 deletions pages/user/session/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { User } from '@open-source-bazaar/activityhub-service';
import { observer } from 'mobx-react';
import { useRouter } from 'next/router';
import { compose, JWTProps, jwtVerifier } from 'next-ssr-middleware';
import { FC, useContext } from 'react';

import { userMenu } from '../../../components/Activity/menu';
import { SessionList } from '../../../components/Session/List';
import { SessionBox } from '../../../components/User/SessionBox';
import { I18nContext } from '../../../models/Translation';

interface SessionListPageProps extends JWTProps<User> {}

export const getServerSideProps = compose<{}, SessionListPageProps>(
jwtVerifier(),
async () => ({ props: {} }),
);

const SessionListPage: FC<SessionListPageProps> = observer(({ jwtPayload }) => {
const { asPath } = useRouter(),
i18n = useContext(I18nContext);

const title = i18n.t('session_list');

return (
<SessionBox
{...{ title, jwtPayload }}
path={asPath}
menu={userMenu(i18n)}
>
<SessionList />
</SessionBox>
);
});

export default SessionListPage;
26 changes: 26 additions & 0 deletions translation/en-US.ts
Original file line number Diff line number Diff line change
Expand Up @@ -145,5 +145,31 @@ export default {
logo: 'Logo',
activity_list: 'Activity List',
session_list: 'Session List',

// Session Management
session_management: 'Session Management',
create_session: 'Create Session',
edit_session: 'Edit Session',
session_title: 'Session Title',
session_summary: 'Session Summary',
duration_minutes: 'Duration (Minutes)',
minutes: 'minutes',
people_capacity: 'People Capacity',
session_created_successfully: 'Session created successfully!',
session_updated_successfully: 'Session updated successfully!',
submit_to_activity: 'Submit to Activity',
select_activity: 'Select Activity',
please_select: 'Please select...',
submitting: 'Submitting...',
agenda_submitted_successfully: 'Agenda submitted successfully!',
submission_failed: 'Submission failed. Please try again.',
submitted: 'Submitted',
agenda_management: 'Agenda Management',
submitted_agendas: 'Submitted Agendas',
review_agenda: 'Review Agenda',
mentors: 'Mentors',
approved: 'Approved',
pending_review: 'Pending Review',

unknown: 'Unknown',
} as const;
Loading
Loading