diff --git a/project-warstone/src/components/SchemaBuilder/field-editor.tsx b/project-warstone/src/components/SchemaBuilder/field-editor.tsx index ad3e159..94262ef 100644 --- a/project-warstone/src/components/SchemaBuilder/field-editor.tsx +++ b/project-warstone/src/components/SchemaBuilder/field-editor.tsx @@ -1,8 +1,6 @@ import { FC, useCallback, useEffect } from 'react' import { FieldType, FieldTypes, fieldTypeOptions, fieldTypesWithValues } from '../../types/schema' import { useObjectStateWrapper } from '../../hooks/useObjectState'; -import { FieldTypeInput } from './field-type-input'; -import { InputBinder } from '../../types/inputBinder'; import { ValueField } from './value-field'; import { HelpPopper } from '../Poppables/help'; @@ -13,7 +11,7 @@ interface IProps { } export const FieldEditor: FC = ({ update, field, fieldName }) => { - const { update: updateField, bindProperty, bindPropertyCheck } = useObjectStateWrapper(field, (e) => update(typeof e === 'function' ? e(field) : e)) + const { bindProperty, bindPropertyCheck } = useObjectStateWrapper(field, (e) => update(typeof e === 'function' ? e(field) : e)) const shouldShowValueField = useCallback(() => fieldTypesWithValues.includes(field.type) || field.isConstant, [field.isConstant, field.type]); diff --git a/project-warstone/src/components/SchemaBuilder/field-type-input.tsx b/project-warstone/src/components/SchemaBuilder/field-type-input.tsx index 0ac0102..05a7854 100644 --- a/project-warstone/src/components/SchemaBuilder/field-type-input.tsx +++ b/project-warstone/src/components/SchemaBuilder/field-type-input.tsx @@ -2,6 +2,7 @@ import { useRecoilValue } from 'recoil'; import { SchemaEditAtom } from '../../recoil/atoms/schema'; import { FCC } from '../../types' import { InputBinder } from '../../types/inputBinder' +import { TEMPLATE_TYPES } from '../../constants/TemplateTypes'; interface IProps { bind: InputBinder @@ -11,13 +12,17 @@ export const FieldTypeInput: FCC = ({ bind }) => { const Schema = useRecoilValue(SchemaEditAtom); return ( - <> + ) } \ No newline at end of file diff --git a/project-warstone/src/components/SchemaBuilder/index.tsx b/project-warstone/src/components/SchemaBuilder/index.tsx index 43ce854..23d0bba 100644 --- a/project-warstone/src/components/SchemaBuilder/index.tsx +++ b/project-warstone/src/components/SchemaBuilder/index.tsx @@ -2,12 +2,13 @@ import { FC, useCallback, useEffect, useState } from 'react' import AnimatedPageContainer from '../AnimatedPageContainer'; import { TypeEditor } from './type-editor'; import { useObjectState, useObjectStateWrapper } from '../../hooks/useObjectState'; -import { Schema, TypeType } from '../../types/schema'; +import { FieldTypes, Schema, Template, TypeType } from '../../types/schema'; import { useInput } from '../../hooks/useInput'; import { useRecoilState } from 'recoil'; import { SchemaEditAtom } from '../../recoil/atoms/schema'; import { GameSystemsService } from '../../services/game-systems'; import { SchemaViewer } from './schema-viewer'; +import { TemplateEditor } from './template-editor'; export const SchemaBuilder: FC = () => { @@ -25,6 +26,7 @@ export const SchemaBuilder: FC = () => { if (result.status !== 200) return; const fetchedSchema = await result.json(); // if (fetchedSchema.name === schema.name) return; + if (!fetchedSchema.templates) fetchedSchema.templates = {} setSchema(fetchedSchema); setLastSaved(fetchedSchema); }, [setSchema]) @@ -58,12 +60,43 @@ export const SchemaBuilder: FC = () => { setPageNumber(1); }, []) + const { value: templateName, bind: bindTemplateName, reset: resetTemplateName } = useInput(''); + const addTemplate = useCallback(() => { + updateSchema(s => ({ + templates: { + ...s.templates, + [templateName]: { + publishable: false, + type: FieldTypes.any + } + } + })); + resetTemplateName(); + }, [resetTemplateName, templateName, updateSchema]) + + const updateTemplate = useCallback((key: string, template: Template) => { + updateSchema(s => ({ + templates: { + ...s.templates, + [key]: template + } + })) + }, [updateSchema]) + return (
+

Add a template

+ + +
    + {Object.entries(schema.templates).map(([templateKey, template]) => ( + + ))} +
-

Add A Type

+

Add a type

diff --git a/project-warstone/src/components/SchemaBuilder/schema-viewer.tsx b/project-warstone/src/components/SchemaBuilder/schema-viewer.tsx index dbfda13..9d6a832 100644 --- a/project-warstone/src/components/SchemaBuilder/schema-viewer.tsx +++ b/project-warstone/src/components/SchemaBuilder/schema-viewer.tsx @@ -14,8 +14,8 @@ export const SchemaViewer: FC = ({ schema, onTypeClick }) => { return 'Constant value:' } switch (field.type) { - case FieldTypes.type: return 'Type' - case FieldTypes.dice: return 'Dice' + case FieldTypes.type: return 'Type:' + case FieldTypes.dice: return 'Dice:' default: return ''; } }, []) @@ -25,6 +25,19 @@ export const SchemaViewer: FC = ({ schema, onTypeClick }) => { {/*
{JSON.stringify(schema, null, 2)}
*/}

{schema.name}

+
+

Templates

+
    + {Object.entries(schema.templates).map(([templateKey, template]) => ( +
  • +

    {templateKey}

    +

    {template.type}

    + {template.publishable &&

    This template can create publications

    } +
  • + ))} +
+
+

Types

    {Object.entries(schema.types).map(([typeKey, type]) => (
  • void; + template: Template +} + +export const TemplateEditor: FC = ({ templateKey, update, template }) => { + + const updateTemplate = useCallback((t: Template | ((arg: Template) => Template)) => { + update(templateKey, typeof t === 'function' ? t(template) : t) + }, [templateKey, update, template]) + + const { bindProperty, bindPropertyCheck } = useObjectStateWrapper(template, updateTemplate) + + return ( +
  • +

    {templateKey}

    +
    + + +
    +
  • + ) +} \ No newline at end of file diff --git a/project-warstone/src/components/SchemaBuilder/type-editor.tsx b/project-warstone/src/components/SchemaBuilder/type-editor.tsx index bf810fc..5e24f2f 100644 --- a/project-warstone/src/components/SchemaBuilder/type-editor.tsx +++ b/project-warstone/src/components/SchemaBuilder/type-editor.tsx @@ -31,8 +31,9 @@ export const TypeEditor: FCC = ({ saveType, name, type: passedType }) => isConstant: false, limit: 1, } - }) - }, [propertyName, updateType]); + }); + resetPropertyName(); + }, [propertyName, updateType, resetPropertyName]); const updateField = useCallback((k: keyof typeof type) => (field: FieldType) => { updateType({ [k]: field }) diff --git a/project-warstone/src/constants/TemplateTypes.ts b/project-warstone/src/constants/TemplateTypes.ts new file mode 100644 index 0000000..1c6cc3f --- /dev/null +++ b/project-warstone/src/constants/TemplateTypes.ts @@ -0,0 +1,70 @@ +import { FieldTypes, TypeType } from '../types/schema'; + +export const TEMPLATE_TYPES: Record = { + section: { + name: { + isConstant: false, + limit: 1, + type: FieldTypes.text, + value: '' + }, + body: { + isConstant: false, + limit: 0, + type: FieldTypes['long text'], + value: '' + }, + }, + steps: { + steps: { + isConstant: false, + limit: 0, + type: FieldTypes.type, + value: 'section' + } + }, + image: { + name: { + isConstant: false, + limit: 1, + type: FieldTypes.text, + value: '' + }, + link: { + isConstant: false, + limit: 1, + type: FieldTypes.text, + value: '' + }, + }, + list: { + items: { + isConstant: false, + limit: 0, + type: FieldTypes['long text'], + value: '' + } + }, + tableRow: { + columns: { + isConstant: false, + limit: 0, + type: FieldTypes.any, + value: '' + } + }, + table: { + rows: { + isConstant: false, + limit: 0, + type: FieldTypes.type, + value: 'tableRow' + }, + header: { + isConstant: false, + limit: 1, + type: FieldTypes.type, + value: 'tableRow' + } + } +}; \ No newline at end of file diff --git a/project-warstone/src/recoil/atoms/schema.ts b/project-warstone/src/recoil/atoms/schema.ts index 9590034..1a6fdc5 100644 --- a/project-warstone/src/recoil/atoms/schema.ts +++ b/project-warstone/src/recoil/atoms/schema.ts @@ -3,5 +3,5 @@ import { Schema } from '../../types/schema'; export const SchemaEditAtom = atom({ key: 'schema-edit', - default: {name: '', types: {}} + default: {name: '', types: {}, templates: {}} }); \ No newline at end of file diff --git a/project-warstone/src/services/game-systems.ts b/project-warstone/src/services/game-systems.ts index 9f0d1e4..5de199c 100644 --- a/project-warstone/src/services/game-systems.ts +++ b/project-warstone/src/services/game-systems.ts @@ -19,7 +19,7 @@ export const GameSystemsService = { return { status: 404, - json: async () => ({name:'', types: {}}) + json: async () => ({name:'', types: {}, templates: {}}) } } } \ No newline at end of file diff --git a/project-warstone/src/types/schema.ts b/project-warstone/src/types/schema.ts index 0fcf26a..1aef0e6 100644 --- a/project-warstone/src/types/schema.ts +++ b/project-warstone/src/types/schema.ts @@ -1,5 +1,5 @@ export type MetadataType = { - [key: string]: string + [key: string]: string; } export type FieldType = { @@ -11,9 +11,15 @@ export type FieldType = { export type TypeType = Record; +export type Template = { + type: string; + publishable: boolean; +} + export type Schema = { name: string; - types: Record + templates: Record; + types: Record; } export enum FieldTypes { @@ -22,7 +28,8 @@ export enum FieldTypes { 'long text' = 'long text', checkbox = 'checkbox', type = '@type', - dice = 'dice' + dice = 'dice', + any = '@select' } export const fieldTypeOptions: (keyof typeof FieldTypes)[] = ['number', 'text', 'long text', 'checkbox', 'type', 'dice']