Skip to content

Commit

Permalink
Merge branch 'release/1.0.0-beta4'
Browse files Browse the repository at this point in the history
  • Loading branch information
Kamil Mrzygłód committed Oct 25, 2017
2 parents 30af883 + 0c624b7 commit 22fe295
Show file tree
Hide file tree
Showing 18 changed files with 1,114 additions and 331 deletions.
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ You can obtain current version of ARMata from our [Releases](https://github.com/
## Our goal
We decided to create new ARM visualizer(apart from currently existing ones like ARMVIZ) because there's no tool, which is being currently maintained and developed. Our goal is to provide a solution, which will fill the gap of ARM visualizers and help people when working with them on daily basis.

## What does "ARMata" mean?
In Polish "armata" means "a cannon". It combines both the main purpose of this application and the idea to solve many issues related to working with ARM templates.

## How can I help?
Anyone can join and we'll welcome all new contributors. Currently we need people for all kinds of different things:
* coding
Expand Down Expand Up @@ -36,7 +39,7 @@ $ npm run dev
## Roadmap
ARMata is currently at the very beginning of development phase and yet there're many thing, which are not implemented. The current roadmap:
* toolbox
* live editing of a template
* ~~live editing of a template~~
* template validation
* ~~ability to generate an image from a parsed template~~
* ~~refreshed UI~~
Expand Down
29 changes: 29 additions & 0 deletions app/actions/layout.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ export const CLOSE_NODE_WINDOW = 'CLOSE_NODE_WINDOW';
export const OPEN_WINDOW = 'OPEN_WINDOW';
export const CLOSE_WINDOW = 'CLOSE_WINDOW';
export const OPEN_VISUALIZATION = 'OPEN_VISUALIZATION';
export const OPEN_TOOLBOX = 'OPEN_TOOLBOX';
export const CLOSE_TOOLBOX = 'CLOSE_TOOLBOX';
export const TOGGLE_PHYSICS = 'TOGGLE_PHYSICS';
export const ADD_RESOURCE = 'ADD_RESOURCE';

type actionType = {
type: string
Expand All @@ -31,6 +35,12 @@ export function toggleHierarchicalLayout() {
};
}

export function togglePhysics() {
return (dispatch: (action: actionType) => void) => {
dispatch({ type: TOGGLE_PHYSICS });
};
}

export function changeView(view: string) {
return (dispatch: (action: changeViewType) => void) => {
dispatch({ type: CHANGE_VIEW, view });
Expand Down Expand Up @@ -62,6 +72,18 @@ export function openVisualization() {
};
}

export function openToolbox() {
return (dispatch: (action: actionType) => void) => {
dispatch({ type: OPEN_TOOLBOX });
};
}

export function closeToolbox() {
return (dispatch: (action: actionType) => void) => {
dispatch({ type: CLOSE_TOOLBOX });
};
}

export function error(errorMessage: string, title: string = 'Error occured') {
const buttons = [{ label: 'Got it', action: CLEAR_ERRORS }, { label: 'Report', action: REPORT_ERROR }];

Expand Down Expand Up @@ -99,3 +121,10 @@ export function closeWindow() {
type: CLOSE_WINDOW
};
}

export function addResource(resourceType: string) {
return (dispatch: (action: actionType) => void) => {
dispatch({ type: ADD_RESOURCE, resourceType });
};
}

98 changes: 56 additions & 42 deletions app/components/App.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
// @flow
import React, { Component } from 'react';
import type { Children } from 'react';
import { Sidebar, Button, Form, Checkbox, Header, Icon } from 'semantic-ui-react';
import { Sidebar, Button, Form, Header, Icon, Checkbox } from 'semantic-ui-react';
import { DragDropContextProvider } from 'react-dnd';
import HTML5Backend from 'react-dnd-html5-backend';
import SideMenu from './SideMenu';
import Alert from './Alert';
import ProgressBar from './Progress';
import StatusBar from './StatusBar';
import RightSidebar from './RightSidebar';
import Toolbox from './Toolbox';
import CustomWindow from './Window';
import { Resource } from '../types/template';
import styles from './App.css'; // eslint-disable-line flowtype-errors/show-errors
Expand All @@ -17,7 +20,10 @@ export default class App extends Component {
changeView: () => void,
openSettings: () => void,
openVisualization: () => void,
openToolbox: () => void,
addResource: (resourceType: string) => void,
toggleHierarchicalLayout: () => void,
togglePhysics: () => void,
children: Children,
resources: Array<Resource>,
layout: Object,
Expand All @@ -28,49 +34,57 @@ export default class App extends Component {

render() {
return (
<div style={{ height: '100%' }}>
<Alert
message={this.props.layout.message === '' ? this.props.fileDialog.message : this.props.layout.message}
dispatchButtonClick={this.props.dispatchButtonClick}
buttons={this.props.layout.buttons}
title={this.props.layout.title === '' ? this.props.fileDialog.title : this.props.layout.title} />
<SideMenu
changeView={this.props.changeView}
currentView={this.props.currentView}
openSettings={this.props.openSettings}
openVisualization={this.props.openVisualization} />
<ProgressBar progress={this.props.layout.progress} />
<CustomWindow
activeWindow={this.props.layout.activeWindow}
window={this.props.layout.window}
dispatchButtonClick={this.props.dispatchButtonClick} />
<StatusBar
selectedFilename={this.props.fileDialog.selectedFilename}
lines={this.props.fileDialog.fileData.lines}
characters={this.props.fileDialog.fileData.characters}
loadedIn={this.props.fileDialog.fileData.loadedIn} />
<Sidebar.Pushable>
<Sidebar as={Form} className={styles.sideBar} animation="scale down" width="wide" visible={this.props.isSettingsWindowOpen} icon="labeled" inverted>
<Header as="h3" icon style={{ color: '#FFF' }}>
<Icon name="settings" />
Settings
<DragDropContextProvider backend={HTML5Backend}>
<div style={{ height: '100%' }}>
<Alert
message={this.props.layout.message === '' ? this.props.fileDialog.message : this.props.layout.message}
dispatchButtonClick={this.props.dispatchButtonClick}
buttons={this.props.layout.buttons}
title={this.props.layout.title === '' ? this.props.fileDialog.title : this.props.layout.title} />
<SideMenu
changeView={this.props.changeView}
currentView={this.props.currentView}
openSettings={this.props.openSettings}
openVisualization={this.props.openVisualization}
openToolbox={this.props.openToolbox} />
<ProgressBar progress={this.props.layout.progress} />
<CustomWindow
activeWindow={this.props.layout.activeWindow}
window={this.props.layout.window}
dispatchButtonClick={this.props.dispatchButtonClick} />
<StatusBar
selectedFilename={this.props.fileDialog.selectedFilename}
lines={this.props.fileDialog.fileData.lines}
characters={this.props.fileDialog.fileData.characters}
loadedIn={this.props.fileDialog.fileData.loadedIn} />
<Sidebar.Pushable>
<Sidebar as={Form} className={styles.sideBar} animation="scale down" width="wide" visible={this.props.isSettingsWindowOpen} icon="labeled" inverted>
<Header as="h3" icon style={{ color: '#FFF' }}>
<Icon name="settings" />
Settings
<Header.Subheader style={{ color: '#FFF' }}>
Manage graph settings and set preferences.
Manage graph settings and set preferences.
</Header.Subheader>
</Header>
<Form.Field><Checkbox toggle label="Hierarchical layout?" onChange={() => this.props.toggleHierarchicalLayout()} /></Form.Field>
<Form.Field><Button type="button" fluid onClick={() => this.props.dispatchButtonClick('CLOSE_SETTINGS')}>Close</Button></Form.Field>
</Sidebar>
<RightSidebar
dispatchButtonClick={(action) => this.props.dispatchButtonClick(action)}
isNodeWindowOpen={this.props.layout.isNodeWindowOpen}
nodes={this.props.layout.nodes}
resources={this.props.resources} />
<Sidebar.Pusher dimmed={this.props.isSettingsWindowOpen} style={{ height: '100%' }}>
{this.props.children}
</Sidebar.Pusher>
</Sidebar.Pushable>
</div>
</Header>
<Form.Field><Checkbox toggle label="Hierarchical layout?" onChange={() => this.props.toggleHierarchicalLayout()} /></Form.Field>
<Form.Field><Checkbox toggle label="Disable physics?" onChange={() => this.props.togglePhysics()} /></Form.Field>
<Form.Field><Button type="button" fluid onClick={() => this.props.dispatchButtonClick('CLOSE_SETTINGS')}>Close</Button></Form.Field>
</Sidebar>
<Toolbox
dispatchButtonClick={(action) => this.props.dispatchButtonClick(action)}
addResource={(type) => this.props.addResource(type)}
isToolboxOpen={this.props.layout.isToolboxOpen} />
<RightSidebar
dispatchButtonClick={(action) => this.props.dispatchButtonClick(action)}
isNodeWindowOpen={this.props.layout.isNodeWindowOpen}
nodes={this.props.layout.nodes}
resources={this.props.resources} />
<Sidebar.Pusher dimmed={this.props.isSettingsWindowOpen} style={{ height: '100%' }}>
{this.props.children}
</Sidebar.Pusher>
</Sidebar.Pushable>
</div>
</DragDropContextProvider>
);
}
}
23 changes: 19 additions & 4 deletions app/components/Home.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,27 @@
// @flow
import React, { Component } from 'react';
import { DropTarget } from 'react-dnd';
import styles from './Home.css'; // eslint-disable-line flowtype-errors/show-errors
import Visualization from './Visualization';

export default class Home extends Component {
const boxTarget = {
drop() {
return { name: 'Dustbin' };
},
};

class Home extends Component {
props: {
openNodeWindow: (nodes: Array<string>) => void,
json: Object,
selectedFilename: string,
hierarchicalLayout: boolean
hierarchicalLayout: boolean,
physicsEnabled: boolean
}

render() {
if (this.props.selectedFilename === '') {
return (
return this.props.connectDropTarget( // eslint-disable-line react/prop-types
<div className={styles.container} data-tid="container">
{this.props.selectedFilename === '' ?
<div>
Expand All @@ -27,14 +35,21 @@ export default class Home extends Component {
);
}

return (
return this.props.connectDropTarget( // eslint-disable-line react/prop-types
<div className={styles.container} data-tid="container">
<Visualization
json={this.props.json}
hierarchicalLayout={this.props.hierarchicalLayout}
openNodeWindow={(nodes: Array<string>) => this.props.openNodeWindow(nodes)}
physicsEnabled={this.props.physicsEnabled}
/>
</div>
);
}
}

export default DropTarget('Component', boxTarget, (connect, monitor) => ({
connectDropTarget: connect.dropTarget(),
isOver: monitor.isOver(),
canDrop: monitor.canDrop(),
}))(Home);
11 changes: 10 additions & 1 deletion app/components/SideMenu.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export default class SideMenu extends Component {
props: {
openSettings: () => void,
openVisualization: () => void,
openToolbox: () => void,
currentView: string
}

Expand All @@ -22,9 +23,17 @@ export default class SideMenu extends Component {
position="right center"
size="mini"
/>
<Popup
trigger={<Menu.Item onClick={() => this.props.openToolbox()}>
<Link to="/"><Icon name="sitemap" size="big" /></Link>
</Menu.Item>}
content="Toolbox"
position="right center"
size="mini"
/>
<Popup
trigger={<Menu.Item active={this.props.currentView === '/editor'}>
<Link to="/editor"><Icon name="write" size="big" /></Link>
<Link to="/editor"><Icon name="code" size="big" /></Link>
</Menu.Item>}
content="Editor"
position="right center"
Expand Down
9 changes: 9 additions & 0 deletions app/components/Toolbox.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
.toolbox {
color: #fff !important;
left: 70px !important;
padding-left: 10px;
padding-right: 10px;
padding-top: 10px;
text-align: center;
background-color: #586f80;
}
68 changes: 68 additions & 0 deletions app/components/Toolbox.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// @flow
import React, { Component } from 'react';
import { Sidebar, Button, Form, Header, Icon, Grid } from 'semantic-ui-react';
import ToolboxComponent from './ToolboxComponent';
import styles from './Toolbox.css'; // eslint-disable-line flowtype-errors/show-errors

export default class Toolbox extends Component {
props: {
dispatchButtonClick: (action: string) => void,
addResource: (resourceType: string) => void,
isToolboxOpen: boolean
}

generateGrid() {
const types = [
{ type: 'Microsoft.Web/serverfarms', name: 'App Service' },
{ type: 'Microsoft.Web/sites', name: 'Web App' },
{ type: 'Microsoft.Insights/components', name: 'Application Insights' },
{ type: 'Microsoft.Storage/storageAccounts', name: 'Storage Account' },
{ type: 'Microsoft.EventHub/namespaces', name: 'Event Hub' },
{ type: 'Microsoft.Network/trafficManagerProfiles', name: 'Traffic Manager' },
{ type: 'Microsoft.NotificationHubs/namespaces', name: 'Notification Hub' },
{ type: 'Microsoft.Network/networkInterfaces', name: 'Virtual Network' },
{ type: 'Microsoft.Compute/virtualMachines', name: 'Virtual Machine' },
{ type: 'Microsoft.Search/searchServices', name: 'Azure Search' },
{ type: 'Microsoft.Compute/virtualMachines', name: 'Virtual Machine' },
{ type: 'Microsoft.Network/applicationGateways', name: 'Application Gateway' },
{ type: 'Microsoft.ApiManagement/service', name: 'API Management' },
{ type: 'Microsoft.Backup/BackupVault', name: 'Azure Backup' }];

const grid = [];
for (let i = 0; i <= types.length - 1; i += 2) {
grid.push(<Grid.Row columns={2} key={i}>
<Grid.Column>
<ToolboxComponent
resourceType={types[i].type}
addResource={(type) => this.props.addResource(type)} />
{types[i].name}
</Grid.Column>
<Grid.Column>
<ToolboxComponent
resourceType={types[i + 1].type}
addResource={(type) => this.props.addResource(type)} />
{types[i + 1].name}
</Grid.Column>
</Grid.Row>);
}

return grid;
}

render() {
return (<Sidebar as={Form} className={styles.toolbox} animation="overlay" width="wide" visible={this.props.isToolboxOpen} icon="labeled" inverted>
<Header as="h3" icon style={{ color: '#FFF' }}>
<Icon name="sitemap" />
Toolbox
<Header.Subheader style={{ color: '#FFF' }}>
Build & customize a template
</Header.Subheader>
</Header>
<Grid>
{this.generateGrid()}
</Grid>
<br />
<Form.Field><Button type="button" fluid onClick={() => this.props.dispatchButtonClick('CLOSE_TOOLBOX')}>Close</Button></Form.Field>
</Sidebar>);
}
}
Loading

0 comments on commit 22fe295

Please sign in to comment.