mirror of
https://github.com/DeNNiiInc/dbgate.git
synced 2026-04-17 23:45:59 +00:00
form style refactor + charts
This commit is contained in:
@@ -12,6 +12,8 @@ import { loadChartData, loadChartStructure } from './chartDataLoader';
|
||||
import useExtensions from '../utility/useExtensions';
|
||||
import { getConnectionInfo } from '../utility/metadataLoaders';
|
||||
import { findEngineDriver } from 'dbgate-tools';
|
||||
import { FormFieldTemplateTiny } from '../utility/formStyle';
|
||||
import { ManagerInnerContainer } from '../datagrid/ManagerStyles';
|
||||
|
||||
const LeftContainer = styled.div`
|
||||
background-color: ${(props) => props.theme.manager_background};
|
||||
@@ -72,36 +74,46 @@ export default function ChartEditor({ data, config, setConfig, sql, conid, datab
|
||||
}, [config, sql, conid, database]);
|
||||
|
||||
return (
|
||||
<FormProviderCore values={config} setValues={setConfig}>
|
||||
<FormProviderCore values={config} setValues={setConfig} template={FormFieldTemplateTiny}>
|
||||
<HorizontalSplitter initialValue="300px" size={managerSize} setSize={setManagerSize}>
|
||||
<LeftContainer theme={theme}>
|
||||
<WidgetColumnBar>
|
||||
<WidgetColumnBarItem title="Style" name="style" height="40%">
|
||||
<FormSelectField label="Chart type" name="chartType">
|
||||
<option value="bar">Bar</option>
|
||||
<option value="line">Line</option>
|
||||
{/* <option value="radar">Radar</option> */}
|
||||
<option value="pie">Pie</option>
|
||||
<option value="polarArea">Polar area</option>
|
||||
{/* <option value="bubble">Bubble</option>
|
||||
<ManagerInnerContainer style={{ maxWidth: managerSize }}>
|
||||
<FormSelectField label="Chart type" name="chartType">
|
||||
<option value="bar">Bar</option>
|
||||
<option value="line">Line</option>
|
||||
{/* <option value="radar">Radar</option> */}
|
||||
<option value="pie">Pie</option>
|
||||
<option value="polarArea">Polar area</option>
|
||||
{/* <option value="bubble">Bubble</option>
|
||||
<option value="scatter">Scatter</option> */}
|
||||
</FormSelectField>
|
||||
<FormTextField label="Color seed" name="colorSeed" />
|
||||
</FormSelectField>
|
||||
<FormSelectField label="Color set" name="colorSeed">
|
||||
<option value="1">1</option>
|
||||
<option value="2">2</option>
|
||||
<option value="3">3</option>
|
||||
<option value="4">4</option>
|
||||
<option value="5">5</option>
|
||||
</FormSelectField>
|
||||
</ManagerInnerContainer>
|
||||
</WidgetColumnBarItem>
|
||||
<WidgetColumnBarItem title="Data" name="data">
|
||||
{availableColumnNames.length > 0 && (
|
||||
<FormSelectField label="Label column" name="labelColumn">
|
||||
<option value=""></option>
|
||||
{availableColumnNames.map((col) => (
|
||||
<option value={col} key={col}>
|
||||
{col}
|
||||
</option>
|
||||
))}
|
||||
</FormSelectField>
|
||||
)}
|
||||
{availableColumnNames.map((col) => (
|
||||
<FormCheckboxField label={col} name={`dataColumn_${col}`} key={col} />
|
||||
))}
|
||||
<ManagerInnerContainer style={{ maxWidth: managerSize }}>
|
||||
{availableColumnNames.length > 0 && (
|
||||
<FormSelectField label="Label column" name="labelColumn">
|
||||
<option value=""></option>
|
||||
{availableColumnNames.map((col) => (
|
||||
<option value={col} key={col}>
|
||||
{col}
|
||||
</option>
|
||||
))}
|
||||
</FormSelectField>
|
||||
)}
|
||||
{availableColumnNames.map((col) => (
|
||||
<FormCheckboxField label={col} name={`dataColumn_${col}`} key={col} />
|
||||
))}
|
||||
</ManagerInnerContainer>
|
||||
</WidgetColumnBarItem>
|
||||
</WidgetColumnBar>
|
||||
</LeftContainer>
|
||||
|
||||
@@ -1,82 +1,28 @@
|
||||
import React from 'react';
|
||||
import _ from 'lodash';
|
||||
import Chart from 'react-chartjs-2';
|
||||
import randomcolor from 'randomcolor';
|
||||
import styled from 'styled-components';
|
||||
import useTheme from '../theme/useTheme';
|
||||
import useDimensions from '../utility/useDimensions';
|
||||
import { HorizontalSplitter } from '../widgets/Splitter';
|
||||
import WidgetColumnBar, { WidgetColumnBarItem } from '../widgets/WidgetColumnBar';
|
||||
import { FormSelectField } from '../utility/forms';
|
||||
import { useForm } from '../utility/FormProvider';
|
||||
import { saturateByTenth } from '../theme/colorUtil';
|
||||
|
||||
const ChartWrapper = styled.div`
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
`;
|
||||
|
||||
// const chartData = {
|
||||
// labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
|
||||
// datasets: [
|
||||
// {
|
||||
// label: '# of Votes',
|
||||
// data: [12, 19, 3, 5, 2, 3],
|
||||
// backgroundColor: [
|
||||
// 'rgba(255, 99, 132, 0.2)',
|
||||
// 'rgba(54, 162, 235, 0.2)',
|
||||
// 'rgba(255, 206, 86, 0.2)',
|
||||
// 'rgba(75, 192, 192, 0.2)',
|
||||
// 'rgba(153, 102, 255, 0.2)',
|
||||
// 'rgba(255, 159, 64, 0.2)',
|
||||
// ],
|
||||
// borderColor: [
|
||||
// 'rgba(255, 99, 132, 1)',
|
||||
// 'rgba(54, 162, 235, 1)',
|
||||
// 'rgba(255, 206, 86, 1)',
|
||||
// 'rgba(75, 192, 192, 1)',
|
||||
// 'rgba(153, 102, 255, 1)',
|
||||
// 'rgba(255, 159, 64, 1)',
|
||||
// ],
|
||||
// borderWidth: 1,
|
||||
// },
|
||||
// ],
|
||||
// };
|
||||
|
||||
function createChartData(freeData, labelColumn, dataColumns, colorSeed, chartType) {
|
||||
if (!freeData || !labelColumn || !dataColumns || dataColumns.length == 0) return {};
|
||||
const labels = _.uniq(freeData.rows.map((x) => x[labelColumn]));
|
||||
const colors = randomcolor({
|
||||
count: labels.length,
|
||||
count: freeData.rows.length,
|
||||
seed: colorSeed,
|
||||
});
|
||||
const res = {
|
||||
labels: freeData.rows.map((x) => x[labelColumn]),
|
||||
datasets: dataColumns.map((dataColumn) => ({
|
||||
label: dataColumn,
|
||||
// data: [12, 19, 3, 5, 2, 3],
|
||||
data: labels.map((label) =>
|
||||
_.sum(freeData.rows.filter((row) => row[labelColumn] == label).map((row) => row[dataColumn]))
|
||||
),
|
||||
data: freeData.rows.map((row) => row[dataColumn]),
|
||||
backgroundColor: chartType != 'line' ? colors : null,
|
||||
borderColor: chartType == 'line' ? colors : null,
|
||||
// borderColor: colors, // .map(saturateByTenth),
|
||||
// backgroundColor: [
|
||||
// 'rgba(255, 99, 132, 0.2)',
|
||||
// 'rgba(54, 162, 235, 0.2)',
|
||||
// 'rgba(255, 206, 86, 0.2)',
|
||||
// 'rgba(75, 192, 192, 0.2)',
|
||||
// 'rgba(153, 102, 255, 0.2)',
|
||||
// 'rgba(255, 159, 64, 0.2)',
|
||||
// ],
|
||||
// borderColor: [
|
||||
// 'rgba(255, 99, 132, 1)',
|
||||
// 'rgba(54, 162, 235, 1)',
|
||||
// 'rgba(255, 206, 86, 1)',
|
||||
// 'rgba(75, 192, 192, 1)',
|
||||
// 'rgba(153, 102, 255, 1)',
|
||||
// 'rgba(255, 159, 64, 1)',
|
||||
// ],
|
||||
borderWidth: 1,
|
||||
})),
|
||||
};
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import React from 'react';
|
||||
import ModalBase from './ModalBase';
|
||||
import { FormButtonRow } from '../utility/forms';
|
||||
import FormStyledButton from '../widgets/FormStyledButton';
|
||||
import SqlEditor from '../sqleditor/SqlEditor';
|
||||
import styled from 'styled-components';
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import React from 'react';
|
||||
import ModalBase from './ModalBase';
|
||||
import { FormButtonRow } from '../utility/forms';
|
||||
import FormStyledButton from '../widgets/FormStyledButton';
|
||||
import SqlEditor from '../sqleditor/SqlEditor';
|
||||
import styled from 'styled-components';
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import React from 'react';
|
||||
import ModalBase from './ModalBase';
|
||||
import { FormTextField, FormSubmit, FormArchiveFolderSelect, FormRow, FormLabel } from '../utility/forms';
|
||||
import { FormTextField, FormSubmit, FormArchiveFolderSelect } from '../utility/forms';
|
||||
import styled from 'styled-components';
|
||||
import ModalHeader from './ModalHeader';
|
||||
import ModalContent from './ModalContent';
|
||||
import ModalFooter from './ModalFooter';
|
||||
import { FormProvider } from '../utility/FormProvider';
|
||||
import { FormFieldTemplateDefault } from '../utility/formStyle';
|
||||
|
||||
const SelectWrapper = styled.div`
|
||||
width: 150px;
|
||||
@@ -24,13 +25,11 @@ export default function SaveArchiveModal({ file = 'new-table', folder = 'default
|
||||
<ModalHeader modalState={modalState}>Save to archive</ModalHeader>
|
||||
<FormProvider initialValues={{ file, folder }}>
|
||||
<ModalContent>
|
||||
{/* <Label>Archive folder</Label> */}
|
||||
<FormRow>
|
||||
<FormLabel>Folder</FormLabel>
|
||||
<FormFieldTemplateDefault label="Folder" type="select">
|
||||
<SelectWrapper>
|
||||
<FormArchiveFolderSelect name="folder" />
|
||||
</SelectWrapper>
|
||||
</FormRow>
|
||||
</FormFieldTemplateDefault>
|
||||
<FormTextField label="File name" name="file" />
|
||||
</ModalContent>
|
||||
<ModalFooter>
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
import React from 'react';
|
||||
import axios from '../utility/axios';
|
||||
import ModalBase from './ModalBase';
|
||||
import { FormButtonRow, FormButton, FormTextField, FormSelectField, FormSubmit } from '../utility/forms';
|
||||
import { TextField } from '../utility/inputs';
|
||||
import { FormTextField, FormSubmit } from '../utility/forms';
|
||||
import ModalHeader from './ModalHeader';
|
||||
import ModalContent from './ModalContent';
|
||||
import ModalFooter from './ModalFooter';
|
||||
import { FormProvider } from '../utility/FormProvider';
|
||||
// import FormikForm from '../utility/FormikForm';
|
||||
|
||||
export default function SaveFileModal({ data, folder, format, modalState, name, onSave = undefined }) {
|
||||
const handleSubmit = async (values) => {
|
||||
|
||||
@@ -2,19 +2,13 @@ import React from 'react';
|
||||
import ModalBase from './ModalBase';
|
||||
import FormStyledButton from '../widgets/FormStyledButton';
|
||||
import styled from 'styled-components';
|
||||
import {
|
||||
FormButtonRow,
|
||||
FormSubmit,
|
||||
FormSelectFieldRaw,
|
||||
FormRow,
|
||||
FormRadioGroupItem,
|
||||
FormTextFieldRaw,
|
||||
} from '../utility/forms';
|
||||
import { FormSubmit, FormSelectFieldRaw, FormRadioGroupItem, FormTextFieldRaw } from '../utility/forms';
|
||||
import ModalHeader from './ModalHeader';
|
||||
import ModalFooter from './ModalFooter';
|
||||
import ModalContent from './ModalContent';
|
||||
import { TextField } from '../utility/inputs';
|
||||
import { FormProvider } from '../utility/FormProvider';
|
||||
import { FormRow } from '../utility/formStyle';
|
||||
|
||||
const Wrapper = styled.div`
|
||||
display: flex;
|
||||
|
||||
@@ -1,18 +1,20 @@
|
||||
import React from 'react';
|
||||
import { FormFieldTemplateDefault } from './formStyle';
|
||||
import keycodes from './keycodes';
|
||||
|
||||
const FormContext = React.createContext(null);
|
||||
const FormFieldTemplateContext = React.createContext(null);
|
||||
|
||||
export function FormProvider({ children, initialValues = {} }) {
|
||||
export function FormProvider({ children, initialValues = {}, template = FormFieldTemplateDefault }) {
|
||||
const [values, setValues] = React.useState(initialValues);
|
||||
return (
|
||||
<FormProviderCore values={values} setValues={setValues}>
|
||||
<FormProviderCore values={values} setValues={setValues} template={template}>
|
||||
{children}
|
||||
</FormProviderCore>
|
||||
);
|
||||
}
|
||||
|
||||
export function FormProviderCore({ children, values, setValues }) {
|
||||
export function FormProviderCore({ children, values, setValues, template = FormFieldTemplateDefault }) {
|
||||
const [submitAction, setSubmitAction] = React.useState(null);
|
||||
const handleEnter = React.useCallback(
|
||||
(e) => {
|
||||
@@ -43,9 +45,21 @@ export function FormProviderCore({ children, values, setValues }) {
|
||||
setFieldValue,
|
||||
setSubmitAction,
|
||||
};
|
||||
return <FormContext.Provider value={provider}>{children}</FormContext.Provider>;
|
||||
return (
|
||||
<FormContext.Provider value={provider}>
|
||||
<FormFieldTemplateProvider template={template}>{children}</FormFieldTemplateProvider>
|
||||
</FormContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
export function useForm() {
|
||||
return React.useContext(FormContext);
|
||||
}
|
||||
|
||||
export function FormFieldTemplateProvider({ children, template = FormFieldTemplateDefault }) {
|
||||
return <FormFieldTemplateContext.Provider value={template}>{children}</FormFieldTemplateContext.Provider>;
|
||||
}
|
||||
|
||||
export function useFormFieldTemplate() {
|
||||
return React.useContext(FormFieldTemplateContext);
|
||||
}
|
||||
|
||||
54
packages/web/src/utility/formStyle.js
Normal file
54
packages/web/src/utility/formStyle.js
Normal file
@@ -0,0 +1,54 @@
|
||||
import styled from 'styled-components';
|
||||
import React from 'react';
|
||||
import useTheme from '../theme/useTheme';
|
||||
|
||||
export const FormRow = styled.div`
|
||||
display: flex;
|
||||
margin: 10px;
|
||||
`;
|
||||
|
||||
export const FormLabel = styled.div`
|
||||
width: 10vw;
|
||||
font-weight: bold;
|
||||
`;
|
||||
|
||||
export const FormValue = styled.div``;
|
||||
|
||||
export function FormFieldTemplateDefault({ label, children, type }) {
|
||||
return (
|
||||
<FormRow>
|
||||
<FormLabel>{label}</FormLabel>
|
||||
<FormValue>{children}</FormValue>
|
||||
</FormRow>
|
||||
);
|
||||
}
|
||||
|
||||
export const FormRowTiny = styled.div`
|
||||
margin: 5px;
|
||||
`;
|
||||
|
||||
export const FormLabelTiny = styled.div`
|
||||
color: ${(props) => props.theme.manager_font3};
|
||||
`;
|
||||
|
||||
export const FormValueTiny = styled.div`
|
||||
margin-left: 15px;
|
||||
margin-top: 3px;
|
||||
`;
|
||||
|
||||
export function FormFieldTemplateTiny({ label, children, type }) {
|
||||
const theme = useTheme();
|
||||
if (type == 'checkbox') {
|
||||
return (
|
||||
<FormRowTiny>
|
||||
{children} {label}
|
||||
</FormRowTiny>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<FormRowTiny>
|
||||
<FormLabelTiny theme={theme}>{label}</FormLabelTiny>
|
||||
<FormValueTiny>{children}</FormValueTiny>
|
||||
</FormRowTiny>
|
||||
);
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
import Select from 'react-select';
|
||||
import Creatable from 'react-select/creatable';
|
||||
import { TextField, SelectField, CheckboxField } from './inputs';
|
||||
@@ -14,25 +13,8 @@ import {
|
||||
import getAsArray from './getAsArray';
|
||||
import axios from './axios';
|
||||
import useTheme from '../theme/useTheme';
|
||||
import { useForm } from './FormProvider';
|
||||
import { useForm, useFormFieldTemplate } from './FormProvider';
|
||||
|
||||
export const FormRow = styled.div`
|
||||
display: flex;
|
||||
margin: 10px;
|
||||
`;
|
||||
|
||||
export const FormButtonRow = styled.div`
|
||||
display: flex;
|
||||
// justify-content: flex-end;
|
||||
margin: 10px;
|
||||
`;
|
||||
|
||||
export const FormLabel = styled.div`
|
||||
width: 10vw;
|
||||
font-weight: bold;
|
||||
`;
|
||||
|
||||
export const FormValue = styled.div``;
|
||||
|
||||
export function FormTextFieldRaw({ name, focused = false, ...other }) {
|
||||
const { values, setFieldValue } = useForm();
|
||||
@@ -48,13 +30,11 @@ export function FormTextFieldRaw({ name, focused = false, ...other }) {
|
||||
}
|
||||
|
||||
export function FormTextField({ name, label, focused = false, ...other }) {
|
||||
const FieldTemplate = useFormFieldTemplate();
|
||||
return (
|
||||
<FormRow>
|
||||
<FormLabel>{label}</FormLabel>
|
||||
<FormValue>
|
||||
<FormTextFieldRaw name={name} focused={focused} {...other} />
|
||||
</FormValue>
|
||||
</FormRow>
|
||||
<FieldTemplate label={label} type="text">
|
||||
<FormTextFieldRaw name={name} focused={focused} {...other} />
|
||||
</FieldTemplate>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -70,13 +50,11 @@ export function FormCheckboxFieldRaw({ name = undefined, defaultValue = undefine
|
||||
}
|
||||
|
||||
export function FormCheckboxField({ label, ...other }) {
|
||||
const FieldTemplate = useFormFieldTemplate();
|
||||
return (
|
||||
<FormRow>
|
||||
<FormLabel>{label}</FormLabel>
|
||||
<FormValue>
|
||||
<FormCheckboxFieldRaw {...other} />
|
||||
</FormValue>
|
||||
</FormRow>
|
||||
<FieldTemplate label={label} type="checkbox">
|
||||
<FormCheckboxFieldRaw {...other} />
|
||||
</FieldTemplate>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -93,15 +71,13 @@ export function FormSelectFieldRaw({ children, name, ...other }) {
|
||||
}
|
||||
|
||||
export function FormSelectField({ label, name, children = null, ...other }) {
|
||||
const FieldTemplate = useFormFieldTemplate();
|
||||
return (
|
||||
<FormRow>
|
||||
<FormLabel>{label}</FormLabel>
|
||||
<FormValue>
|
||||
<FormSelectFieldRaw name={name} {...other}>
|
||||
{children}
|
||||
</FormSelectFieldRaw>
|
||||
</FormValue>
|
||||
</FormRow>
|
||||
<FieldTemplate label={label} type="select">
|
||||
<FormSelectFieldRaw name={name} {...other}>
|
||||
{children}
|
||||
</FormSelectFieldRaw>
|
||||
</FieldTemplate>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user