Haike List – Level 1 and Level 2 Permission Increase – react-mongoose-react-redux

//backend
const mongoose = require('mongoose')
mongoose.set('strictQuery',true)

mongoose.connect('mongodb://127.0.0.1:27017/db_zg4yk')

conn=mongoose.connection
conn.on('open',()=>{<!-- -->
    console.log('Database connection succeeded')
})

conn.on('error',err=>{<!-- -->
    console.log('Database connection failed')
})

module.exports=mongoose

//model.js
const mongoose = require('./db')

const Schema = mongoose.Schema

const listScheam=new Schema({<!-- -->
    name: String,
    form:Array,
    browse:Number,
    sort:Number,
    isshow: Boolean,
    date: Date,
    children: Array,
  
},{<!-- -->versionKey:false})

let listModel = mongoose. model('list', listScheam, 'list')

module.exports={<!-- -->
    listModel,

}
//router.js
var express = require('express');
var router = express. Router();
var jwt = require('jsonwebtoken')
var multiparty = require('multiparty')
var {<!-- --> listModel} = require('../model/model')

router.get('/list', async function(req, res) {<!-- -->
  let list = await listModel. find()
  res.send({<!-- -->
    code:200,
    data: list,
  });
});
router. post('/Addchildren', async function(req, res) {<!-- -->
  let data = req. body
  console. log(data);
  let da = await listModel. find({<!-- -->_id:data._id})
  da[0].children.push(data.children)
  await listModel.updateOne({<!-- -->_id:data._id},{<!-- -->children:da[0].children})
  res.send({<!-- -->
    code:200,
  });
});
router. post('/add', async function(req, res) {<!-- -->
  let data = req.body
  await listModel.create({<!-- -->
    name: data. title,
    form:data.list,
    browse:0,
    sort:255,
    isshow:true,
    date:new Date().toISOString(),
    children:[],
})
  console. log(data);
  res.send({<!-- -->
    code:200,
  });
});
module.exports = router;

//front end
//index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import './index.css'
import {<!-- -->BrowserRouter as Router} from 'react-router-dom'
import {<!-- --> Provider } from 'react-redux'
import store from './store/counterSlice'

const root = ReactDOM.createRoot(document.getElementById('root'));
root. render(
  <>
  <Provider store={<!-- -->store}>
    <Router>
      <App />
    </Router>
  </Provider>
  </>
);

//index.css
*{<!-- -->
    margin: 0;
    padding: 0;
}

html,body,#root{<!-- -->
    height: 100%;
}

.list{<!-- -->
    margin: 10px;
    padding: 5px;
    background-color: #fff;
}
.row1,.row6{<!-- -->
    display: inline-block;
    width: 180px;
    font-size: 18px;
    font-weight: 500;
}
.row2,.row3,.row4,.row5{<!-- -->
    display: inline-block;
    width: 150px;
    font-size: 18px;
    font-weight: 500;
}
.row7{<!-- -->
    display: inline-block;
    width: 200px;
    font-size: 18px;
    font-weight: 500;
}
//router.js
import Add from "./components/Add"
import Home from "./components/Home"
import List from "./components/List"

const routes=[
    {<!-- -->
        path:'/',
        element:<Home></Home>,
        children:[
            {<!-- -->
                path:'/',
                element:<List></List>
            },
            {<!-- -->
                path:'/add',
                element:<Add></Add>
            }
        ]
    },
        
]

export default routes

//App.js
import React from 'react'

import {<!-- --> useRoutes } from 'react-router-dom'
import routes from './router'

export default function App(props) {<!-- -->
  return (
    <div>
        {<!-- -->useRoutes(routes)}
    </div>
  )
}
//Parent component Home.js
import {<!-- --> FileOutlined, PieChartOutlined, UserOutlined,DesktopOutlined,TeamOutlined } from '@ant-design/icons';
import {<!-- --> Layout, Menu, theme } from 'antd';
import {<!-- --> useState } from 'react';
import {<!-- --> Outlet ,useNavigate} from 'react-router-dom';
import {<!-- --> Input, Button } from 'antd';


