Unify admin list pages
This commit is contained in:
+7
-1
@@ -23,7 +23,13 @@ export interface Event {
|
||||
signupForm: SignupForm[];
|
||||
}
|
||||
|
||||
export async function getEvents(options: any = {}): Promise<Event[]> {
|
||||
interface Options {
|
||||
onlyNonPast?: boolean;
|
||||
limit?: number;
|
||||
auth?: boolean;
|
||||
}
|
||||
|
||||
export async function getEvents(options: Options = {}): Promise<Event[]> {
|
||||
const { onlyNonPast, limit, auth } = options;
|
||||
try {
|
||||
const params = {
|
||||
|
||||
+7
-2
@@ -20,10 +20,15 @@ export interface Post {
|
||||
autohide_enabled: boolean;
|
||||
}
|
||||
|
||||
interface Options {
|
||||
auth?: boolean;
|
||||
}
|
||||
|
||||
export async function getFeed(): Promise<Post[]> {
|
||||
export async function getFeed(options: Options = {}): Promise<Post[]> {
|
||||
const { auth } = options;
|
||||
const headers = auth ? { "Authorization": getAuthHeader() } : null;
|
||||
try {
|
||||
const resp = await axios.get(url);
|
||||
const resp = await axios.get(url, { headers });
|
||||
return resp.data["results"];
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
@import "../../assets/scss/globals";
|
||||
|
||||
|
||||
.admin-event-page {
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
table,
|
||||
th,
|
||||
td {
|
||||
border: 1px solid color(white1);
|
||||
padding: 0.5rem;
|
||||
|
||||
a {
|
||||
color: color(orange1);
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,118 +1,63 @@
|
||||
import React from "react";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { Helmet } from "react-helmet";
|
||||
import Anchor from "@components/Anchor";
|
||||
import { formatRelative } from "date-fns";
|
||||
|
||||
import "./AdminEventPage.scss";
|
||||
import { Event, getEvents } from "@models/Event";
|
||||
import { StaticContext } from "@server/StaticContext";
|
||||
import AdminListCommon from "./AdminListCommon";
|
||||
import Anchor from "@components/Anchor";
|
||||
import AddIcon from "@assets/img/add-icon.png";
|
||||
import { Event, getEvents } from "@models/Event";
|
||||
|
||||
const URL = "/admin/events"
|
||||
|
||||
export interface AdminEventPageProps {
|
||||
staticContext: StaticContext;
|
||||
}
|
||||
export interface AdminEventPageState {
|
||||
events: Event[];
|
||||
error?: string;
|
||||
}
|
||||
const renderAddLink = () => (
|
||||
<Anchor className="add-link" to={`${URL}/create`}>
|
||||
<img src={AddIcon} /> Create event
|
||||
</Anchor>
|
||||
)
|
||||
|
||||
class AdminEventPage extends React.Component<AdminEventPageProps, AdminEventPageState> {
|
||||
constructor(props: AdminEventPageProps) {
|
||||
super(props);
|
||||
const { staticContext } = props;
|
||||
|
||||
if (staticContext) {
|
||||
/* The static context is an object that manages promises when
|
||||
rendering on the server. If staticContext exists, that means
|
||||
we have to store all promises in it. Otherwise, operate
|
||||
normally. See server/index.ts. */
|
||||
if (staticContext.resolutions.getEvents) {
|
||||
const events = staticContext.resolutions.getEvents as Event[];
|
||||
this.state = {
|
||||
events,
|
||||
};
|
||||
} else {
|
||||
this.state = {
|
||||
events: [],
|
||||
};
|
||||
const promiseEvents = this.fetchEvents();
|
||||
staticContext.promises.getEvents = promiseEvents;
|
||||
}
|
||||
} else {
|
||||
this.state = {
|
||||
events: [],
|
||||
};
|
||||
this.fetchEvents();
|
||||
}
|
||||
const renderData = (events: Event[]) => {
|
||||
if (!events || events.length === 0) {
|
||||
return <div>No events.</div>;
|
||||
}
|
||||
|
||||
fetchEvents = async () => {
|
||||
const getEventsPromise = getEvents({ auth: true });
|
||||
try {
|
||||
const events = await getEventsPromise;
|
||||
this.setState({
|
||||
events,
|
||||
});
|
||||
return getEventsPromise;
|
||||
} catch (err) {
|
||||
this.setState({
|
||||
error: String(err),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
renderAddLink = () => (
|
||||
<Anchor className="add-link" to="/admin/events/create">
|
||||
<img src={AddIcon} /> Create event
|
||||
</Anchor>
|
||||
)
|
||||
|
||||
renderData = () => {
|
||||
const { events, error } = this.state;
|
||||
|
||||
if (error) {
|
||||
return <div className="error">{error}</div>;
|
||||
}
|
||||
|
||||
if (!events || events.length === 0) {
|
||||
return <div>No events.</div>;
|
||||
}
|
||||
|
||||
return (
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Title</th>
|
||||
<th>Start time</th>
|
||||
<th>End time</th>
|
||||
return (
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Title</th>
|
||||
<th>Start time</th>
|
||||
<th>End time</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{events.map(event => (
|
||||
<tr key={event.id}>
|
||||
<td><Anchor to={`${URL}/${event.id}`}>{event.title_fi}</Anchor></td>
|
||||
<td>{formatRelative(new Date(event.start_time), new Date())}</td>
|
||||
<td>{formatRelative(new Date(event.end_time), new Date())}</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{events.map(event => (
|
||||
<tr key={event.id}>
|
||||
<td><Anchor to={`/admin/events/${event.id}`}>{event.title_fi}</Anchor></td>
|
||||
<td>{formatRelative(new Date(event.start_time), new Date())}</td>
|
||||
<td>{formatRelative(new Date(event.end_time), new Date())}</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
);
|
||||
}
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
);
|
||||
}
|
||||
const AdminEventPage: React.FC = () => {
|
||||
const [events, setEvents] = useState<Event[]>(null);
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className="admin-event-page">
|
||||
<Helmet>
|
||||
<link rel="canonical" href="https://sik.ayy.fi/admin/events" />
|
||||
</Helmet>
|
||||
<h1>Events</h1>
|
||||
{this.renderAddLink()}
|
||||
{this.renderData()}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
useEffect(() => {
|
||||
getEvents({ auth: true })
|
||||
.then(res => setEvents(res))
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<AdminListCommon>
|
||||
<Helmet>
|
||||
<link rel="canonical" href={`https://sik.ayy.fi/${URL}`} />
|
||||
</Helmet>
|
||||
<h1>Feed</h1>
|
||||
{renderAddLink()}
|
||||
{renderData(events)}
|
||||
</AdminListCommon>
|
||||
);
|
||||
}
|
||||
|
||||
export default AdminEventPage;
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
@import "../../assets/scss/globals";
|
||||
|
||||
|
||||
.admin-feed-page {
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
table,
|
||||
th,
|
||||
td {
|
||||
border: 1px solid color(white1);
|
||||
padding: 0.5rem;
|
||||
|
||||
a {
|
||||
color: color(orange1);
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,117 +1,65 @@
|
||||
import React from "react";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { Helmet } from "react-helmet";
|
||||
import Anchor from "@components/Anchor";
|
||||
import "./AdminFeedPage.scss";
|
||||
import { StaticContext } from "@server/StaticContext";
|
||||
import { Post, getFeed } from "@models/Feed";
|
||||
import { formatRelative } from "date-fns";
|
||||
import { th } from "date-fns/esm/locale";
|
||||
import AdminListCommon from "./AdminListCommon";
|
||||
import Anchor from "@components/Anchor";
|
||||
import AddIcon from "@assets/img/add-icon.png";
|
||||
import { Post, getFeed } from "@models/Feed";
|
||||
|
||||
interface AdminFeedPageProps {
|
||||
staticContext: StaticContext;
|
||||
}
|
||||
interface AdminFeedPageState {
|
||||
feed: Post[];
|
||||
error?: string;
|
||||
}
|
||||
const URL = "/admin/feed"
|
||||
|
||||
class AdminFeedPage extends React.Component<AdminFeedPageProps, AdminFeedPageState> {
|
||||
constructor(props: AdminFeedPageProps) {
|
||||
super(props);
|
||||
const { staticContext } = props;
|
||||
|
||||
if (staticContext) {
|
||||
/* The static context is an object that manages promises when
|
||||
rendering on the server. If staticContext exists, that means
|
||||
we have to store all promises in it. Otherwise, operate
|
||||
normally. See server/index.ts. */
|
||||
if (staticContext.resolutions.getFeed) {
|
||||
const feed = staticContext.resolutions.getFeed as Post[];
|
||||
this.state = {
|
||||
feed,
|
||||
};
|
||||
} else {
|
||||
this.state = {
|
||||
feed: [],
|
||||
};
|
||||
const promiseFeed = this.fetchFeed();
|
||||
staticContext.promises.getFeed = promiseFeed;
|
||||
}
|
||||
} else {
|
||||
this.state = {
|
||||
feed: [],
|
||||
};
|
||||
this.fetchFeed();
|
||||
}
|
||||
const renderAddLink = () => (
|
||||
<Anchor className="add-link" to={`${URL}/create`}>
|
||||
<img src={AddIcon} /> Create post
|
||||
</Anchor>
|
||||
)
|
||||
|
||||
const renderData = (feed: Post[]) => {
|
||||
if (!feed || feed.length === 0) {
|
||||
return <div>No posts.</div>;
|
||||
}
|
||||
|
||||
fetchFeed = async () => {
|
||||
const getFeedPromise = getFeed();
|
||||
try {
|
||||
const feed = await getFeedPromise;
|
||||
this.setState({
|
||||
feed,
|
||||
});
|
||||
return getFeedPromise;
|
||||
} catch (err) {
|
||||
this.setState({
|
||||
error: String(err),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
renderAddLink = () => (
|
||||
<Anchor className="add-link" to="/admin/feed/create">
|
||||
<img src={AddIcon} /> Create post
|
||||
</Anchor>
|
||||
)
|
||||
|
||||
renderData = () => {
|
||||
const { feed, error } = this.state;
|
||||
|
||||
if (error) {
|
||||
return <div className="error">{error}</div>;
|
||||
}
|
||||
|
||||
if (!feed || feed.length === 0) {
|
||||
return <div>No posts.</div>;
|
||||
}
|
||||
|
||||
return (
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Title</th>
|
||||
<th>Description</th>
|
||||
<th>Publish time</th>
|
||||
return (
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Title</th>
|
||||
<th>Description</th>
|
||||
<th>Publish time</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{feed.map(post => (
|
||||
<tr key={post.id}>
|
||||
<td><Anchor to={`${URL}/${post.id}`}>{post.title_fi}</Anchor></td>
|
||||
<td>{post.description_fi}</td>
|
||||
<td>{formatRelative(new Date(post.publish_time), new Date())}</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{feed.map(post => (
|
||||
<tr key={post.id}>
|
||||
<td><Anchor to={`/admin/feed/${post.id}`}>{post.title_fi}</Anchor></td>
|
||||
<td>{post.description_fi}</td>
|
||||
<td>{formatRelative(new Date(post.publish_time), new Date())}</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
);
|
||||
}
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className="admin-feed-page">
|
||||
<Helmet>
|
||||
<link rel="canonical" href="https://sik.ayy.fi/admin/feed" />
|
||||
</Helmet>
|
||||
<h1>Feed</h1>
|
||||
{this.renderAddLink()}
|
||||
{this.renderData()}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
const AdminFeedPage: React.FC = () => {
|
||||
const [forms, setForms] = useState<Post[]>(null);
|
||||
|
||||
useEffect(() => {
|
||||
getFeed({ auth: true })
|
||||
.then(res => setForms(res))
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<AdminListCommon>
|
||||
<Helmet>
|
||||
<link rel="canonical" href={`https://sik.ayy.fi/${URL}`} />
|
||||
</Helmet>
|
||||
<h1>Feed</h1>
|
||||
{renderAddLink()}
|
||||
{renderData(forms)}
|
||||
</AdminListCommon>
|
||||
);
|
||||
}
|
||||
|
||||
export default AdminFeedPage;
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
.admin-front-page {
|
||||
a {
|
||||
text-decoration: underline;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
import React from "react";
|
||||
import { Helmet } from "react-helmet";
|
||||
import Anchor from "@components/Anchor";
|
||||
import "./AdminFrontPage.scss";
|
||||
|
||||
export interface AdminFrontPageProps { }
|
||||
export interface AdminFrontPageState { }
|
||||
|
||||
class AdminFrontPage extends React.Component<AdminFrontPageProps, AdminFrontPageState> {
|
||||
render() {
|
||||
return (
|
||||
<div className="admin-front-page">
|
||||
<Helmet>
|
||||
<link rel="canonical" href="https://sik.ayy.fi/admin" />
|
||||
</Helmet>
|
||||
<h1>SIK Admin</h1>
|
||||
<Anchor to="/admin/events">Events</Anchor>
|
||||
<Anchor to="/admin/feed">Feed</Anchor>
|
||||
<Anchor to="/admin/jobads">Job advertisements</Anchor>
|
||||
<Anchor to="https:https://static.sika.sik.party/admin">Files</Anchor>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default AdminFrontPage;
|
||||
@@ -0,0 +1,13 @@
|
||||
import React from "react";
|
||||
import { Helmet } from "react-helmet";
|
||||
|
||||
const AdminFrontView: React.FC = () => (
|
||||
<main>
|
||||
<Helmet>
|
||||
<link rel="canonical" href="https://sik.ayy.fi/admin" />
|
||||
</Helmet>
|
||||
<h1>SIK Admin</h1>
|
||||
</main>
|
||||
);
|
||||
|
||||
export default AdminFrontView;
|
||||
@@ -1,6 +1,7 @@
|
||||
import React from "react";
|
||||
import { Helmet } from "react-helmet";
|
||||
import { formatRelative } from "date-fns";
|
||||
import AdminListCommon from "./AdminListCommon";
|
||||
import useFetchJobAds from "@hooks/useFetchJobAds";
|
||||
import { JobAd } from "@models/JobAd";
|
||||
import Anchor from "@components/Anchor";
|
||||
@@ -49,14 +50,14 @@ const renderData = (jobAds: JobAd[]) => {
|
||||
const AdminJobAdPage: React.FC = () => {
|
||||
const jobAds = useFetchJobAds({ auth: true });
|
||||
return (
|
||||
<div>
|
||||
<AdminListCommon>
|
||||
<Helmet>
|
||||
<link rel="canonical" href={`https://sik.ayy.fi/${URL}`} />
|
||||
</Helmet>
|
||||
<h1>Job advertisements</h1>
|
||||
{renderAddLink()}
|
||||
{renderData(jobAds)}
|
||||
</div>
|
||||
</AdminListCommon>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
import styled from "styled-components";
|
||||
import { colors } from "@theme/colors";
|
||||
|
||||
const Main = styled.main`
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
table,
|
||||
th,
|
||||
td {
|
||||
border: 1px solid ${colors.white};
|
||||
padding: 0.5rem;
|
||||
|
||||
a {
|
||||
color: ${colors.orange1};
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export default Main;
|
||||
@@ -1,5 +0,0 @@
|
||||
.admin-login-page {
|
||||
input {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,17 @@
|
||||
import React from "react";
|
||||
import styled from "styled-components";
|
||||
import { Helmet } from "react-helmet";
|
||||
import { Redirect } from "react-router-dom";
|
||||
import qs from "query-string";
|
||||
import { generateToken, setTokenCookie, isAuthenticated } from "@utils/auth";
|
||||
import "./AdminLoginPage.scss";
|
||||
|
||||
export interface AdminLoginPageProps {
|
||||
const Main = styled.main`
|
||||
input {
|
||||
display: block;
|
||||
}
|
||||
`;
|
||||
|
||||
interface AdminLoginPageProps {
|
||||
history: {
|
||||
push: (to: string | string[]) => void;
|
||||
};
|
||||
@@ -13,7 +19,7 @@ export interface AdminLoginPageProps {
|
||||
search: string;
|
||||
};
|
||||
}
|
||||
export interface AdminLoginPageState {
|
||||
interface AdminLoginPageState {
|
||||
username: string;
|
||||
password: string;
|
||||
isAuthenticated: boolean;
|
||||
@@ -104,7 +110,7 @@ class AdminLoginPage extends React.Component<AdminLoginPageProps, AdminLoginPage
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="admin-login-page">
|
||||
<Main>
|
||||
<Helmet>
|
||||
<link rel="canonical" href="https://sik.ayy.fi/admin/login" />
|
||||
</Helmet>
|
||||
@@ -122,7 +128,7 @@ class AdminLoginPage extends React.Component<AdminLoginPageProps, AdminLoginPage
|
||||
<input id="login-submit" type="submit" value="Log in" />
|
||||
</form>
|
||||
{ this.renderError() }
|
||||
</div>
|
||||
</Main>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
@import "../../assets/scss/globals";
|
||||
|
||||
.signup-create-page {
|
||||
a {
|
||||
color: color(orange1);
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
|
||||
.admin-signup-page {
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
table,
|
||||
th,
|
||||
td {
|
||||
border: 1px solid color(white1);
|
||||
padding: 0.5rem;
|
||||
|
||||
a {
|
||||
color: color(orange1);
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,117 +1,65 @@
|
||||
import React from "react";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { Helmet } from "react-helmet";
|
||||
import { formatRelative } from "date-fns";
|
||||
import AdminListCommon from "./AdminListCommon";
|
||||
import Anchor from "@components/Anchor";
|
||||
|
||||
import "./AdminSignupPage.scss";
|
||||
import { SignupForm, getForms } from "@models/SignupForm";
|
||||
import { StaticContext } from "@server/StaticContext";
|
||||
import AddIcon from "@assets/img/add-icon.png";
|
||||
import { SignupForm, getForms } from "@models/SignupForm";
|
||||
|
||||
export interface AdminSignupPageProps {
|
||||
staticContext: StaticContext;
|
||||
}
|
||||
export interface AdminSignupPageState {
|
||||
signupForms: SignupForm[];
|
||||
error?: string;
|
||||
}
|
||||
const URL = "/admin/signups"
|
||||
|
||||
class AdminSignupPage extends React.Component<AdminSignupPageProps, AdminSignupPageState> {
|
||||
constructor(props: AdminSignupPageProps) {
|
||||
super(props);
|
||||
const { staticContext } = props;
|
||||
|
||||
if (staticContext) {
|
||||
/* The static context is an object that manages promises when
|
||||
rendering on the server. If staticContext exists, that means
|
||||
we have to store all promises in it. Otherwise, operate
|
||||
normally. See server/index.ts. */
|
||||
if (staticContext.resolutions.getSignupForms) {
|
||||
const signupForms = staticContext.resolutions.getSignupForms as SignupForm[];
|
||||
this.state = {
|
||||
signupForms,
|
||||
};
|
||||
} else {
|
||||
this.state = {
|
||||
signupForms: [],
|
||||
};
|
||||
const promiseSignupForms = this.fetchSignupForms();
|
||||
staticContext.promises.getSignupForms = promiseSignupForms;
|
||||
}
|
||||
} else {
|
||||
this.state = {
|
||||
signupForms: [],
|
||||
};
|
||||
this.fetchSignupForms();
|
||||
}
|
||||
const renderAddLink = () => (
|
||||
<Anchor className="add-link" to={`${URL}/create`}>
|
||||
<img src={AddIcon} /> Create signup form
|
||||
</Anchor>
|
||||
)
|
||||
|
||||
const renderData = (signupForms: SignupForm[]) => {
|
||||
if (!signupForms || signupForms.length === 0) {
|
||||
return <div>No signup forms.</div>;
|
||||
}
|
||||
|
||||
fetchSignupForms = async () => {
|
||||
const getSignupFormsPromise = getForms(true);
|
||||
try {
|
||||
const signupForms = await getSignupFormsPromise;
|
||||
this.setState({
|
||||
signupForms,
|
||||
});
|
||||
return getSignupFormsPromise;
|
||||
} catch (err) {
|
||||
this.setState({
|
||||
error: String(err),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
renderAddLink = () => (
|
||||
<Anchor className="add-link" to="/admin/signups/create">
|
||||
<img src={AddIcon} /> Create signup form
|
||||
</Anchor>
|
||||
)
|
||||
|
||||
renderData = () => {
|
||||
const { signupForms, error } = this.state;
|
||||
|
||||
if (error) {
|
||||
return <div className="error">{error}</div>;
|
||||
}
|
||||
|
||||
if (!signupForms || signupForms.length === 0) {
|
||||
return <div>No signup forms.</div>;
|
||||
}
|
||||
|
||||
return (
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Title</th>
|
||||
<th>Start time</th>
|
||||
<th>End time</th>
|
||||
return (
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Title</th>
|
||||
<th>Start time</th>
|
||||
<th>End time</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{signupForms.map(signupForm => (
|
||||
<tr key={signupForm.id}>
|
||||
<td><Anchor to={`${URL}/${signupForm.id}`}>{signupForm.title_fi}</Anchor></td>
|
||||
<td>{formatRelative(new Date(signupForm.start_time), new Date())}</td>
|
||||
<td>{formatRelative(new Date(signupForm.end_time), new Date())}</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{signupForms.map(signupForm => (
|
||||
<tr key={signupForm.id}>
|
||||
<td><Anchor to={`/admin/signups/${signupForm.id}`}>{signupForm.title_fi}</Anchor></td>
|
||||
<td>{formatRelative(new Date(signupForm.start_time), new Date())}</td>
|
||||
<td>{formatRelative(new Date(signupForm.end_time), new Date())}</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
);
|
||||
}
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className="admin-signup-page">
|
||||
<Helmet>
|
||||
<link rel="canonical" href="https://sik.ayy.fi/admin/events" />
|
||||
</Helmet>
|
||||
<h1>Sign-up forms</h1>
|
||||
{this.renderAddLink()}
|
||||
{this.renderData()}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
const AdminSignupPage: React.FC = () => {
|
||||
const [forms, setForms] = useState<SignupForm[]>(null);
|
||||
|
||||
useEffect(() => {
|
||||
getForms(true)
|
||||
.then(res => setForms(res))
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<AdminListCommon>
|
||||
<Helmet>
|
||||
<link rel="canonical" href={`https://sik.ayy.fi/${URL}`} />
|
||||
</Helmet>
|
||||
<h1>Sign-up forms</h1>
|
||||
{renderAddLink()}
|
||||
{renderData(forms)}
|
||||
</AdminListCommon>
|
||||
);
|
||||
}
|
||||
|
||||
export default AdminSignupPage;
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
import React from "react";
|
||||
import { Switch, Route, Redirect } from "react-router-dom";
|
||||
import { Switch, Route } from "react-router-dom";
|
||||
import { Helmet } from "react-helmet";
|
||||
import FrontPage from "./pages/FrontPage";
|
||||
import GuildPage from "./pages/GuildPage";
|
||||
@@ -7,7 +7,7 @@ import NotFoundPage from "./pages/NotFoundPage";
|
||||
import CommonPage from "./pages/CommonPage";
|
||||
import JsonLD from "@components/JsonLD";
|
||||
import "./index.scss";
|
||||
import AdminFrontPage from "./pages/admin/AdminFrontPage";
|
||||
import AdminFrontPage from "./pages/admin/AdminFrontView";
|
||||
import AdminEventPage from "./pages/admin/AdminEventPage";
|
||||
import AdminFeedPage from "./pages/admin/AdminFeedPage";
|
||||
import AdminCommonPage from "./pages/admin/AdminCommonPage";
|
||||
|
||||
Reference in New Issue
Block a user