import React, {useState, useEffect, useMemo, useRef, Fragment} from 'react';
import logo from './logo.svg';
import './App.css';
import Select from 'react-select/async'
import {sortableContainer, sortableElement} from 'react-sortable-hoc';
import Dropzone from 'react-dropzone'
import { GraphQLClient } from 'graphql-request';
import createModels2 from './front-models'
let gql;
const getGQL = () => new GraphQLClient(localStorage.url + 'graphql', {headers: localStorage.authToken ? {Authorization: 'Bearer '+localStorage.authToken} : {}})
if (localStorage.authToken && localStorage.url){
gql = getGQL()
}
const ShortName = ({record, options}) => {
if (record && record.constructor)
if (options.view.relations[record.constructor.name]){
const Formatter = options.view.relations[record.constructor.name]
return {record}
}
return (<>{record && (record.name || record.key || record.login || record.originalFileName || record._id)}>)
}
const EditFormRow = ({field, models={}, value, options=defaultAdminOptions, record, onChange}) => {
return (
{field.name} |
{value} | |
)
}
const EditForm = ({record, models={}, model, options=defaultAdminOptions, Components:{EditFormRow:EFR}={EditFormRow}}) => {
const [edit, setEdit] = useState({...record})
if (!record) return <>>
if (!record.save || !record._id){
Object.assign(record, edit)
}
const fields = model.fields
const onlyInputs = model.inputs.filter(input => !fields.find(field => field.name === input.name))
return (
<>
{Object.entries(fields).map(([key,field]) => {
setEdit({...edit, [field.name]: event && event.target ? event.target.value : event})
}}
/>)}
{Object.entries(onlyInputs).map(([key,field]) => setEdit({...edit, [field.name]: event && event.target ? event.target.value : event})}
/>)}
{record._id && record.save &&
}
>
)
}
const Row = ({top, selected, children}) => {
console.log('row')
return (
<>
{children}
>
)
}
const Cell = ({children, options, record, field, selected, model, models={}, onClick, ...props}) => {
let Formatter = React.Fragment
const type = (children && typeof children === 'object' && children.constructor) || model
const viewOrEdit = (!record.constructor.inputs || record.constructor.inputs.some(input => input.name === field.name)) && selected ? 'edit' : 'view'
const typeName = field.type.name || field.type.ofType.name
if (typeName in options[viewOrEdit].formatters){
Formatter = options[viewOrEdit].formatters[typeName]
}
if (field.name in options[viewOrEdit].fields){
Formatter = options[viewOrEdit].fields[field.name]
}
if (type){
if (type.name in options[viewOrEdit].formatters)
Formatter = options[viewOrEdit].formatters[type.name]
else
Formatter = options[viewOrEdit].formatters.Object
}
return(
{Formatter === React.Fragment ? (children && children.toString()) : children}
)
}
const ModelListItem = "div"
const ModelList = ({models, selected, onChange, Item=ModelListItem}) => {
return (
)
}
const Search = ({...props}) =>
const Count = ({...props}) =>
const searchQueryBuilder = (search, model) => {
if (!search) return {}
const queryRegexp = `/${search.trim().split(/\s+/).join('|')}/`
return {$or: model.fields.filter(field => field.type.kind == 'SCALAR').map(field => ({[field.name]: queryRegexp}))}
}
const GridHeaderItem = ({field, sort:[sort], ...props}) =>
{field.name in sort && sort[field.name] === -1 && '^ '}
{field.name}
{field.name in sort && sort[field.name] === 1 && ' v'}
const GridHeader = ({fields, sort, onSort}) =>
{fields.map(field => onSort(field.name)}/>)}
const getModelByField = (field, models={}) => {
if (field.type.kind === 'OBJECT') {
return models[field.type.name]
}
if (field.type.kind === 'LIST') return models[field.type.ofType.name]
}
const VirtualScroll = ({options, gridHeight, count, rowHeight, onScroll, records, skip, models={}}) => {
const limit = gridHeight/rowHeight
//const {Row, Cell} = Components
const [edit, setEdit] = useState({field: null, record: null})
useEffect(() => setEdit({field: null, record: null}), [records])
const fields = records && records[0] && records[0].constructor.fields
//console.log(Fragment, Row)
return (
<>
{records && records.map((record,i) =>
{edit.record && edit.record._id === record._id ? :
{fields.map(field =>
setEdit({record: {...record}, field})}>
{record[field.name]}
| )}
}
)}
>
)
}
const ModelView = ({model, models={}, options, components:Components={Search, Count, GridHeader, Grid:VirtualScroll}, rowHeight=150, gridHeight=500, overload=2}) => {
const [records, setRecords] = useState([])
const [search, setSearch] = useState("")
const [count, setCount] = useState(0)
const [query, setQuery] = useState({})
const [cursorCalls, setCursorCalls] = useState({sort:[{}], skip: [0]/*, limit: [gridHeight/rowHeight]*/})
const skip = cursorCalls.skip[0]
console.log(cursorCalls)
useEffect(() => {
model.count(query, cursorCalls).then(count => setCount(count))
model.find(query, cursorCalls).then(records => Promise.all(records)).then(records => setRecords(records))
}, [query, model, cursorCalls])
const timeout = useRef(0)
useEffect(() => {
clearInterval(timeout.current)
if (!search)
setQuery(searchQueryBuilder(search, model))
else {
timeout.current = setTimeout(() => {
setQuery(searchQueryBuilder(search, model))
},1000)
}
},[search, model])
//console.log(Components)
//
const Add = options.add[model.name] || "button"
return (
<>
setSearch(value)}/>
{count}
setCursorCalls({...cursorCalls,
sort: [{[sort]: cursorCalls.sort[0][sort] === 1 ? -1 : 1}]
})}/>
{
if (Add === 'button') (new model).save()
setCursorCalls({...cursorCalls, sort: [{_id: -1}]})
setSearch('')
}} model={model}>+
{records && {
limit = undefined;
model.find(query, {...cursorCalls, limit: [limit], skip: [skip]}).then(records => Promise.all(records)).then(records => setRecords(records)).then(() =>
setCursorCalls({...cursorCalls, limit: [limit], skip: [skip]}))
}}/> }
>
)
}
const ObjectShortView = ({children, options}) => {
const [record, setRecord] = useState(children)
if (!children) return <>>
if (typeof children === 'object' && 'then' in children){
children.then(child => setRecord({...child}))
}
if (typeof children === 'object' && children._id){
return (
)
}
else {
return (
{JSON.stringify(record, null, 4)}
)
}
}
const ForeignAutocomplete = ({models={}, children:value, onChange, model, options={}}) => {
return (