export default function Home () {<!-- -->
  const navigate = useNavigate();
  const {<!-- --> Header, Content, Footer, Sider } = Layout;
  function getItem(label, key, icon, children) {<!-- -->
    return {<!-- -->
      key,
      icon,
      children,
      label,
    };
  }
  const items = [
    getItem('Home', '1', <PieChartOutlined onClick={<!-- -->()=>navigate('/')}/>),
    getItem('Form management', 'sub1', <UserOutlined />, [
      getItem('Form List', '3',<UserOutlined onClick={<!-- -->()=>navigate('/')}/>),
      getItem('Form Add', '4',<UserOutlined onClick={<!-- -->()=>navigate('/add')}/>),
    ]),
    
  ];

  
  const [collapsed, setCollapsed] = useState(false);
  const {<!-- -->
    token: {<!-- --> colorBgContainer },
  } = theme. useToken();

  const {<!-- --> Search } = Input;
  const onSearch = (value) => console. log(value);


  return (
    <Layout
      style={<!-- -->{<!-- -->
        minHeight: '100vh',
        
      }}
    >
      <Sider collapsible collapsed={<!-- -->collapsed} style={<!-- -->{<!-- -->background: '#fff',}} onCollapse={<!-- - ->(value) => setCollapsed(value)}>
        <div
          style={<!-- -->{<!-- -->
            height: 32,
            margin: 16,
            textAlign:'center',
          }}
        >
            Haike form
        </div>
        <Menu theme="light" defaultSelectedKeys={<!-- -->['1']} mode="inline" items={<!-- -->items} />
      </Sider>
      <Layout className="site-layout">
        <Header
          style={<!-- -->{<!-- -->
            padding: 0,
            background: colorBgContainer,
          }}
        />
        <Content
          style={<!-- -->{<!-- -->
            margin: '0 16px',
            background:'#f4f9fc',
          }}
        >
          
          <Outlet></Outlet>
        </Content>
        <Footer
          style={<!-- -->{<!-- -->
            textAlign: 'center',
          }}
        >
          Ant Design ?2023 Created by Ant UED
        </Footer>
      </Layout>
    </Layout>
  );
};

