feat: add option to save custom username suggestions (#415)

* 💄 add option to save custom username suggestions that shall be used instead of the docker style usernames.

* 🚸 add minimum of 10 usernames / update wording

* Prettified Code!

* 🚸 add message for the default name generator / indicate that no further action is required

Co-authored-by: jeyemwey <jeyemwey@users.noreply.github.com>
This commit is contained in:
Jannik 2022-01-12 19:17:14 +01:00 committed by GitHub
parent 0f3051960f
commit 030b936f05
6 changed files with 106 additions and 15 deletions

View file

@ -5,6 +5,7 @@ import { Typography, Tag } from 'antd';
import TextField from './form-textfield';
import { UpdateArgs } from '../../types/config-section';
import { StatusState } from '../../utils/input-statuses';
import FormStatusIndicator from './form-status-indicator';
const { Title } = Typography;
@ -17,6 +18,7 @@ interface EditStringArrayProps {
maxLength?: number;
values: string[];
submitStatus?: StatusState;
continuousStatusMessage?: StatusState;
handleDeleteIndex: (index: number) => void;
handleCreateString: (arg: string) => void;
}
@ -32,6 +34,7 @@ export default function EditValueArray(props: EditStringArrayProps) {
handleDeleteIndex,
handleCreateString,
submitStatus,
continuousStatusMessage,
} = props;
const handleInputChange = ({ value }: UpdateArgs) => {
@ -63,7 +66,11 @@ export default function EditValueArray(props: EditStringArrayProps) {
);
})}
</div>
{continuousStatusMessage && (
<div className="continuous-status-section">
<FormStatusIndicator status={continuousStatusMessage} />
</div>
)}
<div className="add-new-string-section">
<TextField
fieldName="string-input"
@ -83,4 +90,5 @@ EditValueArray.defaultProps = {
maxLength: 50,
description: null,
submitStatus: null,
continuousStatusMessage: null,
};

View file

