initial poc for template editor
This commit is contained in:
30
src/App.js
Normal file
30
src/App.js
Normal file
@@ -0,0 +1,30 @@
|
||||
import { Navbar, Nav, Container, Row, Col } from 'react-bootstrap';
|
||||
import YAMLEditor from './components/YamlEditor';
|
||||
import JinjaEditor from './components/JinjaEditor';
|
||||
import ResultViewer from './components/ResultViewer';
|
||||
|
||||
function App() {
|
||||
return (
|
||||
<>
|
||||
<Navbar bg="light" expand="lg">
|
||||
<Navbar.Brand href="#home">Field Automation Template Editor</Navbar.Brand>
|
||||
<Navbar.Toggle aria-controls="basic-navbar-nav" />
|
||||
<Navbar.Collapse id="basic-navbar-nav">
|
||||
<Nav className="ml-auto">
|
||||
<Nav.Link href="#home">About This</Nav.Link>
|
||||
<Nav.Link href="#link">Help</Nav.Link>
|
||||
</Nav>
|
||||
</Navbar.Collapse>
|
||||
</Navbar>
|
||||
|
||||
<Row>
|
||||
<Col><YAMLEditor></YAMLEditor></Col>
|
||||
<Col><JinjaEditor></JinjaEditor></Col>
|
||||
<Col><ResultViewer></ResultViewer></Col>
|
||||
</Row>
|
||||
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default App;
|
||||
8
src/App.test.js
Normal file
8
src/App.test.js
Normal file
@@ -0,0 +1,8 @@
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import App from './App';
|
||||
|
||||
test('renders learn react link', () => {
|
||||
render(<App />);
|
||||
const linkElement = screen.getByText(/learn react/i);
|
||||
expect(linkElement).toBeInTheDocument();
|
||||
});
|
||||
47
src/components/JinjaEditor.js
Normal file
47
src/components/JinjaEditor.js
Normal file
@@ -0,0 +1,47 @@
|
||||
import { useState } from 'react';
|
||||
import { Button, InputGroup, DropdownButton, Dropdown } from 'react-bootstrap';
|
||||
import AceEditor from "react-ace";
|
||||
|
||||
import "ace-builds/src-noconflict/mode-django";
|
||||
import "ace-builds/src-noconflict/theme-solarized_dark";
|
||||
|
||||
|
||||
function JinjaEditor() {
|
||||
const [textContent, setTextContent] = useState("Hello!")
|
||||
function onChange(newValue) {
|
||||
console.log("change", newValue);
|
||||
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<>
|
||||
<strong>Template to Use</strong>
|
||||
<InputGroup className="mb-3">
|
||||
|
||||
<DropdownButton id="dropdown-basic-button" title="Select Template">
|
||||
<Dropdown.Item href="#/action-1">Interfaces</Dropdown.Item>
|
||||
<Dropdown.Item href="#/action-2">VLANs</Dropdown.Item>
|
||||
<Dropdown.Item href="#/action-3">Something else</Dropdown.Item>
|
||||
</DropdownButton>
|
||||
|
||||
<InputGroup.Append>
|
||||
<Button variant="outline-secondary">Fetch Template</Button>
|
||||
</InputGroup.Append>
|
||||
</InputGroup>
|
||||
<AceEditor
|
||||
mode="django"
|
||||
theme="solarized_dark"
|
||||
onChange={onChange}
|
||||
value = { textContent }
|
||||
name="source_data"
|
||||
editorProps={{ $blockScrolling: true }}
|
||||
/>
|
||||
<Button className="float-right mt-2" variant="success">Generate Result</Button>
|
||||
</>
|
||||
|
||||
|
||||
);
|
||||
}
|
||||
|
||||
export default JinjaEditor;
|
||||
50
src/components/ResultViewer.js
Normal file
50
src/components/ResultViewer.js
Normal file
@@ -0,0 +1,50 @@
|
||||
import { useState } from 'react';
|
||||
import { Button, InputGroup, DropdownButton, FormControl, Dropdown } from 'react-bootstrap';
|
||||
import AceEditor from "react-ace";
|
||||
|
||||
import "ace-builds/src-noconflict/mode-text";
|
||||
import "ace-builds/src-noconflict/theme-solarized_dark";
|
||||
|
||||
|
||||
function ResultViewer() {
|
||||
const [textContent, setTextContent] = useState("Hello!")
|
||||
function onChange(newValue) {
|
||||
let insertText = "Text to insert\n";
|
||||
// setTextContent(insertText + textContent)
|
||||
console.log("change", newValue);
|
||||
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<>
|
||||
<strong>Result</strong>
|
||||
<InputGroup className="mb-3">
|
||||
<FormControl
|
||||
placeholder="Diff Against Device"
|
||||
/>
|
||||
<DropdownButton id="dropdown-basic-button" title="Diff Against">
|
||||
<Dropdown.Item href="#/action-1">Interfaces</Dropdown.Item>
|
||||
<Dropdown.Item href="#/action-2">VLANs</Dropdown.Item>
|
||||
<Dropdown.Item href="#/action-3">Something else</Dropdown.Item>
|
||||
</DropdownButton>
|
||||
|
||||
<InputGroup.Append>
|
||||
<Button variant="outline-secondary">View Diff</Button>
|
||||
</InputGroup.Append>
|
||||
</InputGroup>
|
||||
<AceEditor
|
||||
mode="django"
|
||||
theme="solarized_dark"
|
||||
onChange={onChange}
|
||||
value = { textContent }
|
||||
name="result_data"
|
||||
editorProps={{ $blockScrolling: true }}
|
||||
/>
|
||||
</>
|
||||
|
||||
|
||||
);
|
||||
}
|
||||
|
||||
export default ResultViewer;
|
||||
60
src/components/YamlEditor.js
Normal file
60
src/components/YamlEditor.js
Normal file
@@ -0,0 +1,60 @@
|
||||
import { useState } from 'react';
|
||||
import { Button, InputGroup, FormControl, DropdownButton, Dropdown } from 'react-bootstrap';
|
||||
import AceEditor from "react-ace";
|
||||
|
||||
import "ace-builds/src-noconflict/mode-yaml";
|
||||
import "ace-builds/src-noconflict/theme-solarized_dark";
|
||||
|
||||
const startText = `
|
||||
test: Yes
|
||||
integer: 1
|
||||
Another:
|
||||
- should have
|
||||
- yaml highlighting
|
||||
|
||||
|
||||
`
|
||||
|
||||
function YAMLEditor() {
|
||||
const [textContent, setTextContent] = useState(startText)
|
||||
function onChange(newValue) {
|
||||
let insertText = "Text to insert\n";
|
||||
setTextContent(insertText + textContent)
|
||||
console.log("change", newValue);
|
||||
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<>
|
||||
<strong>Data Source</strong>
|
||||
<InputGroup className="mb-3">
|
||||
<FormControl
|
||||
placeholder="Device Hostname"
|
||||
/>
|
||||
<InputGroup.Append>
|
||||
<DropdownButton id="dropdown-basic-button" title="SubData to Fetch">
|
||||
<Dropdown.Item href="#/action-1">Interfaces</Dropdown.Item>
|
||||
<Dropdown.Item href="#/action-2">VLANs</Dropdown.Item>
|
||||
<Dropdown.Item href="#/action-3">Something else</Dropdown.Item>
|
||||
</DropdownButton>
|
||||
</InputGroup.Append>
|
||||
<InputGroup.Append>
|
||||
<Button variant="outline-secondary">Fetch Data</Button>
|
||||
</InputGroup.Append>
|
||||
</InputGroup>
|
||||
<AceEditor
|
||||
mode="yaml"
|
||||
theme="solarized_dark"
|
||||
onChange={onChange}
|
||||
value = { textContent }
|
||||
name="source_data"
|
||||
editorProps={{ $blockScrolling: true }}
|
||||
/>
|
||||
</>
|
||||
|
||||
|
||||
);
|
||||
}
|
||||
|
||||
export default YAMLEditor;
|
||||
17
src/index.js
Normal file
17
src/index.js
Normal file
@@ -0,0 +1,17 @@
|
||||
import 'bootstrap/dist/css/bootstrap.min.css';
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import App from './App';
|
||||
import reportWebVitals from './reportWebVitals';
|
||||
|
||||
ReactDOM.render(
|
||||
<React.StrictMode>
|
||||
<App />
|
||||
</React.StrictMode>,
|
||||
document.getElementById('root')
|
||||
);
|
||||
|
||||
// If you want to start measuring performance in your app, pass a function
|
||||
// to log results (for example: reportWebVitals(console.log))
|
||||
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
|
||||
reportWebVitals();
|
||||
13
src/reportWebVitals.js
Normal file
13
src/reportWebVitals.js
Normal file
@@ -0,0 +1,13 @@
|
||||
const reportWebVitals = onPerfEntry => {
|
||||
if (onPerfEntry && onPerfEntry instanceof Function) {
|
||||
import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
|
||||
getCLS(onPerfEntry);
|
||||
getFID(onPerfEntry);
|
||||
getFCP(onPerfEntry);
|
||||
getLCP(onPerfEntry);
|
||||
getTTFB(onPerfEntry);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
export default reportWebVitals;
|
||||
5
src/setupTests.js
Normal file
5
src/setupTests.js
Normal file
@@ -0,0 +1,5 @@
|
||||
// jest-dom adds custom jest matchers for asserting on DOM nodes.
|
||||
// allows you to do things like:
|
||||
// expect(element).toHaveTextContent(/react/i)
|
||||
// learn more: https://github.com/testing-library/jest-dom
|
||||
import '@testing-library/jest-dom';
|
||||
Reference in New Issue
Block a user