Compare commits
10 Commits
cb5cad7de6
...
a211aaf696
Author | SHA1 | Date | |
---|---|---|---|
a211aaf696 | |||
23ccfd10fd | |||
de20681bce | |||
0903a24433 | |||
ad3627491e | |||
55c1483052 | |||
8460dd5f9a | |||
b62b972e46 | |||
52a9f6c9d3 | |||
0382fb2a6f |
19
LICENSE
Normal file
19
LICENSE
Normal file
@ -0,0 +1,19 @@
|
||||
Copyright © 2022 Rokas Puzonas
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the “Software”), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
123
package-lock.json
generated
123
package-lock.json
generated
@ -3062,6 +3062,11 @@
|
||||
"resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
|
||||
"integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw=="
|
||||
},
|
||||
"array-uniq": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz",
|
||||
"integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY="
|
||||
},
|
||||
"array.prototype.flat": {
|
||||
"version": "1.2.5",
|
||||
"resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.5.tgz",
|
||||
@ -4532,6 +4537,11 @@
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.65.tgz",
|
||||
"integrity": "sha512-0/d8Skk8sW3FxXP0Dd6MnBlrwx7Qo9cqQec3BlIAlvKnrmS3pHsIbaroEi+nd0kZkGpQ6apMEre7xndzjlEnLw=="
|
||||
},
|
||||
"email-addresses": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/email-addresses/-/email-addresses-3.1.0.tgz",
|
||||
"integrity": "sha512-k0/r7GrWVL32kZlGwfPNgB2Y/mMXVTq/decgLczm/j34whdaspNrZO8CnXPf1laaHxI6ptUlsnAxN+UAPw+fzg=="
|
||||
},
|
||||
"emittery": {
|
||||
"version": "0.8.1",
|
||||
"resolved": "https://registry.npmjs.org/emittery/-/emittery-0.8.1.tgz",
|
||||
@ -5336,6 +5346,21 @@
|
||||
"minimatch": "^3.0.4"
|
||||
}
|
||||
},
|
||||
"filename-reserved-regex": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz",
|
||||
"integrity": "sha1-q/c9+rc10EVECr/qLZHzieu/oik="
|
||||
},
|
||||
"filenamify": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/filenamify/-/filenamify-4.3.0.tgz",
|
||||
"integrity": "sha512-hcFKyUG57yWGAzu1CMt/dPzYZuv+jAJUT85bL8mrXvNe6hWj6yEHEc4EdcgiA6Z3oi1/9wXJdZPXF2dZNgwgOg==",
|
||||
"requires": {
|
||||
"filename-reserved-regex": "^2.0.0",
|
||||
"strip-outer": "^1.0.1",
|
||||
"trim-repeated": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"filesize": {
|
||||
"version": "8.0.7",
|
||||
"resolved": "https://registry.npmjs.org/filesize/-/filesize-8.0.7.tgz",
|
||||
@ -5629,6 +5654,70 @@
|
||||
"get-intrinsic": "^1.1.1"
|
||||
}
|
||||
},
|
||||
"gh-pages": {
|
||||
"version": "3.2.3",
|
||||
"resolved": "https://registry.npmjs.org/gh-pages/-/gh-pages-3.2.3.tgz",
|
||||
"integrity": "sha512-jA1PbapQ1jqzacECfjUaO9gV8uBgU6XNMV0oXLtfCX3haGLe5Atq8BxlrADhbD6/UdG9j6tZLWAkAybndOXTJg==",
|
||||
"requires": {
|
||||
"async": "^2.6.1",
|
||||
"commander": "^2.18.0",
|
||||
"email-addresses": "^3.0.1",
|
||||
"filenamify": "^4.3.0",
|
||||
"find-cache-dir": "^3.3.1",
|
||||
"fs-extra": "^8.1.0",
|
||||
"globby": "^6.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"array-union": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz",
|
||||
"integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=",
|
||||
"requires": {
|
||||
"array-uniq": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"commander": {
|
||||
"version": "2.20.3",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
|
||||
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
|
||||
},
|
||||
"fs-extra": {
|
||||
"version": "8.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
|
||||
"integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==",
|
||||
"requires": {
|
||||
"graceful-fs": "^4.2.0",
|
||||
"jsonfile": "^4.0.0",
|
||||
"universalify": "^0.1.0"
|
||||
}
|
||||
},
|
||||
"globby": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz",
|
||||
"integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=",
|
||||
"requires": {
|
||||
"array-union": "^1.0.1",
|
||||
"glob": "^7.0.3",
|
||||
"object-assign": "^4.0.1",
|
||||
"pify": "^2.0.0",
|
||||
"pinkie-promise": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"jsonfile": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
|
||||
"integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=",
|
||||
"requires": {
|
||||
"graceful-fs": "^4.1.6"
|
||||
}
|
||||
},
|
||||
"universalify": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
|
||||
"integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"glob": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz",
|
||||
@ -8462,6 +8551,24 @@
|
||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
|
||||
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="
|
||||
},
|
||||
"pify": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
|
||||
"integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw="
|
||||
},
|
||||
"pinkie": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
|
||||
"integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA="
|
||||
},
|
||||
"pinkie-promise": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz",
|
||||
"integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=",
|
||||
"requires": {
|
||||
"pinkie": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"pirates": {
|
||||
"version": "4.0.5",
|
||||
"resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz",
|
||||
@ -10460,6 +10567,14 @@
|
||||
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
|
||||
"integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig=="
|
||||
},
|
||||
"strip-outer": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz",
|
||||
"integrity": "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==",
|
||||
"requires": {
|
||||
"escape-string-regexp": "^1.0.2"
|
||||
}
|
||||
},
|
||||
"style-loader": {
|
||||
"version": "3.3.1",
|
||||
"resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.1.tgz",
|
||||
@ -10769,6 +10884,14 @@
|
||||
"punycode": "^2.1.1"
|
||||
}
|
||||
},
|
||||
"trim-repeated": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz",
|
||||
"integrity": "sha1-42RqLqTokTEr9+rObPsFOAvAHCE=",
|
||||
"requires": {
|
||||
"escape-string-regexp": "^1.0.2"
|
||||
}
|
||||
},
|
||||
"tryer": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/tryer/-/tryer-1.0.1.tgz",
|
||||
|
@ -1,7 +1,8 @@
|
||||
{
|
||||
"name": "table-method-generator",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"homepage": "https://rokaspuzonas.github.io/table-method-generator",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@testing-library/jest-dom": "^5.16.2",
|
||||
"@testing-library/react": "^12.1.2",
|
||||
@ -10,6 +11,7 @@
|
||||
"@types/node": "^16.11.22",
|
||||
"@types/react": "^17.0.39",
|
||||
"@types/react-dom": "^17.0.11",
|
||||
"gh-pages": "^3.2.3",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-scripts": "5.0.0",
|
||||
@ -21,7 +23,9 @@
|
||||
"start": "react-scripts start",
|
||||
"build": "react-scripts build",
|
||||
"test": "react-scripts test",
|
||||
"eject": "react-scripts eject"
|
||||
"eject": "react-scripts eject",
|
||||
"predeploy": "npm run build",
|
||||
"deploy": "gh-pages -d build"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"extends": [
|
||||
|
34
src/App.css
34
src/App.css
@ -1,14 +1,3 @@
|
||||
.App-logo {
|
||||
height: 40vmin;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
.App-logo {
|
||||
animation: App-logo-spin infinite 20s linear;
|
||||
}
|
||||
}
|
||||
|
||||
.App {
|
||||
padding: 3em;
|
||||
background-color: #1E1E1E;
|
||||
@ -17,19 +6,22 @@
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
font-size: calc(10px + 1vmin);
|
||||
font-size: 16px;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.App-link {
|
||||
color: #61dafb;
|
||||
input, select, button {
|
||||
background-color: #131313;
|
||||
color: white;
|
||||
border: 1px solid black;
|
||||
margin: 0.25em 0.5em;
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
@keyframes App-logo-spin {
|
||||
from {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
button:hover {
|
||||
background-color: #1F1F1F;
|
||||
}
|
||||
|
||||
button:active {
|
||||
background-color: black;
|
||||
}
|
||||
|
65
src/App.tsx
65
src/App.tsx
@ -2,33 +2,64 @@ import { useState } from 'react';
|
||||
import './App.css';
|
||||
import TableDefinitionForm from './TableDefinitionForm';
|
||||
import TableMethodCodeBlock from './TableMethodCodeBlock';
|
||||
import { TableDefinition } from './TableMethodGenerator';
|
||||
import { TableColumns } from './TableMethodGenerator';
|
||||
|
||||
// TODO: Add section for testing how rendered table looks
|
||||
|
||||
// TODO: Render resizeable table which automatically update the necessary fields
|
||||
|
||||
function App() {
|
||||
let [definition, setDefinition] = useState<TableDefinition>({
|
||||
names: ["Miestas", "Atsakingas", "Vardas", "Adresas", "Metai"],
|
||||
fields: ["City", "Manager", "Name", "Address", "Year"],
|
||||
widths: [10, 20, 18, 15, 5],
|
||||
alignments: ["left", "left", "left", "left", "right"]
|
||||
})
|
||||
let initialColumns: TableColumns = []
|
||||
|
||||
let [data, setData] = useState({
|
||||
definition
|
||||
});
|
||||
if (process.env.NODE_ENV === "development") {
|
||||
initialColumns = [
|
||||
{
|
||||
name: "Miestas",
|
||||
field: "City",
|
||||
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"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
const onChange = (e: TableDefinition) => {
|
||||
definition = e
|
||||
data.definition = e
|
||||
setDefinition(e)
|
||||
setData({...data})
|
||||
let [columns, setColumns] = useState<TableColumns>(initialColumns)
|
||||
|
||||
// let [generatorOptions, setGeneratorOptions] = useState<TableMethodGeneratorOptions>({});
|
||||
|
||||
const onChange = (e: TableColumns) => {
|
||||
setColumns([...e])
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="App">
|
||||
<main>
|
||||
<TableDefinitionForm value={definition} onChange={onChange} />
|
||||
<TableDefinitionForm value={columns} onChange={onChange} />
|
||||
<hr />
|
||||
{TableMethodCodeBlock(data)}
|
||||
<TableMethodCodeBlock columns={columns}/>
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
|
@ -1,47 +1,38 @@
|
||||
import { ChangeEvent, useState } from "react"
|
||||
import { Alignment, TableDefinition } from "./TableMethodGenerator"
|
||||
import { Alignment, generate, TableColumn, TableColumns } from "./TableMethodGenerator"
|
||||
|
||||
|
||||
interface TableDefinitionRowProps {
|
||||
value: Row
|
||||
onChange?: { (e: Row): void }
|
||||
interface TableColumnProps {
|
||||
value: TableColumn
|
||||
onChange: { (e: TableColumn): void }
|
||||
}
|
||||
|
||||
function TableDefinitionRow(props: TableDefinitionRowProps) {
|
||||
function TableDefinitionRow(props: TableColumnProps) {
|
||||
let [, setName] = useState(props.value.name)
|
||||
const onChangeName = (e: ChangeEvent<HTMLInputElement>) => {
|
||||
props.value.name = e.target.value
|
||||
setName(props.value.name)
|
||||
if (props.onChange) {
|
||||
props.onChange(props.value)
|
||||
}
|
||||
props.onChange(props.value)
|
||||
}
|
||||
|
||||
let [, setField] = useState(props.value.field)
|
||||
const onChangeField = (e: ChangeEvent<HTMLInputElement>) => {
|
||||
props.value.field = e.target.value
|
||||
setField(props.value.field)
|
||||
if (props.onChange) {
|
||||
props.onChange(props.value)
|
||||
}
|
||||
props.onChange(props.value)
|
||||
}
|
||||
|
||||
let [, setWidth] = useState(props.value.width)
|
||||
const onChangeWidth = (e: ChangeEvent<HTMLInputElement>) => {
|
||||
props.value.width = parseFloat(e.target.value)
|
||||
setWidth(props.value.width)
|
||||
if (props.onChange) {
|
||||
props.onChange(props.value)
|
||||
}
|
||||
props.onChange(props.value)
|
||||
}
|
||||
|
||||
let [, setAlignment] = useState(props.value.alighment)
|
||||
let [, setAlignment] = useState(props.value.alignment)
|
||||
const onChangeAlignment = (e: ChangeEvent<HTMLSelectElement>) => {
|
||||
props.value.alighment = e.target.value as Alignment
|
||||
setAlignment(props.value.alighment)
|
||||
if (props.onChange) {
|
||||
props.onChange(props.value)
|
||||
}
|
||||
props.value.alignment = e.target.value as Alignment
|
||||
setAlignment(props.value.alignment)
|
||||
props.onChange(props.value)
|
||||
}
|
||||
|
||||
return (
|
||||
@ -49,7 +40,7 @@ function TableDefinitionRow(props: TableDefinitionRowProps) {
|
||||
<input type="text" value={props.value.name} onChange={onChangeName} />
|
||||
<input type="text" value={props.value.field} onChange={onChangeField} />
|
||||
<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="left">Left</option>
|
||||
</select>
|
||||
@ -58,91 +49,57 @@ function TableDefinitionRow(props: TableDefinitionRowProps) {
|
||||
}
|
||||
|
||||
interface TableDefinitionProps {
|
||||
value: TableDefinition
|
||||
onChange?: { (e: TableDefinition): 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
|
||||
value: TableColumns
|
||||
onChange?: { (e: TableColumns): void }
|
||||
}
|
||||
|
||||
function TableDefinitionForm(props: TableDefinitionProps) {
|
||||
let [currentName, setCurrentName] = useState("")
|
||||
|
||||
let [rows, setRows] = useState<Row[]>(intoRows(props.value))
|
||||
let [columns, setColumns] = useState<TableColumns>(props.value)
|
||||
|
||||
const addRow = () => {
|
||||
rows.push({ name: currentName })
|
||||
setCurrentName("")
|
||||
if (props.onChange !== undefined) {
|
||||
props.onChange(fromRows(rows))
|
||||
if (currentName.length > 0) {
|
||||
columns.push({ name: currentName })
|
||||
setCurrentName("")
|
||||
if (props.onChange !== undefined) {
|
||||
props.onChange(columns)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const updateRow = (i: number, row: Row) => {
|
||||
if (row.name === "") {
|
||||
rows.splice(i, 1)
|
||||
rows = [...rows]
|
||||
setRows(rows)
|
||||
const updateRow = (i: number, column: TableColumn) => {
|
||||
if (column.name === "") {
|
||||
columns.splice(i, 1)
|
||||
setColumns([...columns])
|
||||
} else {
|
||||
rows = [...rows]
|
||||
rows[i] = row
|
||||
setRows(rows)
|
||||
columns[i] = column
|
||||
setColumns([...columns])
|
||||
}
|
||||
if (props.onChange !== undefined) {
|
||||
props.onChange(fromRows(rows))
|
||||
props.onChange(columns)
|
||||
}
|
||||
}
|
||||
|
||||
const onClickCopy = () => {
|
||||
navigator.clipboard.writeText(generate(columns))
|
||||
}
|
||||
|
||||
return (
|
||||
<form onSubmit={(e) => e.preventDefault()}>
|
||||
<label>Column:</label>
|
||||
<label>Column name:</label>
|
||||
<input
|
||||
type="text"
|
||||
value={currentName}
|
||||
onChange={(e) => setCurrentName(e.target.value)}
|
||||
onKeyPress={(e) => e.key === "Enter" && addRow()}
|
||||
/>
|
||||
<button onClick={addRow}>Insert column</button>
|
||||
<button onClick={onClickCopy}>Copy code 📋!</button>
|
||||
<ol>
|
||||
{
|
||||
rows.map((item, i) =>
|
||||
<TableDefinitionRow key={i} value={item} onChange={(e) => updateRow(i, e)}/>
|
||||
)
|
||||
}
|
||||
{columns.map((item, i) =>
|
||||
<TableDefinitionRow key={i} value={item} onChange={(e) => updateRow(i, e)}/>
|
||||
)}
|
||||
</ol>
|
||||
</form>
|
||||
)
|
||||
|
@ -1,16 +1,24 @@
|
||||
import { Light as SyntaxHighlighter } from 'react-syntax-highlighter';
|
||||
import csharp from 'react-syntax-highlighter/dist/esm/languages/hljs/csharp';
|
||||
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);
|
||||
|
||||
function TableMethodCodeBlock(props: TableMethodGeneratorOptions) {
|
||||
interface Props {
|
||||
columns: TableColumns
|
||||
options?: TableMethodGeneratorOptions
|
||||
}
|
||||
|
||||
function TableMethodCodeBlock(props: Props) {
|
||||
return (
|
||||
<SyntaxHighlighter language="csharp" style={vs2015}>
|
||||
{generate(props)}
|
||||
</SyntaxHighlighter>
|
||||
<div>
|
||||
<SyntaxHighlighter language="csharp" style={vs2015}>
|
||||
{generate(props.columns, props.options)}
|
||||
</SyntaxHighlighter>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
export default TableMethodCodeBlock
|
||||
|
@ -1,15 +1,15 @@
|
||||
export type Alignment = "left"|"right"
|
||||
|
||||
export interface TableDefinition {
|
||||
names?: string[]
|
||||
fields?: (string|undefined)[]
|
||||
widths?: (number|undefined)[]
|
||||
alignments?: (Alignment|undefined)[]
|
||||
export interface TableColumn {
|
||||
name: string
|
||||
field?: string
|
||||
width?: number
|
||||
alignment?: Alignment
|
||||
}
|
||||
|
||||
export interface TableMethodGeneratorOptions {
|
||||
definition: TableDefinition
|
||||
export type TableColumns = TableColumn[]
|
||||
|
||||
export interface TableMethodGeneratorOptions {
|
||||
method_name?: string
|
||||
empty_message?: string
|
||||
|
||||
@ -19,47 +19,38 @@ export interface TableMethodGeneratorOptions {
|
||||
entry_name?: string
|
||||
}
|
||||
|
||||
function get_total_width(definition: TableDefinition): number {
|
||||
let names = definition.names || []
|
||||
if (names.length === 0) { return 0; }
|
||||
function get_total_width(columns: TableColumns): number {
|
||||
let total_width = 0;
|
||||
|
||||
let total_width = 0
|
||||
let widths = definition.widths || []
|
||||
for (let i = 0; i < names.length; i++) {
|
||||
const name = names[i]
|
||||
total_width += widths[i] || name.length
|
||||
for (const column of columns) {
|
||||
total_width += column.width || column.name.length
|
||||
}
|
||||
total_width += 2 + 2;
|
||||
total_width += 3*(names.length-1);
|
||||
total_width += 3*(columns.length-1);
|
||||
|
||||
return total_width;
|
||||
}
|
||||
|
||||
export function generate(options: TableMethodGeneratorOptions): string {
|
||||
const section_names = options.definition.names || []
|
||||
const method_name = options.method_name || "PrintTable"
|
||||
if (section_names.length === 0) {
|
||||
export function generate(columns: TableColumns, options?: TableMethodGeneratorOptions): string {
|
||||
const method_name = options?.method_name || "PrintTable"
|
||||
if (columns.length === 0) {
|
||||
return `static void ${method_name}()\n{\n}`;
|
||||
}
|
||||
|
||||
const empty_message = options.empty_message || "Empty"
|
||||
const container_name = options.container_name || "container"
|
||||
const container_type = options.container_type || "Container"
|
||||
const entry_name = options.entry_name || "e"
|
||||
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 || []
|
||||
const empty_message = options?.empty_message || "Empty"
|
||||
const container_name = options?.container_name || "container"
|
||||
const container_type = options?.container_type || "Container"
|
||||
const entry_name = options?.entry_name || "e"
|
||||
const entry_type = options?.entry_type || "Entry"
|
||||
|
||||
// Total width
|
||||
const total_width = get_total_width(options.definition)
|
||||
const total_width = get_total_width(columns)
|
||||
|
||||
// Table row
|
||||
let row_components: string[] = []
|
||||
for (let i = 0; i < section_names.length; i++) {
|
||||
const section = section_names[i]
|
||||
const width = section_widths[i] || section.length
|
||||
const alighment = section_alignments[i] || "right"
|
||||
for (let i = 0; i < columns.length; i++) {
|
||||
const width = columns[i].width || columns[i].name.length
|
||||
const alighment = columns[i].alignment || "right"
|
||||
if (alighment === "left") {
|
||||
row_components.push(`{${i},-${width}}`)
|
||||
} else {
|
||||
@ -67,24 +58,19 @@ export function generate(options: TableMethodGeneratorOptions): string {
|
||||
}
|
||||
}
|
||||
|
||||
let table_row = "";
|
||||
if (row_components.length > 0) {
|
||||
table_row = "| " + row_components.join(" | ") + " |"
|
||||
}
|
||||
const table_row = "| " + row_components.join(" | ") + " |"
|
||||
|
||||
// Section names
|
||||
const joined_names = section_names.map((n) => `"${n}"`).join(", ")
|
||||
const joined_names = columns.map((c) => `"${c.name}"`).join(", ")
|
||||
|
||||
// Section fields
|
||||
const formatted_fields = []
|
||||
for (let i = 0; i < section_names.length; i++) {
|
||||
if (section_fields[i]) {
|
||||
formatted_fields.push(`${entry_name}.${section_fields[i]}`)
|
||||
const joined_fields = columns.map((column) => {
|
||||
if (column.field) {
|
||||
return `${entry_name}.${column.field}`
|
||||
} else {
|
||||
formatted_fields.push(`"-"`)
|
||||
return `"-"`
|
||||
}
|
||||
}
|
||||
const joined_fields = formatted_fields.join(", ")
|
||||
}).join(", ")
|
||||
|
||||
// Final code string
|
||||
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}`;
|
||||
}
|
||||
|
||||
function render_table_row(definition: TableDefinition, entry: string[]): string {
|
||||
let names = definition.names || []
|
||||
if (names.length === 0) { return ""; }
|
||||
function render_table_row(columns: TableColumns, entry: (string|undefined)[]): string {
|
||||
if (columns.length === 0) { return "" }
|
||||
|
||||
const columns: string[] = []
|
||||
const alighments = definition.alignments || []
|
||||
const widths = definition.widths || []
|
||||
for (let i = 0; i < names.length; i++) {
|
||||
const value = entry[i] || "";
|
||||
const alighment = alighments[i] || "right"
|
||||
const width = widths[i] || names[i].length
|
||||
let formated_cells = []
|
||||
for (let i = 0; i < columns.length; i++) {
|
||||
const alighment = columns[i].alignment || "right"
|
||||
const width = columns[i].width || columns[i].name.length
|
||||
|
||||
const filler = " ".repeat(Math.max(width - value.length, 0));
|
||||
if (alighment === "left") {
|
||||
columns.push(value + filler);
|
||||
} else {
|
||||
columns.push(filler + value);
|
||||
}
|
||||
const value = entry[i] || "";
|
||||
const filler = " ".repeat(Math.max(width - value.length, 0));
|
||||
if (alighment === "left") {
|
||||
formated_cells.push(value + filler);
|
||||
} else {
|
||||
formated_cells.push(filler + value);
|
||||
}
|
||||
}
|
||||
return "| " + columns.join(" | ") + " |"
|
||||
|
||||
return "| " + formated_cells.join(" | ") + " |"
|
||||
}
|
||||
|
||||
export function render_table(definition: TableDefinition, entries: string[][]): string {
|
||||
if (!definition.names) {return ""; }
|
||||
export function render_table(columns: TableColumns, entries: string[][]): string {
|
||||
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 column_names = columns.map((column) => column.name)
|
||||
const lines = []
|
||||
lines.push(seperator)
|
||||
lines.push(render_table_row(definition, definition.names))
|
||||
lines.push(render_table_row(columns, column_names))
|
||||
lines.push(seperator)
|
||||
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)
|
||||
|
||||
|
@ -1,14 +1,14 @@
|
||||
import { render_table, TableDefinition } from "./TableMethodGenerator"
|
||||
import { render_table, TableColumns } from "./TableMethodGenerator"
|
||||
|
||||
export interface TableRendererProps {
|
||||
definition: TableDefinition,
|
||||
columns: TableColumns,
|
||||
entries: string[][]
|
||||
}
|
||||
|
||||
function TableRenderer(props: TableRendererProps) {
|
||||
return (
|
||||
<pre>
|
||||
{render_table(props.definition, props.entries)}
|
||||
{render_table(props.columns, props.entries)}
|
||||
</pre>
|
||||
)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user