import {Modal, spawnReactModal} from "tc-shared/ui/react-elements/Modal"; import {ConnectionHandler} from "tc-shared/ConnectionHandler"; import {Registry} from "tc-shared/events"; import {useRef, useState} from "react"; import {FlatSelect} from "tc-shared/ui/react-elements/InputField"; import {Translatable} from "tc-shared/ui/react-elements/i18n"; import * as React from "react"; import {Button} from "tc-shared/ui/react-elements/Button"; import {GroupType} from "tc-shared/permission/GroupManager"; import PermissionType from "tc-shared/permission/PermissionType"; import {CommandResult, ErrorID} from "tc-shared/connection/ServerConnectionDeclaration"; import {createErrorModal, createInfoModal} from "tc-shared/ui/elements/Modal"; import {tra} from "tc-shared/i18n/localize"; const cssStyle = require("./ModalGroupPermissionCopy.scss"); export type GroupInfo = { id: number, name: string, type: "query" | "template" | "normal" }; export interface GroupPermissionCopyModalEvents { action_set_source: { group: number }, action_set_target: { group: number } action_cancel: {}, action_copy: { source: number; target: number; } query_available_groups: { }, query_available_groups_result: { groups: GroupInfo[] }, query_client_permissions: {}, notify_client_permissions: { createTemplateGroup: boolean, createQueryGroup: boolean }, notify_destroy: {} } const GroupSelector = (props: { events: Registry, defaultGroup: number, updateEvent: "action_set_source" | "action_set_target", label: string, className: string}) => { const [ selectedGroup, setSelectedGroup ] = useState(undefined); const [ permissions, setPermissions ] = useState<"loading" | { createTemplate, createQuery }>("loading"); const [ exitingGroups, setExitingGroups ] = useState<"loading" | GroupInfo[]>("loading"); const refSelect = useRef(); props.events.reactUse("notify_client_permissions", event => setPermissions({ createQuery: event.createQueryGroup, createTemplate: event.createTemplateGroup })); props.events.reactUse("query_available_groups_result", event => setExitingGroups(event.groups)); props.events.reactUse(props.updateEvent, event => setSelectedGroup(event.group)); const groupName = (group: GroupInfo) => { let prefix = group.type === "template" ? "[T] " : group.type === "query" ? "[Q] " : ""; return prefix + group.name + " (" + group.id + ")"; }; const isLoading = exitingGroups === "loading" || permissions === "loading"; if(!isLoading && selectedGroup === undefined) props.events.fire_async(props.updateEvent, { group: (exitingGroups as GroupInfo[]).findIndex(e => e.id === props.defaultGroup) === -1 ? 0 : props.defaultGroup }); return ( {props.label}} className={props.className} disabled={isLoading} value={isLoading || selectedGroup === undefined ? "-1" : selectedGroup.toString()} onChange={event => props.events.fire(props.updateEvent, { group: parseInt(event.target.value) })} > {exitingGroups === "loading" ? undefined : exitingGroups.filter(e => e.type === "query").map(e => ( )) } {exitingGroups === "loading" ? undefined : exitingGroups.filter(e => e.type === "template").map(e => ( )) } {exitingGroups === "loading" ? undefined : exitingGroups.filter(e => e.type === "normal").map(e => ( )) } ) }; const CopyButton = (props: { events: Registry }) => { const [ sourceGroup, setSourceGroup ] = useState(0); const [ targetGroup, setTargetGroup ] = useState(0); props.events.reactUse("action_set_source", event => setSourceGroup(event.group)); props.events.reactUse("action_set_target", event => setTargetGroup(event.group)); return }; class ModalGroupPermissionCopy extends Modal { readonly events = new Registry(); readonly defaultSource: number; readonly defaultTarget: number; constructor(connection: ConnectionHandler, target: "server" | "channel", sourceGroup?: number, targetGroup?: number) { super(); this.defaultSource = sourceGroup; this.defaultTarget = targetGroup; initializeGroupPermissionCopyController(connection, this.events, target); } protected onInitialize() { this.modalController().events.on("destroy", () => this.events.fire("notify_destroy")); this.events.fire_async("query_available_groups"); this.events.fire_async("query_client_permissions"); this.events.on(["action_cancel", "action_copy"], () => this.modalController().destroy()); } renderBody() { return
; } title(): string { return tr("Copy group permissions"); } } export function spawnModalGroupPermissionCopy(connection: ConnectionHandler, target: "channel" | "server", sourceGroup?: number, targetGroup?: number) { const modal = spawnReactModal(ModalGroupPermissionCopy, connection, target, sourceGroup, targetGroup); modal.show(); } const stringifyError = error => { if(error instanceof CommandResult) { if(error.id === ErrorID.PERMISSION_ERROR) return tr("insufficient permissions"); else return error.message + (error.extra_message ? " (" + error.extra_message + ")" : ""); } else if(error instanceof Error) { return error.message; } else if(typeof error !== "string") { return tr("Lookup the console"); } return error; }; function initializeGroupPermissionCopyController(connection: ConnectionHandler, events: Registry, target: "server" | "channel") { events.on("query_available_groups", event => { const groups = target === "server" ? connection.groups.serverGroups : connection.groups.channelGroups; events.fire_async("query_available_groups_result", { groups: groups.map(e => { return { name: e.name, id: e.id, type: e.type === GroupType.TEMPLATE ? "template" : e.type === GroupType.QUERY ? "query" : "normal" } }) }); }); const notifyClientPermissions = () => events.fire_async("notify_client_permissions", { createQueryGroup: connection.permissions.neededPermission(PermissionType.B_SERVERINSTANCE_MODIFY_QUERYGROUP).granted(1), createTemplateGroup: connection.permissions.neededPermission(PermissionType.B_SERVERINSTANCE_MODIFY_TEMPLATES).granted(1) }); events.on("query_client_permissions", notifyClientPermissions); events.on("notify_destroy", connection.permissions.events.on("client_permissions_changed", notifyClientPermissions)); events.on("action_copy", event => { connection.serverConnection.send_command("servergroupcopy", { ssgid: event.source, tsgid: event.target }).then(() => { createInfoModal(tr("Group permissions have been copied"), tr("The group permissions have been successfully copied.")).open(); }).catch(error => { if(error instanceof CommandResult && error.id === ErrorID.PERMISSION_ERROR) { createErrorModal(tr("Failed to copy group permissions"), tra("Failed to copy group permissions.\nMissing permission {}", connection.permissions.resolveInfo(parseInt(error.json["failed_permid"]))?.name || tr("unknwon"))).open(); return; } console.warn(tr("Failed to copy group permissions: %o"), error); createErrorModal(tr("Failed to copy group permissions"), tra("Failed to copy group permissions.\n{}", stringifyError(error))).open(); }); }); }