//List.js
import React from 'react'
import {<!-- --> useState,useEffect } from 'react';
import {<!-- --> fetchList,Addchildren } from '../store/counterSlice';
import {<!-- --> useSelector,useDispatch } from 'react-redux'
import {<!-- --> useNavigate } from 'react-router-dom'
import {<!-- --> Input, Button ,Form} from 'antd';
import {<!-- -->FolderOutlined,ProfileOutlined,AppstoreOutlined} from '@ant-design/icons';
import {<!-- --> Switch ,Drawer} from 'antd';
export default function List() {<!-- -->
  const navigate = useNavigate()
  const dispatch = useDispatch();
  const state = useSelector(state=>state)
  console.log(state,'state');
  useEffect(() => {<!-- -->
    dispatch(fetchList())
  }, []);

  const [form] = Form. useForm();

  // control style
  const [style, setstyle] = useState(true)
  //Switch
  const onChange = (checked) => {<!-- -->
    console.log(`switch to ${<!-- -->checked}`);
  };
  //install item
  let [_id,setId]=useState([])
  // control drawer
  const [open, setOpen] = useState(false)
  //The component form of the item
  let [yulan,setYulan] = useState([])
  //Click to preview whether to display the form
  function isShowForm(item){<!-- -->
    setId(item)
    setYulan(item. form)
    setOpen(true)
  }

  const onFinish = (values) => {<!-- -->
    console.log(values,'finish');//{tel:'18932742964,nickname:'giaogiao'}
    dispatch(Addchildren({<!-- -->_id:_id._id,children:values}))
    setId([])
    setOpen(false)
    dispatch(fetchList())
  };
  

  // search
  const {<!-- --> Search } = Input;
  const onSearch = (value) => console. log(value);
  return (
    <div>
      {<!-- -->/* top search section */}
      <div style={<!-- -->{<!-- -->height:'90px',padding:'28px 20px'}}>
            <ProfileOutlined style={<!-- -->{<!-- -->fontSize:'25px'}} onClick={<!-- -->()=>setstyle(true)}/>
            <AppstoreOutlined style={<!-- -->{<!-- -->fontSize:'25px',marginLeft:'10px'}} onClick={<!-- -->()=>setstyle(false )}/>
            <Search
                placeholder="input search text"
                onSearch={<!-- -->onSearch}
                style={<!-- -->{<!-- -->
                    width: 200,
                    marginLeft: 10,
                }}
            />
            <Button type="primary" style={<!-- -->{<!-- -->marginLeft:10,}} onClick={<!-- -->()=>navigate('/add ')}> + New Form</Button>
            <Button style={<!-- -->{<!-- -->marginLeft:10,}}><FolderOutlined />Create a new directory</Button>
      </div>
      {<!-- -->/* table part */}
      <div
        style={<!-- -->{<!-- -->
          padding: 24,
          minHeight: 360,
          background: '#fff',
        }}
      >
            <div className="list" style={<!-- -->{<!-- -->margin: '10px',padding: '5px'}}>
              <span className='row1'>Form Name</span>
              <span className='row2'>Number of submissions</span>
              <span className='row3'>Views</span>
              <span className='row4'>sort</span>
              <span className='row5'>Whether to display</span>
              <span className='row6'>Date Added</span>
              <span className='row7'>Operation</span>
            </div>
            {<!-- -->style?(
              <>
                {<!-- -->
                  state.list.map(item=>(
                    <div className="list" style={<!-- -->{<!-- -->margin: '10px',padding: '5px'}}>
                      <span className='row1'>{<!-- -->item.name}</span>
                      <span className='row2'>{<!-- -->item.children.length}</span>
                      <span className='row3'>{<!-- -->item.browse}</span>
                      <span className='row4'>{<!-- -->item.sort}</span>
                      <span className='row5'>
                        <Switch defaultChecked={<!-- -->item.isshow} onChange={<!-- -->onChange} />
                      </span>
                      <span className='row6'>
                        {<!-- -->new Date(item.date).toLocaleString()}
                      </span>
                      <span className='row7'>
                        <span style={<!-- -->{<!-- -->color:'blue'}} >Edit</span> & amp;nbsp; & amp;nbsp; & amp;nbsp; & amp ;nbsp;
                        <span style={<!-- -->{<!-- -->color:'blue'}} >Set</span> & amp;nbsp; & amp;nbsp; & amp;nbsp; & amp ;nbsp;
                        <span style={<!-- -->{<!-- -->color:'blue'}} onClick={<!-- -->()=>{<!-- -->isShowForm (item)}} >Preview</span> &nbsp; &nbsp; &nbsp; &nbsp;
                        <span style={<!-- -->{<!-- -->color:'blue'}} >...</span>
                      </span>
                    </div>
                  ))
                }
              </>
            ):(
              <div style={<!-- -->{<!-- -->display:'flex',flexWrap:'wrap'}}>
                {<!-- -->
                  state.list.map(item=>(
                   <div style={<!-- -->{<!-- -->border:'1px solid',margin:'10px',width:'150px',height:'150px',textAlign:'center' }} key={<!-- -->item._id}>
                      <div style={<!-- -->{<!-- -->marginTop:'30px'}}>{<!-- -->item.name}</div>
                      <div style={<!-- -->{<!-- -->marginTop:'30px'}}>{<!-- -->item.children.length} submitted data</div>
                   </div>
                  ))
                }
              </div>
            )}

      <Drawer title="Submit information" placement="right" onClose={<!-- -->()=>setOpen(false)} open={<!-- -->open}>
        <Form
         
          form={<!-- -->form}
          name="control-hooks"
          onFinish={<!-- -->onFinish}
          style={<!-- -->{<!-- -->
            maxWidth: 600,
          }}
        >
          {<!-- -->
            yulan.map((item,index)=>(
              <Form.Item
              rules={<!-- -->[{<!-- --> required: item.ischecked, message: 'Please input your username!' }]}
              label={<!-- -->item.ischecked?<><span style={<!-- -->{<!-- -->color:'red'}}>*</span>{ <!-- -->item.title2}</>:item.title2} name={<!-- -->item.title2}
              >
                <Input placeholder={<!-- -->item.tip}/>
              </Form.Item>
            ))
          }
          <Form.Item>
            <Button type="primary" htmlType="submit">Submit</Button>
          </Form.Item>

        </Form>
      </Drawer>
            
      </div>
    </div>
  )
}

//Add.js
import React, {<!-- --> useEffect, useState } from 'react'
import {<!-- --> useNavigate } from 'react-router-dom'
import {<!-- --> useDispatch } from 'react-redux';
import {<!-- --> AddList } from '../store/counterSlice';
import {<!-- --> Layout, Space,Button,Input,Switch,Menu,message } from 'antd';
import {<!-- -->PhoneOutlined,FormOutlined,SearchOutlined,LineHeightOutlined} from '@ant-design/icons';

