Skip to content

Commit

Permalink
Merge pull request #104 from kthcloud/beta
Browse files Browse the repository at this point in the history
Add teams
  • Loading branch information
pierrelefevre authored Nov 17, 2023
2 parents b39b200 + 7df19fc commit 988e188
Show file tree
Hide file tree
Showing 10 changed files with 444 additions and 8 deletions.
9 changes: 9 additions & 0 deletions src/Router.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import Status from "./pages/status";
import ProtectedRoute from "./components/ProtectedRoute";
import Onboarding from "./pages/onboarding";
import Inbox from "./pages/inbox/Inbox";
import Teams from "./pages/teams/Teams";

// ----------------------------------------------------------------------

Expand Down Expand Up @@ -52,6 +53,14 @@ export default function Router() {
</ProtectedRoute>
),
},
{
path: "teams",
element: (
<ProtectedRoute>
<Teams />
</ProtectedRoute>
),
},
{
path: "edit/:type/:id",
element: (
Expand Down
61 changes: 61 additions & 0 deletions src/api/deploy/teams.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,64 @@ export const joinTeam = async (token, teamId, code) => {
const result = await response.json();
return result;
};

export const getTeams = async (token) => {
const url = `${process.env.REACT_APP_DEPLOY_API_URL}/teams`;

const response = await fetch(url, {
method: "GET",
headers: {
Authorization: `Bearer ${token}`,
},
});

let result = await response.json();
result.sort((a, b) => {
return new Date(b.createdAt) - new Date(a.createdAt);
});


for (let i = 0; i < result.length; i++) {
result[i].members &&
result[i].members.sort((a, b) => {
return new Date(a.addedAt) - new Date(b.addedAt);
});
}
return result;
};

export const createTeam = async (token, name, description) => {
const url = `${process.env.REACT_APP_DEPLOY_API_URL}/teams`;

await fetch(url, {
method: "POST",
headers: {
Authorization: `Bearer ${token}`,
},
body: JSON.stringify({ name, description }),
});
};

export const deleteTeam = async (token, teamId) => {
const url = `${process.env.REACT_APP_DEPLOY_API_URL}/teams/${teamId}`;

await fetch(url, {
method: "DELETE",
headers: {
Authorization: `Bearer ${token}`,
},
});
};

export const addMembers = async (token, teamId, members) => {
const url = `${process.env.REACT_APP_DEPLOY_API_URL}/teams/${teamId}`;
const body = { members: members };

await fetch(url, {
method: "POST",
headers: {
Authorization: `Bearer ${token}`,
},
body: JSON.stringify(body),
});
};
19 changes: 19 additions & 0 deletions src/contexts/ResourceContext.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { errorHandler } from "src/utils/errorHandler";
import { getUser } from "src/api/deploy/users";
import { getZones } from "src/api/deploy/zones";
import { getNotifications } from "src/api/deploy/notifications";
import { getTeams } from "src/api/deploy/teams";

const initialState = {
rows: [],
Expand All @@ -34,6 +35,7 @@ export const ResourceContextProvider = ({ children }) => {
const [jobs, setJobs] = useState([]);
const [user, setUser] = useState(null);
const [notifications, setNotifications] = useState([]);
const [teams, setTeams] = useState([]);
const [zones, setZones] = useState([]);
const [initialLoad, setInitialLoad] = useState(false);
const [nextLoad, setNextLoad] = useState(0);
Expand Down Expand Up @@ -134,6 +136,20 @@ export const ResourceContextProvider = ({ children }) => {
}
};

const loadTeams = async () => {
if (!(initialized && keycloak.authenticated)) return;
try {
const teams = await getTeams(keycloak.token);
setTeams(teams);
} catch (error) {
errorHandler(error).forEach((e) =>
enqueueSnackbar("Error fetching teams: " + e, {
variant: "error",
})
);
}
};

const loadUser = async () => {
try {
if (!(initialized && keycloak.authenticated)) return;
Expand All @@ -142,6 +158,7 @@ export const ResourceContextProvider = ({ children }) => {
setConnectionError(false);

loadNotifications();
loadTeams();
} catch (error) {
errorHandler(error).forEach((e) =>
enqueueSnackbar("Error fetching user: " + e, {
Expand Down Expand Up @@ -228,6 +245,8 @@ export const ResourceContextProvider = ({ children }) => {
setUser,
notifications,
setNotifications,
teams,
setTeams,
zones,
setZones,
queueJob,
Expand Down
26 changes: 25 additions & 1 deletion src/layouts/dashboard/Menu.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,20 @@ export default function Menu() {
>
{t("menu-create-new")}
</MenuItem>
</Stack>

<Divider sx={{ borderStyle: "dashed" }} />

<Box sx={{ mt: 1.5, px: 2.5 }}>
<Typography
variant="body2"
sx={{ color: "text.secondary" }}
noWrap
>
{t("menu-manage-account")}
</Typography>
</Box>
<Stack sx={{ p: 1 }}>
<MenuItem
to={"/profile"}
component={RouterLink}
Expand All @@ -116,7 +129,18 @@ export default function Menu() {
component={RouterLink}
onClick={handleClose}
>
{t("inbox") + " " + (notifications.length > 0 ? "(" + notifications.length + ")" : "")}
{t("inbox") +
" " +
(notifications.length > 0
? "(" + notifications.length + ")"
: "")}
</MenuItem>
<MenuItem
to={"/teams"}
component={RouterLink}
onClick={handleClose}
>
{t("teams")}
</MenuItem>
<MenuItem
to={"/tiers"}
Expand Down
8 changes: 8 additions & 0 deletions src/layouts/dashboard/ProfileButton.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,14 @@ const ProfileButton = () => {
>
{`${t("inbox")} (${notifications?.length})`}
</Button>
<Button
startIcon={<Iconify icon="mdi:account-group" />}
color="inherit"
component={Link}
to="/teams"
>
{t("teams")}
</Button>
</Stack>
}
>
Expand Down
10 changes: 9 additions & 1 deletion src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,7 @@
"landing-hero-cpu": "CPU cores",
"landing-hero-ram": "Terabytes of memory",
"landing-intro-header": "Welcome to",
"landing-intro-subheader": "Start deploying your projects today",
"landing-intro-body": "We offer a cutting-edge private cloud infrastructure tailored to meet the unique needs of KTH's bright minds. Seamlessly run experiments, collaborate on groundbreaking research, and harness the power of cloud technology to drive innovation.",
"landing-intro-footer": "Register today free of charge - all you need is a KTH account.",
"connection-status": "Connection status",
Expand Down Expand Up @@ -386,6 +387,13 @@
"transferred-a-deployment-to-you": "transferred a deployment to you",
"transferred-a-vm-to-you": "transferred a VM to you",
"accept": "Accept",
"read": "Read"
"read": "Read",
"menu-manage-account": "Manage account",
"teams": "Teams",
"current-teams": "Current teams",
"teams-subheader": "Teams are a way to organize your resources and collaborate with others. You can create a team and invite others to join.",
"create-team": "Create team",
"description": "Description",
"invite": "Invite"
}
}
10 changes: 9 additions & 1 deletion src/locales/se.json
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@
"deploy-hidden": "Denna deployment är privat, och går inte att nå från internet",
"ssh-string": "SSH-kommando",
"landing-hero-cpu": "CPU-kärnor",
"landing-intro-subheader": "Driftssätt dina projekt idag",
"memory": "Minne",
"vm-in-progress": " VM pågår...",
"404-title": "404 - Sidan kunde inte hittas",
Expand Down Expand Up @@ -386,6 +387,13 @@
"transferred-a-deployment-to-you": "överförde en deployment till dig",
"transferred-a-vm-to-you": "överförde en virtuell maskin till dig",
"accept": "Acceptera",
"read": "Läst"
"read": "Läst",
"menu-manage-account": "Hantera konto",
"teams": "Grupper",
"current-teams": "Dina grupper",
"teams-subheader": "Grupper är ett sätt att organisera dina resurser och samarbeta med andra. Du kan skapa en grupp och bjuda in andra.",
"create-team": "Skapa grupp",
"description": "Beskrivning",
"invite": "Bjud in"
}
}
7 changes: 5 additions & 2 deletions src/pages/landing/Landing.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { useTranslation } from "react-i18next";

export function Landing() {
const { keycloak, initialized } = useKeycloak();
const {t} = useTranslation();
const { t } = useTranslation();

if (!initialized) {
return (
Expand All @@ -26,7 +26,10 @@ export function Landing() {
<Box mt={5}></Box>
<Hero />
<Intro />
<Typography variant="body2" align="center" mt={5} sx={{ display: { sm: "none" }}}><Iconify icon="twemoji:sparkles" /> {t("this-content-is-ai-generated")}</Typography>
<Typography variant="body2" align="center" mt={5}>
<Iconify icon="twemoji:sparkles" />{" "}
{t("this-content-is-ai-generated")}
</Typography>
</Page>
);
}
Expand Down
14 changes: 11 additions & 3 deletions src/pages/landing/components/hero/Hero.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { Link } from "react-router-dom";

const Hero = () => {
const { keycloak, initialized } = useKeycloak();
const { t } = useTranslation();
const { t, i18n } = useTranslation();

// Capacities
const [capacitiesLoading, setCapacitiesLoading] = useState(true);
Expand Down Expand Up @@ -107,14 +107,22 @@ const Hero = () => {
pr={5}
opacity={headerLoading ? 0 : 1}
>
<GenAITooltip>{header}</GenAITooltip>
{i18n.language !== "en" ? (
t("onboarding-welcome")
) : (
<GenAITooltip>{header}</GenAITooltip>
)}
</Typography>
<div className="hero-p">
<Typography
variant="body"
sx={{ fontSize: "1.4rem", opacity: headerLoading ? 0 : 1 }}
>
<GenAITooltip>{subheader}</GenAITooltip>
{i18n.language !== "en" ? (
t("landing-intro-subheader")
) : (
<GenAITooltip>{subheader}</GenAITooltip>
)}
</Typography>
</div>
<Stack
Expand Down
Loading

0 comments on commit 988e188

Please sign in to comment.