reorganize styles and pages (wip); update readme
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import 'antd/dist/antd.css';
|
||||
import '../styles/colors.scss';
|
||||
import '../styles/globals.scss';
|
||||
import '../styles/ant-overrides.scss';
|
||||
|
||||
import '../styles/home.scss';
|
||||
import '../styles/chat.scss';
|
||||
|
||||
@@ -1,5 +1,49 @@
|
||||
# Config
|
||||
# About the Config editing section
|
||||
|
||||
An adventure with React, React Hooks and Ant Design forms.
|
||||
|
||||
## General data flow in this React app
|
||||
|
||||
### First things to note
|
||||
- When the Admin app loads, the `ServerStatusContext` (in addition to checking server `/status` on a timer) makes a call to the `/serverconfig` API to get your config details. This data will be stored as **`serverConfig`** in app state, and _provided_ to the app via `useContext` hook.
|
||||
|
||||
- The `serverConfig` in state is be the central source of data that pre-populates the forms.
|
||||
|
||||
- The `ServerStatusContext` also provides a method for components to update the serverConfig state, called `setFieldInConfigState()`.
|
||||
|
||||
- After you have updated a config value in a form field, and successfully submitted it through its endpoint, you should call `setFieldInConfigState` to update the global state with the new value.
|
||||
|
||||
- Each top field of the serverConfig has its own API update endpoint.
|
||||
|
||||
### Form Flow
|
||||
Each form input (or group of inputs) you make, you should
|
||||
1. Get the field values that you want out of `serverConfig` from ServerStatusContext with `useContext`.
|
||||
2. Next we'll have to put these field values of interest into a `useState` in each grouping. This will help you edit the form.
|
||||
3. Because ths config data is populated asynchronously, Use a `useEffect` to check when that data has arrived before putting it into state.
|
||||
4. You will be using the state's value to populate the `defaultValue` and the `value` props of each Ant input component (`Input`, `Toggle`, `Switch`, `Select`, `Slider` are currently used).
|
||||
5. When an `onChange` event fires for each type of input component, you will update the local state of each page with the changed value.
|
||||
6. Depending on the form, an `onChange` of the input component, or a subsequent `onClick` of a submit button will take the value from local state and POST the field's API.
|
||||
7. `onSuccess` of the post, you should update the global app state with the new value.
|
||||
|
||||
There are also a variety of other local states to manage the display of error/success messaging.
|
||||
|
||||
## Using Ant's `<Form>` with `form-textfield`.
|
||||
You may see that a couple of pages (currently Public Details and Server Details page), is mainly a grouping of similar Text fields.
|
||||
|
||||
`const [form] = Form.useForm();`
|
||||
`form.setFieldsValue(initialValues);`
|
||||
|
||||
|
||||
A special `TextField` component was created to be used with form.
|
||||
|
||||
|
||||
## Potential Optimizations
|
||||
|
||||
Looking back at the pages with `<Form>` + `form-textfield`, t
|
||||
|
||||
This pattern might be overly engineered.
|
||||
|
||||
There are also a few patterns across all the form groups that repeat quite a bit. Perhaps these patterns could be consolidated into a custom hook that could handle all the steps.
|
||||
|
||||
TODO: explain how to use <Form> and how the custom `form-xxxx` components work together.
|
||||
|
||||
@@ -48,4 +92,12 @@ TODO:
|
||||
- page headers - diff color?
|
||||
- fix social handles icon in table
|
||||
- consolidate things into 1 page?
|
||||
- things could use smaller font?
|
||||
- things could use smaller font?
|
||||
- maybe convert common form pattern to custom hook?
|
||||
|
||||
|
||||
Possibly over engineered
|
||||
|
||||
https://uxcandy.co/demo/label_pro/preview/demo_2/pages/forms/form-elements.html
|
||||
|
||||
https://www.bootstrapdash.com/demo/corona/jquery/template/modern-vertical/pages/forms/basic_elements.html
|
||||
@@ -2,16 +2,18 @@ import React, { useState, useContext, useEffect } from 'react';
|
||||
import { Typography, Table, Button, Modal, Input } from 'antd';
|
||||
import { ColumnsType } from 'antd/lib/table';
|
||||
import { DeleteOutlined } from '@ant-design/icons';
|
||||
import SocialDropdown from './components/config/social-icons-dropdown';
|
||||
import { fetchData, NEXT_PUBLIC_API_HOST, SOCIAL_PLATFORMS_LIST } from '../utils/apis';
|
||||
import { ServerStatusContext } from '../utils/server-status-context';
|
||||
import { API_SOCIAL_HANDLES, postConfigUpdateToAPI, RESET_TIMEOUT, SUCCESS_STATES, DEFAULT_SOCIAL_HANDLE, OTHER_SOCIAL_HANDLE_OPTION } from './components/config/constants';
|
||||
import { SocialHandle } from '../types/config-section';
|
||||
import {isValidUrl} from '../utils/urls';
|
||||
import SocialDropdown from './social-icons-dropdown';
|
||||
import { fetchData, NEXT_PUBLIC_API_HOST, SOCIAL_PLATFORMS_LIST } from '../../../utils/apis';
|
||||
import { ServerStatusContext } from '../../../utils/server-status-context';
|
||||
import { API_SOCIAL_HANDLES, postConfigUpdateToAPI, RESET_TIMEOUT, SUCCESS_STATES, DEFAULT_SOCIAL_HANDLE, OTHER_SOCIAL_HANDLE_OPTION } from './constants';
|
||||
import { SocialHandle } from '../../../types/config-section';
|
||||
import {isValidUrl} from '../../../utils/urls';
|
||||
|
||||
import configStyles from '../../../styles/config-pages.module.scss';
|
||||
|
||||
const { Title } = Typography;
|
||||
|
||||
export default function ConfigSocialLinks() {
|
||||
export default function EditSocialLinks() {
|
||||
const [availableIconsList, setAvailableIconsList] = useState([]);
|
||||
const [currentSocialHandles, setCurrentSocialHandles] = useState([]);
|
||||
|
||||
@@ -228,14 +230,14 @@ export default function ConfigSocialLinks() {
|
||||
|
||||
|
||||
return (
|
||||
<div className="config-social-links">
|
||||
<div className={configStyles.socialLinksEditor}>
|
||||
<Title level={2}>Social Links</Title>
|
||||
<p>Add all your social media handles and links to your other profiles here.</p>
|
||||
|
||||
{statusMessage}
|
||||
|
||||
<Table
|
||||
className="variants-table"
|
||||
className="dataTable"
|
||||
pagination={false}
|
||||
size="small"
|
||||
rowKey={record => record.url}
|
||||
@@ -155,10 +155,9 @@ export default function TextField(props: TextFieldProps) {
|
||||
|
||||
return (
|
||||
<div className={`textfield-container type-${type}`}>
|
||||
<div className="textfield-label">{label}</div>
|
||||
<div className="textfield">
|
||||
<InfoTip tip={tip} />
|
||||
<Form.Item
|
||||
label={label}
|
||||
name={fieldName}
|
||||
hasFeedback
|
||||
validateStatus={submitStatus}
|
||||
@@ -176,8 +175,8 @@ export default function TextField(props: TextFieldProps) {
|
||||
{...fieldProps}
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
</div>
|
||||
<InfoTip tip={tip} />
|
||||
|
||||
{ hasChanged ? <Button type="primary" size="small" className="submit-button" onClick={handleSubmit}>Update</Button> : null }
|
||||
|
||||
|
||||
@@ -141,12 +141,14 @@ export default function MainLayout(props) {
|
||||
<Menu.Item key="config-public-details">
|
||||
<Link href="/config-public-details">Public Details</Link>
|
||||
</Menu.Item>
|
||||
<Menu.Item key="config-social-items">
|
||||
<Link href="/config-social-items">Social items</Link>
|
||||
</Menu.Item>
|
||||
|
||||
<Menu.Item key="config-page-content">
|
||||
<Link href="/config-page-content">Custom page content</Link>
|
||||
</Menu.Item>
|
||||
<Menu.Item key="config-social-links">
|
||||
<Link href="/config-social-links">Social links</Link>
|
||||
</Menu.Item>
|
||||
|
||||
<Menu.Item key="config-server-details">
|
||||
<Link href="/config-server-details">Server Details</Link>
|
||||
</Menu.Item>
|
||||
|
||||
@@ -4,12 +4,11 @@ import Link from 'next/link';
|
||||
|
||||
import TextField, { TEXTFIELD_TYPE_TEXTAREA, TEXTFIELD_TYPE_URL } from './components/config/form-textfield';
|
||||
|
||||
import EditInstanceTags from './components/config/edit-tags';
|
||||
import EditDirectoryDetails from './components/config/edit-directory';
|
||||
|
||||
import { ServerStatusContext } from '../utils/server-status-context';
|
||||
import { TEXTFIELD_DEFAULTS, postConfigUpdateToAPI } from './components/config/constants';
|
||||
|
||||
import configStyles from '../styles/config-pages.module.scss';
|
||||
|
||||
const { Title } = Typography;
|
||||
|
||||
export default function PublicFacingDetails() {
|
||||
@@ -29,11 +28,6 @@ export default function PublicFacingDetails() {
|
||||
form.setFieldsValue(initialValues);
|
||||
}, [instanceDetails]);
|
||||
|
||||
// const handleResetValue = (fieldName: string) => {
|
||||
// const defaultValue = defaultFields[fieldName] && defaultFields[fieldName].defaultValue || '';
|
||||
|
||||
// form.setFieldsValue({ [fieldName]: initialValues[fieldName] || defaultValue });
|
||||
// }
|
||||
|
||||
// if instanceUrl is empty, we should also turn OFF the `enabled` field of directory.
|
||||
const handleSubmitInstanceUrl = () => {
|
||||
@@ -49,17 +43,16 @@ export default function PublicFacingDetails() {
|
||||
}
|
||||
|
||||
const extraProps = {
|
||||
// handleResetValue,
|
||||
initialValues,
|
||||
configPath: 'instanceDetails',
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="config-public-details-form">
|
||||
<>
|
||||
<Title level={2}>Edit your public facing instance details</Title>
|
||||
|
||||
<div className="config-public-details-container">
|
||||
<div className="text-fields">
|
||||
<div className={configStyles.publicDetailsContainer}>
|
||||
<div className={configStyles.textFieldsSection}>
|
||||
<Form
|
||||
form={form}
|
||||
layout="vertical"
|
||||
@@ -78,20 +71,13 @@ export default function PublicFacingDetails() {
|
||||
<TextField fieldName="summary" type={TEXTFIELD_TYPE_TEXTAREA} {...extraProps} />
|
||||
<TextField fieldName="logo" {...extraProps} />
|
||||
</Form>
|
||||
<Link href="/admin/config-page-content">
|
||||
<a>this page!</a>
|
||||
</Link>
|
||||
</div>
|
||||
<div className="misc-fields">
|
||||
{/* add social handles comp
|
||||
<br/>
|
||||
add tags comp */}
|
||||
<EditInstanceTags />
|
||||
|
||||
<EditDirectoryDetails />
|
||||
<Link href="/admin/config-page-content">
|
||||
<a>Edit your extra page content here.</a>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
20
web/pages/config-social-items.tsx
Normal file
20
web/pages/config-social-items.tsx
Normal file
@@ -0,0 +1,20 @@
|
||||
import React from 'react';
|
||||
import { Typography } from 'antd';
|
||||
import EditSocialLinks from './components/config/edit-social-links';
|
||||
import EditInstanceTags from './components/config/edit-tags';
|
||||
import EditDirectoryDetails from './components/config/edit-directory';
|
||||
|
||||
const { Title } = Typography;
|
||||
|
||||
export default function ConfigSocialThings() {
|
||||
return (
|
||||
<div className="config-social-items">
|
||||
<Title level={2}>Social Items</Title>
|
||||
|
||||
<EditDirectoryDetails />
|
||||
<EditSocialLinks />
|
||||
<EditInstanceTags />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user