v1.6.2/mass message, filters
This commit is contained in:
+14
-8
@@ -1,7 +1,7 @@
|
|||||||
import firebase from 'firebase/app';
|
import firebase from "firebase/app";
|
||||||
import 'firebase/auth';
|
import "firebase/auth";
|
||||||
|
|
||||||
const API = 'http://localhost:5000/watch-party-crx/us-central1/admin';
|
const API = "http://localhost:5000/watch-party-crx/us-central1/admin";
|
||||||
|
|
||||||
const fetcher = async ({ endpoint, method, bodyData }) => {
|
const fetcher = async ({ endpoint, method, bodyData }) => {
|
||||||
const idToken = await firebase.auth().currentUser.getIdToken();
|
const idToken = await firebase.auth().currentUser.getIdToken();
|
||||||
@@ -10,15 +10,21 @@ const fetcher = async ({ endpoint, method, bodyData }) => {
|
|||||||
method,
|
method,
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: `Token ${idToken}:${firebase.auth().currentUser.uid}`,
|
Authorization: `Token ${idToken}:${firebase.auth().currentUser.uid}`,
|
||||||
'Access-Control-Allow-Origin': '*',
|
"Access-Control-Allow-Origin": "*",
|
||||||
},
|
},
|
||||||
body,
|
body,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getPartyDashboardData = () => fetcher({ endpoint: 'partyDashboard', method: 'GET' });
|
export const getPartyDashboardData = () =>
|
||||||
export const getServerDashboardData = () => fetcher({ endpoint: 'serverDashboard', method: 'GET' });
|
fetcher({ endpoint: "partyDashboard", method: "GET" });
|
||||||
|
export const getServerDashboardData = () =>
|
||||||
|
fetcher({ endpoint: "serverDashboard", method: "GET" });
|
||||||
export const postUpdateVersionActive = (bodyData) =>
|
export const postUpdateVersionActive = (bodyData) =>
|
||||||
fetcher({ endpoint: 'updateVersionActive', method: 'POST', bodyData });
|
fetcher({ endpoint: "updateVersionActive", method: "POST", bodyData });
|
||||||
export const postUpdateVideoSelectors = (bodyData) =>
|
export const postUpdateVideoSelectors = (bodyData) =>
|
||||||
fetcher({ endpoint: 'updateVideoSelectors', method: 'POST', bodyData });
|
fetcher({ endpoint: "updateVideoSelectors", method: "POST", bodyData });
|
||||||
|
export const postUpdateVideoNameSelectors = (bodyData) =>
|
||||||
|
fetcher({ endpoint: "updateVideoNameSelectors", method: "POST", bodyData });
|
||||||
|
export const postSendMessage = (bodyData) =>
|
||||||
|
fetcher({ endpoint: "sendMessage", method: "POST", bodyData });
|
||||||
|
|||||||
+496
-150
@@ -1,7 +1,7 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from "react";
|
||||||
import firebase from 'firebase/app';
|
import firebase from "firebase/app";
|
||||||
import 'firebase/auth';
|
import "firebase/auth";
|
||||||
import 'firebase/firestore';
|
import "firebase/firestore";
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
Card,
|
Card,
|
||||||
@@ -15,13 +15,21 @@ import {
|
|||||||
Row,
|
Row,
|
||||||
Col,
|
Col,
|
||||||
PageHeader,
|
PageHeader,
|
||||||
} from 'antd';
|
InputNumber,
|
||||||
|
Descriptions,
|
||||||
|
Badge,
|
||||||
|
Collapse,
|
||||||
|
Modal,
|
||||||
|
Select,
|
||||||
|
} from "antd";
|
||||||
import {
|
import {
|
||||||
getPartyDashboardData,
|
getPartyDashboardData,
|
||||||
getServerDashboardData,
|
getServerDashboardData,
|
||||||
postUpdateVersionActive,
|
postUpdateVersionActive,
|
||||||
postUpdateVideoSelectors,
|
postUpdateVideoSelectors,
|
||||||
} from './Api';
|
postUpdateVideoNameSelectors,
|
||||||
|
postSendMessage,
|
||||||
|
} from "./Api";
|
||||||
import {
|
import {
|
||||||
CheckCircleTwoTone,
|
CheckCircleTwoTone,
|
||||||
CloseCircleTwoTone,
|
CloseCircleTwoTone,
|
||||||
@@ -35,88 +43,60 @@ import {
|
|||||||
LogoutOutlined,
|
LogoutOutlined,
|
||||||
SendOutlined,
|
SendOutlined,
|
||||||
PlusCircleOutlined,
|
PlusCircleOutlined,
|
||||||
} from '@ant-design/icons';
|
} from "@ant-design/icons";
|
||||||
|
|
||||||
const PLAYER_SOURCES = [
|
const PLAYER_SOURCES = [
|
||||||
{ text: 'Netflix', value: 'netflix.' },
|
{ text: "Netflix", value: "netflix." },
|
||||||
{ text: 'Amazon', value: 'amazon.' },
|
{ text: "Amazon", value: "amazon." },
|
||||||
{ text: 'Hulu', value: 'hulu.' },
|
{ text: "Hulu", value: "hulu." },
|
||||||
{ text: 'Disney+', value: 'disneyplus.' },
|
{ text: "Disney+", value: "disneyplus." },
|
||||||
{ text: 'YouTube', value: 'youtube.' },
|
{ text: "YouTube", value: "youtube." },
|
||||||
{ text: 'HBO Now', value: 'hbonow.' },
|
{ text: "HBO Now", value: "hbonow." },
|
||||||
{ text: 'HBO Max', value: 'hbomax.' },
|
{ text: "HBO Max", value: "hbomax." },
|
||||||
{ text: 'Peacock', value: 'peacocktv.' },
|
{ text: "Peacock", value: "peacocktv." },
|
||||||
{ text: 'Google Play', value: 'play.google.' },
|
{ text: "Google Play", value: "play.google." },
|
||||||
{ text: 'Crunchyroll', value: 'crunchyroll.' },
|
{ text: "Crunchyroll", value: "crunchyroll." },
|
||||||
];
|
];
|
||||||
|
|
||||||
const partiesColumns = [
|
const MESSAGE_TYPES = [
|
||||||
{
|
{
|
||||||
title: 'Party Name',
|
text: "REPLY",
|
||||||
dataIndex: 'id',
|
value: "interactive/text",
|
||||||
sorter: (a, b) => (a.id.toLowerCase() < b.id.toLowerCase() ? -1 : 1),
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Source',
|
text: "LINK",
|
||||||
dataIndex: 'source',
|
value: "interactive/link",
|
||||||
sorter: (a, b) => (a.source.toLowerCase() < b.source.toLowerCase() ? -1 : 1),
|
|
||||||
filters: PLAYER_SOURCES,
|
|
||||||
onFilter: (v, r) => r.source === v,
|
|
||||||
render: (a) => PLAYER_SOURCES.filter((p) => p.value === a)[0].text,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Created At',
|
text: "MESSAGE",
|
||||||
dataIndex: 'createTime',
|
value: "",
|
||||||
defaultSortOrder: 'descend',
|
|
||||||
sorter: (a, b) => Date.parse(a.createTime) - Date.parse(b.createTime),
|
|
||||||
render: (a) => new Date(Date.parse(a)).toLocaleString(),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Updated At',
|
|
||||||
dataIndex: 'updateTime',
|
|
||||||
sorter: (a, b) => Date.parse(a.updateTime) - Date.parse(b.updateTime),
|
|
||||||
render: (a) => {
|
|
||||||
const minutes = (Date.now() - Date.parse(a)) / 60000;
|
|
||||||
const dS = new Date(a).toLocaleString();
|
|
||||||
return (
|
|
||||||
<Tag color={minutes <= 5 ? 'success' : minutes <= 15 ? 'processing' : 'default'}>{dS}</Tag>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'On Call',
|
|
||||||
dataIndex: 'onCall',
|
|
||||||
filters: [
|
|
||||||
{
|
|
||||||
text: 'On Call',
|
|
||||||
value: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: 'Not On Call',
|
|
||||||
value: false,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
render: (a) =>
|
|
||||||
a ? (
|
|
||||||
<CheckCircleTwoTone color="#c0f300" id="call-icon" />
|
|
||||||
) : (
|
|
||||||
<CloseCircleTwoTone id="call-icon" />
|
|
||||||
),
|
|
||||||
onFilter: (v, r) => r.onCall === v,
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const emptyMessage = {
|
||||||
|
type: "",
|
||||||
|
text: "",
|
||||||
|
uid: "<system>",
|
||||||
|
name: "",
|
||||||
|
endpoint: "",
|
||||||
|
// time set on send,
|
||||||
|
};
|
||||||
|
|
||||||
export default class Dashboard extends Component {
|
export default class Dashboard extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
this.state = {
|
||||||
partiesOverview: null,
|
partiesOverview: null,
|
||||||
activeTab: '1',
|
activeTab: "1",
|
||||||
refreshing: true,
|
refreshing: true,
|
||||||
selectedParties: [],
|
selectedParties: [],
|
||||||
nameSelectors: {},
|
nameSelectors: {},
|
||||||
selectors: {},
|
selectors: {},
|
||||||
versions: [],
|
versions: [],
|
||||||
|
activeLimit: 5,
|
||||||
|
afkLimit: 10,
|
||||||
|
messageModel: false,
|
||||||
|
newMessage: emptyMessage,
|
||||||
};
|
};
|
||||||
this.serverStatusListener = null;
|
this.serverStatusListener = null;
|
||||||
}
|
}
|
||||||
@@ -128,7 +108,6 @@ export default class Dashboard extends Component {
|
|||||||
getPartyDashboardData()
|
getPartyDashboardData()
|
||||||
.then((res) => res.json())
|
.then((res) => res.json())
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
console.log(res);
|
|
||||||
this.setState({ partiesOverview: res.partyData, refreshing: false });
|
this.setState({ partiesOverview: res.partyData, refreshing: false });
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@@ -141,14 +120,16 @@ export default class Dashboard extends Component {
|
|||||||
this.setState({ refreshing: true });
|
this.setState({ refreshing: true });
|
||||||
const { activeTab } = this.state;
|
const { activeTab } = this.state;
|
||||||
switch (activeTab) {
|
switch (activeTab) {
|
||||||
case '1':
|
case "1":
|
||||||
this.getPartiesOverview();
|
this.getPartiesOverview();
|
||||||
break;
|
break;
|
||||||
case '2':
|
case "2":
|
||||||
case '3':
|
case "3":
|
||||||
case '4':
|
case "4":
|
||||||
this.getVersionsOverview();
|
this.getVersionsOverview();
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
tabChange = (activeTab) => {
|
tabChange = (activeTab) => {
|
||||||
@@ -157,14 +138,18 @@ export default class Dashboard extends Component {
|
|||||||
updateVersionMessage = (message, version) => {
|
updateVersionMessage = (message, version) => {
|
||||||
this.setState({ refreshing: true });
|
this.setState({ refreshing: true });
|
||||||
const { versions } = this.state;
|
const { versions } = this.state;
|
||||||
const versionData = versions.filter((v) => v.version.split('.').join('') === version)[0];
|
const versionData = versions.filter(
|
||||||
|
(v) => v.version.split(".").join("") === version
|
||||||
|
)[0];
|
||||||
versionData.message = message;
|
versionData.message = message;
|
||||||
this.updateVersion(version, versionData);
|
this.updateVersion(version, versionData);
|
||||||
};
|
};
|
||||||
updateVersionActive = (active, version) => {
|
updateVersionActive = (active, version) => {
|
||||||
this.setState({ refreshing: true });
|
this.setState({ refreshing: true });
|
||||||
const { versions } = this.state;
|
const { versions } = this.state;
|
||||||
const versionData = versions.filter((v) => v.version.split('.').join('') === version)[0];
|
const versionData = versions.filter(
|
||||||
|
(v) => v.version.split(".").join("") === version
|
||||||
|
)[0];
|
||||||
versionData.active = active;
|
versionData.active = active;
|
||||||
this.updateVersion(version, versionData);
|
this.updateVersion(version, versionData);
|
||||||
};
|
};
|
||||||
@@ -174,13 +159,10 @@ export default class Dashboard extends Component {
|
|||||||
.catch((err) =>
|
.catch((err) =>
|
||||||
notification.error({
|
notification.error({
|
||||||
description: err.message,
|
description: err.message,
|
||||||
message: 'Unable To Update',
|
message: "Unable To Update",
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
viewPartyDetails(party) {
|
|
||||||
console.log(party);
|
|
||||||
}
|
|
||||||
getSourceName(source) {
|
getSourceName(source) {
|
||||||
return PLAYER_SOURCES.filter((p) => p.value === source)[0].text;
|
return PLAYER_SOURCES.filter((p) => p.value === source)[0].text;
|
||||||
}
|
}
|
||||||
@@ -197,7 +179,7 @@ export default class Dashboard extends Component {
|
|||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
notification.error({
|
notification.error({
|
||||||
description: err.message,
|
description: err.message,
|
||||||
message: 'Unable To Update',
|
message: "Unable To Update",
|
||||||
});
|
});
|
||||||
|
|
||||||
this.setState({ refreshing: false });
|
this.setState({ refreshing: false });
|
||||||
@@ -210,32 +192,43 @@ export default class Dashboard extends Component {
|
|||||||
};
|
};
|
||||||
handleAlertTitleChange = (value, version, index) => {
|
handleAlertTitleChange = (value, version, index) => {
|
||||||
const { versions } = this.state;
|
const { versions } = this.state;
|
||||||
versions.filter((vs) => vs.version === version)[0].alerts[index].title = value;
|
versions.filter((vs) => vs.version === version)[0].alerts[
|
||||||
|
index
|
||||||
|
].title = value;
|
||||||
this.setState({ versions });
|
this.setState({ versions });
|
||||||
};
|
};
|
||||||
handleAlertDescriptionChange = (value, version, index) => {
|
handleAlertDescriptionChange = (value, version, index) => {
|
||||||
const { versions } = this.state;
|
const { versions } = this.state;
|
||||||
versions.filter((vs) => vs.version === version)[0].alerts[index].description = value;
|
versions.filter((vs) => vs.version === version)[0].alerts[
|
||||||
|
index
|
||||||
|
].description = value;
|
||||||
this.setState({ versions });
|
this.setState({ versions });
|
||||||
};
|
};
|
||||||
handleAlertLinkChange = (value, version, index) => {
|
handleAlertLinkChange = (value, version, index) => {
|
||||||
const { versions } = this.state;
|
const { versions } = this.state;
|
||||||
versions.filter((vs) => vs.version === version)[0].alerts[index].link = value;
|
versions.filter((vs) => vs.version === version)[0].alerts[
|
||||||
|
index
|
||||||
|
].link = value;
|
||||||
this.setState({ versions });
|
this.setState({ versions });
|
||||||
};
|
};
|
||||||
handleAlertLinkTextChange = (value, version, index) => {
|
handleAlertLinkTextChange = (value, version, index) => {
|
||||||
const { versions } = this.state;
|
const { versions } = this.state;
|
||||||
versions.filter((vs) => vs.version === version)[0].alerts[index].linkText = value;
|
versions.filter((vs) => vs.version === version)[0].alerts[
|
||||||
|
index
|
||||||
|
].linkText = value;
|
||||||
this.setState({ versions });
|
this.setState({ versions });
|
||||||
};
|
};
|
||||||
deleteAlert = (version, index) => {
|
deleteAlert = (version, index) => {
|
||||||
const { versions } = this.state;
|
const { versions } = this.state;
|
||||||
versions.filter((vs) => vs.version === version)[0].alerts.splice(index, 1);
|
versions.filter((vs) => vs.version === version)[0].alerts.splice(index, 1);
|
||||||
if (
|
if (
|
||||||
versions.filter((vs) => vs.version === version)[0].importantAlert === index ||
|
versions.filter((vs) => vs.version === version)[0].importantAlert ===
|
||||||
|
index ||
|
||||||
versions.filter((vs) => vs.version === version)[0].alerts.length < index
|
versions.filter((vs) => vs.version === version)[0].alerts.length < index
|
||||||
) {
|
) {
|
||||||
versions.filter((vs) => vs.version === version)[0].importantAlert = undefined;
|
versions.filter(
|
||||||
|
(vs) => vs.version === version
|
||||||
|
)[0].importantAlert = undefined;
|
||||||
}
|
}
|
||||||
this.setState({ versions });
|
this.setState({ versions });
|
||||||
};
|
};
|
||||||
@@ -244,10 +237,10 @@ export default class Dashboard extends Component {
|
|||||||
versions
|
versions
|
||||||
.filter((vs) => vs.version === version)[0]
|
.filter((vs) => vs.version === version)[0]
|
||||||
.alerts.push({
|
.alerts.push({
|
||||||
title: '',
|
title: "",
|
||||||
description: '',
|
description: "",
|
||||||
link: '',
|
link: "",
|
||||||
linkText: '',
|
linkText: "",
|
||||||
});
|
});
|
||||||
this.setState({ versions });
|
this.setState({ versions });
|
||||||
};
|
};
|
||||||
@@ -255,11 +248,12 @@ export default class Dashboard extends Component {
|
|||||||
this.setState({ refreshing: true });
|
this.setState({ refreshing: true });
|
||||||
const { versions } = this.state;
|
const { versions } = this.state;
|
||||||
const versionData = versions.filter((v) => v.version === version)[0];
|
const versionData = versions.filter((v) => v.version === version)[0];
|
||||||
if (versionData.alerts.length > 0) this.updateVersion(version.split('.').join(''), versionData);
|
if (versionData.alerts.length > 0)
|
||||||
|
this.updateVersion(version.split(".").join(""), versionData);
|
||||||
else {
|
else {
|
||||||
notification.error({
|
notification.error({
|
||||||
message: 'Missing Alerts',
|
message: "Missing Alerts",
|
||||||
description: 'Must have atleast one alert',
|
description: "Must have atleast one alert",
|
||||||
});
|
});
|
||||||
|
|
||||||
this.setState({ refreshing: false });
|
this.setState({ refreshing: false });
|
||||||
@@ -268,7 +262,9 @@ export default class Dashboard extends Component {
|
|||||||
changeImportantAlert = (active, version, index) => {
|
changeImportantAlert = (active, version, index) => {
|
||||||
const { versions } = this.state;
|
const { versions } = this.state;
|
||||||
if (active === false) {
|
if (active === false) {
|
||||||
versions.filter((vs) => vs.version === version)[0].importantAlert = undefined;
|
versions.filter(
|
||||||
|
(vs) => vs.version === version
|
||||||
|
)[0].importantAlert = undefined;
|
||||||
} else {
|
} else {
|
||||||
versions.filter((vs) => vs.version === version)[0].importantAlert = index;
|
versions.filter((vs) => vs.version === version)[0].importantAlert = index;
|
||||||
}
|
}
|
||||||
@@ -277,16 +273,73 @@ export default class Dashboard extends Component {
|
|||||||
getAddMessageText = () => {
|
getAddMessageText = () => {
|
||||||
const { activeTab } = this.state;
|
const { activeTab } = this.state;
|
||||||
switch (activeTab) {
|
switch (activeTab) {
|
||||||
case '1':
|
case "1":
|
||||||
return 'Send Message';
|
return "Send Message";
|
||||||
case '2':
|
case "2":
|
||||||
return 'Add Version';
|
return "Add Version";
|
||||||
case '3':
|
case "3":
|
||||||
return 'Add Video Selector';
|
return "Add Video Selector";
|
||||||
case '4':
|
case "4":
|
||||||
return 'Add Name Selector';
|
return "Add Name Selector";
|
||||||
|
default:
|
||||||
|
return "";
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
getPrettyTime = (t) => {
|
||||||
|
return t > 3600
|
||||||
|
? new Date(t * 1000).toISOString().substr(11, 8)
|
||||||
|
: new Date(t * 1000).toISOString().substr(14, 5);
|
||||||
|
};
|
||||||
|
handleVideoNameSelectorChange = (event, source, type) => {
|
||||||
|
const { nameSelectors } = this.state;
|
||||||
|
nameSelectors[source][type] = event.target.value;
|
||||||
|
this.setState({ nameSelectors });
|
||||||
|
};
|
||||||
|
updateVideoNameSelector = () => {
|
||||||
|
this.setState({ refreshing: true });
|
||||||
|
const { nameSelectors } = this.state;
|
||||||
|
postUpdateVideoNameSelectors({ nameSelectors })
|
||||||
|
.then(() => this.refreshData())
|
||||||
|
.catch((err) => {
|
||||||
|
notification.error({
|
||||||
|
description: err.message,
|
||||||
|
message: "Unable To Update",
|
||||||
|
});
|
||||||
|
|
||||||
|
this.setState({ refreshing: false });
|
||||||
|
});
|
||||||
|
};
|
||||||
|
sendOrAdd = () => {
|
||||||
|
const { activeTab } = this.state;
|
||||||
|
switch (activeTab) {
|
||||||
|
case "1":
|
||||||
|
this.setState({ messageModel: true });
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
editMessage = (value, field) => {
|
||||||
|
const { newMessage } = this.state;
|
||||||
|
newMessage[field] = value;
|
||||||
|
this.setState({ newMessage });
|
||||||
|
};
|
||||||
|
sendMessage = async () => {
|
||||||
|
this.setState({ refreshing: true });
|
||||||
|
const { selectedParties, newMessage } = this.state;
|
||||||
|
newMessage.time = new Date().toLocaleString();
|
||||||
|
await postSendMessage({ selectedParties, newMessage }).catch((err) => {
|
||||||
|
notification.error({
|
||||||
|
description: err.message,
|
||||||
|
message: "Unable To Send Message",
|
||||||
|
});
|
||||||
|
});
|
||||||
|
this.setState({
|
||||||
|
refreshing: false,
|
||||||
|
newMessage: emptyMessage,
|
||||||
|
messageModel: false,
|
||||||
|
});
|
||||||
|
};
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
partiesOverview,
|
partiesOverview,
|
||||||
@@ -296,26 +349,133 @@ export default class Dashboard extends Component {
|
|||||||
versions,
|
versions,
|
||||||
nameSelectors,
|
nameSelectors,
|
||||||
selectors,
|
selectors,
|
||||||
|
activeLimit,
|
||||||
|
afkLimit,
|
||||||
|
messageModel,
|
||||||
|
newMessage,
|
||||||
} = this.state;
|
} = this.state;
|
||||||
|
|
||||||
const versionsColumns = [
|
const partiesColumns = [
|
||||||
{
|
{
|
||||||
title: 'Version',
|
title: "Party Name",
|
||||||
dataIndex: 'version',
|
dataIndex: "id",
|
||||||
defaultSortOrder: 'descend',
|
sorter: (a, b) => (a.id.toLowerCase() < b.id.toLowerCase() ? -1 : 1),
|
||||||
sorter: (a, b) =>
|
|
||||||
parseInt(a.version.split('.').join('')) - parseInt(b.version.split('.').join('')),
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Active',
|
title: "Source",
|
||||||
dataIndex: 'active',
|
dataIndex: "source",
|
||||||
|
sorter: (a, b) =>
|
||||||
|
a.source.toLowerCase() < b.source.toLowerCase() ? -1 : 1,
|
||||||
|
filters: [
|
||||||
|
...PLAYER_SOURCES,
|
||||||
|
{
|
||||||
|
text: "Is Playing",
|
||||||
|
value: "PLAYING",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: "Is Paused",
|
||||||
|
value: "PAUSED",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
onFilter: (v, r) => r.source === v || r.status === v,
|
||||||
|
render: (a, r) => (
|
||||||
|
<Badge
|
||||||
|
status={
|
||||||
|
r.status === "PLAYING"
|
||||||
|
? "success"
|
||||||
|
: r.status === "PAUSED"
|
||||||
|
? "warning"
|
||||||
|
: "error"
|
||||||
|
}
|
||||||
|
text={this.getSourceName(a)}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Created At",
|
||||||
|
dataIndex: "createTime",
|
||||||
|
defaultSortOrder: "descend",
|
||||||
|
sorter: (a, b) => Date.parse(a.createTime) - Date.parse(b.createTime),
|
||||||
|
render: (a) => new Date(Date.parse(a)).toLocaleString(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Updated At",
|
||||||
|
dataIndex: "updateTime",
|
||||||
filters: [
|
filters: [
|
||||||
{
|
{
|
||||||
text: 'Active',
|
text: "Active",
|
||||||
|
value: "a",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: "Inactive",
|
||||||
|
value: "i",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
onFilter: (v, r) =>
|
||||||
|
v === "a"
|
||||||
|
? (Date.now() - Date.parse(r.updateTime)) / 60000 < afkLimit
|
||||||
|
: (Date.now() - Date.parse(r.updateTime)) / 60000 > afkLimit,
|
||||||
|
sorter: (a, b) => Date.parse(a.updateTime) - Date.parse(b.updateTime),
|
||||||
|
render: (a) => {
|
||||||
|
const minutes = (Date.now() - Date.parse(a)) / 60000;
|
||||||
|
const dS = new Date(a).toLocaleString();
|
||||||
|
return (
|
||||||
|
<Tag
|
||||||
|
color={
|
||||||
|
minutes <= activeLimit
|
||||||
|
? "success"
|
||||||
|
: minutes <= afkLimit
|
||||||
|
? "processing"
|
||||||
|
: "default"
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{dS}
|
||||||
|
</Tag>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "On Call",
|
||||||
|
dataIndex: "onCall",
|
||||||
|
filters: [
|
||||||
|
{
|
||||||
|
text: "On Call",
|
||||||
value: true,
|
value: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: 'Inactive',
|
text: "Not On Call",
|
||||||
|
value: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
render: (a) =>
|
||||||
|
a ? (
|
||||||
|
<CheckCircleTwoTone twoToneColor="#c0f300" id="call-icon" />
|
||||||
|
) : (
|
||||||
|
<CloseCircleTwoTone twoToneColor="#ff5f5f" id="call-icon" />
|
||||||
|
),
|
||||||
|
onFilter: (v, r) => r.onCall === v,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const versionsColumns = [
|
||||||
|
{
|
||||||
|
title: "Version",
|
||||||
|
dataIndex: "version",
|
||||||
|
defaultSortOrder: "descend",
|
||||||
|
sorter: (a, b) =>
|
||||||
|
parseInt(a.version.split(".").join("")) -
|
||||||
|
parseInt(b.version.split(".").join("")),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Active",
|
||||||
|
dataIndex: "active",
|
||||||
|
filters: [
|
||||||
|
{
|
||||||
|
text: "Active",
|
||||||
|
value: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: "Inactive",
|
||||||
value: false,
|
value: false,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@@ -323,18 +483,22 @@ export default class Dashboard extends Component {
|
|||||||
render: (a, r) => (
|
render: (a, r) => (
|
||||||
<Switch
|
<Switch
|
||||||
disabled={refreshing}
|
disabled={refreshing}
|
||||||
onChange={(c) => this.updateVersionActive(c, r.version.split('.').join(''))}
|
onChange={(c) =>
|
||||||
|
this.updateVersionActive(c, r.version.split(".").join(""))
|
||||||
|
}
|
||||||
checked={a}
|
checked={a}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Inactive Message',
|
title: "Inactive Message",
|
||||||
dataIndex: 'message',
|
dataIndex: "message",
|
||||||
render: (a, r) => (
|
render: (a, r) => (
|
||||||
<Input.Search
|
<Input.Search
|
||||||
disabled={refreshing}
|
disabled={refreshing}
|
||||||
onSearch={(v) => this.updateVersionMessage(v, r.version.split('.').join(''))}
|
onSearch={(v) =>
|
||||||
|
this.updateVersionMessage(v, r.version.split(".").join(""))
|
||||||
|
}
|
||||||
value={a}
|
value={a}
|
||||||
onChange={(e) => this.handleVersionMessageChange(e, r.version)}
|
onChange={(e) => this.handleVersionMessageChange(e, r.version)}
|
||||||
enterButton={<EnterOutlined />}
|
enterButton={<EnterOutlined />}
|
||||||
@@ -344,9 +508,98 @@ export default class Dashboard extends Component {
|
|||||||
];
|
];
|
||||||
return (
|
return (
|
||||||
<div className="dashboard-wrapper">
|
<div className="dashboard-wrapper">
|
||||||
|
<PageHeader
|
||||||
|
className="title-header"
|
||||||
|
title="WATCH PARTY"
|
||||||
|
subTitle="ADMIN DASHBOARD"
|
||||||
|
extra={[
|
||||||
|
<Button
|
||||||
|
onClick={() => firebase.auth().signOut()}
|
||||||
|
key="1"
|
||||||
|
type="primary"
|
||||||
|
danger
|
||||||
|
icon={<LogoutOutlined />}
|
||||||
|
>
|
||||||
|
Logout
|
||||||
|
</Button>,
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
<Modal
|
||||||
|
visible={messageModel}
|
||||||
|
closable={false}
|
||||||
|
destroyOnClose
|
||||||
|
maskClosable={false}
|
||||||
|
cancelButtonProps={{
|
||||||
|
disabled: refreshing,
|
||||||
|
onClick: () => this.setState({ messageModel: false }),
|
||||||
|
}}
|
||||||
|
okButtonProps={{
|
||||||
|
disabled: refreshing,
|
||||||
|
icon: <SendOutlined />,
|
||||||
|
onClick: this.sendMessage,
|
||||||
|
}}
|
||||||
|
okText="Send Message"
|
||||||
|
>
|
||||||
|
<Select
|
||||||
|
onChange={(e) => this.editMessage(e, "type")}
|
||||||
|
value={newMessage.type}
|
||||||
|
placeholder="Message Type"
|
||||||
|
disabled={refreshing}
|
||||||
|
>
|
||||||
|
{MESSAGE_TYPES.map((v) => (
|
||||||
|
<Select.Option key={`msg-type-option-${v.value}`} value={v.value}>
|
||||||
|
{v.text}
|
||||||
|
</Select.Option>
|
||||||
|
))}
|
||||||
|
</Select>
|
||||||
|
<Input.TextArea
|
||||||
|
disabled={refreshing}
|
||||||
|
value={newMessage.text}
|
||||||
|
onChange={(e) => this.editMessage(e.target.value, "text")}
|
||||||
|
placeholder="Message"
|
||||||
|
/>
|
||||||
|
{(newMessage.type === "interactive/link" ||
|
||||||
|
newMessage.type === "interactive/text") && (
|
||||||
|
<Input
|
||||||
|
disabled={refreshing}
|
||||||
|
value={newMessage.endpoint}
|
||||||
|
onChange={(e) => this.editMessage(e.target.value, "endpoint")}
|
||||||
|
placeholder={
|
||||||
|
newMessage.type === "interactive/link" ? "Link" : "Endpoint"
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{newMessage.type === "interactive/link" && (
|
||||||
|
<Input
|
||||||
|
disabled={refreshing}
|
||||||
|
value={newMessage.name}
|
||||||
|
onChange={(e) => this.editMessage(e.target.value, "name")}
|
||||||
|
placeholder="Link Text"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Modal>
|
||||||
<Card>
|
<Card>
|
||||||
<PageHeader
|
<PageHeader
|
||||||
extra={[
|
extra={[
|
||||||
|
activeTab === "1" && (
|
||||||
|
<Badge key="5" count="ACTIVE" className="active">
|
||||||
|
<InputNumber
|
||||||
|
prefix="Active"
|
||||||
|
value={activeLimit}
|
||||||
|
onChange={(activeLimit) => this.setState({ activeLimit })}
|
||||||
|
/>
|
||||||
|
</Badge>
|
||||||
|
),
|
||||||
|
activeTab === "1" && (
|
||||||
|
<Badge key="4" count="AFK" className="afk">
|
||||||
|
<InputNumber
|
||||||
|
prefix="AFK"
|
||||||
|
key="4"
|
||||||
|
value={afkLimit}
|
||||||
|
onChange={(afkLimit) => this.setState({ afkLimit })}
|
||||||
|
/>
|
||||||
|
</Badge>
|
||||||
|
),
|
||||||
<Button
|
<Button
|
||||||
key="3"
|
key="3"
|
||||||
loading={refreshing}
|
loading={refreshing}
|
||||||
@@ -357,20 +610,36 @@ export default class Dashboard extends Component {
|
|||||||
/>,
|
/>,
|
||||||
<Button
|
<Button
|
||||||
key="2"
|
key="2"
|
||||||
icon={activeTab === '1' ? <SendOutlined /> : <PlusCircleOutlined />}
|
onClick={this.sendOrAdd}
|
||||||
disabled={activeTab === '1' && selectedParties.length === 0}
|
icon={
|
||||||
|
activeTab === "1" ? <SendOutlined /> : <PlusCircleOutlined />
|
||||||
|
}
|
||||||
|
disabled={activeTab === "1" && selectedParties.length === 0}
|
||||||
>
|
>
|
||||||
{this.getAddMessageText()}
|
{this.getAddMessageText()}
|
||||||
</Button>,
|
</Button>,
|
||||||
<Button
|
activeTab === "3" && (
|
||||||
onClick={() => firebase.auth().signOut()}
|
<Button
|
||||||
key="1"
|
type="primary"
|
||||||
type="primary"
|
onClick={this.updateVideoSelector}
|
||||||
danger
|
icon={<SaveOutlined />}
|
||||||
icon={<LogoutOutlined />}
|
key="6"
|
||||||
>
|
loading={refreshing}
|
||||||
Logout
|
>
|
||||||
</Button>,
|
Save Video Selectors
|
||||||
|
</Button>
|
||||||
|
),
|
||||||
|
activeTab === "4" && (
|
||||||
|
<Button
|
||||||
|
type="primary"
|
||||||
|
onClick={this.updateVideoNameSelector}
|
||||||
|
icon={<SaveOutlined />}
|
||||||
|
key="7"
|
||||||
|
loading={refreshing}
|
||||||
|
>
|
||||||
|
Save Video Name Selectors
|
||||||
|
</Button>
|
||||||
|
),
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
<Tabs activeKey={activeTab} onChange={this.tabChange}>
|
<Tabs activeKey={activeTab} onChange={this.tabChange}>
|
||||||
@@ -378,11 +647,12 @@ export default class Dashboard extends Component {
|
|||||||
<Table
|
<Table
|
||||||
rowSelection={{
|
rowSelection={{
|
||||||
selectedRowKeys: selectedParties,
|
selectedRowKeys: selectedParties,
|
||||||
onChange: (selectedParties) => this.setState({ selectedParties }),
|
onChange: (selectedParties) =>
|
||||||
|
this.setState({ selectedParties }),
|
||||||
}}
|
}}
|
||||||
loading={partiesOverview === null || refreshing}
|
loading={partiesOverview === null || refreshing}
|
||||||
pagination={{
|
pagination={{
|
||||||
position: ['bottomCenter'],
|
position: ["bottomCenter"],
|
||||||
total: partiesOverview ? partiesOverview.length : 0,
|
total: partiesOverview ? partiesOverview.length : 0,
|
||||||
showTotal: (t, r) => `${r[0]} to ${r[1]} of ${t}`,
|
showTotal: (t, r) => `${r[0]} to ${r[1]} of ${t}`,
|
||||||
defaultPageSize: 10,
|
defaultPageSize: 10,
|
||||||
@@ -390,23 +660,52 @@ export default class Dashboard extends Component {
|
|||||||
pageSizeOptions: [10, 25, 50],
|
pageSizeOptions: [10, 25, 50],
|
||||||
}}
|
}}
|
||||||
rowKey={(p) => p.id}
|
rowKey={(p) => p.id}
|
||||||
onRow={(r) => ({
|
|
||||||
onClick: () => this.viewPartyDetails(r),
|
|
||||||
})}
|
|
||||||
dataSource={partiesOverview}
|
dataSource={partiesOverview}
|
||||||
columns={partiesColumns}
|
columns={partiesColumns}
|
||||||
|
expandable={{
|
||||||
|
rowExpandable: (r) => true,
|
||||||
|
expandedRowClassName: () => "party-details-wrapper",
|
||||||
|
expandedRowRender: (r) => (
|
||||||
|
<Descriptions bordered column={5}>
|
||||||
|
<Descriptions.Item span={2} label="# Of Users">
|
||||||
|
{r.userCount}
|
||||||
|
</Descriptions.Item>
|
||||||
|
<Descriptions.Item span={3} label="# Of Messages">
|
||||||
|
{r.messageCount}
|
||||||
|
</Descriptions.Item>
|
||||||
|
<Descriptions.Item span={5} label="Show Name">
|
||||||
|
{r.showName}
|
||||||
|
</Descriptions.Item>
|
||||||
|
<Descriptions.Item span={2} label="Show Time">
|
||||||
|
{this.getPrettyTime(r.time)}
|
||||||
|
</Descriptions.Item>
|
||||||
|
<Descriptions.Item span={3} label="Show Status">
|
||||||
|
<Badge
|
||||||
|
status={
|
||||||
|
r.status === "PLAYING"
|
||||||
|
? "success"
|
||||||
|
: r.status === "PAUSED"
|
||||||
|
? "warning"
|
||||||
|
: "error"
|
||||||
|
}
|
||||||
|
text={r.status}
|
||||||
|
/>
|
||||||
|
</Descriptions.Item>
|
||||||
|
</Descriptions>
|
||||||
|
),
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</Tabs.TabPane>
|
</Tabs.TabPane>
|
||||||
<Tabs.TabPane tab="Versions" key="2">
|
<Tabs.TabPane tab="Versions" key="2">
|
||||||
<Table
|
<Table
|
||||||
loading={refreshing}
|
loading={refreshing}
|
||||||
pagination={{ position: ['bottomCenter'] }}
|
pagination={{ position: ["bottomCenter"] }}
|
||||||
rowKey={(p) => p.version}
|
rowKey={(p) => p.version}
|
||||||
dataSource={versions}
|
dataSource={versions}
|
||||||
columns={versionsColumns}
|
columns={versionsColumns}
|
||||||
expandable={{
|
expandable={{
|
||||||
rowExpandable: (r) => r.alerts,
|
rowExpandable: (r) => r.alerts,
|
||||||
expandedRowClassName: () => 'alerts-wrapper',
|
expandedRowClassName: () => "alerts-wrapper",
|
||||||
expandedRowRender: (r) => (
|
expandedRowRender: (r) => (
|
||||||
<Row>
|
<Row>
|
||||||
{r.alerts.map((a, i) => (
|
{r.alerts.map((a, i) => (
|
||||||
@@ -422,9 +721,15 @@ export default class Dashboard extends Component {
|
|||||||
/>,
|
/>,
|
||||||
<Switch
|
<Switch
|
||||||
onClick={(active) =>
|
onClick={(active) =>
|
||||||
this.changeImportantAlert(active, r.version, i)
|
this.changeImportantAlert(
|
||||||
|
active,
|
||||||
|
r.version,
|
||||||
|
i
|
||||||
|
)
|
||||||
|
}
|
||||||
|
checked={
|
||||||
|
r.importantAlert && r.importantAlert === i
|
||||||
}
|
}
|
||||||
checked={r.importantAlert && r.importantAlert === i}
|
|
||||||
/>,
|
/>,
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
@@ -432,7 +737,11 @@ export default class Dashboard extends Component {
|
|||||||
placeholder="title"
|
placeholder="title"
|
||||||
value={a.title}
|
value={a.title}
|
||||||
onChange={(e) =>
|
onChange={(e) =>
|
||||||
this.handleAlertTitleChange(e.target.value, r.version, i)
|
this.handleAlertTitleChange(
|
||||||
|
e.target.value,
|
||||||
|
r.version,
|
||||||
|
i
|
||||||
|
)
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<Input.TextArea
|
<Input.TextArea
|
||||||
@@ -440,7 +749,11 @@ export default class Dashboard extends Component {
|
|||||||
autoSize={{ minRows: 2, maxRows: 2 }}
|
autoSize={{ minRows: 2, maxRows: 2 }}
|
||||||
value={a.description}
|
value={a.description}
|
||||||
onChange={(e) =>
|
onChange={(e) =>
|
||||||
this.handleAlertDescriptionChange(e.target.value, r.version, i)
|
this.handleAlertDescriptionChange(
|
||||||
|
e.target.value,
|
||||||
|
r.version,
|
||||||
|
i
|
||||||
|
)
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<Divider orientation="left">Link</Divider>
|
<Divider orientation="left">Link</Divider>
|
||||||
@@ -449,14 +762,22 @@ export default class Dashboard extends Component {
|
|||||||
value={a.linkText}
|
value={a.linkText}
|
||||||
placeholder="Link Text"
|
placeholder="Link Text"
|
||||||
onChange={(e) =>
|
onChange={(e) =>
|
||||||
this.handleAlertLinkTextChange(e.target.value, r.version, i)
|
this.handleAlertLinkTextChange(
|
||||||
|
e.target.value,
|
||||||
|
r.version,
|
||||||
|
i
|
||||||
|
)
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<Input
|
<Input
|
||||||
value={a.link}
|
value={a.link}
|
||||||
placeholder="Link"
|
placeholder="Link"
|
||||||
onChange={(e) =>
|
onChange={(e) =>
|
||||||
this.handleAlertLinkChange(e.target.value, r.version, i)
|
this.handleAlertLinkChange(
|
||||||
|
e.target.value,
|
||||||
|
r.version,
|
||||||
|
i
|
||||||
|
)
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</Input.Group>
|
</Input.Group>
|
||||||
@@ -472,7 +793,10 @@ export default class Dashboard extends Component {
|
|||||||
</Card>
|
</Card>
|
||||||
</Col>
|
</Col>
|
||||||
<Col>
|
<Col>
|
||||||
<Card onClick={() => this.saveAlerts(r.version)} className="add-alert-card">
|
<Card
|
||||||
|
onClick={() => this.saveAlerts(r.version)}
|
||||||
|
className="add-alert-card"
|
||||||
|
>
|
||||||
<SaveFilled />
|
<SaveFilled />
|
||||||
</Card>
|
</Card>
|
||||||
</Col>
|
</Col>
|
||||||
@@ -493,19 +817,41 @@ export default class Dashboard extends Component {
|
|||||||
onChange={(e) => this.handleVideoSelectorChange(e, source)}
|
onChange={(e) => this.handleVideoSelectorChange(e, source)}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
<Button
|
|
||||||
block
|
|
||||||
type="primary"
|
|
||||||
icon={<SaveOutlined />}
|
|
||||||
className="save-video-selector"
|
|
||||||
onClick={this.updateVideoSelector}
|
|
||||||
loading={refreshing}
|
|
||||||
>
|
|
||||||
Save Video Selectors
|
|
||||||
</Button>
|
|
||||||
</Tabs.TabPane>
|
</Tabs.TabPane>
|
||||||
<Tabs.TabPane tab="Name Selectors" key="4">
|
<Tabs.TabPane tab="Name Selectors" key="4">
|
||||||
name selectors
|
<Collapse ghost>
|
||||||
|
{Object.keys(nameSelectors)
|
||||||
|
.sort()
|
||||||
|
.map((source) => (
|
||||||
|
<Collapse.Panel
|
||||||
|
key={`name-selector-${source}`}
|
||||||
|
header={this.getSourceName(source)}
|
||||||
|
>
|
||||||
|
<Input
|
||||||
|
key={`video-selector-${source}-show`}
|
||||||
|
className="video-selector-input"
|
||||||
|
addonBefore={"Show"}
|
||||||
|
value={nameSelectors[source]["show"]}
|
||||||
|
onChange={(e) =>
|
||||||
|
this.handleVideoNameSelectorChange(e, source, "show")
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<Input
|
||||||
|
key={`video-selector-${source}-episode`}
|
||||||
|
className="video-selector-input"
|
||||||
|
addonBefore={"Episode"}
|
||||||
|
value={nameSelectors[source]["episode"]}
|
||||||
|
onChange={(e) =>
|
||||||
|
this.handleVideoNameSelectorChange(
|
||||||
|
e,
|
||||||
|
source,
|
||||||
|
"episode"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</Collapse.Panel>
|
||||||
|
))}
|
||||||
|
</Collapse>
|
||||||
</Tabs.TabPane>
|
</Tabs.TabPane>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
</Card>
|
</Card>
|
||||||
|
|||||||
+52
-3
@@ -1,5 +1,5 @@
|
|||||||
@import '~antd/dist/antd.css';
|
@import "~antd/dist/antd.css";
|
||||||
@import '~antd/dist/antd.dark.css' screen and (prefers-color-scheme: dark);
|
@import "~antd/dist/antd.dark.css" screen and (prefers-color-scheme: dark);
|
||||||
|
|
||||||
#root,
|
#root,
|
||||||
#root .app-wrapper {
|
#root .app-wrapper {
|
||||||
@@ -29,8 +29,12 @@
|
|||||||
border-top-left-radius: 0px;
|
border-top-left-radius: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dashboard-wrapper {
|
||||||
|
padding: 35px 70px;
|
||||||
|
padding-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.dashboard-wrapper .ant-card {
|
.dashboard-wrapper .ant-card {
|
||||||
margin: 35px 70px;
|
|
||||||
border-radius: 26px;
|
border-radius: 26px;
|
||||||
filter: drop-shadow(0px 0px 5px rgba(221, 221, 221, 0.438));
|
filter: drop-shadow(0px 0px 5px rgba(221, 221, 221, 0.438));
|
||||||
}
|
}
|
||||||
@@ -52,6 +56,7 @@
|
|||||||
margin: 5px 2px !important;
|
margin: 5px 2px !important;
|
||||||
filter: none !important;
|
filter: none !important;
|
||||||
border-radius: initial !important;
|
border-radius: initial !important;
|
||||||
|
max-width: 400px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.alerts-wrapper .ant-card-body input,
|
.alerts-wrapper .ant-card-body input,
|
||||||
@@ -81,3 +86,47 @@ span#call-icon svg {
|
|||||||
width: 25px;
|
width: 25px;
|
||||||
height: 25px;
|
height: 25px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.title-header {
|
||||||
|
margin-bottom: 17.5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title-header .ant-page-header-heading-title,
|
||||||
|
.title-header .ant-page-header-heading-sub-title {
|
||||||
|
letter-spacing: 1.5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.party-details-wrapper > td {
|
||||||
|
padding: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.party-details-wrapper .ant-descriptions-view table {
|
||||||
|
width: 100% !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.party-details-wrapper .ant-descriptions-view table td,
|
||||||
|
.party-details-wrapper .ant-descriptions-view table th {
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-page-header .ant-badge {
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-page-header .ant-badge-count {
|
||||||
|
right: 100%;
|
||||||
|
z-index: 9;
|
||||||
|
top: -10%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-page-header .active .ant-badge-count {
|
||||||
|
background: green;
|
||||||
|
}
|
||||||
|
.ant-page-header .afk .ant-badge-count {
|
||||||
|
background: rgb(79, 120, 209);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-modal-body > * {
|
||||||
|
margin: 5px 0px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|||||||
+6
-4
@@ -9,14 +9,16 @@ ALL CONTENT ON WATCH PARTY'S WEBSITE OR IN WATCH PARTY'S CHROME EXTENSION APP, U
|
|||||||
CITED ARE THE SOLE INTELECTUAL PROPERTY OF AYUSHYA AMITABH, AND MAY NOT BE
|
CITED ARE THE SOLE INTELECTUAL PROPERTY OF AYUSHYA AMITABH, AND MAY NOT BE
|
||||||
COPIED, EDITED, OR REPRODUCED WITHOUT PERMISSION.
|
COPIED, EDITED, OR REPRODUCED WITHOUT PERMISSION.
|
||||||
************************************************************************/
|
************************************************************************/
|
||||||
import React from 'react';
|
import React from "react";
|
||||||
import { Typography } from '@material-ui/core';
|
import { Typography } from "@material-ui/core";
|
||||||
import { Warning } from '@material-ui/icons';
|
import { Warning } from "@material-ui/icons";
|
||||||
|
|
||||||
const Inactive = (props) => (
|
const Inactive = (props) => (
|
||||||
<div id="party-loading" className="inactive">
|
<div id="party-loading" className="inactive">
|
||||||
<Warning />
|
<Warning />
|
||||||
<Typography variant="overline">SORRY, WATCH PARTY IS UNAVAILABLE RIGHT NOW</Typography>
|
<Typography variant="overline">
|
||||||
|
SORRY, WATCH PARTY IS UNAVAILABLE RIGHT NOW
|
||||||
|
</Typography>
|
||||||
<Typography variant="caption">{props.status}</Typography>
|
<Typography variant="caption">{props.status}</Typography>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,10 +1,14 @@
|
|||||||
const superAuth = require('./superAuth');
|
const superAuth = require("./superAuth");
|
||||||
const partyDashboard = require('./partyDashboard');
|
const partyDashboard = require("./partyDashboard");
|
||||||
const serverDashboard = require('./serverDashboard');
|
const serverDashboard = require("./serverDashboard");
|
||||||
const updateVersionActive = require('./updateVersionActive');
|
const updateVersionActive = require("./updateVersionActive");
|
||||||
const updateVideoSelectors = require('./updateVideoSelectors');
|
const updateVideoSelectors = require("./updateVideoSelectors");
|
||||||
|
const updateVideoNameSelectors = require("./updateVideoNameSelectors");
|
||||||
|
const sendMessage = require("./sendMessage");
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
sendMessage,
|
||||||
|
updateVideoNameSelectors,
|
||||||
updateVideoSelectors,
|
updateVideoSelectors,
|
||||||
updateVersionActive,
|
updateVersionActive,
|
||||||
serverDashboard,
|
serverDashboard,
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
/* eslint-disable promise/no-nesting */
|
/* eslint-disable promise/no-nesting */
|
||||||
const admin = require('firebase-admin');
|
const admin = require("firebase-admin");
|
||||||
const Logger = require('../Logger');
|
const Logger = require("../Logger");
|
||||||
const mLogger = new Logger('admin', 'partyDashboard');
|
const mLogger = new Logger("admin", "partyDashboard");
|
||||||
|
|
||||||
module.exports = async (req, res) => {
|
module.exports = async (req, res) => {
|
||||||
mLogger.start();
|
mLogger.start();
|
||||||
|
|
||||||
var partyData = await admin
|
var partyData = await admin
|
||||||
.firestore()
|
.firestore()
|
||||||
.collection('rooms')
|
.collection("rooms")
|
||||||
.get()
|
.get()
|
||||||
.then((roomSnapshot) => {
|
.then((roomSnapshot) => {
|
||||||
const docData = [];
|
const docData = [];
|
||||||
@@ -18,38 +18,43 @@ module.exports = async (req, res) => {
|
|||||||
createTime: doc.createTime.toDate().toUTCString(),
|
createTime: doc.createTime.toDate().toUTCString(),
|
||||||
updateTime: doc.updateTime.toDate().toUTCString(),
|
updateTime: doc.updateTime.toDate().toUTCString(),
|
||||||
source: doc.data().player.source,
|
source: doc.data().player.source,
|
||||||
onCall: doc.data().hasOwnProperty('conference'),
|
onCall: doc.data().hasOwnProperty("conference"),
|
||||||
showName: doc.data().player.showName || '',
|
showName: doc.data().player.showName || "",
|
||||||
time: doc.data().player.time || 0,
|
time: doc.data().player.time || 0,
|
||||||
status: doc.data().player.status || '',
|
status: doc.data().player.status || "",
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
return docData;
|
return docData;
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
mLogger.error('FAILED TO RESOLVE PARTIES', err);
|
mLogger.error("FAILED TO RESOLVE PARTIES", err);
|
||||||
res.status(500).send({ message: 'Unable to get all parties', error: err });
|
res
|
||||||
|
.status(500)
|
||||||
|
.send({ message: "Unable to get all parties", error: err });
|
||||||
});
|
});
|
||||||
|
|
||||||
await partyData.forEach((party) => {
|
const p = await partyData.map(async (party) => {
|
||||||
const messageCount = admin
|
const messageCount = await admin
|
||||||
.firestore()
|
.firestore()
|
||||||
.collection('rooms')
|
.collection("rooms")
|
||||||
.doc(party.id)
|
.doc(party.id)
|
||||||
.collection('messages')
|
.collection("messages")
|
||||||
.get()
|
.get()
|
||||||
.then((snap) => snap.size);
|
.then((snap) => snap.size);
|
||||||
const userCount = admin
|
const userCount = await admin
|
||||||
.firestore()
|
.firestore()
|
||||||
.collection('rooms')
|
.collection("rooms")
|
||||||
.doc(party.id)
|
.doc(party.id)
|
||||||
.collection('users')
|
.collection("users")
|
||||||
.get()
|
.get()
|
||||||
.then((snap) => snap.size);
|
.then((snap) => snap.size);
|
||||||
party.messageCount = messageCount || 0;
|
party.messageCount = messageCount || 0;
|
||||||
party.userCount = userCount || 0;
|
party.userCount = userCount || 0;
|
||||||
|
return party;
|
||||||
});
|
});
|
||||||
|
|
||||||
mLogger.success('GOT ALL PARTIES', { parties: partyData.length });
|
return Promise.all(p).then((v) => {
|
||||||
return res.status(200).send({ partyData });
|
mLogger.success("GOT ALL PARTIES", { parties: partyData.length });
|
||||||
|
return res.status(200).send({ partyData });
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
const admin = require("firebase-admin");
|
||||||
|
const Logger = require("../Logger");
|
||||||
|
const mLogger = new Logger("admin", "sendMessage");
|
||||||
|
|
||||||
|
module.exports = async (req, res) => {
|
||||||
|
mLogger.start();
|
||||||
|
const { selectedParties, newMessage } = JSON.parse(req.body);
|
||||||
|
if (selectedParties && newMessage && selectedParties.length > 0) {
|
||||||
|
if (newMessage.text && newMessage.time && newMessage.uid) {
|
||||||
|
newMessage.time = new Date();
|
||||||
|
await selectedParties.map(async (partyId) => {
|
||||||
|
await admin
|
||||||
|
.firestore()
|
||||||
|
.collection("rooms")
|
||||||
|
.doc(partyId)
|
||||||
|
.collection("messages")
|
||||||
|
.add(newMessage)
|
||||||
|
.catch((err) => {
|
||||||
|
mLogger.error("FAILED TO SEND MESSAGE", { partyId, err });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
mLogger.success("SENT MESSAGES", { newMessage, selectedParties });
|
||||||
|
res.status(200).send({ message: "SENT MESSAGES" });
|
||||||
|
} else {
|
||||||
|
mLogger.error("MESSAGE NOT VALID");
|
||||||
|
res.status(500).send({ message: "Message is missing fields" });
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
mLogger.error("VALUES NOT RECEIVED");
|
||||||
|
res.status(500).send({ message: "Values not received" });
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
const admin = require("firebase-admin");
|
||||||
|
const Logger = require("../Logger");
|
||||||
|
const mLogger = new Logger("admin", "updateVideoNameSelectors");
|
||||||
|
|
||||||
|
module.exports = async (req, res) => {
|
||||||
|
mLogger.start();
|
||||||
|
const { nameSelectors } = JSON.parse(req.body);
|
||||||
|
if (nameSelectors) {
|
||||||
|
await admin
|
||||||
|
.firestore()
|
||||||
|
.collection("server")
|
||||||
|
.doc("status")
|
||||||
|
.update({
|
||||||
|
nameSelectors,
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
mLogger.error("FAILED TO UPDATE", err);
|
||||||
|
res.status(500).send({ message: "FAILED TO UPDATE", error: err });
|
||||||
|
});
|
||||||
|
mLogger.success("UPDATED NAME SELECTORS");
|
||||||
|
res.status(200).send({ message: "Updated video name selectors" });
|
||||||
|
} else {
|
||||||
|
mLogger.error("VALUES NOT RECEIVED");
|
||||||
|
res.status(500).send({ message: "Values not received" });
|
||||||
|
}
|
||||||
|
};
|
||||||
+30
-24
@@ -1,40 +1,46 @@
|
|||||||
const FunctionModules = require('./modules/index');
|
const FunctionModules = require("./modules/index");
|
||||||
const Webhooks = require('./webhooks/index');
|
const Webhooks = require("./webhooks/index");
|
||||||
const AdminModules = require('./admin/index');
|
const AdminModules = require("./admin/index");
|
||||||
const express = require('express');
|
const express = require("express");
|
||||||
const cors = require('cors');
|
const cors = require("cors");
|
||||||
|
|
||||||
// WEBHOOKS
|
// WEBHOOKS
|
||||||
const webhooks = express();
|
const webhooks = express();
|
||||||
webhooks.use(cors({ origin: true }));
|
webhooks.use(cors({ origin: true }));
|
||||||
webhooks.all('/conferenceEnded', Webhooks.conferenceEnd);
|
webhooks.all("/conferenceEnded", Webhooks.conferenceEnd);
|
||||||
webhooks.all('/scheduledCleanup', Webhooks.scheduledCleanUp);
|
webhooks.all("/scheduledCleanup", Webhooks.scheduledCleanUp);
|
||||||
webhooks.all('/ask', Webhooks.ask);
|
webhooks.all("/ask", Webhooks.ask);
|
||||||
webhooks.all('/userCleanUp', Webhooks.userCleanUp);
|
webhooks.all("/userCleanUp", Webhooks.userCleanUp);
|
||||||
|
|
||||||
// VERSION 1
|
// VERSION 1
|
||||||
const app = express();
|
const app = express();
|
||||||
app.use(cors({ origin: true }));
|
app.use(cors({ origin: true }));
|
||||||
app.use(FunctionModules.authenticator);
|
app.use(FunctionModules.authenticator);
|
||||||
app.get('/validator/:partyName', FunctionModules.tokenValidator);
|
app.get("/validator/:partyName", FunctionModules.tokenValidator);
|
||||||
app.get('/refresher/:token', FunctionModules.tokenRefresher);
|
app.get("/refresher/:token", FunctionModules.tokenRefresher);
|
||||||
app.post('/create', FunctionModules.createRoom);
|
app.post("/create", FunctionModules.createRoom);
|
||||||
app.post('/join', FunctionModules.joinRoom);
|
app.post("/join", FunctionModules.joinRoom);
|
||||||
app.post('/message', FunctionModules.sendMessage);
|
app.post("/message", FunctionModules.sendMessage);
|
||||||
app.post('/updatePlayer', FunctionModules.updatePlayer);
|
app.post("/updatePlayer", FunctionModules.updatePlayer);
|
||||||
app.post('/updateVoxeet', FunctionModules.updateVoxeet);
|
app.post("/updateVoxeet", FunctionModules.updateVoxeet);
|
||||||
app.delete('/leave/:rid/users/:uid', FunctionModules.leaveRoom);
|
app.delete("/leave/:rid/users/:uid", FunctionModules.leaveRoom);
|
||||||
app.delete('/delete/:rid', FunctionModules.deleteRoom);
|
app.delete("/delete/:rid", FunctionModules.deleteRoom);
|
||||||
app.put('/updateAdminOnly/:rid/:adminOnly', FunctionModules.updateAdminOnly);
|
app.put("/updateAdminOnly/:rid/:adminOnly", FunctionModules.updateAdminOnly);
|
||||||
|
|
||||||
// ADMIN
|
// ADMIN
|
||||||
const admin = express();
|
const admin = express();
|
||||||
admin.use(cors({ origin: ['http://localhost:3000', 'https://admin.chromewatchparty.com/*'] }));
|
admin.use(
|
||||||
|
cors({
|
||||||
|
origin: ["http://localhost:3000", "https://admin.chromewatchparty.com/*"],
|
||||||
|
})
|
||||||
|
);
|
||||||
admin.use(AdminModules.superAuth);
|
admin.use(AdminModules.superAuth);
|
||||||
admin.get('/partyDashboard', AdminModules.partyDashboard);
|
admin.get("/partyDashboard", AdminModules.partyDashboard);
|
||||||
admin.get('/serverDashboard', AdminModules.serverDashboard);
|
admin.get("/serverDashboard", AdminModules.serverDashboard);
|
||||||
admin.post('/updateVersionActive', AdminModules.updateVersionActive);
|
admin.post("/updateVersionActive", AdminModules.updateVersionActive);
|
||||||
admin.post('/updateVideoSelectors', AdminModules.updateVideoSelectors);
|
admin.post("/updateVideoSelectors", AdminModules.updateVideoSelectors);
|
||||||
|
admin.post("/updateVideoNameSelectors", AdminModules.updateVideoNameSelectors);
|
||||||
|
admin.post("/sendMessage", AdminModules.sendMessage);
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
v1: app,
|
v1: app,
|
||||||
|
|||||||
Reference in New Issue
Block a user