• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mendersoftware / gui / 1350829378

27 Jun 2024 01:46PM UTC coverage: 83.494% (-16.5%) from 99.965%
1350829378

Pull #4465

gitlab-ci

mzedel
chore: test fixes

Signed-off-by: Manuel Zedel <manuel.zedel@northern.tech>
Pull Request #4465: MEN-7169 - feat: added multi sorting capabilities to devices view

4506 of 6430 branches covered (70.08%)

81 of 100 new or added lines in 14 files covered. (81.0%)

1661 existing lines in 163 files now uncovered.

8574 of 10269 relevant lines covered (83.49%)

160.6 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

75.0
/src/js/components/settings/organization/ssoeditor.js
1
// Copyright 2022 Northern.tech AS
2
//
3
//    Licensed under the Apache License, Version 2.0 (the "License");
4
//    you may not use this file except in compliance with the License.
5
//    You may obtain a copy of the License at
6
//
7
//        http://www.apache.org/licenses/LICENSE-2.0
8
//
9
//    Unless required by applicable law or agreed to in writing, software
10
//    distributed under the License is distributed on an "AS IS" BASIS,
11
//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
//    See the License for the specific language governing permissions and
13
//    limitations under the License.
14
import React, { useCallback, useEffect, useRef, useState } from 'react';
15
import Dropzone from 'react-dropzone';
16

17
// material ui
18
import { Close as CloseIcon, CloudUpload, FileCopyOutlined as CopyPasteIcon } from '@mui/icons-material';
19
import { Button, Divider, Drawer, IconButton } from '@mui/material';
20

21
import Editor, { loader } from '@monaco-editor/react';
22
import copy from 'copy-to-clipboard';
23

24
import { JSON_METADATA_FORMAT, XML_METADATA_FORMAT } from '../../../constants/organizationConstants.js';
25
import { createFileDownload } from '../../../helpers';
26
import Loader from '../../common/loader';
27

28
loader.config({ paths: { vs: '/ui/vs' } });
8✔
29

30
const editorProps = {
8✔
31
  height: 700,
32
  loading: <Loader show />,
33
  options: {
34
    autoClosingOvertype: 'auto',
35
    codeLens: false,
36
    contextmenu: false,
37
    enableSplitViewResizing: false,
38
    formatOnPaste: true,
39
    lightbulb: { enabled: false },
40
    lineNumbers: 'off',
41
    minimap: { enabled: false },
42
    quickSuggestions: false,
43
    readOnly: true,
44
    renderOverviewRuler: false,
45
    scrollBeyondLastLine: false,
46
    wordWrap: 'on'
47
  }
48
};
49

