import React, { useContext, useEffect, useState } from 'react'; import { Button, Col, Collapse, Row, Slider, Space } from 'antd'; import Paragraph from 'antd/lib/typography/Paragraph'; import Title from 'antd/lib/typography/Title'; import { EditCustomStyles } from '../../EditCustomStyles'; import s from './appearance.module.scss'; import { postConfigUpdateToAPI, RESET_TIMEOUT } from '../../../../utils/config-constants'; import { createInputStatus, StatusState, STATUS_ERROR, STATUS_SUCCESS, } from '../../../../utils/input-statuses'; import { ServerStatusContext } from '../../../../utils/server-status-context'; import { FormStatusIndicator } from '../../FormStatusIndicator'; const { Panel } = Collapse; const ENDPOINT = '/appearance'; interface AppearanceVariable { value: string; description: string; } const chatColorVariables = [ { name: 'theme-color-users-0', description: '' }, { name: 'theme-color-users-1', description: '' }, { name: 'theme-color-users-2', description: '' }, { name: 'theme-color-users-3', description: '' }, { name: 'theme-color-users-4', description: '' }, { name: 'theme-color-users-5', description: '' }, { name: 'theme-color-users-6', description: '' }, { name: 'theme-color-users-7', description: '' }, ]; const paletteVariables = [ { name: 'theme-color-palette-0', description: '' }, { name: 'theme-color-palette-1', description: '' }, { name: 'theme-color-palette-2', description: '' }, { name: 'theme-color-palette-3', description: '' }, { name: 'theme-color-palette-4', description: '' }, { name: 'theme-color-palette-5', description: '' }, { name: 'theme-color-palette-6', description: '' }, { name: 'theme-color-palette-7', description: '' }, { name: 'theme-color-palette-8', description: '' }, { name: 'theme-color-palette-9', description: '' }, { name: 'theme-color-palette-10', description: '' }, { name: 'theme-color-palette-11', description: '' }, { name: 'theme-color-palette-12', description: '' }, ]; const componentColorVariables = [ { name: 'theme-color-background-main', description: 'Background' }, { name: 'theme-color-action', description: 'Action' }, { name: 'theme-color-action-hover', description: 'Action Hover' }, { name: 'theme-color-components-chat-background', description: 'Chat Background' }, { name: 'theme-color-components-chat-text', description: 'Text: Chat' }, { name: 'theme-color-components-text-on-dark', description: 'Text: Light' }, { name: 'theme-color-components-text-on-light', description: 'Text: Dark' }, { name: 'theme-color-background-header', description: 'Header/Footer' }, { name: 'theme-color-components-content-background', description: 'Page Content' }, { name: 'theme-color-components-scrollbar-background', description: 'Scrollbar Background' }, { name: 'theme-color-components-scrollbar-thumb', description: 'Scrollbar Thumb' }, ]; const others = [{ name: 'theme-rounded-corners', description: 'Corner radius' }]; // Create an object so these vars can be indexed by name. const allAvailableValues = [ ...paletteVariables, ...componentColorVariables, ...chatColorVariables, ...others, ].reduce((obj, val) => { // eslint-disable-next-line no-param-reassign obj[val.name] = { name: val.name, description: val.description }; return obj; }, {}); // eslint-disable-next-line react/function-component-definition function ColorPicker({ value, name, description, onChange, }: { value: string; name: string; description: string; onChange: (name: string, value: string, description: string) => void; }) { return ( onChange(name, e.target.value, description)} />
{description}
); } // eslint-disable-next-line react/function-component-definition export default function Appearance() { const serverStatusData = useContext(ServerStatusContext); const { serverConfig } = serverStatusData; const { instanceDetails } = serverConfig; const { appearanceVariables } = instanceDetails; const [colors, setColors] = useState>(); const [submitStatus, setSubmitStatus] = useState(null); let resetTimer = null; const resetStates = () => { setSubmitStatus(null); resetTimer = null; clearTimeout(resetTimer); }; const setColorDefaults = () => { const c = {}; [...paletteVariables, ...componentColorVariables, ...chatColorVariables, ...others].forEach( color => { const resolvedColor = getComputedStyle(document.documentElement).getPropertyValue( `--${color.name}`, ); c[color.name] = { value: resolvedColor.trim(), description: color.description }; }, ); setColors(c); }; useEffect(() => { setColorDefaults(); }, []); useEffect(() => { if (Object.keys(appearanceVariables).length === 0) return; const c = colors || {}; Object.keys(appearanceVariables).forEach(key => { c[key] = { value: appearanceVariables[key], description: allAvailableValues[key]?.description || '', }; }); setColors(c); }, [appearanceVariables]); const updateColor = (variable: string, color: string, description: string) => { setColors({ ...colors, [variable]: { value: color, description }, }); }; const reset = async () => { await postConfigUpdateToAPI({ apiPath: ENDPOINT, data: { value: {} }, onSuccess: () => { setSubmitStatus(createInputStatus(STATUS_SUCCESS, 'Updated.')); resetTimer = setTimeout(resetStates, RESET_TIMEOUT); setColorDefaults(); }, onError: (message: string) => { setSubmitStatus(createInputStatus(STATUS_ERROR, message)); resetTimer = setTimeout(resetStates, RESET_TIMEOUT); }, }); }; const save = async () => { const c = {}; Object.keys(colors).forEach(color => { c[color] = colors[color].value; }); await postConfigUpdateToAPI({ apiPath: ENDPOINT, data: { value: c }, onSuccess: () => { setSubmitStatus(createInputStatus(STATUS_SUCCESS, 'Updated.')); resetTimer = setTimeout(resetStates, RESET_TIMEOUT); }, onError: (message: string) => { setSubmitStatus(createInputStatus(STATUS_ERROR, message)); resetTimer = setTimeout(resetStates, RESET_TIMEOUT); }, }); }; const onBorderRadiusChange = (value: string) => { const variableName = 'theme-rounded-corners'; updateColor(variableName, `${value.toString()}px`, ''); }; if (!colors) { return
Loading...
; } return ( Customize Appearance The following colors are used across the user interface.
Section Colors} key="1">

Certain sections of the interface can be customized by selecting new colors for them.

{componentColorVariables.map(colorVar => { const { name } = colorVar; const c = colors[name]; return ( ); })}
Chat User Colors} key="2"> {chatColorVariables.map(colorVar => { const { name } = colorVar; const c = colors[name]; return ( ); })} Theme Colors} key="3"> {paletteVariables.map(colorVar => { const { name } = colorVar; const c = colors[name]; return ( ); })} Other Settings} key="4"> How rounded should corners be? { onBorderRadiusChange(v); }} value={Number(colors['theme-rounded-corners']?.value?.replace('px', '') || 0)} />
); }