export default function Add() {<!-- -->
  const {<!-- --> Header, Footer, Sider, Content } = Layout;
  const navigate = useNavigate()
  const dispatch = useDispatch();
  let [title2,setTitle2]=useState('') //Mobile nickname title
  let [tip,setTip]=useState('Please enter') //phone nickname input
  const [list,setList]=useState([]) // put the array of components
  let [children,setchildren] = useState([])
  let [index,setIndex]=useState(0) //component subscript
  const [rightShow,setRightShow]=useState(false) //Control the display of the right component properties
  const [checked,setChecked]=useState(false) //control is visible
  const [formShow,setFormShow]=useState(false) //Control form properties are visible
  let [title,setTitle]=useState('') //input
  const {<!-- --> TextArea } = Input;
  let [value, setValue] = useState(''); //textarea
  const items=[
    {<!-- -->
      label: 'Component properties',
      key: 'com',
    },
    {<!-- -->
      label: 'form attribute',
      key: 'form',
    },
  ]
  const [current, setCurrent] = useState('com');
  //submit
  function sub(){<!-- -->
    if(title==''){<!-- -->
      message.warning('Please enter the title of the form')
    }else{<!-- -->
      list.forEach(item=>{<!-- -->
        children.push({<!-- -->
          title2: item.props.children[1].props.children,
          tip: item.props.children[2].props.value,
          is checked: checked
        })
        console.log(children,'ischecked');
      })

      let data={<!-- -->title:title,list:children}
      dispatch(AddList(data)).then(()=>{<!-- -->
        navigate('/')
      })
    }
  }
  function pre(){<!-- -->
    console. log(2);
  }
  function del(){<!-- -->
    console. log(3);
  }

  function addCom(name){<!-- -->
    console. log(name);
    setIndex(list. length)
    title2=name
    setTitle2(name)

    let html=
    <>
      <span style={<!-- -->{<!-- -->color:'red',display:'inline-block',width:'10px'}}>{<!-- --> false?'*':''}{<!-- -->false}</span>
      <span>{<!-- -->title2}</span>
      <Input style={<!-- -->{<!-- -->marginTop:'10px'}} value={<!-- -->tip} />
    </>
    let newList=[...list,html]
    setList(newList)
  }

  //Click to pass the component to the right
  function getCom(index,item){<!-- -->
    setRightShow(true)
    setIndex(index)
    console.log(item,'component item');
    console.log(index,'index');
    setChecked(item. props. children[0]. props. children[1])
    setTitle2(item.props.children[1].props.children)
    setTip(item.props.children[2].props.value)

  }
  //Component property modification component
  function setComState(val,name){<!-- -->
    //Find the component from the component list and replace the component again
    let html=list[index]
    if(name=='title'){<!-- -->
      setTitle2(val)
      html=<>
      <span style={<!-- -->{<!-- -->color:'red',display:'inline-block',width:'10px'}}>{<!-- --> checked?'*':''}</span>
      <span>{<!-- -->val}</span>
      <Input style={<!-- -->{<!-- -->marginTop:'10px'}} value={<!-- -->tip} />
    </>
    }
    
    if(name=='tip'){<!-- -->
      setTip(val)
      html=<>
      <span style={<!-- -->{<!-- -->color:'red',display:'inline-block',width:'10px'}}>{<!-- --> checked?'*':''}</span>
      <span>{<!-- -->title2}</span>
      <Input style={<!-- -->{<!-- -->marginTop:'10px'}} value={<!-- -->val} />
    </>
    }

    if(name=='checked'){<!-- -->
      setChecked(val)
      html=<>
      <span style={<!-- -->{<!-- -->color:'red',display:'inline-block',width:'10px'}}>{<!-- --> val?'*':''}</span>
      <span>{<!-- -->title2}</span>
      <Input style={<!-- -->{<!-- -->marginTop:'10px'}} value={<!-- -->tip} />
      </>
    }
    list.splice(index,1,html)
  }
  

  const onClick = (e) => {<!-- --> //menu
    console.log('click', e);
    setCurrent(e.key);
  };
  
  return (
    <>
      <div style={<!-- -->{<!-- -->marginTop:'20px'}}>
        <span style={<!-- -->{<!-- -->marginLeft:'680px',color:'blue'}} onClick={<!-- -->sub}>submit</span >
        <span style={<!-- -->{<!-- -->marginLeft:'20px',color:'blue'}} onClick={<!-- -->pre}>Preview</span >
        <span style={<!-- -->{<!-- -->marginLeft:'20px',color:'red'}} onClick={<!-- -->del}>Clear</span >
      </div>
      <Space>
        <Layout>
          {<!-- -->/* component area */}
          <Sider width={<!-- -->'300px'} style={<!-- -->{<!-- -->color:'black',background:'#f4f9fc',paddingLeft:' 50px'}}>
            <div>
              <div>Special component</div>
              <Space style={<!-- -->{<!-- -->marginTop:'20px'}} wrap>
                <Button onClick={<!-- -->()=>addCom('phone number')}><PhoneOutlined />phone number</Button>
                <Button onClick={<!-- -->()=>addCom('nickname')}><FormOutlined />nickname</Button>
              </Space>
            </div>
          </Sider>
          {<!-- -->/* form field */}
          <Sider width={<!-- -->'600px'} style={<!-- -->{<!-- -->color:'black',background:'#f4f9fc',width:' 500px', padding:'10px 30px'}}>
            <div>
              form title
              <Input prefix={<!-- --><SearchOutlined />} style={<!-- -->{<!-- -->marginTop:'10px'}}
                placeholder="Please enter the title of the form"
                value={<!-- -->title}
                onChange={<!-- -->(e)=>setTitle(e.target.value)}
              />
            </div>
            <div style={<!-- -->{<!-- -->marginTop:'20px',border:'1px solid #d4dbde',background:'#ffffff'}}>
                <div style={<!-- -->{<!-- -->borderBottom:'1px solid #d4dbde',display:'flex',flexWrap:'wrap'}}>
                  <LineHeightOutlined style={<!-- -->{<!-- -->margin:'5px 10px'}} />
                </div>
                <TextArea
                  style={<!-- -->{<!-- -->border:'none'}}
                  value={<!-- -->value}
                  onChange={<!-- -->(e) => setValue(e.target.value)}
                  placeholder="Please enter the text"
                  autoSize={<!-- -->{<!-- -->
                    minRows: 6,
                    maxRows: 8,
                  }}
                />
            </div>
            {<!-- -->/* render component */}
            {<!-- -->
              list.map((item,index)=>(
              <div key={<!-- -->index} style={<!-- -->{<!-- -->marginTop:'20px'}} onClick={<!-- -->( )=>getCom(index, item)}>
                {<!-- -->item}
              </div>
              ))
            }

          </Sider>
          <Sider width={<!-- -->'350px'} style={<!-- -->{<!-- -->color:'black',background:'#f4f9fc',width:' 400px'}}>
          <Menu onClick={<!-- -->onClick} selectedKeys={<!-- -->[current]} mode="horizontal" items={<!-- -->items} />
            {<!-- -->
              rightShow? (
                <div>
                  <h3>Title</h3>
                  <Input size="large" onChange={<!-- -->(e)=>setComState(e.target.value,'title')} value={<!-- -->title2} prefix={ <!-- --><SearchOutlined />} /><br/>
                  <h3>Placeholder hint</h3>
                  <Input size="large" onChange={<!-- -->(e)=>setComState(e.target.value,'tip')} value={<!-- -->tip} prefix={ <!-- --><SearchOutlined />} /><br/>
                  <h3>Whether to display</h3>
                  <Switch defaultChecked={<!-- -->checked} onChange={<!-- -->(e)=>setComState(e,'checked')} />
                </div>
              ):<></>
            }

            {<!-- -->
              formShow? (
                <div style={<!-- -->{<!-- -->marginLeft:'30px',background:""}}>
                  {<!-- -->
                    list.map((item,index)=>(
                      <div key={<!-- -->index} style={<!-- -->{<!-- -->marginTop:'20px'}}>
                        {<!-- -->item}
                      </div>
                      ))
                  }
                  <Button style={<!-- -->{<!-- -->marginTop:'50px',marginLeft:'150px'}}>Submit</Button><br/>
                </div>
              ):<></>
            }

          </Sider>
        </Layout>
      </Space>
    </>
  )
}

