refactor: adjust how table definitions are stored
This commit is contained in:
parent
8460dd5f9a
commit
55c1483052
54
src/App.tsx
54
src/App.tsx
@ -5,30 +5,52 @@ import TableMethodCodeBlock from './TableMethodCodeBlock';
|
|||||||
import { TableDefinition } from './TableMethodGenerator';
|
import { TableDefinition } from './TableMethodGenerator';
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
let [definition, setDefinition] = useState<TableDefinition>({
|
let [columns, setColumns] = useState<TableColumns>([
|
||||||
names: ["Miestas", "Atsakingas", "Vardas", "Adresas", "Metai"],
|
{
|
||||||
fields: ["City", "Manager", "Name", "Address", "Year"],
|
name: "Miestas",
|
||||||
widths: [10, 20, 18, 15, 5],
|
field: "City",
|
||||||
alignments: ["left", "left", "left", "left", "right"]
|
width: 10,
|
||||||
})
|
alignment: "left"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Atsakingas",
|
||||||
|
field: "Manager",
|
||||||
|
width: 20,
|
||||||
|
alignment: "left"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Vardas",
|
||||||
|
field: "Name",
|
||||||
|
width: 18,
|
||||||
|
alignment: "left"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Address",
|
||||||
|
field: "Adress",
|
||||||
|
width: 15,
|
||||||
|
alignment: "left"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Metai",
|
||||||
|
field: "Year",
|
||||||
|
width: 5,
|
||||||
|
alignment: "right"
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
let [data, setData] = useState({
|
let [generatorOptions, setGeneratorOptions] = useState<TableMethodGeneratorOptions>({});
|
||||||
definition
|
|
||||||
});
|
|
||||||
|
|
||||||
const onChange = (e: TableDefinition) => {
|
const onChange = (e: TableColumns) => {
|
||||||
definition = e
|
columns = e
|
||||||
data.definition = e
|
setColumns(e)
|
||||||
setDefinition(e)
|
|
||||||
setData({...data})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="App">
|
<div className="App">
|
||||||
<main>
|
<main>
|
||||||
<TableDefinitionForm value={definition} onChange={onChange} />
|
<TableDefinitionForm value={columns} onChange={onChange} />
|
||||||
<hr />
|
<hr />
|
||||||
{TableMethodCodeBlock(data)}
|
<TableMethodCodeBlock columns={columns} options={generatorOptions}/>
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
import { ChangeEvent, useState } from "react"
|
import { ChangeEvent, useState } from "react"
|
||||||
import { Alignment, TableDefinition } from "./TableMethodGenerator"
|
import { Alignment, TableColumn, TableColumns } from "./TableMethodGenerator"
|
||||||
|
|
||||||
|
|
||||||
interface TableDefinitionRowProps {
|
interface TableColumnProps {
|
||||||
value: Row
|
value: TableColumn
|
||||||
onChange?: { (e: Row): void }
|
onChange?: { (e: TableColumn): void }
|
||||||
}
|
}
|
||||||
|
|
||||||
function TableDefinitionRow(props: TableDefinitionRowProps) {
|
function TableDefinitionRow(props: TableColumnProps) {
|
||||||
let [, setName] = useState(props.value.name)
|
let [, setName] = useState(props.value.name)
|
||||||
const onChangeName = (e: ChangeEvent<HTMLInputElement>) => {
|
const onChangeName = (e: ChangeEvent<HTMLInputElement>) => {
|
||||||
props.value.name = e.target.value
|
props.value.name = e.target.value
|
||||||
@ -35,10 +35,10 @@ function TableDefinitionRow(props: TableDefinitionRowProps) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let [, setAlignment] = useState(props.value.alighment)
|
let [, setAlignment] = useState(props.value.alignment)
|
||||||
const onChangeAlignment = (e: ChangeEvent<HTMLSelectElement>) => {
|
const onChangeAlignment = (e: ChangeEvent<HTMLSelectElement>) => {
|
||||||
props.value.alighment = e.target.value as Alignment
|
props.value.alignment = e.target.value as Alignment
|
||||||
setAlignment(props.value.alighment)
|
setAlignment(props.value.alignment)
|
||||||
if (props.onChange) {
|
if (props.onChange) {
|
||||||
props.onChange(props.value)
|
props.onChange(props.value)
|
||||||
}
|
}
|
||||||
@ -49,7 +49,7 @@ function TableDefinitionRow(props: TableDefinitionRowProps) {
|
|||||||
<input type="text" value={props.value.name} onChange={onChangeName} />
|
<input type="text" value={props.value.name} onChange={onChangeName} />
|
||||||
<input type="text" value={props.value.field} onChange={onChangeField} />
|
<input type="text" value={props.value.field} onChange={onChangeField} />
|
||||||
<input type="number" value={props.value.width || props.value.name.length} onChange={onChangeWidth}/>
|
<input type="number" value={props.value.width || props.value.name.length} onChange={onChangeWidth}/>
|
||||||
<select value={props.value.alighment} onChange={onChangeAlignment}>
|
<select value={props.value.alignment} onChange={onChangeAlignment}>
|
||||||
<option value="right">Right</option>
|
<option value="right">Right</option>
|
||||||
<option value="left">Left</option>
|
<option value="left">Left</option>
|
||||||
</select>
|
</select>
|
||||||
@ -58,73 +58,35 @@ function TableDefinitionRow(props: TableDefinitionRowProps) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface TableDefinitionProps {
|
interface TableDefinitionProps {
|
||||||
value: TableDefinition
|
value: TableColumns
|
||||||
onChange?: { (e: TableDefinition): void }
|
onChange?: { (e: TableColumns): void }
|
||||||
}
|
|
||||||
|
|
||||||
interface Row {
|
|
||||||
name: string
|
|
||||||
width?: number
|
|
||||||
field?: string
|
|
||||||
alighment?: Alignment
|
|
||||||
}
|
|
||||||
|
|
||||||
function intoRows(definition: TableDefinition): Row[] {
|
|
||||||
const rows: Row[] = []
|
|
||||||
if (definition.names !== undefined) {
|
|
||||||
for (let i = 0; i < definition.names.length; i++) {
|
|
||||||
rows.push({
|
|
||||||
name: definition.names[i],
|
|
||||||
width: (definition.widths || [])[i],
|
|
||||||
field: (definition.fields || [])[i],
|
|
||||||
alighment: (definition.alignments || [])[i],
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return rows
|
|
||||||
}
|
|
||||||
|
|
||||||
function fromRows(rows: Row[]): TableDefinition {
|
|
||||||
const definition: TableDefinition = {
|
|
||||||
names: [],
|
|
||||||
widths: [],
|
|
||||||
fields: [],
|
|
||||||
alignments: []
|
|
||||||
}
|
|
||||||
for (const row of rows) {
|
|
||||||
(definition.names as string[]).push(row.name);
|
|
||||||
(definition.widths as (number|undefined)[]).push(row.width);
|
|
||||||
(definition.fields as (string|undefined)[]).push(row.field);
|
|
||||||
(definition.alignments as (Alignment|undefined)[]).push(row.alighment);
|
|
||||||
}
|
|
||||||
return definition
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function TableDefinitionForm(props: TableDefinitionProps) {
|
function TableDefinitionForm(props: TableDefinitionProps) {
|
||||||
let [currentName, setCurrentName] = useState("")
|
let [currentName, setCurrentName] = useState("")
|
||||||
|
|
||||||
let [rows, setRows] = useState<Row[]>(intoRows(props.value))
|
let [columns, setColumns] = useState<TableColumns>(props.value)
|
||||||
|
|
||||||
const addRow = () => {
|
const addRow = () => {
|
||||||
rows.push({ name: currentName })
|
columns.push({ name: currentName })
|
||||||
setCurrentName("")
|
setCurrentName("")
|
||||||
if (props.onChange !== undefined) {
|
if (props.onChange !== undefined) {
|
||||||
props.onChange(fromRows(rows))
|
props.onChange(columns)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const updateRow = (i: number, row: Row) => {
|
const updateRow = (i: number, column: TableColumn) => {
|
||||||
if (row.name === "") {
|
if (column.name === "") {
|
||||||
rows.splice(i, 1)
|
columns.splice(i, 1)
|
||||||
rows = [...rows]
|
columns = [...columns]
|
||||||
setRows(rows)
|
setColumns(columns)
|
||||||
} else {
|
} else {
|
||||||
rows = [...rows]
|
columns = [...columns]
|
||||||
rows[i] = row
|
columns[i] = column
|
||||||
setRows(rows)
|
setColumns(columns)
|
||||||
}
|
}
|
||||||
if (props.onChange !== undefined) {
|
if (props.onChange !== undefined) {
|
||||||
props.onChange(fromRows(rows))
|
props.onChange(columns)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,7 +101,7 @@ function TableDefinitionForm(props: TableDefinitionProps) {
|
|||||||
/>
|
/>
|
||||||
<ol>
|
<ol>
|
||||||
{
|
{
|
||||||
rows.map((item, i) =>
|
columns.map((item, i) =>
|
||||||
<TableDefinitionRow key={i} value={item} onChange={(e) => updateRow(i, e)}/>
|
<TableDefinitionRow key={i} value={item} onChange={(e) => updateRow(i, e)}/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,17 @@
|
|||||||
import { Light as SyntaxHighlighter } from 'react-syntax-highlighter';
|
import { Light as SyntaxHighlighter } from 'react-syntax-highlighter';
|
||||||
import csharp from 'react-syntax-highlighter/dist/esm/languages/hljs/csharp';
|
import csharp from 'react-syntax-highlighter/dist/esm/languages/hljs/csharp';
|
||||||
import { vs2015 } from 'react-syntax-highlighter/dist/esm/styles/hljs';
|
import { vs2015 } from 'react-syntax-highlighter/dist/esm/styles/hljs';
|
||||||
import { generate, TableMethodGeneratorOptions } from './TableMethodGenerator';
|
import { generate, TableColumns, TableMethodGeneratorOptions } from './TableMethodGenerator';
|
||||||
|
|
||||||
SyntaxHighlighter.registerLanguage('csharp', csharp);
|
SyntaxHighlighter.registerLanguage('csharp', csharp);
|
||||||
|
|
||||||
function TableMethodCodeBlock(props: TableMethodGeneratorOptions) {
|
interface Props {
|
||||||
let script = generate(props)
|
columns: TableColumns
|
||||||
|
options: TableMethodGeneratorOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
function TableMethodCodeBlock(props: Props) {
|
||||||
|
let script = generate(props.columns, props.options)
|
||||||
|
|
||||||
const onClickCopy = () => {
|
const onClickCopy = () => {
|
||||||
navigator.clipboard.writeText(script)
|
navigator.clipboard.writeText(script)
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
export type Alignment = "left"|"right"
|
export type Alignment = "left"|"right"
|
||||||
|
|
||||||
export interface TableDefinition {
|
export interface TableColumn {
|
||||||
names?: string[]
|
name: string
|
||||||
fields?: (string|undefined)[]
|
field?: string
|
||||||
widths?: (number|undefined)[]
|
width?: number
|
||||||
alignments?: (Alignment|undefined)[]
|
alignment?: Alignment
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TableMethodGeneratorOptions {
|
export type TableColumns = TableColumn[]
|
||||||
definition: TableDefinition
|
|
||||||
|
|
||||||
|
export interface TableMethodGeneratorOptions {
|
||||||
method_name?: string
|
method_name?: string
|
||||||
empty_message?: string
|
empty_message?: string
|
||||||
|
|
||||||
@ -19,26 +19,21 @@ export interface TableMethodGeneratorOptions {
|
|||||||
entry_name?: string
|
entry_name?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
function get_total_width(definition: TableDefinition): number {
|
function get_total_width(columns: TableColumns): number {
|
||||||
let names = definition.names || []
|
let total_width = 0;
|
||||||
if (names.length === 0) { return 0; }
|
|
||||||
|
|
||||||
let total_width = 0
|
for (const column of columns) {
|
||||||
let widths = definition.widths || []
|
total_width += column.width || column.name.length
|
||||||
for (let i = 0; i < names.length; i++) {
|
|
||||||
const name = names[i]
|
|
||||||
total_width += widths[i] || name.length
|
|
||||||
}
|
}
|
||||||
total_width += 2 + 2;
|
total_width += 2 + 2;
|
||||||
total_width += 3*(names.length-1);
|
total_width += 3*(columns.length-1);
|
||||||
|
|
||||||
return total_width;
|
return total_width;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function generate(options: TableMethodGeneratorOptions): string {
|
export function generate(columns: TableColumns, options: TableMethodGeneratorOptions): string {
|
||||||
const section_names = options.definition.names || []
|
|
||||||
const method_name = options.method_name || "PrintTable"
|
const method_name = options.method_name || "PrintTable"
|
||||||
if (section_names.length === 0) {
|
if (columns.length === 0) {
|
||||||
return `static void ${method_name}()\n{\n}`;
|
return `static void ${method_name}()\n{\n}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,19 +42,15 @@ export function generate(options: TableMethodGeneratorOptions): string {
|
|||||||
const container_type = options.container_type || "Container"
|
const container_type = options.container_type || "Container"
|
||||||
const entry_name = options.entry_name || "e"
|
const entry_name = options.entry_name || "e"
|
||||||
const entry_type = options.entry_type || "Entry"
|
const entry_type = options.entry_type || "Entry"
|
||||||
const section_widths = options.definition.widths || []
|
|
||||||
const section_alignments = options.definition.alignments || []
|
|
||||||
const section_fields = options.definition.fields || []
|
|
||||||
|
|
||||||
// Total width
|
// Total width
|
||||||
const total_width = get_total_width(options.definition)
|
const total_width = get_total_width(columns)
|
||||||
|
|
||||||
// Table row
|
// Table row
|
||||||
let row_components: string[] = []
|
let row_components: string[] = []
|
||||||
for (let i = 0; i < section_names.length; i++) {
|
for (let i = 0; i < columns.length; i++) {
|
||||||
const section = section_names[i]
|
const width = columns[i].width || columns[i].name.length
|
||||||
const width = section_widths[i] || section.length
|
const alighment = columns[i].alignment || "right"
|
||||||
const alighment = section_alignments[i] || "right"
|
|
||||||
if (alighment === "left") {
|
if (alighment === "left") {
|
||||||
row_components.push(`{${i},-${width}}`)
|
row_components.push(`{${i},-${width}}`)
|
||||||
} else {
|
} else {
|
||||||
@ -67,24 +58,19 @@ export function generate(options: TableMethodGeneratorOptions): string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let table_row = "";
|
const table_row = "| " + row_components.join(" | ") + " |"
|
||||||
if (row_components.length > 0) {
|
|
||||||
table_row = "| " + row_components.join(" | ") + " |"
|
|
||||||
}
|
|
||||||
|
|
||||||
// Section names
|
// Section names
|
||||||
const joined_names = section_names.map((n) => `"${n}"`).join(", ")
|
const joined_names = columns.map((c) => `"${c.name}"`).join(", ")
|
||||||
|
|
||||||
// Section fields
|
// Section fields
|
||||||
const formatted_fields = []
|
const joined_fields = columns.map((column) => {
|
||||||
for (let i = 0; i < section_names.length; i++) {
|
if (column.field) {
|
||||||
if (section_fields[i]) {
|
return `${entry_name}.${column.field}`
|
||||||
formatted_fields.push(`${entry_name}.${section_fields[i]}`)
|
|
||||||
} else {
|
} else {
|
||||||
formatted_fields.push(`"-"`)
|
return `"-"`
|
||||||
}
|
}
|
||||||
}
|
}).join(", ")
|
||||||
const joined_fields = formatted_fields.join(", ")
|
|
||||||
|
|
||||||
// Final code string
|
// Final code string
|
||||||
return `static void ${method_name}(${container_type} ${container_name})\n{
|
return `static void ${method_name}(${container_type} ${container_name})\n{
|
||||||
@ -105,40 +91,39 @@ export function generate(options: TableMethodGeneratorOptions): string {
|
|||||||
Console.WriteLine(new string('-', ${total_width}));\n}`;
|
Console.WriteLine(new string('-', ${total_width}));\n}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function render_table_row(definition: TableDefinition, entry: string[]): string {
|
function render_table_row(columns: TableColumns, entry: (string|undefined)[]): string {
|
||||||
let names = definition.names || []
|
if (columns.length === 0) { return "" }
|
||||||
if (names.length === 0) { return ""; }
|
|
||||||
|
|
||||||
const columns: string[] = []
|
let formated_cells = []
|
||||||
const alighments = definition.alignments || []
|
for (let i = 0; i < columns.length; i++) {
|
||||||
const widths = definition.widths || []
|
const alighment = columns[i].alignment || "right"
|
||||||
for (let i = 0; i < names.length; i++) {
|
const width = columns[i].width || columns[i].name.length
|
||||||
const value = entry[i] || "";
|
|
||||||
const alighment = alighments[i] || "right"
|
|
||||||
const width = widths[i] || names[i].length
|
|
||||||
|
|
||||||
const filler = " ".repeat(Math.max(width - value.length, 0));
|
const value = entry[i] || "";
|
||||||
if (alighment === "left") {
|
const filler = " ".repeat(Math.max(width - value.length, 0));
|
||||||
columns.push(value + filler);
|
if (alighment === "left") {
|
||||||
} else {
|
formated_cells.push(value + filler);
|
||||||
columns.push(filler + value);
|
} else {
|
||||||
}
|
formated_cells.push(filler + value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return "| " + columns.join(" | ") + " |"
|
|
||||||
|
return "| " + formated_cells.join(" | ") + " |"
|
||||||
}
|
}
|
||||||
|
|
||||||
export function render_table(definition: TableDefinition, entries: string[][]): string {
|
export function render_table(columns: TableColumns, entries: string[][]): string {
|
||||||
if (!definition.names) {return ""; }
|
if (columns.length === 0) { return "" }
|
||||||
|
|
||||||
const total_width = get_total_width(definition)
|
const total_width = get_total_width(columns)
|
||||||
const seperator = "-".repeat(total_width)
|
const seperator = "-".repeat(total_width)
|
||||||
|
|
||||||
|
const column_names = columns.map((column) => column.name)
|
||||||
const lines = []
|
const lines = []
|
||||||
lines.push(seperator)
|
lines.push(seperator)
|
||||||
lines.push(render_table_row(definition, definition.names))
|
lines.push(render_table_row(columns, column_names))
|
||||||
lines.push(seperator)
|
lines.push(seperator)
|
||||||
for (let i = 0; i < entries.length; i++) {
|
for (let i = 0; i < entries.length; i++) {
|
||||||
lines.push(render_table_row(definition, entries[i]))
|
lines.push(render_table_row(columns, entries[i]))
|
||||||
}
|
}
|
||||||
lines.push(seperator)
|
lines.push(seperator)
|
||||||
|
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
import { render_table, TableDefinition } from "./TableMethodGenerator"
|
import { render_table, TableColumns } from "./TableMethodGenerator"
|
||||||
|
|
||||||
export interface TableRendererProps {
|
export interface TableRendererProps {
|
||||||
definition: TableDefinition,
|
columns: TableColumns,
|
||||||
entries: string[][]
|
entries: string[][]
|
||||||
}
|
}
|
||||||
|
|
||||||
function TableRenderer(props: TableRendererProps) {
|
function TableRenderer(props: TableRendererProps) {
|
||||||
return (
|
return (
|
||||||
<pre>
|
<pre>
|
||||||
{render_table(props.definition, props.entries)}
|
{render_table(props.columns, props.entries)}
|
||||||
</pre>
|
</pre>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user