Enhance school creation functionality by introducing support for name sets in the API and UI. Update the catalog to include skills, traits, body attributes, needs, and name sets, improving character generation capabilities. Revise localization strings for better user guidance and update tests to validate the new name set functionality and ensure robustness in school creation processes.
This commit is contained in:
@@ -41,9 +41,11 @@ const ru = {
|
||||
errorInvalidMap: 'Карта должна быть связным графом: двор и хотя бы одна комната.',
|
||||
errorUnknownMod: 'Выбранный мод не найден.',
|
||||
errorInvalidCatalog: 'Не удалось загрузить выбранные моды.',
|
||||
errorUnknownNameSet: 'Выбранный набор имён не найден.',
|
||||
catalogLoadFailed: 'Не удалось загрузить каталог модов.',
|
||||
|
||||
modsTitle: 'Моды',
|
||||
nameSetTitle: 'Набор имён',
|
||||
coreModLocked: '{id} (всегда включён)',
|
||||
mapEditorTitle: 'Карта',
|
||||
editMap: 'Редактировать карту',
|
||||
@@ -126,9 +128,11 @@ const en: Messages = {
|
||||
errorInvalidMap: 'The map must be a connected graph: a yard and at least one room.',
|
||||
errorUnknownMod: 'A selected mod is missing.',
|
||||
errorInvalidCatalog: 'The selected packs could not be loaded.',
|
||||
errorUnknownNameSet: 'The selected name set is not in the catalog.',
|
||||
catalogLoadFailed: 'Could not load the mod catalog.',
|
||||
|
||||
modsTitle: 'Mods',
|
||||
nameSetTitle: 'Name set',
|
||||
coreModLocked: '{id} (always on)',
|
||||
mapEditorTitle: 'Map',
|
||||
editMap: 'Edit map',
|
||||
|
||||
@@ -44,6 +44,7 @@ export async function fetchRandomName(lang: string): Promise<string> {
|
||||
export interface CreateSchoolOptions {
|
||||
readonly modIds?: readonly string[];
|
||||
readonly map?: MapLayout;
|
||||
readonly nameSetId?: string;
|
||||
}
|
||||
|
||||
export async function createSchool(
|
||||
@@ -59,6 +60,7 @@ export async function createSchool(
|
||||
startDate: startDate.toISOString(),
|
||||
modIds: extras.modIds ?? [],
|
||||
map: extras.map ?? null,
|
||||
nameSetId: extras.nameSetId ?? null,
|
||||
}),
|
||||
});
|
||||
}
|
||||
@@ -109,6 +111,7 @@ export interface CatalogResponse {
|
||||
readonly rooms: readonly RoomInfo[];
|
||||
readonly things: readonly DefInfo[];
|
||||
readonly defaultMap: MapLayout;
|
||||
readonly nameSets: readonly DefInfo[];
|
||||
}
|
||||
|
||||
export async function fetchMods(): Promise<readonly ModInfo[]> {
|
||||
|
||||
@@ -32,12 +32,20 @@ export function createSchoolDialog(options: CreateSchoolOptions): Promise<School
|
||||
const extraModIds = new Set<string>();
|
||||
let catalog: CatalogResponse | null = null;
|
||||
let currentMap: MapLayout | null = null;
|
||||
let nameSetId: string | null = null;
|
||||
|
||||
const modsField = el('div', { class: 'field' });
|
||||
const modsLabel = el('span', { class: 'field__label' });
|
||||
const modsList = el('div', { class: 'mod-list' });
|
||||
modsField.append(modsLabel, modsList);
|
||||
|
||||
const nameSetLabel = el('span', { class: 'field__label' });
|
||||
const nameSetSelect = el('select', { class: 'input' });
|
||||
const nameSetField = el('label', { class: 'field' }, nameSetLabel, nameSetSelect);
|
||||
nameSetSelect.addEventListener('change', () => {
|
||||
nameSetId = nameSetSelect.value === '' ? null : nameSetSelect.value;
|
||||
});
|
||||
|
||||
const mapLabel = el('span', { class: 'field__label' });
|
||||
const editMapButton = el('button', { class: 'button', type: 'button' });
|
||||
const mapHint = el('p', { class: 'hint' });
|
||||
@@ -78,6 +86,7 @@ export function createSchoolDialog(options: CreateSchoolOptions): Promise<School
|
||||
el('label', { class: 'field' }, nameLabel, el('div', { class: 'field__row' }, nameInput, randomButton)),
|
||||
el('div', { class: 'field' }, startLabel, el('div', { class: 'field__row' }, dateInput, timeInput)),
|
||||
modsField,
|
||||
nameSetField,
|
||||
mapField,
|
||||
error,
|
||||
el('div', { class: 'dialog__actions' }, cancelButton, submitButton),
|
||||
@@ -112,10 +121,25 @@ export function createSchoolDialog(options: CreateSchoolOptions): Promise<School
|
||||
const applyCatalog = (next: CatalogResponse): void => {
|
||||
catalog = next;
|
||||
currentMap = structuredClone(next.defaultMap);
|
||||
const stillThere = next.nameSets.some((set) => set.defName === nameSetId);
|
||||
nameSetId = stillThere ? nameSetId : (next.nameSets[0]?.defName ?? null);
|
||||
paintNameSets(next);
|
||||
paintMapHint();
|
||||
setBusy(busy);
|
||||
};
|
||||
|
||||
const paintNameSets = (next: CatalogResponse): void => {
|
||||
nameSetSelect.replaceChildren();
|
||||
for (const set of next.nameSets) {
|
||||
const option = el('option', { text: set.label });
|
||||
option.value = set.defName;
|
||||
nameSetSelect.append(option);
|
||||
}
|
||||
|
||||
nameSetSelect.value = nameSetId ?? '';
|
||||
nameSetSelect.disabled = next.nameSets.length <= 1;
|
||||
};
|
||||
|
||||
const reloadCatalog = async (): Promise<void> => {
|
||||
try {
|
||||
applyCatalog(await fetchCatalog(getLocale(), [...extraModIds]));
|
||||
@@ -168,6 +192,7 @@ export function createSchoolDialog(options: CreateSchoolOptions): Promise<School
|
||||
const localize = (): void => {
|
||||
title.textContent = t('newSchool');
|
||||
modsLabel.textContent = t('modsTitle');
|
||||
nameSetLabel.textContent = t('nameSetTitle');
|
||||
nameLabel.textContent = t('schoolName');
|
||||
startLabel.textContent = t('gameStart');
|
||||
mapLabel.textContent = t('mapEditorTitle');
|
||||
@@ -178,6 +203,9 @@ export function createSchoolDialog(options: CreateSchoolOptions): Promise<School
|
||||
submitButton.textContent = t('create');
|
||||
cancelButton.textContent = t('cancel');
|
||||
paintMapHint();
|
||||
if (catalog !== null) {
|
||||
paintNameSets(catalog);
|
||||
}
|
||||
};
|
||||
|
||||
localize();
|
||||
@@ -227,6 +255,7 @@ export function createSchoolDialog(options: CreateSchoolOptions): Promise<School
|
||||
.create(nameInput.value.trim(), startDate, {
|
||||
modIds: [...extraModIds],
|
||||
map: currentMap,
|
||||
nameSetId: nameSetId ?? undefined,
|
||||
})
|
||||
.then((school) => modal.close(school))
|
||||
.catch((reason: unknown) => {
|
||||
@@ -263,6 +292,8 @@ function describe(reason: unknown): string {
|
||||
return t('errorUnknownMod');
|
||||
case 'invalid-catalog':
|
||||
return t('errorInvalidCatalog');
|
||||
case 'unknown-name-set':
|
||||
return t('errorUnknownNameSet');
|
||||
default:
|
||||
return reason.message;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user