Moortiii

Fuck Autocomplete

Mar 4th, 2020
111
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import 'index.css'
  2. import 'react-quill/dist/quill.snow.css';
  3. import "react-mde/lib/styles/css/react-mde-all.css";
  4.  
  5. import React, { useState, useEffect } from 'react'
  6.  
  7. import { RootState } from "../../app/rootReducer"
  8. import { useParams } from 'react-router-dom'
  9. import { useTranslation } from 'react-i18next'
  10. import { useSelector, useDispatch } from 'react-redux'
  11.  
  12. // @ts-ignore
  13. import renderHTML from 'react-render-html';
  14. import ReactQuill from 'react-quill';
  15.  
  16. import ReferenceList from './ReferenceList';
  17. import VulnerabilityList from './VulnerabilityList';
  18. import DeleteModal from './DeleteModal'
  19.  
  20. import {
  21.     fetchArticle,
  22.     addReference,
  23.     addVulnerability,
  24.     removeReference,
  25.     removeVulnerability,
  26.     fetchAutocompleteSuggestions
  27. } from "./ArticleSlice"
  28.  
  29. import {
  30.     Grid, Container, Button,
  31.     Form, Input, Select,
  32.     Header, Message, Dropdown
  33. } from 'semantic-ui-react'
  34.  
  35. interface Suggestion {
  36.     description: string,
  37.     id: string
  38. }
  39.  
  40. interface Option {
  41.     key: string,
  42.     value: string,
  43.     text: string
  44. }
  45.  
  46. interface Reference {
  47.     id: number,
  48.     text: string
  49. }
  50.  
  51. interface Vulnerability {
  52.     identifier: string,
  53.     id: number
  54. }
  55.  
  56. interface FormState {
  57.     title: string,
  58.     severity: number,
  59.     summary: string,
  60.     type: string,
  61.     references: Array<Reference>,
  62.     reference: string,
  63.     vulnerability: string,
  64.     vulnerabilities: Array<Vulnerability>,
  65.     autocompleteOptions: Array<Option>
  66. }
  67.  
  68. const Article = () => {
  69.     let { id } = useParams();
  70.     const { t } = useTranslation();
  71.     const dispatch = useDispatch()
  72.  
  73.     const articleOptions = [
  74.         { key: "article", text: t("article_options.news"), value: "article" },
  75.         { key: "vulnerability", text: t("article_options.vulnerability"), value: "vulnerability" },
  76.         { key: "update", text: t("article_options.update"), value: "update" }
  77.     ]
  78.  
  79.     const severityOptions = [
  80.         { key: "low", text: t("severity_options.low"), value: "1" },
  81.         { key: "medium", text: t("severity_options.medium"), value: "2" },
  82.         { key: "high", text: t("severity_options.high"), value: "3" },
  83.         { key: "critical", text: t("severity_options.critical"), value: "4" }
  84.     ]
  85.  
  86.     const { title, summary, severity, references, type, vulnerabilities } = useSelector(
  87.         (state: RootState) => state.articles.article
  88.     )
  89.  
  90.     const { error, autocompleteSuggestions } = useSelector(
  91.         (state: RootState) => state.articles
  92.     )
  93.  
  94.     useEffect(() => {
  95.         if (id) {
  96.             dispatch(fetchArticle(id))
  97.         }
  98.     }, [dispatch, title, summary, type, severity, id])
  99.  
  100.     const [form, setForm] = useState<FormState>({
  101.         title: title,
  102.         type: type,
  103.         summary: summary,
  104.         severity: severity,
  105.         references: references,
  106.         vulnerabilities: vulnerabilities,
  107.         reference: "",
  108.         vulnerability: "",
  109.         autocompleteOptions: [] as Array<Option>
  110.     })
  111.  
  112.     // Whenever the vulnerability search is updated, repopulate the dropdown options
  113.     useEffect(() => {
  114.         if (autocompleteSuggestions.length > 0) {
  115.             const options = autocompleteSuggestions.reduce((options: Array<Option>, x: Suggestion) => {
  116.  
  117.                 let option = {
  118.                     key: x.id,
  119.                     value: x.id,
  120.                     text: x.id
  121.                 }
  122.  
  123.                 options.push(option)
  124.                 return options
  125.             }, [])
  126.  
  127.             setForm({
  128.                 ...form,
  129.                 autocompleteOptions: options
  130.             })
  131.         }
  132.     }, [form.vulnerability])
  133.  
  134.     useEffect(() => {
  135.         setForm({ ...form, references: references })
  136.     }, [references])
  137.  
  138.     useEffect(() => {
  139.         setForm({ ...form, vulnerabilities: vulnerabilities })
  140.     }, [vulnerabilities])
  141.  
  142.     const handleFormChange = (event: any, { name, value }: any) => {
  143.         setForm({
  144.             ...form,
  145.             [name]: value
  146.         })
  147.     }
  148.  
  149.     const handleAddReference = () => {
  150.         if (form.reference) {
  151.             dispatch(addReference(form.reference))
  152.             setForm({ ...form, reference: "" })
  153.         }
  154.     }
  155.  
  156.     const handleRemoveReference = (reference: Reference) => {
  157.         dispatch(removeReference(reference.id))
  158.     }
  159.  
  160.     const handleAddVulnerability = () => {
  161.         if(form.vulnerability) {
  162.             dispatch(addVulnerability(form.vulnerability))
  163.             setForm({...form, vulnerability: ""})
  164.         }
  165.     }
  166.  
  167.     const handleRemoveVulnerability = (vulnerability: Vulnerability) => {
  168.         dispatch(removeVulnerability(vulnerability.id))
  169.     }
  170.  
  171.     const handleQuillUpdate = (value: any) => {
  172.         setForm({ ...form, summary: value })
  173.     }
  174.  
  175.     const handleAutocompleteSearch = (event: any) => {
  176.         const key = event.key
  177.  
  178.         if(key === "ArrowDown" || key === "ArrowUp" || key === "Enter") return
  179.  
  180.         if (event.target.value !== "")
  181.             dispatch(fetchAutocompleteSuggestions(event.target.value))
  182.        
  183.         setForm({...form, vulnerability: event.target.value})
  184.     }
  185.  
  186.     const [preview, setPreview] = useState("")
  187.  
  188.     // TODO: Cleanup or move elsewheres
  189.     useEffect(() => {
  190.         const headline = `<h3>${form.title}</h3>`
  191.  
  192.         // Combine the necessary fields for the preview
  193.         let output = headline + form.summary
  194.  
  195.         for (let i = 0; i < form.references.length; i++) {
  196.             output += `<a href="#">${form.references[i].text}</a><br>`
  197.         }
  198.  
  199.         if (form.vulnerabilities.length > 0) {
  200.             output += "<h3>Svakheter:</h3>"
  201.  
  202.             for (let i = 0; i < form.vulnerabilities.length; i++) {
  203.                 output += `<a href="#">${form.vulnerabilities[i].identifier}</a><br>`
  204.             }
  205.         }
  206.  
  207.         // Replace empty lines with a more sensible format
  208.         output = output.replace(/<p><br><\/p>/g, "");
  209.  
  210.         setPreview(output)
  211.     }, [form])
  212.  
  213.  
  214.     const handleArticleDeletion = () => {
  215.         alert("Article Deleted inside callback")
  216.     }
  217.  
  218.     return (
  219.         <Container>
  220.             <Grid columns={2} divided>
  221.                 <Grid.Row>
  222.                     <Grid.Column>
  223.                         <Header as='h1'>{t("write")}</Header>
  224.                         <Form error>
  225.                             <Form.Field
  226.                                 autoComplete="off"
  227.                                 name="title"
  228.                                 value={form.title}
  229.                                 onChange={handleFormChange}
  230.                                 control={Input}
  231.                                 label={t('form.title')}
  232.                                 placeholder={t('form.title')}
  233.                             />
  234.                             <Form.Select
  235.                                 name="type"
  236.                                 value={form.type}
  237.                                 onChange={handleFormChange}
  238.                                 options={articleOptions}
  239.                                 label={t('form.article_type')}
  240.                                 placeholder={t('form.article_type')}
  241.                                 search
  242.                             />
  243.  
  244.                             <Form.Input
  245.                                 fluid
  246.                                 action
  247.                                 label={t("form.CVE")}
  248.                                 placeholder={t("form.CVE")}
  249.                             >
  250.                                 <Dropdown
  251.                                     name="vulnerability"
  252.                                     onKeyUp={handleAutocompleteSearch}
  253.                                     options={form.autocompleteOptions}
  254.                                     value={form.vulnerability}
  255.                                     onChange={handleFormChange}
  256.                                     selection
  257.                                     search
  258.                                     fluid
  259.                                     style={{borderRadius: "4px 0px 0px 4px"}}
  260.                                 />
  261.                                 <Button attached="left" color="green" icon="add" content={t("form.add")} labelPosition="right" onClick={handleAddVulnerability} onKeyPress={handleAddVulnerability}/>
  262.                             </Form.Input>
  263.  
  264.                             {error && (
  265.                                 <Message visible warning content="Fant ikke informasjon om gitt CVE" />
  266.                             )}
  267.  
  268.                             <Form.Field
  269.                                 control={VulnerabilityList}
  270.                                 handleRemove={handleRemoveVulnerability}
  271.                                 vulnerabilities={form.vulnerabilities}
  272.                             />
  273.                             <Form.Field
  274.                                 name="summary"
  275.                                 control={ReactQuill}
  276.                                 value={form.summary}
  277.                                 onChange={handleQuillUpdate}
  278.                                 label={{ children: t("form.summary"), htmlFor: 'form-select-control-summary' }}
  279.                                 modules={{
  280.                                     toolbar: [
  281.                                         ['bold', 'italic', 'underline'],
  282.                                         [{ 'list': 'ordered' }, { 'list': 'bullet' }],
  283.                                         ['code', 'clean']
  284.                                     ],
  285.                                 }}
  286.                             />
  287.  
  288.  
  289.                             <Form.Field
  290.                                 autoComplete="off"
  291.                                 control={Input}
  292.                                 name="reference"
  293.                                 value={form.reference}
  294.                                 onChange={handleFormChange}
  295.                                 action={
  296.                                     <Button labelPosition='right'
  297.                                         icon='add'
  298.                                         content={t("form.add")}
  299.                                         color='green'
  300.                                         onClick={handleAddReference}
  301.                                     >
  302.                                     </Button>
  303.                                 }
  304.                                 label={t("form.reference")}
  305.                                 placeholder="URL"
  306.                                 onKeyPress={(event: any) => { if (event.key === "Enter") { handleAddReference() } }}
  307.                             />
  308.                             <Form.Field
  309.                                 control={ReferenceList}
  310.                                 references={form.references}
  311.                                 handleRemove={handleRemoveReference}
  312.                             />
  313.                             <Form.Field
  314.                                 control={Select}
  315.                                 name="severity"
  316.                                 value={form.severity}
  317.                                 onChange={handleFormChange}
  318.                                 options={severityOptions}
  319.                                 label={{ children: t("form.severity"), htmlFor: 'form-select-control-severity' }}
  320.                                 placeholder={t("form.severity")}
  321.                                 search
  322.                                 searchInput={{ id: 'form-select-control-severity' }}
  323.                             />
  324.                             <Form.Group>
  325.                                 <Form.Field
  326.                                     id='form-button-control-public'
  327.                                     control={Button}
  328.                                     color="green"
  329.                                     content={t("form.save")}
  330.                                     onClick={() => { alert(JSON.stringify(form)) }}
  331.                                 />
  332.                                 <DeleteModal callback={handleArticleDeletion} />
  333.                             </Form.Group>
  334.                         </Form>
  335.                     </Grid.Column>
  336.                     <Grid.Column>
  337.                         <Header as='h1'>{t("preview")}</Header>
  338.                         <div>
  339.                             {renderHTML(preview)}
  340.                         </div>
  341.                     </Grid.Column>
  342.                 </Grid.Row>
  343.             </Grid>
  344.         </Container>
  345.     )
  346. }
  347.  
  348. export default Article
Add Comment
Please, Sign In to add comment