@ -4,28 +4,35 @@ import { TEXTFIELD_TYPE_TEXTAREA } from '../components/config/form-textfield';
import TextFieldWithSubmit from '../components/config/form-textfield-with-submit';
import ToggleSwitch from '../components/config/form-toggleswitch';
import EditValueArray from '../components/config/edit-string-array';
import { createInputStatus, STATUS_ERROR, STATUS_SUCCESS } from '../utils/input-statuses';
import {
createInputStatus,
StatusState,
STATUS_ERROR,
STATUS_SUCCESS,
} from '../utils/input-statuses';
import { UpdateArgs } from '../types/config-section';
import {
FIELD_PROPS_DISABLE_CHAT,
TEXTFIELD_PROPS_CHAT_FORBIDDEN_USERNAMES,
TEXTFIELD_PROPS_SERVER_WELCOME_MESSAGE,
API_CHAT_FORBIDDEN_USERNAMES,
API_CHAT_SUGGESTED_USERNAMES,
FIELD_PROPS_DISABLE_CHAT,
postConfigUpdateToAPI,
RESET_TIMEOUT,
TEXTFIELD_PROPS_CHAT_FORBIDDEN_USERNAMES,
TEXTFIELD_PROPS_CHAT_SUGGESTED_USERNAMES,
TEXTFIELD_PROPS_SERVER_WELCOME_MESSAGE,
} from '../utils/config-constants';
import { ServerStatusContext } from '../utils/server-status-context';
export default function ConfigChat() {
const { Title } = Typography;
const [formDataValues, setFormDataValues] = useState(null);
const [forbiddenUsernameSaveState, setForbidenUsernameSaveState] = useState(null);
const [forbiddenUsernameSaveState, setForbiddenUsernameSaveState] = useState(null);
const [suggestedUsernameSaveState, setSuggestedUsernameSaveState] = useState(null);
const serverStatusData = useContext(ServerStatusContext);
const { serverConfig, setFieldInConfigState } = serverStatusData || {};
const { chatDisabled, forbiddenUsernames } = serverConfig;
const { instanceDetails } = serverConfig;
const { chatDisabled, forbiddenUsernames, instanceDetails, suggestedUsernames } = serverConfig;
const { welcomeMessage } = instanceDetails;
const handleFieldChange = ({ fieldName, value }: UpdateArgs) => {
@ -40,7 +47,7 @@ export default function ConfigChat() {
}
function resetForbiddenUsernameState() {
setForbidenUsernameSaveState(null);
setForbiddenUsernameSaveState(null);
}
function saveForbiddenUsernames() {
@ -52,22 +59,22 @@ export default function ConfigChat() {
fieldName: 'forbiddenUsernames',
value: formDataValues.forbiddenUsernames,
});
setForbidenUsernameSaveState(STATUS_SUCCESS);
setForbiddenUsernameSaveState(STATUS_SUCCESS);
setTimeout(resetForbiddenUsernameState, RESET_TIMEOUT);
},
onError: (message: string) => {
setForbidenUsernameSaveState(createInputStatus(STATUS_ERROR, message));
setForbiddenUsernameSaveState(createInputStatus(STATUS_ERROR, message));
setTimeout(resetForbiddenUsernameState, RESET_TIMEOUT);
},
});
}
function handleDeleteUsername(index: number) {
function handleDeleteForbiddenUsernameIndex(index: number) {
formDataValues.forbiddenUsernames.splice(index, 1);
saveForbiddenUsernames();
}
function handleCreateUsername(tag: string) {
function handleCreateForbiddenUsername(tag: string) {
formDataValues.forbiddenUsernames.push(tag);
handleFieldChange({
fieldName: 'forbiddenUsernames',
@ -76,10 +83,56 @@ export default function ConfigChat() {
saveForbiddenUsernames();
}
function resetSuggestedUsernameState() {
setSuggestedUsernameSaveState(null);
}
function saveSuggestedUsernames() {
postConfigUpdateToAPI({
apiPath: API_CHAT_SUGGESTED_USERNAMES,
data: { value: formDataValues.suggestedUsernames },
onSuccess: () => {
setFieldInConfigState({
fieldName: 'suggestedUsernames',
value: formDataValues.suggestedUsernames,
});
setSuggestedUsernameSaveState(STATUS_SUCCESS);
setTimeout(resetSuggestedUsernameState, RESET_TIMEOUT);
},
onError: (message: string) => {
setForbiddenUsernameSaveState(createInputStatus(STATUS_ERROR, message));
setTimeout(resetSuggestedUsernameState, RESET_TIMEOUT);
},
});
}
function handleDeleteSuggestedUsernameIndex(index: number) {
formDataValues.suggestedUsernames.splice(index, 1);
saveSuggestedUsernames();
}
function handleCreateSuggestedUsername(tag: string) {
formDataValues.suggestedUsernames.push(tag);
handleFieldChange({
fieldName: 'suggestedUsernames',
value: formDataValues.suggestedUsernames,
});
saveSuggestedUsernames();
}
function getSuggestedUsernamesLimitWarning(length: number): StatusState | null {
if (length === 0)
return createInputStatus('success', TEXTFIELD_PROPS_CHAT_SUGGESTED_USERNAMES.no_entries);
if (length > 0 && length < 10)
return createInputStatus('warning', TEXTFIELD_PROPS_CHAT_SUGGESTED_USERNAMES.min_not_reached);
return null;
}
useEffect(() => {
setFormDataValues({
chatDisabled,
forbiddenUsernames,
suggestedUsernames,
welcomeMessage,
});
}, [serverConfig]);
@ -114,10 +167,24 @@ export default function ConfigChat() {
placeholder={TEXTFIELD_PROPS_CHAT_FORBIDDEN_USERNAMES.placeholder}
description={TEXTFIELD_PROPS_CHAT_FORBIDDEN_USERNAMES.tip}
values={formDataValues.forbiddenUsernames}
handleDeleteIndex={handleDeleteUsername}
handleCreateString={handleCreateUsername}
handleDeleteIndex={handleDeleteForbiddenUsernameIndex}
handleCreateString={handleCreateForbiddenUsername}
submitStatus={createInputStatus(forbiddenUsernameSaveState)}
/>
<br />
<br />
<EditValueArray
title={TEXTFIELD_PROPS_CHAT_SUGGESTED_USERNAMES.label}
placeholder={TEXTFIELD_PROPS_CHAT_SUGGESTED_USERNAMES.placeholder}
description={TEXTFIELD_PROPS_CHAT_SUGGESTED_USERNAMES.tip}
values={formDataValues.suggestedUsernames}
handleDeleteIndex={handleDeleteSuggestedUsernameIndex}
handleCreateString={handleCreateSuggestedUsername}
submitStatus={createInputStatus(suggestedUsernameSaveState)}
continuousStatusMessage={getSuggestedUsernamesLimitWarning(
formDataValues.suggestedUsernames.length,
)}
/>
</div>
</div>
);

View file

@ -37,3 +37,7 @@
align-items: center;
margin-top: 2em;
}
.continuous-status-section {
margin-top: 1em;
}

View file

@ -102,5 +102,6 @@ export interface ConfigDetails {
supportedCodecs: string[];
videoCodec: string;
forbiddenUsernames: string[];
suggestedUsernames: string[];
chatDisabled: boolean;
}

View file

@ -31,6 +31,7 @@ export const API_WEB_PORT = '/webserverport';
export const API_YP_SWITCH = '/directoryenabled';
export const API_CHAT_DISABLE = '/chat/disable';
export const API_CHAT_FORBIDDEN_USERNAMES = '/chat/forbiddenusernames';
export const API_CHAT_SUGGESTED_USERNAMES = '/chat/suggestedusernames';
export const API_EXTERNAL_ACTIONS = '/externalactions';
export const API_VIDEO_CODEC = '/video/codec';
@ -190,6 +191,15 @@ export const TEXTFIELD_PROPS_CHAT_FORBIDDEN_USERNAMES = {
tip: 'A list of words in chat usernames you disallow.',
};
export const TEXTFIELD_PROPS_CHAT_SUGGESTED_USERNAMES = {
apiPath: API_CHAT_SUGGESTED_USERNAMES,
placeholder: 'username',
label: 'Default usernames',
tip: 'An optional list of chat usernames that new users get assigned. If the list holds less then 10 items, random names will be generated. Users can change their usernames afterwards and the same username may be given out multple times.',
min_not_reached: 'At least 10 items are required for this feature.',
no_entries: 'The default name generator is used.',
};
export const VIDEO_VARIANT_SETTING_DEFAULTS = {
// this one is currently unused
audioBitrate: {

View file

@ -49,6 +49,7 @@ export const initialServerConfigState: ConfigDetails = {
supportedCodecs: [],
videoCodec: '',
forbiddenUsernames: [],
suggestedUsernames: [],
chatDisabled: false,
};