50
export const SSOEditor = ({ ssoItem, config, fileContent, hasSSOConfig, open, onCancel, onClose, onSave, setFileContent, token }) => {
8✔
51
  const [isEditing, setIsEditing] = useState(false);
12✔
52
  const [isMetadataValid, setIsMetadataValid] = useState(false);
12✔
53
  const editorRef = useRef();
12✔
54

55
  useEffect(() => {
12✔
56
    if (!fileContent) {
6✔
57
      return;
2✔
58
    }
59

60
    const parser = new DOMParser();
4✔
61
    let valid = false;
4✔
62
    switch (ssoItem.metadataFormat) {
4✔
63
      case JSON_METADATA_FORMAT:
64
        try {
2✔
65
          JSON.parse(fileContent);
2✔
66
          valid = true;
1✔
67
        } catch (error) {
68
          valid = false;
1✔
69
        }
70
        break;
2✔
71
      case XML_METADATA_FORMAT:
72
      default:
73
        valid = !parser.parseFromString(fileContent, 'application/xml').getElementsByTagName('parsererror').length;
2✔
74
        break;
2✔
75
    }
76
    setIsMetadataValid(valid);
4✔
77
  }, [fileContent, ssoItem.metadataFormat]);
78

79
  const onEditClick = () => setIsEditing(true);
12✔
80

81
  const onDownloadClick = () => createFileDownload(fileContent, `metadata.${ssoItem.metadataFormat}`, token);
12✔
82

83
  const onCancelClick = useCallback(() => {
12✔
UNCOV
84
    if (isEditing) {
×
UNCOV
85
      setFileContent(config);
×
UNCOV
86
      if (!hasSSOConfig) {
×
UNCOV
87
        return onCancel();
×
88
      }
UNCOV
89
      return setIsEditing(false);
×
90
    }
UNCOV
91
    onClose();
×
92
  }, [config, hasSSOConfig, isEditing, onCancel, setFileContent, onClose]);
93

94
  const onSubmitClick = () => {
12✔
UNCOV
95
    onSave();
×
UNCOV
96
    setIsEditing(false);
×
97
  };
98

99
  const onCopyClick = () => copy(fileContent);
12✔
100

101
  const onDrop = acceptedFiles => {
12✔
102
    let reader = new FileReader();
1✔
103
    reader.fileName = acceptedFiles[0].name;
1✔
104
    reader.onerror = error => {
1✔
UNCOV
105
      console.log('Error: ', error);
×
UNCOV
106
      setIsEditing(false);
×
107
    };
108
    reader.onload = () => {
1✔
109
      setFileContent(reader.result);
1✔
110
      setIsEditing(true);
1✔
111
    };
112
    reader.readAsBinaryString(acceptedFiles[0]);
1✔
113
  };
114

115
  const handleEditorDidMount = (editor, monaco) => {
12✔
UNCOV
116
    monaco.languages.html.registerHTMLLanguageService(ssoItem.metadataFormat, {}, { documentFormattingEdits: true });
×
UNCOV
117
    editorRef.current = { editor, monaco, modifiedEditor: editor };
×
118
  };
119

120
  return (
12✔
121
    <Drawer className={`${open ? 'fadeIn' : 'fadeOut'}`} anchor="right" open={open} onClose={onClose} PaperProps={{ style: { minWidth: '75vw' } }}>
12✔
122
      <div className="flexbox margin-bottom-small space-between">
123
        <h3>{ssoItem.title} metadata</h3>
124
        <div className="flexbox center-aligned">
125
          <Dropzone multiple={false} onDrop={onDrop}>
126
            {({ getRootProps, getInputProps }) => (
127
              <div {...getRootProps()}>
10✔
128
                <input {...getInputProps()} />
129
                <Button color="secondary" startIcon={<CloudUpload fontSize="small" />}>
130
                  Import from a file
131
                </Button>
132
              </div>
133
            )}
134
          </Dropzone>
135

136
          <IconButton onClick={onClose} size="large">
137
            <CloseIcon />
138
          </IconButton>
139
        </div>
140
      </div>
141
      <Divider light />
142
      <Editor
143
        {...editorProps}
144
        language={ssoItem.editorLanguage}
145
        defaultLanguage={ssoItem.editorLanguage}
146
        options={{
147
          ...editorProps.options,
148
          readOnly: hasSSOConfig && !isEditing
22✔
149
        }}
150
        className="editor modified"
151
        onChange={setFileContent}
152
        onMount={handleEditorDidMount}
153
        value={fileContent}
154
      />
155
      {!isMetadataValid && fileContent.length > 4 && <div className="error">There was an error parsing the metadata.</div>}
22✔
156
      <Divider className="margin-top-large margin-bottom" light />
157
      <div>
158
        {hasSSOConfig && !isEditing ? (
34✔
159
          <div className="flexbox center-aligned">
160
            <Button onClick={onEditClick}>Edit</Button>
161
            <Button onClick={onDownloadClick}>Download file</Button>
162
            <Button onClick={onCopyClick} startIcon={<CopyPasteIcon />}>
163
              Copy to clipboard
164
            </Button>
165
          </div>
166
        ) : (
167
          <>
168
            <Button onClick={onCancelClick}>Cancel</Button>
169
            <Button variant="contained" disabled={!isMetadataValid} onClick={onSubmitClick} color="secondary" style={{ marginLeft: 10 }}>
170
              Save
171
            </Button>
172
          </>
173
        )}
174
      </div>
175
    </Drawer>
176
  );
177
};
178

179
export default SSOEditor;
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc