Browse Source

metaplate checks: looks like it works

asmer 3 months ago
parent
commit
9c457dab19
3 changed files with 256 additions and 12 deletions
  1. 12 12
      src/App.tsx
  2. 43 0
      src/lib/metaplate/index.tsx
  3. 201 0
      src/test/metaplate.jsx

+ 12 - 12
src/App.tsx

@@ -130,18 +130,18 @@ const Goods = ({children}) =>
 
 const PageCategory = ({data}) => 
     <MetaPlate data={data.payload.data.CategoryFindOne}>
-            <Category prop="category" keyDataKey="_id">
-                <Goods sourceDataKey="goods"> 
-                    <Good prop="good" keyDataKey="_id">
-                        <div sourceDataKey="images">
-                            <Image prop="src" sourceDataKey="url"/>
-                        </div>
-                    </Good>
-                </Goods>
-                <Categories sourceDataKey="subCategories" prop='data'>
-                    <Category prop="category" keyDataKey="_id" />
-                </Categories>
-            </Category>
+        <Category prop="category" keyDataKey="_id">
+            <Goods sourceDataKey="goods"> 
+                <Good prop="good" keyDataKey="_id">
+                    <div sourceDataKey="images">
+                        <Image prop="src" sourceDataKey="url"/>
+                    </div>
+                </Good>
+            </Goods>
+            <Categories sourceDataKey="subCategories" prop='data'>
+                <Category prop="category" keyDataKey="_id" />
+            </Categories>
+        </Category>
     </MetaPlate> 
 
 const LeftMenuItem = ({category:{_id,name}})=>

+ 43 - 0
src/lib/metaplate/index.tsx

@@ -0,0 +1,43 @@
+import React, {Fragment} from 'react';
+
+const MetaPlate = ({ data, children }) => {
+    //console.log(children, data)
+    const buildProps = (data, {props:{prop, keyDataKey, sourceDataKey}}) =>  {
+        let result = {}
+        result[prop || 'children'] = data
+        result.key = data && data[keyDataKey] || sourceDataKey
+
+        return result
+    }
+
+    const build = (data, meta) => {
+        if (!meta) return <></>;
+
+        if (data instanceof Array){ //Array of data - container component
+            if (meta instanceof Array) meta = meta[0];
+            const Render = meta.type
+            const {key, ...props} = buildProps(data, meta)
+            return  (<Render key={key} {...props}>
+                     {data.map(d => build(d, meta.props.children))}
+                     </Render>
+                    )
+        }
+        else if (data instanceof Object){ //object
+            if (!(meta instanceof Array)) meta = [meta]
+
+                return meta.map(m => {
+                    const Render = m.type
+                    const {sourceDataKey}  = m.props
+                    const d = sourceDataKey ? data[sourceDataKey] : data
+                    const {key, ...props} = buildProps(d, m)
+
+                    if (!d) return <Fragment key={key} />
+                    if (d instanceof Array) return build(d, m)
+                        return <Render children={build(d, m.props.children)} key={key} {...props}/>
+                })
+        }
+    }
+    return <React.Fragment>{build(data, children)}</React.Fragment>
+}
+
+export default MetaPlate;

+ 201 - 0
src/test/metaplate.jsx

@@ -0,0 +1,201 @@
+import { useState, useEffect, Fragment } from 'react'
+import './App.css'
+import {createBrowserHistory} from 'history';
+import {Router, Link} from 'react-router-dom'
+import {createQueryPub, NamedRoute, NamedLink} from './lib';
+import {MetaPlate} from './lib';
+
+
+const history = createBrowserHistory()
+
+const token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOnsiaWQiOiI2NjdmZjBkYTIyMzIxMjBjN2M4NzFmN2MiLCJsb2dpbiI6InRzdDE5IiwiYWNsIjpbIjY2N2ZmMGRhMjIzMjEyMGM3Yzg3MWY3YyIsInVzZXIiXX0sImlhdCI6MTcyMDI1OTEwN30.eDcInxQlskt32LjaCe5sdCcJ3B97BKYZtgUARxThYQM'
+
+console.log(JSON.parse(atob(token.split('.')[1])).sub.id)
+
+const shopUrl = 'http://shop-roles.node.ed.asmer.org.ua/'
+
+const gql = (query, variables={}) => 
+    fetch(shopUrl + 'graphql',{
+        method: 'POST',
+        headers: {
+            'Content-Type': 'application/json',
+            Accept: 'application/json',
+            Authorization: 'Bearer ' + token
+        },
+        body: JSON.stringify({query, variables})
+    }).then(res => res.json())
+
+const {queryPub, createQuery, withQueryFunc} = createQueryPub({
+    queryFunc: gql,
+    cacheTimeout: 500000,
+})
+
+const {useCategoriesQuery} = createQuery({
+    promiseName: 'categories',
+    args: [`query MainCategories{
+              CategoryFind(query: "[{}]"){
+                _id name
+                  image{
+                    url
+                  }
+                goods{
+                _id
+                name description price images{
+                  url
+                }
+              }
+              subCategories{ name _id}
+            }
+        }
+    `]
+})
+
+const {useMainCategoriesQuery} = createQuery({
+    promiseName: 'mainCategories',
+    args: [`query MainCategories{
+              CategoryFind(query: "[{\\"parent\\":null}]"){
+                _id name
+                  image{
+                    url
+                  }
+                goods{
+                _id
+                name description price images{
+                  url
+                }
+              }
+              subCategories{ name _id}
+            }
+        }
+    `]
+})
+
+
+const {query: categoryQuery} = createQuery({
+    promiseName: 'category',
+    args: ({_id}) => [`query categoryById($query:String){
+              CategoryFindOne(query: $query){
+                _id name
+                  image{
+                    url
+                  }
+                goods{
+                _id
+                name description price images{
+                  url
+                }
+              }
+              subCategories{ name _id}
+            }
+        }
+    `, {query: JSON.stringify([{_id}])}]
+})
+
+
+//queryPub.subscribe(() => console.log(JSON.stringify(queryPub.queries.user, null, 4)))
+//
+
+
+
+const Image = ({src}) => <img src={`${shopUrl}${src}`} style={{maxWidth: '50%'}}/>
+
+const Good = ({good, children}) =>
+good ? 
+<div className='Good'>
+    <h2>{good.name}</h2>
+    <p>{good.description}</p>
+    <money>{good.price}</money>
+    {children}
+</div>
+: <h3>null</h3>
+
+const Category = ({category:{name, _id}, children}) =>
+<div className='Category'>
+    <h1>{name}</h1>
+    {_id}
+    {children}
+</div>
+
+const Categories = ({children, data}) => 
+<div style={{border: '2px solid', paddingLeft: '20px'}}>
+    <h1>categories({data && data.length})</h1>
+    {children}
+</div>
+
+const Goods = ({children}) => 
+<div style={{border: '2px solid blue', paddingLeft: '10px'}}>
+    <h2>goods</h2>
+    {children}
+</div>
+
+const PageCategory = ({data}) => 
+    <MetaPlate data={data.payload.data.CategoryFindOne}>
+        <Category prop="category" keyDataKey="_id">
+            <Goods sourceDataKey="goods"> 
+                <Good prop="good" keyDataKey="_id">
+                    <div sourceDataKey="images">
+                        <Image prop="src" sourceDataKey="url"/>
+                    </div>
+                </Good>
+            </Goods>
+            <Categories sourceDataKey="subCategories" prop='data'>
+                <Category prop="category" keyDataKey="_id" />
+            </Categories>
+        </Category>
+    </MetaPlate> 
+
+const LeftMenuItem = ({category:{_id,name}})=>
+//<li><NamedLink name='category' params={{_id}}>{name}</NamedLink></li>
+<li><Link  to={`/category/${_id}`}>{name}</Link></li>
+
+const LeftMenu = () => {
+    const {payload} = useMainCategoriesQuery()
+    return (
+        <ul>
+            {payload && 
+                <MetaPlate data={payload.data.CategoryFind}>
+                    <Fragment>
+                        <LeftMenuItem prop="category" keyDataKey="_id"/>
+                    </Fragment>
+                </MetaPlate>}
+        </ul>
+    )
+}
+
+function App() {
+    //const {payload} = useCategoriesQuery()
+    //console.log('update', performance.now())
+    //useEffect(() => console.log('effect',performance.now()), [payload])
+    return (
+        <Router history={history}>
+
+            <LeftMenu />
+            <NamedRoute name="category" 
+                query={categoryQuery}
+                path="/category/:_id" 
+                component={PageCategory}/>
+
+
+
+            {/*payload && 
+            <MetaPlate data={payload.data.CategoryFind}>
+                <Categories prop='data'>
+                    <Category prop="category" keyDataKey="_id">
+                        <Goods sourceDataKey="goods"> 
+                            <Good prop="good" keyDataKey="_id">
+                                <div sourceDataKey="images">
+                                    <Image prop="src" sourceDataKey="url"/>
+                                </div>
+                            </Good>
+                        </Goods>
+                        <Categories sourceDataKey="subCategories" prop='data'>
+                            <Category prop="category" keyDataKey="_id" />
+                        </Categories>
+                    </Category>
+                </Categories>
+            </MetaPlate> */ }
+        </Router>
+    )
+}
+
+export default App