Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Bump decode-uri-component from 0.2.0 to 0.2.2 #94

Merged
merged 2 commits into from
Oct 8, 2023
Merged
Show file tree
Hide file tree
Changes from all 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
1 change: 1 addition & 0 deletions src/@ractf/api/consts.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ export const ENDPOINTS = {
TEAM_CREATE: "/team/create/",
TEAM_JOIN: "/team/join/",
TEAM_LEAVE: "/team/leave/",
LEADERBOARD_GROUPS: "/team/groups/",

LEADERBOARD_GRAPH: "/leaderboard/graph/",
LEADERBOARD_USER: "/leaderboard/user/",
Expand Down
4 changes: 2 additions & 2 deletions src/@ractf/api/team.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ import { reloadAll } from "./reloadAll";

export const modifyTeam = (teamId, data) => http.patch(ENDPOINTS.TEAM + teamId, data);

export const createTeam = (name, password) => {
export const createTeam = (name, password, leaderboard_group) => {
return new Promise((resolve, reject) => {
http.post(ENDPOINTS.TEAM_CREATE, { name, password }).then(async data => {
http.post(ENDPOINTS.TEAM_CREATE, { name, password, leaderboard_group }).then(async data => {
const team = await http.get("/team/self");
store.dispatch(actions.setTeam(team));
resolve(data);
Expand Down
4 changes: 3 additions & 1 deletion src/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@
"no_bio": "No bio set",
"solve": "{{count}} point - Scored by {{user_name}}",
"solve_plural": "{{count}} points - Scored by {{user_name}}",
"already_in_team": "You are already in a team."
"already_in_team": "You are already in a team.",
"no_leaderboard_group_tab": "No group set",
"all_leaderboard_groups": "All teams"
},
"profile": {
"no_bio": "No bio set",
Expand Down
63 changes: 51 additions & 12 deletions src/pages/Leaderboard.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@
import { useTranslation } from "react-i18next";

import {
Button, Graph, Tab, Table, Page, PageHead, Container
Button, Graph, Tab, Table, Page, PageHead, Container,
TabbedView
} from "@ractf/ui-kit";
import { useApi, usePaginated } from "@ractf/util/http";
import { ENDPOINTS } from "@ractf/api";
Expand All @@ -36,6 +37,7 @@
const { t } = useTranslation();

const [graph, , , refreshGraph] = useApi(ENDPOINTS.LEADERBOARD_GRAPH);
const [groups, , gRefresh] = usePaginated(ENDPOINTS.LEADERBOARD_GROUPS);
const [uState, uNext, uRefresh] = usePaginated(ENDPOINTS.LEADERBOARD_USER);
const [tState, tNext, tRefresh] = usePaginated(ENDPOINTS.LEADERBOARD_TEAM);
const start_time = useConfig("start_time");
Expand Down Expand Up @@ -78,7 +80,10 @@

if (!teamPlots.hasOwnProperty(id)) {
teamPlots[id] = {
data: [{ x: minTime, y: 0 }], label: i.team_name
data:
[{ x: minTime, y: 0 }],
label: i.team_name,
leaderboard_group_name: i.leaderboard_group_name ?? t("teams.no_leaderboard_group_tab")
};
points[id] = 0;
}
Expand All @@ -92,13 +97,14 @@
setTeamGraphData(
Object.values(teamPlots).sort((a, b) => points[b.id] - points[a.id])
);
}, [graph, start_time, hasTeams]);
}, [graph, start_time, hasTeams, t]);

useInterval(() => {
if (!liveReload) return;
refreshGraph();
uRefresh();
tRefresh();
gRefresh();
}, 10000);

const userData = (lbdata) => {
Expand All @@ -116,15 +122,48 @@
]);
};

const teamTab = <>
{teamGraphData && teamGraphData.length > 0 && (
<Graph key="teams" data={teamGraphData} timeGraph noAnimate />
)}
<Table noSort headings={["Place", t("team"), t("point_plural")]} data={teamData(tState.data)} />
{tState.hasMore && <Container full centre>
<Button disabled={tState.loading} onClick={() => {tNext();}}>{t("load_more")}</Button>
</Container>}
</>;
const defaultTabContent = (
<>
{teamGraphData && teamGraphData.length > 0 && <Graph key="teams" data={teamGraphData} timeGraph noAnimate />}

Check warning on line 127 in src/pages/Leaderboard.js

View workflow job for this annotation

GitHub Actions / lint

Line 127 exceeds the maximum line length of 120

Check warning on line 127 in src/pages/Leaderboard.js

View workflow job for this annotation

GitHub Actions / lint

Line 127 exceeds the maximum line length of 120
<Table noSort headings={["Place", t("team"), t("point_plural")]} data={teamData(tState.data)} />
{tState.hasMore && (
<Container full centre>
<Button disabled={tState.loading} onClick={() => { tNext(); }}>{t("load_more")}</Button>
</Container>
)}
</>
);

const teamTab = (
<>
{groups.data && groups.data.length > 1 ? (
<TabbedView center initial={0}>
<Tab label={t("teams.all_leaderboard_groups")}>
{defaultTabContent}
</Tab>
{groups.data.map(g => {
const filteredGraphData = teamGraphData.filter(i => i.leaderboard_group_name === g.name);
const filteredTeamData = tState.data.filter(i => i.leaderboard_group_name === g.name);

return (
<Tab label={g.name} key={g.name}>
{filteredGraphData && filteredGraphData.length > 0 && <Graph key="teams" data={filteredGraphData} timeGraph noAnimate />}

Check warning on line 150 in src/pages/Leaderboard.js

View workflow job for this annotation

GitHub Actions / lint

Line 150 exceeds the maximum line length of 120

Check warning on line 150 in src/pages/Leaderboard.js

View workflow job for this annotation

GitHub Actions / lint

Line 150 exceeds the maximum line length of 120
<Table noSort headings={["Place", t("team"), t("point_plural")]} data={teamData(filteredTeamData)} />

Check warning on line 151 in src/pages/Leaderboard.js

View workflow job for this annotation

GitHub Actions / lint

Line 151 exceeds the maximum line length of 120

Check warning on line 151 in src/pages/Leaderboard.js

View workflow job for this annotation

GitHub Actions / lint

Line 151 exceeds the maximum line length of 120
{tState.hasMore && (
<Container full centre>
<Button disabled={tState.loading} onClick={() => { tNext(); }}>{t("load_more")}</Button>

Check warning on line 154 in src/pages/Leaderboard.js

View workflow job for this annotation

GitHub Actions / lint

Line 154 exceeds the maximum line length of 120

Check warning on line 154 in src/pages/Leaderboard.js

View workflow job for this annotation

GitHub Actions / lint

Line 154 exceeds the maximum line length of 120
</Container>
)}
</Tab>
);
})}
</TabbedView>
) : (
<>{defaultTabContent}</>
)}
</>
);

const userTab = <>
{userGraphData && userGraphData.length > 0 && (
<Graph key="users" data={userGraphData} timeGraph noAnimate />
Expand Down
15 changes: 11 additions & 4 deletions src/plugins/base/auth/components/Teams.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,12 @@
import { useTranslation } from "react-i18next";

import {
Form, HR, Input, Button, SubtleText, Container
Form, HR, Input, Button, SubtleText, Container, Select
} from "@ractf/ui-kit";
import { joinTeam, createTeam, reloadAll } from "@ractf/api";
import { useConfig } from "@ractf/shell-util";
import * as http from "@ractf/util/http";
import { usePaginated } from "@ractf/util/http";
import { ENDPOINTS, joinTeam, createTeam, reloadAll } from "@ractf/api";

import Link from "components/Link";

Expand Down Expand Up @@ -100,6 +101,7 @@

const [message, setMessage] = useState("");
const [success, setSuccess] = useState(false);
const [groups, , gRefresh] = usePaginated(ENDPOINTS.LEADERBOARD_GROUPS);

Check warning on line 104 in src/plugins/base/auth/components/Teams.js

View workflow job for this annotation

GitHub Actions / lint

'gRefresh' is assigned a value but never used

Check warning on line 104 in src/plugins/base/auth/components/Teams.js

View workflow job for this annotation

GitHub Actions / lint

'gRefresh' is assigned a value but never used
const [locked, setLocked] = useState(false);
const team = useSelector(state => state.team);
const hasTeams = useConfig("enable_teams");
Expand All @@ -110,14 +112,14 @@
if (team !== null)
return <Redirect to={"/team/me"} />;

const doCreateTeam = ({ name, password }) => {
const doCreateTeam = ({ name, password, leaderboard_group }) => {
if (!name.length)
return setMessage(t("team_wiz.name_missing"));
if (password.length < 8)
return setMessage(t("team_wiz.pass_short"));

setLocked(true);
createTeam(name, password).then(resp => {
createTeam(name, password, leaderboard_group).then(resp => {
reloadAll();
setSuccess(true);
}).catch(e => {
Expand Down Expand Up @@ -147,6 +149,11 @@
<Input autofill={"off"} name={"name"} limit={36} placeholder={t("team_name")} required />
<Input autofill={"off"} name={"password"} placeholder={t("team_secret")} required password />
<SubtleText>{t("team_secret_warn")}</SubtleText>
{groups && groups.data.length &&
<Form.Group htmlFor={"leaderboard_group"} label={"Select your leaderboard group!"}>
<Select options={groups.data.map(i => ({key: i.id, value: i.name}))} name={"leaderboard_group"} />

Check warning on line 154 in src/plugins/base/auth/components/Teams.js

View workflow job for this annotation

GitHub Actions / lint

Line 154 exceeds the maximum line length of 120

Check warning on line 154 in src/plugins/base/auth/components/Teams.js

View workflow job for this annotation

GitHub Actions / lint

Line 154 exceeds the maximum line length of 120
</Form.Group>
}
</Form.Group>

{message && <Form.Error>{message}</Form.Error>}
Expand Down
97 changes: 97 additions & 0 deletions src/plugins/leaderboardGroups.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
// Copyright (C) 2020-2021 Really Awesome Technology Ltd
//
// This file is part of RACTF.
//
// RACTF is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// RACTF is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with RACTF. If not, see <https://www.gnu.org/licenses/>.

import React, { useContext, useState, useRef } from "react";
import { FiEdit2, FiTrash, FiPlus, FiCrosshair } from "react-icons/fi";

import * as http from "@ractf/util/http";
import { usePaginated } from "@ractf/util/http";
import { ENDPOINTS } from "@ractf/api";
import { registerPlugin } from "@ractf/plugins";
import {
Page, PageHead, Grid, Button, Modal, Input, Form, HR,
UiKitModals, Container, Checkbox
} from "@ractf/ui-kit";


const CMSAdmin = () => {
const [groups, , gRefresh] = usePaginated(ENDPOINTS.LEADERBOARD_GROUPS);
const modals = useContext(UiKitModals);
const [editingGroup, setEditingGroup] = useState(false);
const formSubmit = useRef();

const removeGroup = (group) => {
modals.promptConfirm(<>Are you sure you want to remove <code>{group.name}</code>?</>).then(() => {
http.delete_("/team/groups/" + group.id).then(() => {
gRefresh();
}).catch(() => {
modals.alert("Failed to remove group");
});
}).catch();
};
const editGroup = (group) => {
setEditingGroup(group);
};
const addNew = () => {
setEditingGroup({ name: "", description: "", is_self_assignable: true, has_own_leaderboard: true });
};
const postSubmit = ({ resp }) => {
gRefresh();
setEditingGroup(false);
};

return <Page>
{editingGroup !== false ?
<Modal header={"Editing Group"} onClose={() => setEditingGroup(false)} onConfirm={() => formSubmit.current()}>

Check warning on line 59 in src/plugins/leaderboardGroups.js

View workflow job for this annotation

GitHub Actions / lint

Line 59 exceeds the maximum line length of 120

Check warning on line 59 in src/plugins/leaderboardGroups.js

View workflow job for this annotation

GitHub Actions / lint

Line 59 exceeds the maximum line length of 120
<Form postSubmit={postSubmit}
action={(typeof editingGroup.id !== "undefined") ? `/team/groups/${editingGroup.id}/` : "/team/groups/"}

Check warning on line 61 in src/plugins/leaderboardGroups.js

View workflow job for this annotation

GitHub Actions / lint

Line 61 exceeds the maximum line length of 120

Check warning on line 61 in src/plugins/leaderboardGroups.js

View workflow job for this annotation

GitHub Actions / lint

Line 61 exceeds the maximum line length of 120
method={(typeof editingGroup.id !== "undefined") ? "PATCH" : "POST"} submitRef={formSubmit}
>
<Form.Group label={"Name"}>
<Input placeholder={"Name"} name={"name"} val={editingGroup.name} required />
</Form.Group>
<Form.Group label={"Description"}>
<Input placeholder={"Description"} name={"description"} val={""} />
</Form.Group>
<Form.Group label={"Self-assignable on team create?"}>
<Checkbox name={"is_self_assignable"} val={editingGroup.is_self_assignable} />
</Form.Group>
<Form.Group label={"Has its own leaderboard page?"}>
<Checkbox name={"has_own_leaderboard"} val={editingGroup.has_own_leaderboard} />
</Form.Group>

<HR />
</Form>
</Modal> : null
}
<PageHead>Leaderboard Groups</PageHead>
<Grid headings={["Name", "Has own leaderboard group", "Self-assignable", "Actions"]} data={[...groups.data.map(i => [

Check warning on line 82 in src/plugins/leaderboardGroups.js

View workflow job for this annotation

GitHub Actions / lint

Line 82 exceeds the maximum line length of 120

Check warning on line 82 in src/plugins/leaderboardGroups.js

View workflow job for this annotation

GitHub Actions / lint

Line 82 exceeds the maximum line length of 120
i.name, i.has_own_leaderboard ? "Yes" : "No", i.is_self_assignable ? "Yes" : "No", <Container toolbar>
<Button tiny warning Icon={FiEdit2} onClick={() => editGroup(i)} />
<Button tiny danger Icon={FiTrash} onClick={() => removeGroup(i)} />
</Container>
]), [<Button tiny Icon={FiPlus} onClick={addNew}>Add group</Button>, null, null]]} />
</Page>;
};

export default () => {
registerPlugin("adminPage", "leaderboard_groups", {
component: CMSAdmin,
sidebar: "Leaderboard Groups",
Icon: FiCrosshair,
});
};
Loading