diff options
author | Galen Guyer <galen@galenguyer.com> | 2022-11-08 01:29:35 -0500 |
---|---|---|
committer | Galen Guyer <galen@galenguyer.com> | 2022-11-08 01:29:35 -0500 |
commit | 02f49120a3eabe2f855f219682a3fb0fd987db85 (patch) | |
tree | a2b3330ca69a288c9dfdef4ea8d0fa1709981aee | |
parent | 0dea469a59b14905a81dd97dc2e3d026d9f02250 (diff) |
SQL code editor and table stuff
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | package.json | 5 | ||||
-rw-r--r-- | pnpm-lock.yaml | 181 | ||||
-rw-r--r-- | src/App.css | 9 | ||||
-rw-r--r-- | src/App.js | 68 | ||||
-rw-r--r-- | src/Table.css | 23 | ||||
-rw-r--r-- | src/Table.js | 38 | ||||
-rw-r--r-- | src/schema.js | 168 |
8 files changed, 473 insertions, 20 deletions
@@ -2,3 +2,4 @@ node_modules/ dist/ public/data/ +public/fcc.db diff --git a/package.json b/package.json index 9c4fe7f..904fc72 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "main": "index.js", "scripts": { "start": "webpack-dev-server --mode development", - "build": "webpack --mode production", + "build": "NODE_ENV=production webpack", "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], @@ -28,6 +28,9 @@ "webpack-dev-server": "^4.11.1" }, "dependencies": { + "@codemirror/commands": "^6.1.2", + "@codemirror/lang-sql": "^6.3.2", + "@uiw/react-codemirror": "^4.12.4", "lodash": "^4.17.21", "react": "^18.2.0", "react-dom": "^18.2.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c13b802..5134c2e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -5,7 +5,10 @@ specifiers: '@babel/core': ^7.20.2 '@babel/preset-env': ^7.20.2 '@babel/preset-react': ^7.18.6 + '@codemirror/commands': ^6.1.2 + '@codemirror/lang-sql': ^6.3.2 '@pmmmwh/react-refresh-webpack-plugin': ^0.5.8 + '@uiw/react-codemirror': ^4.12.4 babel-loader: ^9.1.0 copy-webpack-plugin: ^11.0.0 css-loader: ^6.7.1 @@ -21,6 +24,9 @@ specifiers: webpack-dev-server: ^4.11.1 dependencies: + '@codemirror/commands': 6.1.2 + '@codemirror/lang-sql': 6.3.2_4edla6ezzmbrt7zherv36dfe34 + '@uiw/react-codemirror': 4.12.4_kla4oh6andn33cozt3edwlrbei lodash: 4.17.21 react: 18.2.0 react-dom: 18.2.0_react@18.2.0 @@ -1241,7 +1247,6 @@ packages: engines: {node: '>=6.9.0'} dependencies: regenerator-runtime: 0.13.10 - dev: true /@babel/template/7.18.10: resolution: {integrity: sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==} @@ -1279,6 +1284,90 @@ packages: to-fast-properties: 2.0.0 dev: true + /@codemirror/autocomplete/6.3.0_7ogqid446aq55x3kbijxdvvhgq: + resolution: {integrity: sha512-4jEvh3AjJZTDKazd10J6ZsCIqaYxDMCeua5ouQxY8hlFIml+nr7le0SgBhT3SIytFBmdzPK3AUhXGuW3T79nVg==} + peerDependencies: + '@codemirror/language': ^6.0.0 + '@codemirror/state': ^6.0.0 + '@codemirror/view': ^6.0.0 + '@lezer/common': ^1.0.0 + dependencies: + '@codemirror/language': 6.3.0 + '@codemirror/state': 6.1.2 + '@codemirror/view': 6.4.1 + '@lezer/common': 1.0.1 + dev: false + + /@codemirror/commands/6.1.2: + resolution: {integrity: sha512-sO3jdX1s0pam6lIdeSJLMN3DQ6mPEbM4yLvyKkdqtmd/UDwhXA5+AwFJ89rRXm6vTeOXBsE5cAmlos/t7MJdgg==} + dependencies: + '@codemirror/language': 6.3.0 + '@codemirror/state': 6.1.2 + '@codemirror/view': 6.4.1 + '@lezer/common': 1.0.1 + dev: false + + /@codemirror/lang-sql/6.3.2_4edla6ezzmbrt7zherv36dfe34: + resolution: {integrity: sha512-lbk2jBVvVK6NkIEn6HU3RwLh368qEcGP5bknwv6kiLGffFZHNoXj/J/F/YNXSynsgswapBofb3J6yVwsjXYQPw==} + dependencies: + '@codemirror/autocomplete': 6.3.0_7ogqid446aq55x3kbijxdvvhgq + '@codemirror/language': 6.3.0 + '@codemirror/state': 6.1.2 + '@lezer/highlight': 1.1.2 + '@lezer/lr': 1.2.4 + transitivePeerDependencies: + - '@codemirror/view' + - '@lezer/common' + dev: false + + /@codemirror/language/6.3.0: + resolution: {integrity: sha512-6jOE5DEt6sKD46SXhn3xPbBehn+l48ACcA6Uxs2k+E2YNH9XGF5WdGMTYr2DlggfK4h0QZBK6zEb5S7lkTriWA==} + dependencies: + '@codemirror/state': 6.1.2 + '@codemirror/view': 6.4.1 + '@lezer/common': 1.0.1 + '@lezer/highlight': 1.1.2 + '@lezer/lr': 1.2.4 + style-mod: 4.0.0 + dev: false + + /@codemirror/lint/6.0.0: + resolution: {integrity: sha512-nUUXcJW1Xp54kNs+a1ToPLK8MadO0rMTnJB8Zk4Z8gBdrN0kqV7uvUraU/T2yqg+grDNR38Vmy/MrhQN/RgwiA==} + dependencies: + '@codemirror/state': 6.1.2 + '@codemirror/view': 6.4.1 + crelt: 1.0.5 + dev: false + + /@codemirror/search/6.2.2: + resolution: {integrity: sha512-2pWY599zXk+lSoJ2iv9EuTO4gB7lhgBPLPwFb/zTbimFH4NmZSaKzJSV51okjABZ7/Rj0DYy5klWbIgaJh2LoQ==} + dependencies: + '@codemirror/state': 6.1.2 + '@codemirror/view': 6.4.1 + crelt: 1.0.5 + dev: false + + /@codemirror/state/6.1.2: + resolution: {integrity: sha512-Mxff85Hp5va+zuj+H748KbubXjrinX/k28lj43H14T2D0+4kuvEFIEIO7hCEcvBT8ubZyIelt9yGOjj2MWOEQA==} + dev: false + + /@codemirror/theme-one-dark/6.1.0: + resolution: {integrity: sha512-AiTHtFRu8+vWT9wWUWDM+cog6ZwgivJogB1Tm/g40NIpLwph7AnmxrSzWfvJN5fBVufsuwBxecQCNmdcR5D7Aw==} + dependencies: + '@codemirror/language': 6.3.0 + '@codemirror/state': 6.1.2 + '@codemirror/view': 6.4.1 + '@lezer/highlight': 1.1.2 + dev: false + + /@codemirror/view/6.4.1: + resolution: {integrity: sha512-QdBpD6E5HYx6YFXXhqwrRyQ83w7CxWZnchM4QpWBVkkmV7/oJT8N+yz2KAi2iRaLObc/aOf7C2RCQTO2yswF8A==} + dependencies: + '@codemirror/state': 6.1.2 + style-mod: 4.0.0 + w3c-keyname: 2.2.6 + dev: false + /@discoveryjs/json-ext/0.5.7: resolution: {integrity: sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==} engines: {node: '>=10.0.0'} @@ -1333,6 +1422,22 @@ packages: resolution: {integrity: sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==} dev: true + /@lezer/common/1.0.1: + resolution: {integrity: sha512-8TR5++Q/F//tpDsLd5zkrvEX5xxeemafEaek7mUp7Y+bI8cKQXdSqhzTOBaOogETcMOVr0pT3BBPXp13477ciw==} + dev: false + + /@lezer/highlight/1.1.2: + resolution: {integrity: sha512-CAun1WR1glxG9ZdOokTZwXbcwB7PXkIEyZRUMFBVwSrhTcogWq634/ByNImrkUnQhjju6xsIaOBIxvcRJtplXQ==} + dependencies: + '@lezer/common': 1.0.1 + dev: false + + /@lezer/lr/1.2.4: + resolution: {integrity: sha512-L/52/oMJBFXXx8qBYF4UgktLP2geQ/qn5Fd8+5L/mqlLLCB9+qdKktFAtejd9FdFMaFx6lrP5rmLz4sN3Kplcg==} + dependencies: + '@lezer/common': 1.0.1 + dev: false + /@nicolo-ribaudo/chokidar-2/2.1.8-no-fsevents.3: resolution: {integrity: sha512-s88O1aVtXftvp5bCPB7WnmXc5IwOZZ7YPuwNPt+GtOOXpPvad1LfbmjYv+qII7zP6RU2QGnqve27dnLycEnyEQ==} requiresBuild: true @@ -1516,6 +1621,53 @@ packages: '@types/node': 18.11.9 dev: true + /@uiw/codemirror-extensions-basic-setup/4.12.4_agsa3mk4x2udiledv2pz7napju: + resolution: {integrity: sha512-owSCcRBtS2wYjxgBFkuIjfjWJHsR8AxgsQtqPpHB/6U0zCLuzKS/OM5ZRS2T3rdOizg0hCPztVvmshWeKjF+qw==} + peerDependencies: + '@codemirror/autocomplete': '>=6.0.0' + '@codemirror/commands': '>=6.0.0' + '@codemirror/language': '>=6.0.0' + '@codemirror/lint': '>=6.0.0' + '@codemirror/search': '>=6.0.0' + '@codemirror/state': '>=6.0.0' + '@codemirror/view': '>=6.0.0' + dependencies: + '@codemirror/autocomplete': 6.3.0_7ogqid446aq55x3kbijxdvvhgq + '@codemirror/commands': 6.1.2 + '@codemirror/language': 6.3.0 + '@codemirror/lint': 6.0.0 + '@codemirror/search': 6.2.2 + '@codemirror/state': 6.1.2 + '@codemirror/view': 6.4.1 + dev: false + + /@uiw/react-codemirror/4.12.4_kla4oh6andn33cozt3edwlrbei: + resolution: {integrity: sha512-92TAvN2z5snPjPtJDLmbqrqsXXYFYlBnWraXZuDc1XGaw80tB26ZkdEW79CD2QM4Y9LhFIt+sauwlmiAVDs/5A==} + peerDependencies: + '@babel/runtime': '>=7.11.0' + '@codemirror/state': '>=6.0.0' + '@codemirror/theme-one-dark': '>=6.0.0' + '@codemirror/view': '>=6.0.0' + codemirror: '>=6.0.0' + react: '>=16.8.0' + react-dom: '>=16.8.0' + dependencies: + '@babel/runtime': 7.20.1 + '@codemirror/commands': 6.1.2 + '@codemirror/state': 6.1.2 + '@codemirror/theme-one-dark': 6.1.0 + '@codemirror/view': 6.4.1 + '@uiw/codemirror-extensions-basic-setup': 4.12.4_agsa3mk4x2udiledv2pz7napju + codemirror: 6.0.1_@lezer+common@1.0.1 + react: 18.2.0 + react-dom: 18.2.0_react@18.2.0 + transitivePeerDependencies: + - '@codemirror/autocomplete' + - '@codemirror/language' + - '@codemirror/lint' + - '@codemirror/search' + dev: false + /@webassemblyjs/ast/1.11.1: resolution: {integrity: sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==} dependencies: @@ -1943,6 +2095,20 @@ packages: shallow-clone: 3.0.1 dev: true + /codemirror/6.0.1_@lezer+common@1.0.1: + resolution: {integrity: sha512-J8j+nZ+CdWmIeFIGXEFbFPtpiYacFMDR8GlHK3IyHQJMCaVRfGx9NT+Hxivv1ckLWPvNdZqndbr/7lVhrf/Svg==} + dependencies: + '@codemirror/autocomplete': 6.3.0_7ogqid446aq55x3kbijxdvvhgq + '@codemirror/commands': 6.1.2 + '@codemirror/language': 6.3.0 + '@codemirror/lint': 6.0.0 + '@codemirror/search': 6.2.2 + '@codemirror/state': 6.1.2 + '@codemirror/view': 6.4.1 + transitivePeerDependencies: + - '@lezer/common' + dev: false + /color-convert/1.9.3: resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} dependencies: @@ -2069,6 +2235,10 @@ packages: resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} dev: true + /crelt/1.0.5: + resolution: {integrity: sha512-+BO9wPPi+DWTDcNYhr/W90myha8ptzftZT+LwcmUbbok0rcP/fequmFYCw8NMoH7pkAZQzU78b3kYrlua5a9eA==} + dev: false + /cross-spawn/7.0.3: resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} engines: {node: '>= 8'} @@ -3320,7 +3490,6 @@ packages: /regenerator-runtime/0.13.10: resolution: {integrity: sha512-KepLsg4dU12hryUO7bp/axHAKvwGOCV0sGloQtpagJ12ai+ojVDqkeGSiRX1zlq+kjIMZ1t7gpze+26QqtdGqw==} - dev: true /regenerator-transform/0.15.0: resolution: {integrity: sha512-LsrGtPmbYg19bcPHwdtmXwbW+TqNvtY4riE3P83foeHRroMbH6/2ddFBfab3t7kbzc7v7p4wbkIecHImqt0QNg==} @@ -3675,6 +3844,10 @@ packages: webpack: 5.74.0_webpack-cli@4.10.0 dev: true + /style-mod/4.0.0: + resolution: {integrity: sha512-OPhtyEjyyN9x3nhPsu76f52yUGXiZcgvsrFVtvTkyGRQJ0XK+GPc6ov1z+lRpbeabka+MYEQxOYRnt5nF30aMw==} + dev: false + /supports-color/5.5.0: resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} engines: {node: '>=4'} @@ -3827,6 +4000,10 @@ packages: engines: {node: '>= 0.8'} dev: true + /w3c-keyname/2.2.6: + resolution: {integrity: sha512-f+fciywl1SJEniZHD6H+kUO8gOnwIr7f4ijKA6+ZvJFjeGi1r4PDLl53Ayud9O/rk64RqgoQine0feoeOU0kXg==} + dev: false + /watchpack/2.4.0: resolution: {integrity: sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==} engines: {node: '>=10.13.0'} diff --git a/src/App.css b/src/App.css index 60e8135..04306c9 100644 --- a/src/App.css +++ b/src/App.css @@ -1,4 +1,9 @@ App { - margin: 1rem; - font-family: Arial, Helvetica, sans-serif; + margin: 1rem auto; + font-family: sans-serif; +} + +.code { + font-family: 'Courier New', Courier, monospace; + white-space: pre-wrap; } @@ -1,7 +1,13 @@ import { useEffect, useState } from 'react'; -import './App.css'; import { createDbWorker } from 'sql.js-httpvfs'; import { debounce } from 'lodash'; +import Table from './Table'; +import './App.css'; + +import CodeMirror from '@uiw/react-codemirror'; +import { sql, SQLite } from '@codemirror/lang-sql'; +import { historyField } from '@codemirror/commands'; +import schema from './schema.js'; // sadly there's no good way to package workers and wasm directly so you need a way to get these two URLs from your bundler. // This is the webpack5 way to create a asset bundle of the worker and wasm: @@ -24,28 +30,34 @@ const worker = createDbWorker( const doQuery = (query, callback) => { worker.then((worker) => { - worker.db.query(query).then((results) => { - callback(results); - localStorage.setItem('query', query); - }).catch((error) => { - console.error(error); - }); + worker.db + .query(query) + .then((results) => { + callback(results); + localStorage.setItem('query', query); + }) + .catch((error) => { + // TODO: Make this a bit nicer somehow... + callback([{ error: error.toString() }]); + console.error(error); + }); }); }; -const handleKeyUp = debounce((event, callback) => { - callback(event.target.innerText); +const handleOnChange = debounce((value, callback) => { + callback(value); }, /*wait:*/ 1000); +const stateFields = { history: historyField }; + export default function App() { const [results, setResults] = useState([]); const [query, setQuery] = useState( - localStorage.getItem("query") || "SELECT first_name, last_name FROM entities WHERE call_sign = 'K9FGT'" + localStorage.getItem('query') || + "SELECT first_name as 'First Name', last_name as 'Last Name', city, state, call_sign FROM entities WHERE frn IN (SELECT frn FROM entities WHERE call_sign = 'K9FGT')" ); - useEffect(() => { - document.getElementById("query").innerText = query; - }, []); + const serializedState = localStorage.getItem('editorState'); useEffect(() => { doQuery(query, setResults); @@ -53,8 +65,34 @@ export default function App() { return ( <div className="App"> - <pre id="query" contentEditable onKeyUp={(e) => handleKeyUp(e, setQuery)}></pre> - <pre>{JSON.stringify(results)}</pre> + <CodeMirror + value={query} + initialState={ + serializedState + ? { + json: JSON.parse(serializedState || ''), + fields: stateFields, + } + : undefined + } + onChange={(value, viewUpdate) => { + localStorage.setItem('query', value); + + const state = viewUpdate.state.toJSON(stateFields); + localStorage.setItem('editorState', JSON.stringify(state)); + + handleOnChange(value, setQuery); + }} + basicSetup={{ autocompletion: true }} + extensions={[ + sql({ + dialect: SQLite, + upperCaseKeywords: true, + schema: schema, + }), + ]} + /> + <Table results={results} /> </div> ); } diff --git a/src/Table.css b/src/Table.css new file mode 100644 index 0000000..c162ae1 --- /dev/null +++ b/src/Table.css @@ -0,0 +1,23 @@ +table { + border-collapse: collapse; + margin: 25px auto; + font-size: 0.9em; + font-family: sans-serif; + min-width: 400px; + box-shadow: 0 0 20px rgba(0, 0, 0, 0.15); +} +table thead tr { + background-color: #119dc0; + color: #ffffff; + text-align: left; +} +table th, +table td { + padding: 12px 15px; +} +table tbody tr { + border-bottom: 1px solid #dddddd; +} +table tbody tr:nth-of-type(even) { + background-color: #f3f3f3; +} diff --git a/src/Table.js b/src/Table.js new file mode 100644 index 0000000..2935f0b --- /dev/null +++ b/src/Table.js @@ -0,0 +1,38 @@ +import './Table.css'; + +export default function Table({ results }) { + if (results == undefined || results.length === 0) { + return ( + <table> + <thead> + <tr> + <th>No Results</th> + </tr> + </thead> + </table> + ); + } + + return ( + <table> + <thead> + <tr> + {Object.keys(results[0]).map((column) => ( + <th key={column}>{column}</th> + ))} + </tr> + </thead> + <tbody> + {results.map((row) => { + return ( + <tr> + {Object.keys(row).map((key) => { + return <td key={key}>{row[key]}</td>; + })} + </tr> + ); + })} + </tbody> + </table> + ); +} diff --git a/src/schema.js b/src/schema.js new file mode 100644 index 0000000..8474b51 --- /dev/null +++ b/src/schema.js @@ -0,0 +1,168 @@ +const schema = { + amateurs: [ + 'record_type', + 'unique_system_identifier', + 'uls_file_number', + 'ebf_number', + 'call_sign', + 'operator_class', + 'group_code', + 'region_code', + 'trustee_call_sign', + 'trustee_indicator', + 'physician_certification', + 've_signature', + 'systematic_call_sign_change', + 'vanity_call_sign_change', + 'vainty_relationship', + 'previous_call_sign', + 'previous_operator_class', + 'trustee_name', + ], + comments: [ + 'record_type', + 'unique_system_identifier', + 'uls_file_number', + 'call_sign', + 'comment_date', + 'description', + 'status_code', + 'status_date', + ], + entities: [ + 'record_type', + 'unique_system_identifier', + 'uls_file_number', + 'ebf_number', + 'call_sign', + 'entity_type', + 'licensee_id', + 'entity_name', + 'first_name', + 'mi', + 'last_name', + 'suffix', + 'phone', + 'fax', + 'email', + 'street_address', + 'city', + 'state', + 'zip_code', + 'po_box', + 'attention_line', + 'sgin', + 'frn', + 'applicant_type_code', + 'applicant_type_other', + 'status_code', + 'status_date', + 'lic_category_code', + 'linked_license_id', + 'linked_callsign', + ], + headers: [ + 'record_type', + 'unique_system_identifier', + 'uls_file_number', + 'ebf_number', + 'call_sign', + 'license_status', + 'radio_service_code', + 'grant_date', + 'expired_date', + 'cancellation_date', + 'eligibility_rule_number', + 'reserved', + 'alien', + 'alien_government', + 'alien_corporation', + 'alien_officer', + 'alien_control', + 'revoked', + 'convicted', + 'adjudged', + 'reserved2', + 'common_carrier', + 'non_common_carrier', + 'private_comm', + 'fixed', + 'mobile', + 'radiolocation', + 'satellite', + 'developmental_or_sta', + 'interconnected_service', + 'certifier_first_name', + 'certifier_mi', + 'certifier_last_name', + 'certifier_suffix', + 'certifier_title', + 'gender', + 'african_american', + 'native_american', + 'hawaiian', + 'asian', + 'white', + 'ethnicity', + 'effective_date', + 'last_action_date', + 'auction_id', + 'reg_stat_broad_serv', + 'band_manager', + 'type_serv_broad_serv', + 'alien_ruling', + 'licensee_name_change', + 'whitespace_ind', + 'additional_cert_choice', + 'additional_cert_answer', + 'discontinuation_ind', + 'regulatory_compliance_ind', + 'eligibility_cert_900', + 'transition_plan_cert_900', + 'return_spectrum_cert_900', + 'payment_cert_900', + ], + history: [ + 'record_type', + 'unique_system_identifier', + 'uls_file_number', + 'call_sign', + 'log_date', + 'code', + ], + license_attachments: [ + 'record_type', + 'unique_system_identifier', + 'call_sign', + 'attachment_code', + 'attachment_description', + 'attachment_date', + 'attachment_file_name', + 'action_performed', + ], + special_conditions: [ + 'record_type', + 'unique_system_identifier', + 'uls_file_number', + 'ebf_number', + 'call_sign', + 'special_conditions_type', + 'special_conditions_code', + 'status_code', + 'status_date', + ], + special_conditions_free_form: [ + 'record_type', + 'unique_system_identifier', + 'uls_file_number', + 'ebf_number', + 'call_sign', + 'license_free_form_type', + 'unique_license_free_form_identifier', + 'sequence_number', + 'license_free_form_condition', + 'status_code', + 'status_date', + ], +}; +export default schema; |