Kaynağa Gözat

env file upload without de-dupe

sunguroku 5 yıl önce
ebeveyn
işleme
a2e30516a5

+ 5 - 0
dashboard/src/assets/upload.svg

@@ -0,0 +1,5 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path opacity="0.4" d="M18.8088 9.021C18.3573 9.021 17.7592 9.011 17.0146 9.011C15.1987 9.011 13.7055 7.508 13.7055 5.675V2.459C13.7055 2.206 13.5026 2 13.253 2H7.96363C5.49517 2 3.5 4.026 3.5 6.509V17.284C3.5 19.889 5.59022 22 8.16958 22H16.0453C18.5058 22 20.5 19.987 20.5 17.502V9.471C20.5 9.217 20.298 9.012 20.0465 9.013C19.6247 9.016 19.1168 9.021 18.8088 9.021Z" fill="white"/>
+<path opacity="0.4" d="M16.0842 2.56729C15.7852 2.25629 15.2632 2.47029 15.2632 2.90129V5.53829C15.2632 6.64429 16.1742 7.55429 17.2792 7.55429C17.9772 7.56229 18.9452 7.56429 19.7672 7.56229C20.1882 7.56129 20.4022 7.05829 20.1102 6.75429C19.0552 5.65729 17.1662 3.69129 16.0842 2.56729Z" fill="white"/>
+<path d="M15.1052 12.8837C14.8142 13.1727 14.3432 13.1747 14.0512 12.8817L12.4622 11.2847V16.1117C12.4622 16.5227 12.1282 16.8567 11.7172 16.8567C11.3062 16.8567 10.9732 16.5227 10.9732 16.1117V11.2847L9.3822 12.8817C9.0922 13.1747 8.6202 13.1727 8.3292 12.8837C8.0382 12.5947 8.0372 12.1227 8.3272 11.8307L11.1892 8.95569C11.1902 8.95469 11.1902 8.95469 11.1902 8.95469C11.2582 8.88669 11.3402 8.83169 11.4302 8.79469C11.5202 8.75669 11.6182 8.73669 11.7172 8.73669C11.8172 8.73669 11.9152 8.75669 12.0052 8.79469C12.0942 8.83169 12.1752 8.88669 12.2432 8.95369C12.2442 8.95469 12.2452 8.95469 12.2452 8.95569L15.1072 11.8307C15.3972 12.1227 15.3972 12.5947 15.1052 12.8837Z" fill="white"/>
+</svg>

+ 106 - 0
dashboard/src/components/values-form/KeyValueArray.tsx

@@ -4,6 +4,8 @@ import Modal from "../../main/home/modals/Modal";
 import LoadEnvGroupModal from "../../main/home/modals/LoadEnvGroupModal";
 
 import sliders from "assets/sliders.svg";
+import upload from "assets/upload.svg";
+import { keysIn } from "lodash";
 
 type PropsType = {
   label?: string;
@@ -14,6 +16,7 @@ type PropsType = {
   namespace?: string;
   clusterId?: number;
   envLoader?: boolean;
+  fileUpload?: boolean;
 };
 
 type StateType = {
@@ -137,6 +140,76 @@ export default class KeyValueArray extends Component<PropsType, StateType> {
     }
   };
 
+    // Parses src into an Object
+  parseEnv = (src: any, options: any) => {
+    const debug = Boolean(options && options.debug)
+    const obj = {} as Record<string, string>
+    const NEWLINE = '\n'
+    const RE_INI_KEY_VAL = /^\s*([\w.-]+)\s*=\s*(.*)?\s*$/
+    const RE_NEWLINES = /\\n/g
+    const NEWLINES_MATCH = /\n|\r|\r\n/
+
+    // convert Buffers before splitting into lines and processing
+    src.toString().split(NEWLINES_MATCH).forEach(function (line: any, idx: any) {
+      // matching "KEY' and 'VAL' in 'KEY=VAL'
+      const keyValueArr = line.match(RE_INI_KEY_VAL)
+      // matched?
+      if (keyValueArr != null) {
+        const key = keyValueArr[1]
+        // default undefined or missing values to empty string
+        let val = (keyValueArr[2] || '')
+        const end = val.length - 1
+        const isDoubleQuoted = val[0] === '"' && val[end] === '"'
+        const isSingleQuoted = val[0] === "'" && val[end] === "'"
+
+        // if single or double quoted, remove quotes
+        if (isSingleQuoted || isDoubleQuoted) {
+          val = val.substring(1, end)
+
+          // if double quoted, expand newlines
+          if (isDoubleQuoted) {
+            val = val.replace(RE_NEWLINES, NEWLINE)
+          }
+        } else {
+          // remove surrounding whitespace
+          val = val.trim()
+        }
+
+        obj[key] = val
+      } else if (debug) {
+        console.log(`did not match key and value when parsing line ${idx + 1}: ${line}`)
+      }
+    })
+
+    return obj
+  }
+
+  readFile = (event: any) => {
+    event.preventDefault()
+    const reader = new FileReader()
+    reader.onload = async (e) => {
+      let text = (e.target.result)
+      let env = this.parseEnv(text, null)
+
+      for (let key in env) {
+        // filter duplicate keys
+        let dup = this.state.values.filter((el) => {
+          console.log(el, key)
+          if (el["key"] == key) {
+            return false
+          }
+        })
+
+        console.log(dup)
+
+        this.state.values.push({ key, value: env[key] });
+      }
+      this.setState({ values: this.state.values });
+    }
+    reader.readAsText(event.target.files[0], 'UTF-8')
+
+  }
+
   render() {
     return (
       <>
@@ -165,6 +238,19 @@ export default class KeyValueArray extends Component<PropsType, StateType> {
                   <img src={sliders} /> Load from Env Group
                 </LoadButton>
               )}
+              {this.props.fileUpload && (
+                <UploadButton
+                  onClick={()=>{
+                    document.getElementById("file").click();
+                  }}
+                >
+                  <img src={upload} /> Upload from File
+                  <input id='file' hidden type="file" onChange={(event) => {
+                    this.readFile(event)
+                    event.currentTarget.value = null
+                  }}/>
+                </UploadButton>
+              )}
             </InputWrapper>
           )}
         </StyledInputArray>
@@ -244,6 +330,26 @@ const LoadButton = styled(AddRowButton)`
   }
 `;
 
+const UploadButton = styled(AddRowButton)`
+  background: none;
+  position: relative;
+  border: 1px solid #ffffff55;
+  > i {
+    color: #ffffff44;
+    font-size: 16px;
+    margin-left: 8px;
+    margin-right: 10px;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+  }
+  > img {
+    width: 14px;
+    margin-left: 10px;
+    margin-right: 12px;
+  }
+`;
+
 const DeleteButton = styled.div`
   width: 15px;
   height: 15px;

+ 1 - 0
dashboard/src/main/home/cluster-dashboard/env-groups/CreateEnvGroup.tsx

@@ -163,6 +163,7 @@ export default class CreateEnvGroup extends Component<PropsType, StateType> {
             namespace={this.state.selectedNamespace}
             values={this.state.envVariables}
             setValues={(x: any) => this.setState({ envVariables: x })}
+            fileUpload={true}
           />
           <SaveButton
             disabled={this.isDisabled()}