mirror of
https://github.com/hyperspacedev/hyperspace
synced 2025-01-30 17:14:57 +01:00
Create announcement type and page
This commit is contained in:
parent
8e3512a95e
commit
67e94d8126
@ -11,6 +11,7 @@ import ProfilePage from "./pages/ProfilePage";
|
||||
import TimelinePage from "./pages/Timeline";
|
||||
import Conversation from "./pages/Conversation";
|
||||
import NotificationsPage from "./pages/Notifications";
|
||||
import AnnouncementsPage from "./pages/Announcements";
|
||||
import SearchPage from "./pages/Search";
|
||||
import Composer from "./pages/Compose";
|
||||
import WelcomePage from "./pages/Welcome";
|
||||
@ -138,6 +139,10 @@ class App extends Component<any, IAppState> {
|
||||
)}
|
||||
/>
|
||||
<PrivateRoute path="/messages" component={MessagesPage} />
|
||||
<PrivateRoute
|
||||
path="/announcements"
|
||||
component={AnnouncementsPage}
|
||||
/>
|
||||
<PrivateRoute
|
||||
path="/notifications"
|
||||
component={NotificationsPage}
|
||||
|
211
src/pages/Announcements.tsx
Normal file
211
src/pages/Announcements.tsx
Normal file
@ -0,0 +1,211 @@
|
||||
import React, { Component } from "react";
|
||||
import {
|
||||
ListSubheader,
|
||||
withStyles,
|
||||
Typography,
|
||||
CircularProgress,
|
||||
Card,
|
||||
CardContent,
|
||||
Paper,
|
||||
CardHeader,
|
||||
Avatar
|
||||
} from "@material-ui/core";
|
||||
|
||||
import { styles } from "./PageLayout.styles";
|
||||
import AnnouncementIcon from "@material-ui/icons/Announcement";
|
||||
|
||||
import Mastodon from "megalodon";
|
||||
import { Announcement } from "../types/Announcement";
|
||||
import { withSnackbar } from "notistack";
|
||||
import moment from "moment";
|
||||
|
||||
/**
|
||||
* The state interface for the notifications page.
|
||||
*/
|
||||
interface IAnnouncementsPageState {
|
||||
/**
|
||||
* The list of notifications, if it exists.
|
||||
*/
|
||||
announcements?: [Announcement];
|
||||
|
||||
/**
|
||||
* Whether the view is still loading.
|
||||
*/
|
||||
viewIsLoading: boolean;
|
||||
|
||||
/**
|
||||
* Whether the view has loaded.
|
||||
*/
|
||||
viewDidLoad?: boolean;
|
||||
|
||||
/**
|
||||
* Whether the view has loaded but in error.
|
||||
*/
|
||||
viewDidError?: boolean;
|
||||
|
||||
/**
|
||||
* The error code for an errored state, if possible.
|
||||
*/
|
||||
viewDidErrorCode?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* The notifications page.
|
||||
*/
|
||||
class AnnouncementsPage extends Component<any, IAnnouncementsPageState> {
|
||||
/**
|
||||
* The Mastodon object to perform notification operations on.
|
||||
*/
|
||||
client: Mastodon;
|
||||
|
||||
/**
|
||||
* The stream listener for tuning in to notifications.
|
||||
*/
|
||||
streamListener: any;
|
||||
|
||||
/**
|
||||
* Construct the notifications page.
|
||||
* @param props The properties to pass in
|
||||
*/
|
||||
constructor(props: any) {
|
||||
super(props);
|
||||
|
||||
// Create the Mastodon object.
|
||||
this.client = new Mastodon(
|
||||
localStorage.getItem("access_token") as string,
|
||||
localStorage.getItem("baseurl") + "/api/v1"
|
||||
);
|
||||
|
||||
// Initialize the state.
|
||||
this.state = {
|
||||
viewIsLoading: true
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform pre-mount tasks
|
||||
*/
|
||||
async componentWillMount() {
|
||||
try {
|
||||
// Get the list of notifications
|
||||
let resp: any = await this.client.get("/announcements");
|
||||
let announcements: [Announcement] = resp.data;
|
||||
|
||||
this.setState({
|
||||
announcements,
|
||||
viewIsLoading: false,
|
||||
viewDidLoad: true
|
||||
});
|
||||
} catch (e) {
|
||||
this.setState({
|
||||
viewDidLoad: true,
|
||||
viewIsLoading: false,
|
||||
viewDidError: true,
|
||||
viewDidErrorCode: e.message
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the announcements page.
|
||||
*/
|
||||
render() {
|
||||
const { classes } = this.props;
|
||||
return (
|
||||
<div className={classes.pageLayoutConstraints}>
|
||||
{this.state.viewDidLoad ? (
|
||||
this.state.announcements &&
|
||||
this.state.announcements.length > 0 ? (
|
||||
<div>
|
||||
<ListSubheader>Current announcements</ListSubheader>
|
||||
{this.state.announcements.map(
|
||||
(announcement: Announcement) => {
|
||||
return (
|
||||
<Card>
|
||||
<CardHeader
|
||||
avatar={
|
||||
<Avatar>
|
||||
<AnnouncementIcon />
|
||||
</Avatar>
|
||||
}
|
||||
title={`Published on ${moment(
|
||||
announcement.published_at
|
||||
).format(
|
||||
"MMMM Do, YYYY [at] hh:mmA"
|
||||
)}`}
|
||||
subheader={
|
||||
announcement.ends_at
|
||||
? `Expires ${moment(
|
||||
announcement.ends_at
|
||||
).format(
|
||||
"MMMM Do, YYYY"
|
||||
)}`
|
||||
: ""
|
||||
}
|
||||
></CardHeader>
|
||||
<CardContent>
|
||||
<Typography
|
||||
dangerouslySetInnerHTML={{
|
||||
__html:
|
||||
announcement.content
|
||||
}}
|
||||
></Typography>
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
<div
|
||||
className={classes.pageLayoutEmptyTextConstraints}
|
||||
style={{ textAlign: "center" }}
|
||||
>
|
||||
<AnnouncementIcon
|
||||
color="action"
|
||||
style={{ fontSize: 48 }}
|
||||
/>
|
||||
<Typography variant="h6">
|
||||
No server announcements
|
||||
</Typography>
|
||||
<Typography paragraph>
|
||||
There aren't any announcements in your
|
||||
community. Announcements that use the
|
||||
announcement feature on Mastodon will appear
|
||||
here.
|
||||
</Typography>
|
||||
<br />
|
||||
</div>
|
||||
)
|
||||
) : null}
|
||||
{this.state.viewDidError ? (
|
||||
<Paper className={classes.errorCard}>
|
||||
<Typography variant="h4">Bummer.</Typography>
|
||||
<Typography variant="h6">
|
||||
Something went wrong when loading announcements.
|
||||
</Typography>
|
||||
<Typography>
|
||||
{this.state.viewDidErrorCode
|
||||
? this.state.viewDidErrorCode
|
||||
: ""}
|
||||
</Typography>
|
||||
</Paper>
|
||||
) : (
|
||||
<span />
|
||||
)}
|
||||
{this.state.viewIsLoading ? (
|
||||
<div style={{ textAlign: "center" }}>
|
||||
<CircularProgress
|
||||
className={classes.progress}
|
||||
color="primary"
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<span />
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default withStyles(styles)(withSnackbar(AnnouncementsPage));
|
17
src/types/Announcement.tsx
Normal file
17
src/types/Announcement.tsx
Normal file
@ -0,0 +1,17 @@
|
||||
import { Account } from "./Account";
|
||||
import { Tag } from "./Tag";
|
||||
import { MastodonEmoji } from "./Emojis";
|
||||
|
||||
export type Announcement = {
|
||||
id: string;
|
||||
content: string;
|
||||
starts_at?: string;
|
||||
ends_at?: string;
|
||||
all_day: boolean;
|
||||
published_at: string;
|
||||
updated_at: string;
|
||||
read: boolean;
|
||||
mentions: [Account];
|
||||
tags: [Tag];
|
||||
emojis: [MastodonEmoji];
|
||||
};
|
Loading…
x
Reference in New Issue
Block a user