diff --git a/frontend/src/components/home/Home.tsx b/frontend/src/components/home/Home.tsx index 5e7d4934b..493693d99 100644 --- a/frontend/src/components/home/Home.tsx +++ b/frontend/src/components/home/Home.tsx @@ -2,19 +2,16 @@ import { Component, } from "solid-js"; import { useAppDimensions } from "../../state/DimensionProvider"; -import { useAppState } from "../../state/StateProvider"; import Grid from "../shared/layout/Grid"; import SimpleTabs from "../shared/tabs/SimpleTabs"; import Summary from "./Summary"; import Builds from "./Tree/Builds"; -import Groups from "./Tree/Groups2"; +import Groups from "./Tree/Groups"; import { TreeProvider } from "./Tree/Provider"; -import Servers from "./Tree/Servers"; import Updates from "./Updates/Updates"; const Home: Component<{}> = (p) => { const { isSemiMobile } = useAppDimensions(); - const { servers } = useAppState(); return ( <> = (p) => { title: "servers", element: () => , }, - // { - // title: "servers", - // element: () => , - // }, { title: "builds", element: () => diff --git a/frontend/src/components/home/Tree/Groups.tsx b/frontend/src/components/home/Tree/Groups.tsx index fbd48efef..6fd7c4633 100644 --- a/frontend/src/components/home/Tree/Groups.tsx +++ b/frontend/src/components/home/Tree/Groups.tsx @@ -1,27 +1,35 @@ -import { Component, createMemo, createSignal, For, Show } from "solid-js"; -import { useAppState } from "../../../state/StateProvider"; -import { useLocalStorageToggle } from "../../../util/hooks"; -import Icon from "../../shared/Icon"; -import Input from "../../shared/Input"; -import Flex from "../../shared/layout/Flex"; +import { Component, For, Show, createMemo, createSignal } from "solid-js"; import Grid from "../../shared/layout/Grid"; +import { useLocalStorage, useToggle } from "../../../util/hooks"; +import Flex from "../../shared/layout/Flex"; +import { TREE_SORTS, TreeSortType, useTreeState } from "./Provider"; +import { useAppState } from "../../../state/StateProvider"; +import Input from "../../shared/Input"; +import Selector from "../../shared/menu/Selector"; import { NewGroup } from "../../New"; -import s from "../home.module.scss"; -import { combineClasses } from "../../../util/helpers"; +import Icon from "../../shared/Icon"; +import { useAppDimensions } from "../../../state/DimensionProvider"; +import ConfirmButton from "../../shared/ConfirmButton"; import Server from "./Server"; +import { useWindowKeyDown } from "../../../util/hooks"; import Menu from "../../shared/menu/Menu"; import { client } from "../../.."; -import ConfirmButton from "../../shared/ConfirmButton"; -import { TreeSortType, TREE_SORTS, useTreeState } from "./Provider"; -import Selector from "../../shared/menu/Selector"; +import { useUser } from "../../../state/UserProvider"; +import { PermissionLevel } from "../../../types"; const Groups: Component<{}> = (p) => { + const { isSemiMobile } = useAppDimensions(); const { groups } = useAppState(); - const [groupFilter, setGroupFilter] = createSignal(""); + const [selected, setSelected] = useLocalStorage( + null, + "home-selected-group-v1" + ); + const [searchFilter, setSearchFilter] = createSignal(""); const { sort, setSort, group_sorter } = useTreeState(); + const [editing, toggleEditing, setEditing] = useToggle(); const groupIDs = createMemo(() => { if (groups.loaded()) { - const filters = groupFilter() + const filters = searchFilter() .split(" ") .filter((term) => term.length > 0) .map((term) => term.toLowerCase()); @@ -42,176 +50,249 @@ const Groups: Component<{}> = (p) => { } }); return ( - - + + + + + +

+ {selected() === "all" ? "all" : groups.get(selected()!)?.name} +

+
+
- sort by:} - selected={sort()} - items={TREE_SORTS as any as string[]} - onSelect={(mode) => setSort(mode as TreeSortType)} - position="bottom right" - targetClass="blue" - targetStyle={{ height: "100%" }} - containerStyle={{ height: "100%" }} - /> - + + sort by:} + selected={sort()} + items={TREE_SORTS as any as string[]} + onSelect={(mode) => setSort(mode as TreeSortType)} + position="bottom right" + targetClass="blue" + targetStyle={{ height: "100%" }} + containerStyle={{ height: "100%" }} + /> + }> + + + + + +
- {(id) => } + + + + {(id) => } + +
+ } + > + { + setSelected(null); + setEditing(false); + }} + editing={editing()} + /> +
); }; export default Groups; -const Group: Component<{ id: string }> = (p) => { - const { groups, servers, ungroupedServerIds } = useAppState(); - const { server_sorter } = useTreeState(); - const group = () => groups.get(p.id); - const serverIDs = () => group()?.servers.sort(server_sorter()); - const [open, toggleOpen] = useLocalStorageToggle(p.id + "-group-homeopen-v1"); - const [showAdd, setShowAdd] = createSignal(false); - const [edit, setEdit] = createSignal(false); +const GroupButton: Component<{ + id: string; + setSelected: (s: string) => void; +}> = (p) => { + const { isSemiMobile } = useAppDimensions(); + const { groups, servers } = useAppState(); + const isAll = () => p.id === "all"; + const name = () => { + if (isAll()) { + return "all"; + } + return groups.get(p.id)?.name; + }; + const serverCount = () => { + if (isAll()) { + return servers.ids()?.length || 0; + } + return ( + groups.get(p.id)?.servers.filter((server_id) => servers.get(server_id)) + .length || 0 + ); + }; return ( - - - 0}> - { - e.stopPropagation(); - setShowAdd(false); - }} - position="bottom right" - target={ - - } - menuStyle={{ gap: "0.5rem" }} - content={ - <> - {/* */} - - {(server_id) => { - const server = () => servers.get(server_id)!; - return ( - - client.update_group({ - ...group()!, - servers: [...group()!.servers, server_id], - }) - } - > - {server().server.name} - - ); - }} - - - } - /> - - + client.delete_group(p.id)} > + + + + ); +}; + +const Group: Component<{ + id: string; + searchFilter: string; + editing: boolean; + exit: () => void; +}> = (p) => { + const { groups, servers } = useAppState(); + const { server_sorter } = useTreeState(); + const group = () => groups.get(p.id); + const serverIDs = createMemo(() => { + if (servers.loaded()) { + const filters = p.searchFilter + .split(" ") + .filter((term) => term.length > 0) + .map((term) => term.toLowerCase()); + const serverIds = ( + p.id === "all" + ? servers.ids() + : groups + .get(p.id) + ?.servers.filter((server_id) => servers.get(server_id)) + )?.sort(server_sorter()); + return serverIds + ?.filter((id) => { + const name = servers.get(id)!.server.name; + for (const term of filters) { + if (!name.includes(term)) { + return false; + } + } + return true; + }) + .sort(server_sorter()); + } else { + return undefined; + } + }); + useWindowKeyDown((e) => { + if (e.key === "ArrowLeft" || e.key === "Escape") { + p.exit(); + } + }); + return ( + + {(id) => ( + + + + { + client.update_group({ + ...group()!, + servers: group()!.servers.filter((member) => member !== id), + }); + }} + > + + + - - - -
-
servers
-
- - - {(id) => { - return ( - - - + )} + + ); +}; + +const AddServerToGroup: Component<{ groupId: string }> = (p) => { + const { user, user_id } = useUser(); + const { groups, servers, ungroupedServerIds } = useAppState(); + const [showAdd, setShowAdd] = createSignal(false); + const group = () => groups.get(p.groupId); + const canEdit = () => + user().admin || + group()?.permissions?.[user_id()] === PermissionLevel.Update; + return ( + 0)} + > + { + e.stopPropagation(); + setShowAdd(false); + }} + position="bottom right" + target={ + + } + menuStyle={{ gap: "0.5rem" }} + content={ + <> + {/* */} + + {(server_id) => { + const server = () => servers.get(server_id)!; + return ( { + class="lightgrey" + style={{ width: "100%" }} + onConfirm={() => client.update_group({ ...group()!, - servers: group()!.servers.filter( - (member) => member !== id - ), - }); - }} + servers: [...group()!.servers, server_id], + }) + } > - + {server().server.name} - - - ); - }} - - -
-
end
-
- - + ); + }} + + + } + /> ); }; diff --git a/frontend/src/components/home/Tree/Groups2.tsx b/frontend/src/components/home/Tree/Groups2.tsx deleted file mode 100644 index e3bbfc66d..000000000 --- a/frontend/src/components/home/Tree/Groups2.tsx +++ /dev/null @@ -1,283 +0,0 @@ -import { Component, For, Show, createMemo, createSignal } from "solid-js"; -import Grid from "../../shared/layout/Grid"; -import { useLocalStorage, useToggle } from "../../../util/hooks"; -import Flex from "../../shared/layout/Flex"; -import { TREE_SORTS, TreeSortType, useTreeState } from "./Provider"; -import { useAppState } from "../../../state/StateProvider"; -import Input from "../../shared/Input"; -import Selector from "../../shared/menu/Selector"; -import { NewGroup } from "../../New"; -import Icon from "../../shared/Icon"; -import { useAppDimensions } from "../../../state/DimensionProvider"; -import ConfirmButton from "../../shared/ConfirmButton"; -import Server from "./Server"; -import { useWindowKeyDown } from "../../../util/hooks"; -import Menu from "../../shared/menu/Menu"; -import { client } from "../../.."; - -const Groups: Component<{}> = (p) => { - const { isSemiMobile } = useAppDimensions(); - const { groups } = useAppState(); - const [selected, setSelected] = useLocalStorage( - null, - "home-selected-group-v1" - ); - const [searchFilter, setSearchFilter] = createSignal(""); - const { sort, setSort, group_sorter } = useTreeState(); - const [editing, toggleEditing, setEditing] = useToggle(); - const groupIDs = createMemo(() => { - if (groups.loaded()) { - const filters = searchFilter() - .split(" ") - .filter((term) => term.length > 0) - .map((term) => term.toLowerCase()); - return groups - .ids() - ?.filter((id) => { - const name = groups.get(id)!.name; - for (const term of filters) { - if (!name.includes(term)) { - return false; - } - } - return true; - }) - .sort(group_sorter()); - } else { - return undefined; - } - }); - return ( - - - - - -

- {selected() === "all" ? "all" : groups.get(selected()!)?.name} -

-
-
- - - sort by:
} - selected={sort()} - items={TREE_SORTS as any as string[]} - onSelect={(mode) => setSort(mode as TreeSortType)} - position="bottom right" - targetClass="blue" - targetStyle={{ height: "100%" }} - containerStyle={{ height: "100%" }} - /> - }> - - - - - - - - - - - {(id) => } - - - } - > - { - setSelected(null); - setEditing(false); - }} - editing={editing()} - /> - - - ); -}; - -export default Groups; - -const GroupButton: Component<{ - id: string; - setSelected: (s: string) => void; -}> = (p) => { - const { isSemiMobile } = useAppDimensions(); - const { groups, servers } = useAppState(); - const isAll = () => p.id === "all"; - const name = () => { - if (isAll()) { - return "all"; - } - return groups.get(p.id)?.name; - }; - const serverCount = () => { - if (isAll()) { - return servers.ids()?.length || 0; - } - return groups.get(p.id)?.servers.length || 0; - }; - return ( - p.setSelected(p.id)} - > -

{name()}

- - -
{serverCount()}
-
{`server${serverCount() > 1 ? "s" : ""}`}
-
- - client.delete_group(p.id)} - > - - - -
-
- ); -}; - -const Group: Component<{ - id: string; - searchFilter: string; - editing: boolean; - exit: () => void; -}> = (p) => { - const { groups, servers } = useAppState(); - const { server_sorter } = useTreeState(); - const group = () => groups.get(p.id); - const serverIDs = createMemo(() => { - if (servers.loaded()) { - const filters = p.searchFilter - .split(" ") - .filter((term) => term.length > 0) - .map((term) => term.toLowerCase()); - const serverIds = ( - p.id === "all" ? servers.ids() : groups.get(p.id)?.servers - )?.sort(server_sorter()); - return serverIds - ?.filter((id) => { - const name = servers.get(id)!.server.name; - for (const term of filters) { - if (!name.includes(term)) { - return false; - } - } - return true; - }) - .sort(server_sorter()); - } else { - return undefined; - } - }); - useWindowKeyDown((e) => { - if (e.key === "ArrowLeft" || e.key === "Escape") { - p.exit(); - } - }); - return ( - - {(id) => ( - - - - { - client.update_group({ - ...group()!, - servers: group()!.servers.filter((member) => member !== id), - }); - }} - > - - - - - )} - - ); -}; - -const AddServerToGroup: Component<{ groupId: string }> = (p) => { - const { groups, servers, ungroupedServerIds } = useAppState(); - const [showAdd, setShowAdd] = createSignal(false); - const group = () => groups.get(p.groupId); - return ( - 0}> - { - e.stopPropagation(); - setShowAdd(false); - }} - position="bottom right" - target={ - - } - menuStyle={{ gap: "0.5rem" }} - content={ - <> - {/* */} - - {(server_id) => { - const server = () => servers.get(server_id)!; - return ( - - client.update_group({ - ...group()!, - servers: [...group()!.servers, server_id], - }) - } - > - {server().server.name} - - ); - }} - - - } - /> - - ); -}; diff --git a/frontend/src/components/home/Tree/Servers.tsx b/frontend/src/components/home/Tree/Servers.tsx deleted file mode 100644 index 8c9e8b679..000000000 --- a/frontend/src/components/home/Tree/Servers.tsx +++ /dev/null @@ -1,66 +0,0 @@ -import { Component, createMemo, createSignal, For, Show } from "solid-js"; -import { useAppState } from "../../../state/StateProvider"; -import { useUser } from "../../../state/UserProvider"; -import Input from "../../shared/Input"; -import Grid from "../../shared/layout/Grid"; -import Selector from "../../shared/menu/Selector"; -import AddServer from "../../topbar/AddServer"; -import { TreeSortType, TREE_SORTS, useTreeState } from "./Provider"; -import Server from "./Server"; - -const Servers: Component<{ serverIDs: string[]; showAdd?: boolean }> = (p) => { - const { user } = useUser(); - const { servers } = useAppState(); - const { sort, setSort, server_sorter } = useTreeState(); - const [serverFilter, setServerFilter] = createSignal(""); - const serverIDs = createMemo(() => { - if (servers.loaded()) { - const filters = serverFilter() - .split(" ") - .filter((term) => term.length > 0) - .map((term) => term.toLowerCase()); - return p.serverIDs.filter((id) => { - const name = servers.get(id)!.server.name; - for (const term of filters) { - if (!name.includes(term)) { - return false; - } - } - return true; - }) - .sort(server_sorter()); - } else { - return undefined; - } - }); - return ( - - - - sort by:
} - selected={sort()} - items={TREE_SORTS as any as string[]} - onSelect={(mode) => setSort(mode as TreeSortType)} - position="bottom right" - targetClass="blue" - targetStyle={{ height: "100%" }} - containerStyle={{ height: "100%" }} - /> - - - -
- {(id) => } - - ); -}; - -export default Servers;