//store==>Counterslice.js

//Single file operation
//npm i @reduxjs/[email protected]
import {<!-- --> configureStore, createAsyncThunk, createSlice } from '@reduxjs/toolkit';
import axios from 'axios';
// asynchronous request
const fetchList = createAsyncThunk('fetchList', async () => {<!-- -->
  const {<!-- --> data } = await axios.get('http://127.0.0.1:8000/list');
  console.log(data,'data');
  return data.data;
});

const AddList=createAsyncThunk('AddList', async (data)=>{<!-- -->
  await axios.post('http://127.0.0.1:8000/add',data)
  return ''
})

const Addchildren=createAsyncThunk('Addchildren', async (data)=>{<!-- -->
  await axios.post('http://127.0.0.1:8000/Addchildren',data)
  return ''
})

const stateSlice = createSlice({<!-- -->
  name: 'state',
  initialState: {<!-- -->
    list:[],
    num:0
  },
  reducers: {<!-- -->
    
 
  },
  extraReducers(builder) {<!-- -->
    builder.addCase(fetchList.fulfilled, (state, action)=>{<!-- -->
      state.list=action.payload
      
    })
  },
});

const store = configureStore({<!-- -->
  reducer: stateSlice. reducer,
});
// all methods need to be exported
// export const { goDetail,del,addform} = stateSlice.actions;

export {<!-- --> fetchList,AddList,Addchildren};
export default store;