mirror of
https://github.com/moghtech/komodo.git
synced 2026-07-18 16:52:16 -05:00
canUserUpdate build and build owner config
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import { BUILD_OWNER_UPDATE } from "@monitor/util";
|
||||
import { FastifyInstance } from "fastify";
|
||||
import fp from "fastify-plugin";
|
||||
|
||||
@@ -22,6 +23,66 @@ const builds = fp((app: FastifyInstance, _: {}, done: () => void) => {
|
||||
res.send(state);
|
||||
}
|
||||
);
|
||||
|
||||
app.post(
|
||||
"/api/build/:id/:owner",
|
||||
{ onRequest: [app.auth, app.userEnabled] },
|
||||
async (req, res) => {
|
||||
// adds an owner to a build
|
||||
const { id, owner } = req.params as { id: string; owner: string };
|
||||
const sender = (await app.users.findById(req.user.id))!;
|
||||
if (sender.permissions! < 1) {
|
||||
res.status(403);
|
||||
res.send("inadequate permissions");
|
||||
return;
|
||||
}
|
||||
const user = await app.users.findOne({ username: owner });
|
||||
if (!user || user.permissions! < 1) {
|
||||
res.status(400);
|
||||
res.send("invalid user");
|
||||
return;
|
||||
}
|
||||
const build = await app.builds.findById(id);
|
||||
if (!build) {
|
||||
res.status(400);
|
||||
res.send("build not found");
|
||||
return;
|
||||
}
|
||||
if (sender.permissions! < 2 && !build.owners.includes(sender.username)) {
|
||||
res.status(403);
|
||||
res.send("inadequate permissions");
|
||||
return;
|
||||
}
|
||||
await app.builds.updateById(id, { $push: { owners: owner } });
|
||||
app.broadcast(BUILD_OWNER_UPDATE, { buildID: id });
|
||||
res.send("owner added");
|
||||
}
|
||||
);
|
||||
|
||||
app.delete(
|
||||
"/api/build/:id/:owner",
|
||||
{ onRequest: [app.auth, app.userEnabled] },
|
||||
async (req, res) => {
|
||||
// removes owner from deployment
|
||||
const { id, owner } = req.params as { id: string; owner: string };
|
||||
const sender = (await app.users.findById(req.user.id))!;
|
||||
if (sender.permissions! < 2) {
|
||||
res.status(403);
|
||||
res.send("inadequate permissions");
|
||||
return;
|
||||
}
|
||||
const build = await app.builds.findById(id);
|
||||
if (!build) {
|
||||
res.status(400);
|
||||
res.send("build not found");
|
||||
return;
|
||||
}
|
||||
await app.builds.updateById(id, { $pull: { owners: owner } });
|
||||
app.broadcast(BUILD_OWNER_UPDATE, { buildID: id });
|
||||
res.send("owner removed");
|
||||
}
|
||||
);
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
|
||||
92
frontend/src/components/builds/tabs/Owners.tsx
Normal file
92
frontend/src/components/builds/tabs/Owners.tsx
Normal file
@@ -0,0 +1,92 @@
|
||||
import { User } from "@monitor/types";
|
||||
import { Component, createEffect, createSignal, For, Show } from "solid-js";
|
||||
import { pushNotification } from "../../..";
|
||||
import { useUser } from "../../../state/UserProvider";
|
||||
import {
|
||||
addOwnerToBuild,
|
||||
getUsers,
|
||||
removeOwnerFromBuild,
|
||||
} from "../../../util/query";
|
||||
import ConfirmButton from "../../util/ConfirmButton";
|
||||
import Input from "../../util/Input";
|
||||
import Flex from "../../util/layout/Flex";
|
||||
import Grid from "../../util/layout/Grid";
|
||||
import Menu from "../../util/menu/Menu";
|
||||
import { useConfig } from "./Provider";
|
||||
|
||||
const Owners: Component<{}> = (p) => {
|
||||
const { build } = useConfig();
|
||||
const { permissions, username } = useUser();
|
||||
const [userSearch, setUserSearch] = createSignal("");
|
||||
const [users, setUsers] = createSignal<User[]>([]);
|
||||
createEffect(() => {
|
||||
if (userSearch().length > 0) {
|
||||
getUsers(userSearch(), true).then((users) => {
|
||||
setUsers(users.filter((user) => !build.owners.includes(user.username)));
|
||||
});
|
||||
} else {
|
||||
setUsers([]);
|
||||
}
|
||||
});
|
||||
return (
|
||||
<Grid class="config-item shadow">
|
||||
<Menu
|
||||
show={userSearch() ? true : false}
|
||||
close={() => setUserSearch("")}
|
||||
target={
|
||||
<Input
|
||||
placeholder="add user"
|
||||
value={userSearch()}
|
||||
onEdit={setUserSearch}
|
||||
style={{ width: "12rem" }}
|
||||
/>
|
||||
}
|
||||
content={
|
||||
<>
|
||||
<For each={users()}>
|
||||
{(user) => (
|
||||
<ConfirmButton
|
||||
color="grey"
|
||||
style={{ width: "100%", "justify-content": "flex-start" }}
|
||||
onConfirm={async () => {
|
||||
await addOwnerToBuild(build._id!, user.username);
|
||||
pushNotification("good", "owner added to deployment");
|
||||
setUserSearch("");
|
||||
}}
|
||||
confirmText="add user"
|
||||
>
|
||||
{user.username}
|
||||
</ConfirmButton>
|
||||
)}
|
||||
</For>
|
||||
<Show when={users().length === 0}>no matching users</Show>
|
||||
</>
|
||||
}
|
||||
style={{ width: "12rem" }}
|
||||
/>
|
||||
<For each={build.owners}>
|
||||
{(owner) => (
|
||||
<Flex alignItems="center" justifyContent="space-between">
|
||||
<div class="big-text">
|
||||
{owner}
|
||||
{owner === username() && " ( you )"}
|
||||
</div>
|
||||
<Show when={permissions() > 1}>
|
||||
<ConfirmButton
|
||||
color="red"
|
||||
onConfirm={async () => {
|
||||
await removeOwnerFromBuild(build._id!, owner);
|
||||
pushNotification("good", "user removed from collaborators");
|
||||
}}
|
||||
>
|
||||
remove
|
||||
</ConfirmButton>
|
||||
</Show>
|
||||
</Flex>
|
||||
)}
|
||||
</For>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
|
||||
export default Owners;
|
||||
@@ -1,23 +1,36 @@
|
||||
import { Build, Update } from "@monitor/types";
|
||||
import { Component, createContext, createEffect, onCleanup, useContext } from "solid-js";
|
||||
import {
|
||||
Component,
|
||||
createContext,
|
||||
createEffect,
|
||||
onCleanup,
|
||||
useContext,
|
||||
} from "solid-js";
|
||||
import { createStore, DeepReadonly, SetStoreFunction } from "solid-js/store";
|
||||
import { ADD_UPDATE, UPDATE_BUILD } from "../../../state/actions";
|
||||
import { useAppState } from "../../../state/StateProvider";
|
||||
import { useUser } from "../../../state/UserProvider";
|
||||
import { getBuild } from "../../../util/query";
|
||||
|
||||
type ConfigBuild = Build & { loaded: boolean; updated: boolean; saving: boolean };
|
||||
type ConfigBuild = Build & {
|
||||
loaded: boolean;
|
||||
updated: boolean;
|
||||
saving: boolean;
|
||||
};
|
||||
|
||||
type State = {
|
||||
build: DeepReadonly<ConfigBuild>;
|
||||
setBuild: SetStoreFunction<ConfigBuild>;
|
||||
reset: () => void;
|
||||
save: () => void;
|
||||
userCanUpdate: () => boolean;
|
||||
};
|
||||
|
||||
const context = createContext<State>();
|
||||
|
||||
export const ConfigProvider: Component<{}> = (p) => {
|
||||
const { ws, selected, builds } = useAppState();
|
||||
const { permissions, username } = useUser();
|
||||
const [build, set] = createStore({
|
||||
...builds.get(selected.id())!,
|
||||
loaded: false,
|
||||
@@ -31,7 +44,7 @@ export const ConfigProvider: Component<{}> = (p) => {
|
||||
};
|
||||
|
||||
const load = () => {
|
||||
console.log("load server");
|
||||
console.log("load build");
|
||||
getBuild(selected.id()).then((build) => {
|
||||
set({
|
||||
...build,
|
||||
@@ -44,7 +57,7 @@ export const ConfigProvider: Component<{}> = (p) => {
|
||||
githubAccount: build.githubAccount,
|
||||
loaded: true,
|
||||
updated: false,
|
||||
saving: false
|
||||
saving: false,
|
||||
});
|
||||
});
|
||||
};
|
||||
@@ -55,23 +68,31 @@ export const ConfigProvider: Component<{}> = (p) => {
|
||||
ws.send(UPDATE_BUILD, { build });
|
||||
};
|
||||
|
||||
const unsub = ws.subscribe(
|
||||
[ADD_UPDATE],
|
||||
({ update }: { update: Update }) => {
|
||||
if (update.buildID === selected.id()) {
|
||||
if ([UPDATE_BUILD].includes(update.operation)) {
|
||||
load();
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
onCleanup(unsub);
|
||||
const unsub = ws.subscribe([ADD_UPDATE], ({ update }: { update: Update }) => {
|
||||
if (update.buildID === selected.id()) {
|
||||
if ([UPDATE_BUILD].includes(update.operation)) {
|
||||
load();
|
||||
}
|
||||
}
|
||||
});
|
||||
onCleanup(unsub);
|
||||
|
||||
const userCanUpdate = () => {
|
||||
if (permissions() > 1) {
|
||||
return true;
|
||||
} else if (permissions() > 0 && build.owners.includes(username()!)) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
const state = {
|
||||
build,
|
||||
setBuild,
|
||||
reset: load,
|
||||
save,
|
||||
userCanUpdate,
|
||||
};
|
||||
return <context.Provider value={state}>{p.children}</context.Provider>;
|
||||
};
|
||||
|
||||
@@ -1,16 +1,28 @@
|
||||
import { Component, Show } from "solid-js";
|
||||
import { useAppState } from "../../../state/StateProvider";
|
||||
import { useUser } from "../../../state/UserProvider";
|
||||
import Tabs from "../../util/tabs/Tabs";
|
||||
import BuildConfig from "./build-config/BuildConfig";
|
||||
import GitConfig from "./git-config/GitConfig";
|
||||
import Owners from "./Owners";
|
||||
import { ConfigProvider } from "./Provider";
|
||||
|
||||
const BuildTabs: Component<{}> = (p) => {
|
||||
const { builds, selected } = useAppState();
|
||||
const { username, permissions } = useUser();
|
||||
const build = () => builds.get(selected.id())!;
|
||||
const userCanUpdate = () => {
|
||||
if (permissions() > 1) {
|
||||
return true;
|
||||
} else if (permissions() > 0 && build().owners.includes(username()!)) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
return (
|
||||
<Show when={build()}>
|
||||
<ConfigProvider build={build()}>
|
||||
<ConfigProvider>
|
||||
<Tabs
|
||||
containerClass="card tabs shadow"
|
||||
tabs={[
|
||||
@@ -20,8 +32,12 @@ const BuildTabs: Component<{}> = (p) => {
|
||||
},
|
||||
{
|
||||
title: "build",
|
||||
element: <BuildConfig />
|
||||
}
|
||||
element: <BuildConfig />,
|
||||
},
|
||||
userCanUpdate() && {
|
||||
title: "collaborators",
|
||||
element: <Owners />,
|
||||
},
|
||||
]}
|
||||
localStorageKey="build-tab"
|
||||
/>
|
||||
|
||||
@@ -9,7 +9,7 @@ import { useConfig } from "../Provider";
|
||||
import Loading from "../../../util/loading/Loading";
|
||||
|
||||
const BuildConfig: Component<{}> = (p) => {
|
||||
const { build, reset, save } = useConfig();
|
||||
const { build, reset, save, userCanUpdate } = useConfig();
|
||||
return (
|
||||
<Show when={build.loaded}>
|
||||
<Grid class="config">
|
||||
@@ -17,7 +17,7 @@ const BuildConfig: Component<{}> = (p) => {
|
||||
<Docker />
|
||||
<CliBuild />
|
||||
</Grid>
|
||||
<Show when={build.updated}>
|
||||
<Show when={userCanUpdate() && build.updated}>
|
||||
<Show
|
||||
when={!build.saving}
|
||||
fallback={
|
||||
|
||||
@@ -5,25 +5,33 @@ import Grid from "../../../util/layout/Grid";
|
||||
import { useConfig } from "../Provider";
|
||||
|
||||
const CliBuild: Component<{}> = (p) => {
|
||||
const { build, setBuild } = useConfig();
|
||||
const { build, setBuild, userCanUpdate } = useConfig();
|
||||
return (
|
||||
<Grid class="config-item shadow">
|
||||
<h1>cli build</h1>
|
||||
<div style={{ opacity: 0.7 }}>build with a custom command</div>
|
||||
<Flex justifyContent="space-between" alignItems="center">
|
||||
<div>build path</div>
|
||||
{/* <div style={{ opacity: 0.7 }}>build with a custom command</div> */}
|
||||
<Flex
|
||||
justifyContent={userCanUpdate() ? "space-between" : undefined}
|
||||
alignItems="center"
|
||||
>
|
||||
<h2>build path: </h2>
|
||||
<Input
|
||||
placeholder="from root of repo"
|
||||
value={build.cliBuild?.path || ""}
|
||||
value={build.cliBuild?.path || (userCanUpdate() ? "" : "/")}
|
||||
onEdit={(path) => setBuild("cliBuild", { path })}
|
||||
disabled={!userCanUpdate()}
|
||||
/>
|
||||
</Flex>
|
||||
<Flex justifyContent="space-between" alignItems="center">
|
||||
<div>command</div>
|
||||
<Flex
|
||||
justifyContent={userCanUpdate() ? "space-between" : undefined}
|
||||
alignItems="center"
|
||||
>
|
||||
<h2>command: </h2>
|
||||
<Input
|
||||
placeholder="ie. yarn build"
|
||||
value={build.cliBuild?.command || ""}
|
||||
onEdit={(command) => setBuild("cliBuild", { command })}
|
||||
disabled={!userCanUpdate()}
|
||||
/>
|
||||
</Flex>
|
||||
</Grid>
|
||||
|
||||
@@ -10,31 +10,45 @@ import { useConfig } from "../Provider";
|
||||
|
||||
const Docker: Component<{}> = (p) => {
|
||||
const { dockerAccounts } = useAppState();
|
||||
const { build, setBuild } = useConfig();
|
||||
const { build, setBuild, userCanUpdate } = useConfig();
|
||||
return (
|
||||
<Grid class="config-item shadow">
|
||||
<h1>docker build</h1> {/* checkbox here? */}
|
||||
<Flex justifyContent="space-between" alignItems="center">
|
||||
<div>build path</div>
|
||||
<Flex
|
||||
justifyContent={userCanUpdate() ? "space-between" : undefined}
|
||||
alignItems="center"
|
||||
>
|
||||
<h2>build path: </h2>
|
||||
<Input
|
||||
placeholder="from root of repo"
|
||||
value={build.dockerBuildArgs?.buildPath || ""}
|
||||
onEdit={(buildPath) => setBuild("dockerBuildArgs", { buildPath })}
|
||||
disabled={!userCanUpdate()}
|
||||
/>
|
||||
</Flex>
|
||||
<Flex justifyContent="space-between" alignItems="center">
|
||||
<div>dockerfile path</div>
|
||||
<Flex
|
||||
justifyContent={userCanUpdate() ? "space-between" : undefined}
|
||||
alignItems="center"
|
||||
>
|
||||
<h2>dockerfile path: </h2>
|
||||
<Input
|
||||
placeholder="from root of build path"
|
||||
value={build.dockerBuildArgs?.dockerfilePath || ""}
|
||||
value={
|
||||
build.dockerBuildArgs?.dockerfilePath ||
|
||||
(userCanUpdate() ? "" : "./dockerfile")
|
||||
}
|
||||
onEdit={(dockerfilePath) =>
|
||||
setBuild("dockerBuildArgs", { dockerfilePath })
|
||||
}
|
||||
disabled={!userCanUpdate()}
|
||||
/>
|
||||
</Flex>
|
||||
<Show when={dockerAccounts() && dockerAccounts()!.length > 0}>
|
||||
<Flex justifyContent="space-between" alignItems="center">
|
||||
<div>account</div>
|
||||
<Flex
|
||||
justifyContent={userCanUpdate() ? "space-between" : undefined}
|
||||
alignItems="center"
|
||||
>
|
||||
<h2>account: </h2>
|
||||
<Selector
|
||||
targetClass="blue"
|
||||
selected={build.dockerAccount || "none"}
|
||||
@@ -46,6 +60,7 @@ const Docker: Component<{}> = (p) => {
|
||||
);
|
||||
}}
|
||||
position="bottom right"
|
||||
disabled={!userCanUpdate()}
|
||||
/>
|
||||
</Flex>
|
||||
</Show>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { Component, Show } from "solid-js";
|
||||
import { combineClasses } from "../../../../util/helpers";
|
||||
import { Component, createEffect, Show } from "solid-js";
|
||||
import Grid from "../../../util/layout/Grid";
|
||||
import { useConfig } from "../Provider";
|
||||
import Flex from "../../../util/layout/Flex";
|
||||
@@ -9,29 +8,41 @@ import Selector from "../../../util/menu/Selector";
|
||||
|
||||
const Git: Component<{}> = (p) => {
|
||||
const { githubAccounts } = useAppState();
|
||||
const { build, setBuild } = useConfig();
|
||||
const { build, setBuild, userCanUpdate } = useConfig();
|
||||
createEffect(() => console.log(build.branch));
|
||||
return (
|
||||
<Grid class="config-item shadow">
|
||||
<h1>github config</h1>
|
||||
<Flex justifyContent="space-between" alignItems="center">
|
||||
<div>repo</div>
|
||||
<Flex
|
||||
justifyContent={userCanUpdate() ? "space-between" : undefined}
|
||||
alignItems="center"
|
||||
>
|
||||
<h2>repo: </h2>
|
||||
<Input
|
||||
placeholder="ie. solidjs/solid"
|
||||
value={build.repo || ""}
|
||||
onEdit={(value) => setBuild("repo", value)}
|
||||
disabled={!userCanUpdate()}
|
||||
/>
|
||||
</Flex>
|
||||
<Flex justifyContent="space-between" alignItems="center">
|
||||
<div>branch</div>
|
||||
<Flex
|
||||
justifyContent={userCanUpdate() ? "space-between" : undefined}
|
||||
alignItems="center"
|
||||
>
|
||||
<h2>branch: </h2>
|
||||
<Input
|
||||
placeholder="defaults to main"
|
||||
value={build.branch || ""}
|
||||
value={build.branch || (userCanUpdate() ? "" : "main")}
|
||||
onEdit={(value) => setBuild("branch", value)}
|
||||
disabled={!userCanUpdate()}
|
||||
/>
|
||||
</Flex>
|
||||
<Show when={githubAccounts() && githubAccounts()!.length > 0}>
|
||||
<Flex justifyContent="space-between" alignItems="center">
|
||||
<div>github account</div>
|
||||
<Flex
|
||||
justifyContent={userCanUpdate() ? "space-between" : undefined}
|
||||
alignItems="center"
|
||||
>
|
||||
<h2>github account: </h2>
|
||||
<Selector
|
||||
targetClass="blue"
|
||||
selected={build.githubAccount || "none"}
|
||||
@@ -43,6 +54,7 @@ const Git: Component<{}> = (p) => {
|
||||
);
|
||||
}}
|
||||
position="bottom right"
|
||||
disabled={!userCanUpdate()}
|
||||
/>
|
||||
</Flex>
|
||||
</Show>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { Component, Show } from "solid-js";
|
||||
import { combineClasses } from "../../../../util/helpers";
|
||||
import ConfirmButton from "../../../util/ConfirmButton";
|
||||
import Icon from "../../../util/Icon";
|
||||
import Flex from "../../../util/layout/Flex";
|
||||
@@ -10,7 +9,7 @@ import Git from "./Git";
|
||||
import OnClone from "./OnClone";
|
||||
|
||||
const GitConfig: Component<{}> = (p) => {
|
||||
const { build, reset, save } = useConfig();
|
||||
const { build, reset, save, userCanUpdate } = useConfig();
|
||||
return (
|
||||
<Show when={build.loaded}>
|
||||
<Grid class="config">
|
||||
@@ -18,7 +17,7 @@ const GitConfig: Component<{}> = (p) => {
|
||||
<Git />
|
||||
<OnClone />
|
||||
</Grid>
|
||||
<Show when={build.updated}>
|
||||
<Show when={userCanUpdate() && build.updated}>
|
||||
<Show
|
||||
when={!build.saving}
|
||||
fallback={
|
||||
|
||||
@@ -7,12 +7,15 @@ import s from "../../build.module.css";
|
||||
import Flex from "../../../util/layout/Flex";
|
||||
|
||||
const OnClone: Component = () => {
|
||||
const { build, setBuild } = useConfig();
|
||||
const { build, setBuild, userCanUpdate } = useConfig();
|
||||
return (
|
||||
<Grid class="config-item shadow">
|
||||
<h1>on clone</h1>
|
||||
<Flex alignItems="center" justifyContent="space-between">
|
||||
path:
|
||||
<Flex
|
||||
alignItems="center"
|
||||
justifyContent={userCanUpdate() ? "space-between" : undefined}
|
||||
>
|
||||
<h2>path:</h2>
|
||||
<Input
|
||||
placeholder="relative to repo"
|
||||
value={build.onClone?.path || ""}
|
||||
@@ -27,10 +30,14 @@ const OnClone: Component = () => {
|
||||
}
|
||||
setBuild("onClone", { path });
|
||||
}}
|
||||
disabled={!userCanUpdate()}
|
||||
/>
|
||||
</Flex>
|
||||
<Flex alignItems="center" justifyContent="space-between">
|
||||
command:
|
||||
<Flex
|
||||
alignItems="center"
|
||||
justifyContent={userCanUpdate() ? "space-between" : undefined}
|
||||
>
|
||||
<h2>command:</h2>
|
||||
<Input
|
||||
placeholder="command"
|
||||
value={build.onClone?.command || ""}
|
||||
@@ -45,6 +52,7 @@ const OnClone: Component = () => {
|
||||
}
|
||||
setBuild("onClone", { command });
|
||||
}}
|
||||
disabled={!userCanUpdate()}
|
||||
/>
|
||||
</Flex>
|
||||
</Grid>
|
||||
|
||||
@@ -44,7 +44,7 @@ const Config: Component<{}> = (p) => {
|
||||
</Grid>
|
||||
),
|
||||
},
|
||||
{
|
||||
(userCanUpdate() || deployment.repo ? true : false) && {
|
||||
title: "repo mount",
|
||||
element: (
|
||||
<Grid class="config-items scroller">
|
||||
@@ -58,7 +58,7 @@ const Config: Component<{}> = (p) => {
|
||||
userCanUpdate() && {
|
||||
title: "collaborators",
|
||||
element: (
|
||||
<Grid class="config-items scroller">
|
||||
<Grid class="config-items scroller" style={{ height: "100%" }}>
|
||||
<Owners />
|
||||
</Grid>
|
||||
),
|
||||
|
||||
@@ -8,29 +8,40 @@ import { useConfig } from "../Provider";
|
||||
|
||||
const Git: Component<{}> = (p) => {
|
||||
const { githubAccounts } = useAppState();
|
||||
const { deployment, setDeployment } = useConfig();
|
||||
const { deployment, setDeployment, userCanUpdate } = useConfig();
|
||||
return (
|
||||
<Grid class="config-item shadow">
|
||||
<h1>github config</h1>
|
||||
<Flex justifyContent="space-between" alignItems="center">
|
||||
<div>repo</div>
|
||||
<Flex
|
||||
justifyContent={userCanUpdate() ? "space-between" : undefined}
|
||||
alignItems="center"
|
||||
>
|
||||
<h2>repo: </h2>
|
||||
<Input
|
||||
placeholder="ie. solidjs/solid"
|
||||
value={deployment.repo || ""}
|
||||
onEdit={(value) => setDeployment("repo", value)}
|
||||
disabled={!userCanUpdate()}
|
||||
/>
|
||||
</Flex>
|
||||
<Flex justifyContent="space-between" alignItems="center">
|
||||
<div>branch</div>
|
||||
<Flex
|
||||
justifyContent={userCanUpdate() ? "space-between" : undefined}
|
||||
alignItems="center"
|
||||
>
|
||||
<h2>branch: </h2>
|
||||
<Input
|
||||
placeholder="defaults to main"
|
||||
value={deployment.branch || ""}
|
||||
onEdit={(value) => setDeployment("branch", value)}
|
||||
disabled={!userCanUpdate()}
|
||||
/>
|
||||
</Flex>
|
||||
<Show when={githubAccounts() && githubAccounts()!.length > 0}>
|
||||
<Flex justifyContent="space-between" alignItems="center">
|
||||
<div>github account</div>
|
||||
<Flex
|
||||
justifyContent={userCanUpdate() ? "space-between" : undefined}
|
||||
alignItems="center"
|
||||
>
|
||||
<h2>github account: </h2>
|
||||
<Selector
|
||||
targetClass="blue"
|
||||
selected={deployment.githubAccount || "none"}
|
||||
@@ -42,6 +53,7 @@ const Git: Component<{}> = (p) => {
|
||||
);
|
||||
}}
|
||||
position="bottom right"
|
||||
disabled={!userCanUpdate()}
|
||||
/>
|
||||
</Flex>
|
||||
</Show>
|
||||
|
||||
@@ -5,15 +5,18 @@ import Grid from "../../../../util/layout/Grid";
|
||||
import { useConfig } from "../Provider";
|
||||
|
||||
export const OnClone: Component<{}> = (p) => {
|
||||
const { deployment, setDeployment } = useConfig();
|
||||
const { deployment, setDeployment, userCanUpdate } = useConfig();
|
||||
return (
|
||||
<Grid class="config-item shadow">
|
||||
<h1>on clone</h1>
|
||||
<Flex alignItems="center" justifyContent="space-between">
|
||||
path:
|
||||
<Flex
|
||||
alignItems="center"
|
||||
justifyContent={userCanUpdate() ? "space-between" : undefined}
|
||||
>
|
||||
<h2>path:</h2>
|
||||
<Input
|
||||
placeholder="relative to repo"
|
||||
value={deployment.onClone?.path || ""}
|
||||
value={deployment.onClone?.path || (userCanUpdate() ? "" : "/")}
|
||||
onEdit={(path) => {
|
||||
if (
|
||||
path.length === 0 &&
|
||||
@@ -25,10 +28,14 @@ export const OnClone: Component<{}> = (p) => {
|
||||
}
|
||||
setDeployment("onClone", { path });
|
||||
}}
|
||||
disabled={!userCanUpdate()}
|
||||
/>
|
||||
</Flex>
|
||||
<Flex alignItems="center" justifyContent="space-between">
|
||||
command:
|
||||
<Flex
|
||||
alignItems="center"
|
||||
justifyContent={userCanUpdate() ? "space-between" : undefined}
|
||||
>
|
||||
<h2>command:</h2>
|
||||
<Input
|
||||
placeholder="command"
|
||||
value={deployment.onClone?.command || ""}
|
||||
@@ -43,6 +50,7 @@ export const OnClone: Component<{}> = (p) => {
|
||||
}
|
||||
setDeployment("onClone", { command });
|
||||
}}
|
||||
disabled={!userCanUpdate()}
|
||||
/>
|
||||
</Flex>
|
||||
</Grid>
|
||||
@@ -50,12 +58,15 @@ export const OnClone: Component<{}> = (p) => {
|
||||
};
|
||||
|
||||
export const OnPull: Component<{}> = (p) => {
|
||||
const { deployment, setDeployment } = useConfig();
|
||||
const { deployment, setDeployment, userCanUpdate } = useConfig();
|
||||
return (
|
||||
<Grid class="config-item shadow">
|
||||
<h1>on pull</h1>
|
||||
<Flex alignItems="center" justifyContent="space-between">
|
||||
path:
|
||||
<Flex
|
||||
alignItems="center"
|
||||
justifyContent={userCanUpdate() ? "space-between" : undefined}
|
||||
>
|
||||
<h2>path:</h2>
|
||||
<Input
|
||||
placeholder="relative to repo"
|
||||
value={deployment.onPull?.path || ""}
|
||||
@@ -70,10 +81,14 @@ export const OnPull: Component<{}> = (p) => {
|
||||
}
|
||||
setDeployment("onPull", { path });
|
||||
}}
|
||||
disabled={!userCanUpdate()}
|
||||
/>
|
||||
</Flex>
|
||||
<Flex alignItems="center" justifyContent="space-between">
|
||||
command:
|
||||
<Flex
|
||||
alignItems="center"
|
||||
justifyContent={userCanUpdate() ? "space-between" : undefined}
|
||||
>
|
||||
<h2>command:</h2>
|
||||
<Input
|
||||
placeholder="command"
|
||||
value={deployment.onPull?.command || ""}
|
||||
@@ -88,6 +103,7 @@ export const OnPull: Component<{}> = (p) => {
|
||||
}
|
||||
setDeployment("onPull", { command });
|
||||
}}
|
||||
disabled={!userCanUpdate()}
|
||||
/>
|
||||
</Flex>
|
||||
</Grid>
|
||||
|
||||
@@ -5,16 +5,20 @@ import Grid from "../../../../util/layout/Grid";
|
||||
import { useConfig } from "../Provider";
|
||||
|
||||
const RepoMount: Component<{}> = (p) => {
|
||||
const { deployment, setDeployment } = useConfig();
|
||||
const { deployment, setDeployment, userCanUpdate } = useConfig();
|
||||
return (
|
||||
<Grid class="config-item shadow">
|
||||
<h1>mount</h1>
|
||||
<Flex alignItems="center" justifyContent="space-between">
|
||||
<Flex
|
||||
alignItems="center"
|
||||
justifyContent={userCanUpdate() ? "space-between" : undefined}
|
||||
>
|
||||
<Input
|
||||
placeholder="repo folder to mount"
|
||||
value={deployment.repoMount || ""}
|
||||
style={{ width: "40%" }}
|
||||
onEdit={(value) => setDeployment("repoMount", value)}
|
||||
disabled={!userCanUpdate()}
|
||||
/>
|
||||
{" : "}
|
||||
<Input
|
||||
@@ -22,6 +26,7 @@ const RepoMount: Component<{}> = (p) => {
|
||||
value={deployment.containerMount || ""}
|
||||
style={{ width: "40%" }}
|
||||
onEdit={(value) => setDeployment("containerMount", value)}
|
||||
disabled={!userCanUpdate()}
|
||||
/>
|
||||
</Flex>
|
||||
</Grid>
|
||||
|
||||
@@ -25,9 +25,9 @@ const Account: Component<{ close: () => void }> = (p) => {
|
||||
manage users
|
||||
</button>
|
||||
</Show>
|
||||
<ConfirmButton onConfirm={logout} color="red">
|
||||
<button onClick={logout} class="red">
|
||||
log out
|
||||
</ConfirmButton>
|
||||
</button>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -53,6 +53,7 @@
|
||||
}
|
||||
|
||||
.config-items {
|
||||
height: fit-content;
|
||||
max-height: 65vh;
|
||||
padding: 0rem 0.5rem;
|
||||
}
|
||||
|
||||
@@ -23,6 +23,13 @@ h1 {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 1.1rem;
|
||||
font-weight: 450;
|
||||
user-select: none;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
button {
|
||||
color: inherit;
|
||||
padding: 0.5rem;
|
||||
|
||||
@@ -39,6 +39,20 @@ export async function getBuildActionState(buildID: string) {
|
||||
);
|
||||
}
|
||||
|
||||
export async function addOwnerToBuild(
|
||||
buildID: string,
|
||||
username: string
|
||||
) {
|
||||
return await client.post(`/api/build/${buildID}/${username}`);
|
||||
}
|
||||
|
||||
export async function removeOwnerFromBuild(
|
||||
buildID: string,
|
||||
username: string
|
||||
) {
|
||||
return await client.delete(`/api/build/${buildID}/${username}`);
|
||||
}
|
||||
|
||||
export async function getDeployments(query?: { serverID?: string }) {
|
||||
return await client.get<Deployments>(
|
||||
"/api/deployments" + generateQuery(query)
|
||||
|
||||
Reference in New Issue
Block a user