1
0
Fork 0
mirror of https://git.rwth-aachen.de/acs/public/villas/web/ synced 2025-03-09 00:00:01 +01:00

Merge branch 'master' into feature-use-json-schema

This commit is contained in:
irismarie 2021-04-30 16:30:10 +02:00
commit 6dd0481437
59 changed files with 4302 additions and 822 deletions

View file

@ -30,7 +30,7 @@ build:
# - build/
# expire_in: 1 week
deploy:
deploy:default:
stage: deploy
image:
name: gcr.io/kaniko-project/executor:debug
@ -40,8 +40,26 @@ deploy:
- echo "{\"auths\":{\"${CI_REGISTRY}\":{\"username\":\"${CI_REGISTRY_USER}\",\"password\":\"${CI_REGISTRY_PASSWORD}\"}}}" > /kaniko/.docker/config.json
- /kaniko/executor
--context ${CI_PROJECT_DIR}
--build-arg REACT_APP_BRAND=villasweb
--dockerfile ${CI_PROJECT_DIR}/Dockerfile
--destination ${DOCKER_IMAGE}:${DOCKER_TAG}
--snapshotMode=redo
dependencies:
- build
deploy:slew:
stage: deploy
image:
name: gcr.io/kaniko-project/executor:debug
entrypoint: [ "" ]
script:
- mkdir -p /kaniko/.docker
- echo "{\"auths\":{\"${CI_REGISTRY}\":{\"username\":\"${CI_REGISTRY_USER}\",\"password\":\"${CI_REGISTRY_PASSWORD}\"}}}" > /kaniko/.docker/config.json
- /kaniko/executor
--context ${CI_PROJECT_DIR}
--build-arg REACT_APP_BRAND=slew
--dockerfile ${CI_PROJECT_DIR}/Dockerfile
--destination ${DOCKER_IMAGE}:${DOCKER_TAG}-slew
--snapshotMode=redo
dependencies:
- build

View file

@ -27,6 +27,7 @@ ADD package.json /usr/src/app
RUN npm install
# Install app dependencies
ARG REACT_APP_BRAND
COPY . /usr/src/app
RUN npm run build

764
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -6,7 +6,6 @@
"@fortawesome/fontawesome-svg-core": "^1.2.35",
"@fortawesome/free-solid-svg-icons": "^5.15.3",
"@fortawesome/react-fontawesome": "^0.1.14",
"@rjsf/core": "^2.5.1",
"babel-runtime": "^6.26.0",
"bootstrap": "^4.6.0",
"classnames": "^2.3.1",
@ -39,8 +38,8 @@
"react-collapse": "^5.1.0",
"react-color": "^2.19.3",
"react-contexify": "^5.0.0",
"react-dnd": "^13.1.1",
"react-dnd-html5-backend": "^12.1.1",
"react-dnd": "^14.0.2",
"react-dnd-html5-backend": "^14.0.0",
"react-dom": "^17.0.2",
"react-fullscreenable": "^2.5.1-0",
"react-grid-system": "^7.1.2",
@ -52,7 +51,7 @@
"react-svg-pan-zoom": "^3.10.0",
"react-trafficlight": "^5.2.1",
"superagent": "^6.1.0",
"swagger-ui-react": "^3.47.1",
"swagger-ui-react": "^3.48.0",
"typescript": "^4.2.4"
},
"devDependencies": {},

View file

@ -3,7 +3,7 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="shortcut icon" type=image/x-icon href="%PUBLIC_URL%/favicon.ico">
<link id="dynamic-favicon" rel="shortcut icon" type=image/x-icon href="%PUBLIC_URL%/favicon.ico">
<!--
Notice the use of %PUBLIC_URL% in the tag above.
It will be replaced with the URL of the `public` folder during the build.

BIN
public/slew_blue.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4 KiB

BIN
public/slew_magenta.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

BIN
public/template_logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

View file

@ -27,7 +27,6 @@ import NotificationsDataManager from './common/data-managers/notifications-data-
import Home from './common/home';
import Header from './common/header';
import Footer from './common/footer';
import Menu from './common/menu';
import InfrastructureComponents from './ic/ics';
@ -42,6 +41,9 @@ import LoginStore from './user/login-store'
import './styles/app.css';
import branding from './branding/branding';
class App extends React.Component {
@ -101,6 +103,7 @@ class App extends React.Component {
}
let currentUser = JSON.parse(currentUserRaw);
let pages = branding.values.pages;
return <DndProvider backend={HTML5Backend} >
<div className="app">
@ -114,19 +117,23 @@ class App extends React.Component {
<div className='app-content app-content-margin-left'>
<Route exact path="/" component={Home} />
<Route path="/home" component={Home} />
<Route exact path="/scenarios" component={Scenarios} />
<Route path="/scenarios/:scenario" component={Scenario} />
<Route path="/dashboards/:dashboard" component={Dashboard} />
<Route exact path="/infrastructure" component={InfrastructureComponents} />
<Route path="/infrastructure/:ic" component={InfrastructureComponent} />
<Route path="/account" component={User} />
{ pages.home ? <Route path="/home" component={Home} /> : '' }
{ pages.scenarios ? <Route exact path="/scenarios" component={Scenarios} /> : '' }
{ pages.scenarios ? <Route path="/scenarios/:scenario" component={Scenario} /> : '' }
{ pages.scenarios ? <Route path="/dashboards/:dashboard" component={Dashboard} /> : '' }
{ currentUser.role === "Admin" || pages.infrastructure ?
<Route exact path="/infrastructure" component={InfrastructureComponents} />
: '' }
{ currentUser.role === "Admin" || pages.infrastructure ?
<Route path="/infrastructure/:ic" component={InfrastructureComponent} />
: '' }
{ pages.account ? <Route path="/account" component={User} /> : '' }
<Route path="/users" component={Users} />
<Route path="/api" component={APIBrowser} />
{ pages.api ? <Route path="/api" component={APIBrowser} /> : '' }
</div>
</div>
<Footer />
{branding.getFooter()}
</div>
</DndProvider>
}

273
src/branding/branding.js Normal file
View file

@ -0,0 +1,273 @@
/**
* This file is part of VILLASweb.
*
* VILLASweb is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* VILLASweb is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with VILLASweb. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
import { villasweb_footer, villasweb_home, villasweb_welcome } from './villasweb/villasweb-functions';
import villasweb_values from './villasweb/villasweb-values';
import { slew_home, slew_welcome } from './slew/slew-functions';
import slew_values from './slew/slew-values';
import { template_welcome, template_home, template_footer } from './template/template-functions';
import template_values from './template/template-values';
class Branding {
constructor(chosenbrand) {
this.brand = chosenbrand;
this.setValues();
this.checkValues();
this.applyStyle();
Branding.branding = this;
}
setValues() {
switch (this.brand) {
case 'villasweb':
this.values = villasweb_values;
break;
case 'slew':
this.values = slew_values;
break;
case 'template':
this.values = template_values;
break;
default:
console.error("Branding '" + this.brand + "' not available, will use 'villasweb' branding");
this.brand = 'villasweb';
this.values = villasweb_values;
break;
}
}
getHome(username = '', userid = '', role = '') {
var homepage = '';
switch (this.brand) {
case 'villasweb':
homepage = villasweb_home(this.getTitle(), username, userid, role);
break;
case 'slew':
homepage = slew_home();
break;
case 'template':
homepage = template_home();
break;
default:
homepage = villasweb_home(this.getTitle(), username, userid, role);
break;
}
return homepage;
}
getFooter() {
var footer = '';
switch(this.brand) {
case 'template':
footer = template_footer();
break;
default:
footer = villasweb_footer();
break;
}
return footer;
}
getWelcome() {
var welcome = '';
switch (this.brand) {
case 'villasweb':
welcome = villasweb_welcome();
break;
case 'slew':
welcome = slew_welcome();
break;
case 'template':
welcome = template_welcome();
break;
default:
welcome = this.defaultWelcome();
break;
}
return welcome;
}
defaultWelcome() {
return (<div><h1>Welcome!</h1><p>This is the welcome page and you are very welcome here.</p></div>);
}
// if icon cannot be found, the default favicon will be used
changeHead() {
// set title of document
let title = this.getTitle();
if (this.getSubtitle()) {
title += " " + this.getSubtitle();
}
document.title = title;
// set document icon
if (!this.values.icon) {
return;
}
var oldlink = document.getElementById('dynamic-favicon');
var link = document.createElement('link');
link.id = 'dynamic-favicon';
link.rel = 'shortcut icon'
link.href = '/' + this.values.icon;
if (oldlink) {
document.head.removeChild(oldlink);
}
document.head.appendChild(link);
}
checkValues() {
if (!this.values.hasOwnProperty('pages')) {
let pages = {};
pages.home = true;
pages.scenarios = true;
pages.infrastructure = true;
pages.users = true;
pages.account = true;
pages.api = true;
this.values.pages = pages;
} else {
if (!this.values.pages.hasOwnProperty('home')) {
this.values.pages['home'] = false;
}
if (!this.values.pages.hasOwnProperty('scenarios')) {
this.values.pages['scenarios'] = false;
}
if (!this.values.pages.hasOwnProperty('infrastructure')) {
this.values.pages['infrastructure'] = false;
}
if (!this.values.pages.hasOwnProperty('users')) {
this.values.pages['users'] = false;
}
if (!this.values.pages.hasOwnProperty('account')) {
this.values.pages['account'] = false;
}
if (!this.values.pages.hasOwnProperty('api')) {
this.values.pages['api'] = false;
}
}
}
applyStyle() {
this.changeHead();
const rootEl = document.querySelector(':root');
let background = this.getBackgroundColor();
if (background) {
rootEl.style.setProperty('--bg', background);
} else {
console.log(document.body.style.backgroundColor)
}
let maincolor = this.getMainColor();
if (maincolor) {
rootEl.style.setProperty('--maincolor', maincolor);
}
let highlight = this.getHighlightColor();
if (highlight) {
rootEl.style.setProperty('--highlights', highlight);
}
let secondary = this.getSecondaryTextColor();
if (secondary) {
rootEl.style.setProperty('--secondarytext', secondary);
}
let font = this.getFont();
if (font) {
rootEl.style.setProperty('--mainfont', font);
}
let borderradius = this.getBorderRadius();
if (borderradius) {
rootEl.style.setProperty('--borderradius', borderradius);
}
}
getLogo(style) {
let image = null;
try {
image = <img style={style} src={require('./' + this.brand + '/img/' + this.values.logo).default} alt={'Logo ' + this.values.title} />
} catch (err) {
console.error("cannot find './" + this.brand + '/img/' + this.values.logo + "'");
}
return image;
}
getBackgroundColor() {
if (this.values.style && this.values.style.background) {
return this.values.style.background;
}
return null;
}
getMainColor() {
if (this.values.style && this.values.style.maincolor) {
return this.values.style.maincolor;
}
return null;
}
getHighlightColor() {
if (this.values.style && this.values.style.highlights) {
return this.values.style.highlights;
}
return null;
}
getSecondaryTextColor() {
if (this.values.style && this.values.style.secondarytext) {
return this.values.style.secondarytext;
}
return null;
}
getFont() {
if (this.values.style && this.values.style.font) {
return this.values.style.secondarytext;
}
return null;
}
getBorderRadius() {
if (this.values.style && this.values.style.borderradius) {
return this.values.style.borderradius;
}
return null;
}
getTitle() {
return this.values.title ? this.values.title : "No Title!";
}
getSubtitle() {
return this.values.subtitle ? this.values.subtitle : null;
}
};
var branding = new Branding(process.env.REACT_APP_BRAND);
export default branding;

View file

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 27 KiB

View file

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View file

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

File diff suppressed because it is too large Load diff

After

Width:  |  Height:  |  Size: 93 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

File diff suppressed because it is too large Load diff

After

Width:  |  Height:  |  Size: 94 KiB

View file

@ -0,0 +1,66 @@
/**
* This file is part of VILLASweb.
*
* VILLASweb is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* VILLASweb is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with VILLASweb. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
import React from 'react';
import './slew.css'
export function slew_home() {
return (
<div className="home-container">
<h1>Home</h1>
<p>
Welcome to <b>SLEW</b>!
</p>
<p>SLEW is a learning platform for running experiments in a virtual power engineering world.
The platform enables interaction with the experiments in real time and performing analysis on the experimental results.</p>
<p>The motivation behind SLEW is the ongoing transformation of the energy system, which is making the system more and more complex.
Hence, understanding new phenomena and underlying interactions is getting more challenging, also because real experimental
activities for obtaining a better understanding are not possible for obvious reasons of security and safety.</p>
<p>The SLEW platform gives the possibility to perform experiments in a virtual infrastructure and to learn from the execution
of complex models. It provides a virtual power engineering world where complex phenomena take place while users can interact
with the system in real time.</p>
<p>The platform is based on the real-time simulation tool DPsim developed in RWTH,
which is available as open-source software project to the power engineering community. Besides, it integrates the interactive
computing environment Jupyter for further analysis of experimental results.</p>
<h3>Contacts</h3>
<ul>
<li><a href="mailto:jdinkelbach@eonerc.rwth-aachen.de">Jan Dinkelbach</a></li>
<li><a href="mailto:mmirz@eonerc.rwth-aachen.de">Markus Mirz</a></li>
<li><a href="mailto:stvogel@eonerc.rwth-aachen.de">Steffen Vogel</a></li>
</ul>
<h3>Credits</h3>
<div>
<img id="images" height={70} src={require('./img/eonerc_rwth.svg').default} alt="Logo EONERC"/>
<img id="images" height={70} src={require('./img/erigrid2.png').default} alt="Logo Erigrid"/>
<img id="images" height={70} src={require('./img/european_commission.svg').default} alt="Logo EU"/>
</div>
</div>)
}
export function slew_welcome() {
return (
<div >
<h1>Welcome!</h1>
<p>SLEW is a learning platform for running experiments in a virtual power engineering world.
The platform enables to interact with the experiments in real time and perform analyses on the experimental results.</p>
</div>)
}

View file

@ -0,0 +1,44 @@
/**
* This file is part of VILLASweb.
*
* VILLASweb is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* VILLASweb is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with VILLASweb. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
const slew_values = {
title: 'SLEW',
subtitle: 'Second Life for Energiewende',
icon: "slew_blue.png",
logo: "slew_logo.png",
pages: {
home: true,
scenarios: true,
infrastructure: false,
account: false,
api: false
},
links: {
"DPsim Simulator": "https://dpsim.fein-aachen.org",
"VILLASframework": "https://villas.fein-aachen.org/doc"
},
style: {
background: 'rgba(207,209,210, 1)',
highlights: 'rgba(0,84,159, 0.75)',
maincolor: 'rgba(80,80,80, 1)',
secondarytext: 'rgba(80,80,80, 0.9)',
font: "16px Roboto, sans-serif",
borderradius: "10px"
}
}
export default slew_values;

View file

@ -0,0 +1,4 @@
#images {
margin-left: 2em;
margin-right: 2em
}

View file

@ -0,0 +1,109 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="210mm"
height="297mm"
viewBox="0 0 210 297"
version="1.1"
id="svg8"
inkscape:version="0.92.3 (2405546, 2018-03-11)">
<defs
id="defs2" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.35"
inkscape:cx="400"
inkscape:cy="560"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1853"
inkscape:window-height="921"
inkscape:window-x="67"
inkscape:window-y="27"
inkscape:window-maximized="1" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<ellipse
id="path3713"
cx="107.34524"
cy="152.6131"
rx="93.738091"
ry="90.714287"
style="fill:#ffb380;stroke-width:0.46149299" />
<path
style="fill:#d45500;stroke-width:0.46149299"
id="path3717"
sodipodi:type="arc"
sodipodi:cx="108.74432"
sodipodi:cy="175.60233"
sodipodi:rx="30.779675"
sodipodi:ry="24.231895"
sodipodi:start="0"
sodipodi:end="0.17905702"
sodipodi:open="true"
d="m 139.524,175.60233 a 30.779675,24.231895 0 0 1 -0.4921,4.31574" />
<ellipse
style="fill:#d45500;stroke-width:0.46149299"
id="path3722"
cx="108.74432"
cy="178.08763"
rx="33.577824"
ry="26.71722" />
<ellipse
style="fill:#008080;stroke-width:0.46149299"
id="path3729"
cx="76.565552"
cy="128.38118"
rx="9.7935324"
ry="10.562623" />
<ellipse
style="fill:#008080;stroke-width:0.46149299"
id="path3729-3"
cx="135.32677"
cy="127.75985"
rx="9.7935324"
ry="10.562623" />
<ellipse
style="fill:#552200;stroke-width:0.46149299"
id="path3748"
cx="96.152611"
cy="183.0583"
rx="4.197228"
ry="5.5919766" />
<ellipse
style="fill:#552200;stroke-width:0.46149299"
id="path3748-6"
cx="117.1388"
cy="183.67961"
rx="4.197228"
ry="5.5919766" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.9 KiB

View file

@ -0,0 +1,52 @@
/**
* This file is part of VILLASweb.
*
* VILLASweb is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* VILLASweb is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with VILLASweb. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
import React from 'react';
export function template_home() {
return (
<div className="home-container">
<img style={{ height: 120, float: 'right' }} src={require('./img/template_logo.svg').default} alt="Template Logo" />
<h1>Home</h1>
<p>
Welcome to <b>BRAND</b>!
</p>
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut
labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum.
Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p>
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore
et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum.
Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p>
</div>)
}
export function template_welcome() {
return (
<div >
<h1>Welcome!</h1>
<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut
labore et dolore magna aliquyam erat, sed diam voluptua.</p>
</div>)
}
export function template_footer() {
return (
<footer className="app-footer">
<p>HELLO WORLD, THIS IS MY FOOTER!</p>
</footer>)
}

View file

@ -15,18 +15,30 @@
* along with VILLASweb. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
const config = {
publicPathBase: 'public/',
instance: 'VILLASweb',
subtitle: 'ACS',
admin: {
name: 'Institute for Automation of Complex Power Systems (ACS), RWTH Aachen University, Germany',
mail: 'stvogel@eonerc.rwth-aachen.de'
const template_values = {
title: 'Template',
subtitle: 'change me!',
icon: "template_logo.svg",
pages: {
home: true,
scenarios: true,
infrastructure: true,
users: true,
account: true,
api: true
},
externalAuth: true,
loginURL: '/oauth2/start?rd=/login/complete',
provider: 'Jupyter',
disableVillasLogin: false,
};
export default config
links: {
"Google": "https://www.google.com/",
"StackOverFlow": "https://stackoverflow.com/"
},
style: {
background: 'rgba(50,30,90, 0.6)',
highlights: 'rgba(0,230,5, 0.75)',
maincolor: 'rgba(255,0,0, 1)',
secondarytext: 'rgba(0,0,100, 0.8)',
font: "16px Comic Sans, sans-serif",
borderradius: "60px"
}
}
export default template_values;

View file

Before

Width:  |  Height:  |  Size: 192 KiB

After

Width:  |  Height:  |  Size: 192 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

View file

@ -0,0 +1,272 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
version="1.1"
width="300"
height="207.72354"
id="svg15656">
<defs
id="defs15658" />
<metadata
id="metadata15661">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
transform="translate(-206.87716,-301.85899)"
id="layer1">
<g
transform="matrix(4.5286013,0,0,4.5286013,-1067.5668,-2047.9402)"
id="g15525">
<path
d="m 281.42172,530.9313 c 0,0 19.6275,-2.54 20.18125,-2.63 0.85,-0.13875 1.60375,-0.30125 2.3075,-0.495 1.5875,-0.435 3.04875,-1.09875 4.3425,-1.97375 1.24125,-0.83125 2.395,-2.04125 3.53875,-3.36875 0.72625,-0.845 1.49,-1.94625 2.2025,-3.00875 l 0,-0.51375 c -0.845,1.25125 -1.6775,2.33 -2.53375,3.28125 -1.135,1.26375 -2.325,2.29625 -3.53875,3.07125 -1.2525,0.8075 -2.66125,1.40875 -4.19,1.79 -0.685,0.1725 -1.4175,0.3125 -2.2425,0.4275 -0.5425,0.0762 -1.1025,0.135 -1.64375,0.19125 -0.21625,0.0238 -18.42375,1.955 -18.42375,1.955 l 0,1.27375 z"
id="path5555"
style="fill:#bdbcbc;fill-opacity:1;fill-rule:nonzero;stroke:none" />
<path
d="m 307.74272,527.64055 c -1.22875,0.70625 -2.6475,1.22375 -4.2175,1.53625 -0.67,0.13625 -1.40125,0.24625 -2.23375,0.33625 -0.49,0.0537 -0.9825,0.0962 -1.47625,0.13875 -0.26625,0.0225 -0.5325,0.0462 -0.79875,0.07 -6.015,0.54 -11.99875,1.11375 -17.595,1.65625 l 0,1.27375 c 5.64,-0.68 11.66625,-1.40125 17.67875,-2.08125 0.2675,-0.0312 0.535,-0.0612 0.8025,-0.09 0.4925,-0.0538 0.98625,-0.10875 1.48,-0.17375 0.85625,-0.11375 1.605,-0.245 2.28875,-0.4 1.63125,-0.365 3.10375,-0.94 4.3775,-1.71125 1.265,-0.75875 2.3825,-1.8225 3.585,-3.1225 0.74875,-0.80875 1.58125,-1.95125 2.36125,-3.02375 l 0,-0.4675 c -0.91875,1.245 -1.79,2.29125 -2.65125,3.18375 -1.17375,1.21625 -2.385,2.1825 -3.60125,2.875"
id="path5559"
style="fill:#bdbcbc;fill-opacity:1;fill-rule:nonzero;stroke:none" />
<path
d="m 311.1776,527.32868 c -1.1975,1.09875 -2.4475,1.9625 -3.71625,2.5675 -1.24125,0.59875 -2.62875,1.01875 -4.245,1.28375 -0.66625,0.11125 -1.39125,0.20125 -2.215,0.27625 l -19.58,1.6075 0,1.27 17.405,-1.84625 2.25125,-0.23625 c 0.84875,-0.0987 1.58875,-0.20875 2.26125,-0.33625 1.67375,-0.31625 3.11,-0.7875 4.38875,-1.4425 1.3075,-0.66125 2.61375,-1.76125 3.82875,-2.92625 0.815,-0.78125 1.6,-1.79 2.43875,-2.8475 l 0,-0.42375 c -0.96875,1.205 -1.89375,2.2075 -2.8175,3.05375"
id="path5563"
style="fill:#bdbcbc;fill-opacity:1;fill-rule:nonzero;stroke:none" />
<path
d="m 306.4431,533.92568 c -1.14,0.6375 -1.9925,1.005 -3.62,1.175 -0.98375,0.10625 -1.995,0.15625 -2.97375,0.205 -0.4725,0.0237 -0.94625,0.0475 -1.42,0.0775 -2.9575,0.16875 -5.8625,0.35625 -8.82625,0.54875 l -8.18125,0.55125 0,1.27 8.26375,-0.7575 c 2.67,-0.24 5.7725,-0.51625 8.80125,-0.76375 l 2.2025,-0.17 c 0.86,-0.0662 1.565,-0.13625 2.2175,-0.22125 1.675,-0.21625 3.10625,-0.555 4.37375,-1.03375 1.365,-0.51 2.6525,-1.3025 3.94125,-2.235 1.1625,-0.84 2.77125,-2.49625 2.7725,-2.5175 l 0,-0.44875 c -1.05125,1.025 -1.65625,1.60125 -2.8075,2.36 -1.37625,0.90625 -3.72125,1.38875 -4.74375,1.96"
id="path5567"
style="fill:#bdbcbc;fill-opacity:1;fill-rule:nonzero;stroke:none" />
<path
d="m 306.85935,536.33993 c -1.235,0.3625 -2.625,0.6075 -4.25,0.74875 -0.65875,0.0575 -1.36875,0.10125 -2.17125,0.13375 l -2.19,0.0962 c -5.44125,0.2525 -10.8575,0.535 -16.82625,0.85125 l 0,1.26625 c 5.7025,-0.44125 11.29,-0.87 16.87625,-1.2675 l 2.1825,-0.14875 c 0.84375,-0.0563 1.5425,-0.11625 2.2,-0.19 1.665,-0.18625 3.09,-0.47375 4.355,-0.87875 1.40125,-0.44375 2.7675,-1.0875 4.06,-1.9125 0.95375,-0.6075 1.90875,-1.3325 2.89875,-2.19625 l 0,-0.0225 c -1.09125,0.93125 -2.13125,1.13875 -3.1675,1.76375 -1.27,0.77 -2.605,1.36 -3.9675,1.75625"
id="path5571"
style="fill:#bdbcbc;fill-opacity:1;fill-rule:nonzero;stroke:none" />
<path
d="m 306.65735,538.44468 c -1.24375,0.29125 -2.5925,0.4775 -4.24375,0.58875 -0.63625,0.0425 -1.32125,0.0738 -2.155,0.1 l -2.16875,0.0775 c -5.465,0.20625 -11.00625,0.44375 -16.66875,0.69 l 0,1.26625 c 5.62625,-0.38375 11.145,-0.7575 16.71125,-1.105 l 2.16375,-0.13 c 0.84875,-0.0488 1.54,-0.0975 2.17625,-0.15625 1.68125,-0.155 3.0575,-0.38125 4.33,-0.71 1.4275,-0.3675 2.815,-0.9075 4.12375,-1.6025 1.0125,-0.53625 2.0225,-1.18125 3.06875,-1.95875 l 0,-0.54125 c -1.13125,0.81625 -2.21625,1.4825 -3.30125,2.025 -1.28625,0.64375 -2.64375,1.13375 -4.03625,1.45625"
id="path5575"
style="fill:#bdbcbc;fill-opacity:1;fill-rule:nonzero;stroke:none" />
<path
d="m 306.4721,540.50831 c -1.24875,0.22875 -2.5925,0.375 -4.23125,0.45875 -0.61625,0.0325 -1.27625,0.055 -2.13875,0.075 l -18.68,0.505 0,1.26625 16.56375,-0.865 2.14625,-0.10875 c 0.8375,-0.04 1.5225,-0.08 2.15625,-0.12875 1.66125,-0.1275 3.0275,-0.31 4.3,-0.57625 1.445,-0.3 2.8475,-0.7375 4.1675,-1.3 1.06375,-0.45125 2.12875,-1.00125 3.23875,-1.67 l 0,-0.50875 c -1.185,0.69 -2.3125,1.2425 -3.4325,1.68625 -1.30125,0.5175 -2.6775,0.91 -4.09,1.16625"
id="path5579"
style="fill:#bdbcbc;fill-opacity:1;fill-rule:nonzero;stroke:none" />
<path
d="m 306.32547,542.58081 c -2.2925,0.30625 -4.65125,0.34125 -6.93375,0.375 -0.5225,0.007 -1.04625,0.015 -1.56875,0.0263 l -16.40125,0.295 0,1.26375 16.43,-0.7075 c 0.52,-0.0237 1.0425,-0.045 1.565,-0.065 2.2975,-0.0925 4.67375,-0.1875 6.9975,-0.55625 1.47,-0.23125 2.885,-0.575 4.20625,-1.01875 1.09375,-0.36625 2.22625,-0.84 3.37375,-1.4 l 0,-0.485 c -1.20625,0.56125 -2.3925,1.02875 -3.53125,1.37875 -1.305,0.4025 -2.69625,0.70375 -4.1375,0.89375"
id="path5583"
style="fill:#bdbcbc;fill-opacity:1;fill-rule:nonzero;stroke:none" />
<path
d="m 306.19522,544.6663 c -2.1475,0.1775 -4.345,0.1775 -6.47125,0.1775 -0.66125,0 -1.3225,0 -1.98375,0.005 -5.43375,0.0238 -10.82375,0.0688 -16.31875,0.11625 l 0,1.26375 c 5.23375,-0.1775 10.785,-0.3625 16.3375,-0.5275 0.65875,-0.0225 1.3175,-0.0387 1.9775,-0.0562 2.1375,-0.0537 4.3475,-0.10875 6.5175,-0.34375 1.515,-0.1625 2.895,-0.40125 4.21625,-0.7275 1.1525,-0.28375 2.33625,-0.66125 3.525,-1.115 l 0,-0.465 c -1.2275,0.44 -2.45,0.8 -3.64125,1.0625 -1.30875,0.28875 -2.66875,0.4875 -4.15875,0.61"
id="path5587"
style="fill:#bdbcbc;fill-opacity:1;fill-rule:nonzero;stroke:none" />
<path
d="m 306.11223,546.72218 c -0.895,0.035 -1.86375,0.0525 -2.9625,0.0525 -0.415,0 -0.83125,-0.002 -1.245,-0.006 l -4.2275,-0.0512 c -2.88375,-0.0213 -5.7575,-0.0263 -8.45375,-0.0287 l -7.80125,0.007 0,1.2625 7.82,-0.20375 c 2.68625,-0.0662 5.5675,-0.135 8.44375,-0.18625 l 4.22375,-0.0563 c 1.15875,-0.0175 2.6875,-0.0525 4.23625,-0.15375 1.5175,-0.0987 2.89875,-0.25 4.2225,-0.46125 1.19125,-0.19 2.40875,-0.44625 3.62625,-0.7575 l 0,-0.4475 c -1.25125,0.2875 -2.495,0.51875 -3.70125,0.68 -1.31625,0.17625 -2.68375,0.29 -4.18125,0.35"
id="path5591"
style="fill:#bdbcbc;fill-opacity:1;fill-rule:nonzero;stroke:none" />
<path
d="m 301.8556,548.7088 -4.2125,-0.045 c -5.375,-0.0763 -10.74375,-0.17375 -16.22125,-0.27625 l 0,1.26375 c 5.2275,-0.0337 10.765,-0.0738 16.225,-0.135 l 4.215,-0.0625 c 1.42,-0.025 2.81125,-0.0512 4.2175,-0.0975 2.89625,-0.0925 5.49125,-0.29625 7.915,-0.6175 l 0,-0.44 c -2.43375,0.2625 -5.03125,0.4 -7.93,0.41875 -1.40125,0.0125 -2.805,0.003 -4.20875,-0.009"
id="path5595"
style="fill:#bdbcbc;fill-opacity:1;fill-rule:nonzero;stroke:none" />
<path
d="m 313.99473,550.94356 -32.5725,-0.82625 0,1.26375 32.5725,0 0,-0.4375 z"
id="path5599"
style="fill:#bdbcbc;fill-opacity:1;fill-rule:nonzero;stroke:none" />
<path
d="m 311.06173,529.71581 c -1.2375,0.99375 -2.1925,1.7 -3.7075,2.30125 -1.31875,0.525 -2.735,0.73875 -4.35375,0.96 -1.04125,0.14625 -2.13,0.36125 -3.17,0.43125 -0.4275,0.0287 -0.855,0.0562 -1.28125,0.09 l -17.1275,1.24875 0,1.2675 17.19625,-1.6675 2.23,-0.20875 c 0.82625,-0.0788 1.56125,-0.16875 2.24375,-0.28 1.66625,-0.2675 3.1025,-0.675 4.39,-1.24875 1.335,-0.58875 2.68625,-1.55375 3.9425,-2.61 0.85375,-0.7175 1.67625,-1.62 2.57,-2.60625 l 0,-0.45375 c -1.08125,1.1175 -1.97875,2.01125 -2.9325,2.77625"
id="path5603"
style="fill:#bdbcbc;fill-opacity:1;fill-rule:nonzero;stroke:none" />
<path
d="m 294.96035,563.49518 28.5325,0 0,-12.68875 -28.5325,0 0,12.68875 z"
id="path5605"
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none" />
<path
d="m 323.49785,532.29018 -28.5375,0 0,19.09 28.5375,0 0,-19.09 z"
id="path5607"
style="fill:#254aa5;fill-opacity:1;fill-rule:nonzero;stroke:none" />
<path
d="m 309.53872,535.00493 0.9925,0 -0.8,0.62375 0.31125,0.98875 -0.7975,-0.60875 -0.7975,0.60875 0.315,-0.98875 -0.8075,-0.62375 0.99,0 0.3,-0.965 0.29375,0.965 z"
id="path5611"
style="fill:#fff200;fill-opacity:1;fill-rule:nonzero;stroke:none" />
<path
d="m 309.57373,547.73581 0.995,0 -0.80125,0.60125 0.31125,0.95 -0.7975,-0.585 -0.79625,0.585 0.31375,-0.95 -0.80875,-0.60125 0.99125,0 0.3,-0.9275 0.2925,0.9275 z"
id="path5615"
style="fill:#fff200;fill-opacity:1;fill-rule:nonzero;stroke:none" />
<path
d="m 312.72285,546.8928 0.995,0 -0.80125,0.6 0.31125,0.95125 -0.7975,-0.5875 -0.79625,0.5875 0.31375,-0.95125 -0.80875,-0.6 0.99125,0 0.3,-0.92875 0.2925,0.92875 z"
id="path5619"
style="fill:#fff200;fill-opacity:1;fill-rule:nonzero;stroke:none" />
<path
d="m 312.72285,535.85418 0.995,0 -0.80125,0.6 0.31125,0.95125 -0.7975,-0.58625 -0.79625,0.58625 0.31375,-0.95125 -0.80875,-0.6 0.99125,0 0.3,-0.9275 0.2925,0.9275 z"
id="path5623"
style="fill:#fff200;fill-opacity:1;fill-rule:nonzero;stroke:none" />
<path
d="m 315.06097,538.19205 0.9925,0 -0.8,0.59875 0.31125,0.9525 -0.7975,-0.58625 -0.795,0.58625 0.31375,-0.9525 -0.80875,-0.59875 0.99,0 0.3,-0.92875 0.29375,0.92875 z"
id="path5627"
style="fill:#fff200;fill-opacity:1;fill-rule:nonzero;stroke:none" />
<path
d="m 315.06097,544.58668 0.9925,0 -0.8,0.60125 0.31125,0.9525 -0.7975,-0.5875 -0.795,0.5875 0.31375,-0.9525 -0.80875,-0.60125 0.99,0 0.3,-0.92875 0.29375,0.92875 z"
id="path5631"
style="fill:#fff200;fill-opacity:1;fill-rule:nonzero;stroke:none" />
<path
d="m 315.93698,541.34055 0.995,0 -0.80125,0.6 0.31125,0.9525 -0.7975,-0.5875 -0.79625,0.5875 0.31375,-0.9525 -0.80875,-0.6 0.99,0 0.30125,-0.9275 0.2925,0.9275 z"
id="path5635"
style="fill:#fff200;fill-opacity:1;fill-rule:nonzero;stroke:none" />
<path
d="m 306.3281,535.86193 0.9925,0 -0.8,0.60125 0.31125,0.95125 -0.7975,-0.5875 -0.7975,0.5875 0.315,-0.95125 -0.8075,-0.60125 0.99,0 0.3,-0.9275 0.29375,0.9275 z"
id="path5639"
style="fill:#fff200;fill-opacity:1;fill-rule:nonzero;stroke:none" />
<path
d="m 304.05485,538.1998 0.995,0 -0.80125,0.6 0.31,0.9525 -0.79625,-0.5875 -0.79625,0.5875 0.3125,-0.9525 -0.8075,-0.6 0.99125,0 0.3,-0.9275 0.2925,0.9275 z"
id="path5643"
style="fill:#fff200;fill-opacity:1;fill-rule:nonzero;stroke:none" />
<path
d="m 303.2111,541.34843 0.99375,0 -0.8,0.6 0.31,0.9525 -0.79625,-0.58625 -0.7975,0.58625 0.31375,-0.9525 -0.80625,-0.6 0.99,0 0.3,-0.9275 0.2925,0.9275 z"
id="path5647"
style="fill:#fff200;fill-opacity:1;fill-rule:nonzero;stroke:none" />
<path
d="m 304.05485,544.59456 0.995,0 -0.80125,0.60125 0.31,0.9525 -0.79625,-0.5875 -0.79625,0.5875 0.3125,-0.9525 -0.8075,-0.60125 0.99125,0 0.3,-0.92625 0.2925,0.92625 z"
id="path5651"
style="fill:#fff200;fill-opacity:1;fill-rule:nonzero;stroke:none" />
<path
d="m 306.36122,546.90068 0.9925,0 -0.8,0.6 0.30875,0.95125 -0.795,-0.58625 -0.7975,0.58625 0.315,-0.95125 -0.8075,-0.6 0.99,0 0.3,-0.92875 0.29375,0.92875 z"
id="path5655"
style="fill:#fff200;fill-opacity:1;fill-rule:nonzero;stroke:none" />
<path
d="m 294.96035,564.74893 28.54,0 0,-1.62875 -28.54,0 0,1.62875 z"
id="path5657"
style="fill:#254aa5;fill-opacity:1;fill-rule:nonzero;stroke:none" />
<path
d="m 327.55922,518.87968 c 0,0 5.95,9.26625 7.03875,10.97 1.0875,1.7025 2.33125,3.05 6.73375,3.965 4.4025,0.915 6.31875,1.3475 6.31875,1.3475 l 0,0.33 c 0,0 -2.7975,-0.585 -6.3975,-1.3725 -3.59875,-0.7875 -5.07,-1.05375 -6.71125,-3.29125 -1.36625,-1.8625 -6.9825,-9.77875 -6.9825,-9.77875 l 0,-2.17 z"
id="path5661"
style="fill:#bdbcbc;fill-opacity:1;fill-rule:nonzero;stroke:none" />
<path
d="m 327.55922,521.51443 c 0,0 6.14875,8.80875 6.965,9.88875 0.81625,1.08 1.915,2.82 6.775,3.8475 1.255,0.265 6.3675,1.27125 6.3675,1.27125 l 0,0.27875 c 0,0 -3.885,-0.74875 -6.3675,-1.27125 -2.48375,-0.5225 -5.0925,-0.99875 -6.7575,-3.09875 -1.5125,-1.9075 -6.99375,-8.9425 -6.99375,-8.9425 l 0.0112,-1.97375 z"
id="path5665"
style="fill:#bdbcbc;fill-opacity:1;fill-rule:nonzero;stroke:none" />
<path
d="m 327.55922,524.16068 c 0,0 5.79375,7.48625 6.965,8.98375 1.17,1.49625 2.78375,2.7325 6.775,3.49875 2.30125,0.4425 6.35,1.18375 6.35,1.18375 l 0,0.27875 c 0,0 -3.5475,-0.66125 -6.35,-1.16625 -2.8025,-0.505 -5.11625,-0.99375 -6.775,-2.855 -1.455,-1.63375 -6.97625,-8.055 -6.97625,-8.055 l 0.0112,-1.86875 z"
id="path5669"
style="fill:#bdbcbc;fill-opacity:1;fill-rule:nonzero;stroke:none" />
<path
d="m 327.54773,526.76056 c 0,0 5.86625,6.79125 6.99375,8.0025 1.75625,1.88625 2.6075,2.53625 6.7575,3.325 1.66,0.31625 6.35,1.1325 6.35,1.1325 l 0,0.295 c 0,0 -3.88375,-0.69625 -6.35,-1.13125 -2.465,-0.435 -4.55125,-0.5975 -6.775,-2.73375 -1.69375,-1.62625 -6.965,-7.1375 -6.965,-7.1375 l -0.0113,-1.7525 z"
id="path5673"
style="fill:#bdbcbc;fill-opacity:1;fill-rule:nonzero;stroke:none" />
<path
d="m 327.55922,529.46493 c 0,0 5.41625,5.56375 6.9825,7.16125 1.66125,1.69375 3.79,2.32125 6.74,2.8375 2.81625,0.4925 6.3675,1.0625 6.3675,1.0625 l 0,0.3125 c 0,0 -3.335,-0.535 -6.3675,-1.04375 -2.97375,-0.5 -5.055,-0.7775 -6.7575,-2.31625 -1.525,-1.3775 -6.965,-6.3775 -6.965,-6.3775 l 0,-1.63625 z"
id="path5677"
style="fill:#bdbcbc;fill-opacity:1;fill-rule:nonzero;stroke:none" />
<path
d="m 327.55922,531.9718 c 0,0 5.15125,4.68875 6.9825,6.29125 1.685,1.47375 3.05125,1.9325 6.7575,2.57625 3.7075,0.64375 6.35,1.04375 6.35,1.04375 l 0,0.33125 c 0,0 -3.3525,-0.54 -6.3675,-1.01 -3.015,-0.47 -4.93625,-0.655 -6.74,-2.08875 -2.08125,-1.655 -6.9825,-5.61125 -6.9825,-5.61125 l 0,-1.5325 z"
id="path5681"
style="fill:#bdbcbc;fill-opacity:1;fill-rule:nonzero;stroke:none" />
<path
d="m 327.54748,534.65293 c 0,0 5.87625,4.5675 6.97625,5.3675 1.1,0.80125 2.55375,1.735 6.775,2.33375 4.18625,0.5925 6.3325,0.8875 6.3325,0.8875 l 0,0.34875 c 0,0 -3.795,-0.54125 -6.3325,-0.85375 -2.53625,-0.31375 -4.48125,-0.44625 -6.7575,-1.9325 -2.21625,-1.44625 -6.9825,-4.735 -6.9825,-4.735 l -0.0113,-1.41625 z"
id="path5685"
style="fill:#bdbcbc;fill-opacity:1;fill-rule:nonzero;stroke:none" />
<path
d="m 327.54748,537.21793 c 0,0 5.89375,3.8475 7.01125,4.4575 1.11875,0.60875 2.43125,1.60125 6.74,2.14125 4.31,0.53875 6.3325,0.7825 6.3325,0.7825 l 0,0.33125 c 0,0 -3.565,-0.3825 -6.35,-0.67875 -2.785,-0.29625 -4.6825,-0.69625 -6.7575,-1.81125 -2.075,-1.11375 -6.965,-3.91125 -6.965,-3.91125 l -0.0113,-1.31125 z"
id="path5689"
style="fill:#bdbcbc;fill-opacity:1;fill-rule:nonzero;stroke:none" />
<path
d="m 327.55922,539.78293 c 0,0 5.21625,2.78125 6.9825,3.65 1.96875,0.96875 3.67125,1.43375 6.7575,1.7925 3.03,0.355 6.35,0.6975 6.35,0.6975 l 0,0.31375 c 0,0 -3.07,-0.3225 -6.35,-0.6275 -3.25125,-0.30125 -4.41,-0.44125 -6.7575,-1.4625 -2.1,-0.9125 -6.99375,-3.145 -6.99375,-3.145 l 0.0112,-1.21875 z"
id="path5693"
style="fill:#bdbcbc;fill-opacity:1;fill-rule:nonzero;stroke:none" />
<path
d="m 327.55922,542.39431 c 0,0 4.10375,1.7225 7,2.84875 2.85,1.10875 5.02625,1.2025 6.7575,1.39375 0.7625,0.0838 6.315,0.64375 6.315,0.64375 l 0,0.3125 c 0,0 -3.3175,-0.26 -6.3325,-0.52125 -3.015,-0.26125 -4.31625,-0.37125 -6.7575,-1.16625 -2.47125,-0.80375 -6.99375,-2.35 -6.99375,-2.35 l 0.0112,-1.16125 z"
id="path5697"
style="fill:#bdbcbc;fill-opacity:1;fill-rule:nonzero;stroke:none" />
<path
d="m 327.55922,545.04056 c 0,0 4.1625,1.265 7,1.99625 2.8375,0.73125 5.445,1.0275 6.7575,1.11375 1.3125,0.0875 6.315,0.4875 6.315,0.4875 l 0,0.29625 c 0,0 -2.8375,-0.19 -6.3325,-0.435 -2.82625,-0.1975 -5.09625,-0.40625 -6.7575,-0.76625 -1.84125,-0.39875 -6.99375,-1.60125 -6.99375,-1.60125 l 0.0112,-1.09125 z"
id="path5701"
style="fill:#bdbcbc;fill-opacity:1;fill-rule:nonzero;stroke:none" />
<path
d="m 327.54773,547.65218 c 0,0 3.415,0.57625 7.01125,1.16 2.69625,0.43875 6.35,0.715 6.74,0.73125 0.39,0.0175 6.35,0.41875 6.35,0.41875 l 0,0.3125 c 0,0 -3.81375,-0.1925 -6.35,-0.33 -2.64125,-0.14375 -5.26625,-0.3 -6.7575,-0.4525 -3.34,-0.3425 -6.99375,-0.795 -6.99375,-0.795 l 0,-1.045 z"
id="path5705"
style="fill:#bdbcbc;fill-opacity:1;fill-rule:nonzero;stroke:none" />
<path
d="m 327.55922,550.35593 c 0,0 5.36875,0.1975 7,0.2325 1.63125,0.035 13.09,0.4875 13.09,0.4875 l 0,0.31375 -20.09,-0.0125 0,-1.02125 z"
id="path5709"
style="fill:#bdbcbc;fill-opacity:1;fill-rule:nonzero;stroke:none" />
<path
d="m 296.6286,553.26193 c 0,-0.0588 0.0275,-0.09 0.09,-0.09 l 1.65625,0 c 0.0538,0 0.0863,0.0312 0.0863,0.085 l 0,0.28 c 0,0.0538 -0.0225,0.0813 -0.09,0.0813 l -1.22875,0 0,0.77375 1.08875,0 c 0.0587,0 0.09,0.0275 0.09,0.0812 l 0,0.27875 c 0,0.0538 -0.0225,0.0812 -0.09,0.0812 l -1.08875,0 0,0.88625 1.26,0 c 0.0537,0 0.0813,0.0275 0.0813,0.0863 l 0,0.27375 c 0,0.0588 -0.0225,0.0812 -0.0863,0.0812 l -1.67875,0 c -0.0625,0 -0.09,-0.0275 -0.09,-0.0812 l 0,-2.8175 z"
id="path5713"
style="fill:#5a5758;fill-opacity:1;fill-rule:nonzero;stroke:none" />
<path
d="m 300.5711,556.16093 -0.32,0 c -0.0675,0 -0.085,-0.0312 -0.085,-0.085 l 0,-0.14 -0.009,-0.005 c -0.17625,0.1225 -0.4825,0.27 -0.75625,0.27 -0.6075,0 -0.66625,-0.36 -0.66625,-0.8325 l 0,-1.32375 c 0,-0.0537 0.0225,-0.0888 0.085,-0.0888 l 0.32875,0 c 0.0588,0 0.0813,0.0312 0.0813,0.0888 l 0,1.265 c 0,0.27125 0.0537,0.44125 0.32875,0.44125 0.19375,0 0.49,-0.14375 0.6075,-0.2025 l 0,-1.50375 c 0,-0.0537 0.0175,-0.0888 0.085,-0.0888 l 0.32,0 c 0.0625,0 0.085,0.0312 0.085,0.0888 l 0,2.03125 c 0,0.0575 -0.0225,0.085 -0.085,0.085"
id="path5717"
style="fill:#5a5758;fill-opacity:1;fill-rule:nonzero;stroke:none" />
<path
d="m 301.5336,556.07543 c 0,0.0538 -0.0225,0.085 -0.085,0.085 l -0.325,0 c -0.0625,0 -0.085,-0.0263 -0.085,-0.085 l 0,-2.03 c 0,-0.0588 0.0225,-0.09 0.085,-0.09 l 0.32,0 c 0.0675,0 0.09,0.0362 0.09,0.09 l 0,0.1975 0.009,0.009 c 0.135,-0.125 0.455,-0.27875 0.66625,-0.31875 0.0588,-0.0138 0.0987,0 0.10875,0.0762 l 0.0312,0.30125 c 0.004,0.0638 0.009,0.09 -0.0862,0.10875 -0.25125,0.0488 -0.57125,0.13875 -0.72875,0.20625 l 0,1.45 z"
id="path5721"
style="fill:#5a5758;fill-opacity:1;fill-rule:nonzero;stroke:none" />
<path
d="m 303.42835,554.3423 c -0.3825,0 -0.46875,0.24375 -0.46875,0.71125 0,0.4775 0.0862,0.71125 0.46375,0.71125 0.41,0 0.49125,-0.23 0.49125,-0.71125 0,-0.4775 -0.0763,-0.71125 -0.48625,-0.71125 m -0.005,1.855 c -0.90375,0 -0.9625,-0.6625 -0.9625,-1.175 0,-0.42375 0.0937,-1.1125 0.9625,-1.1125 0.87375,0 0.995,0.58125 0.995,1.1125 0,0.5125 -0.0625,1.175 -0.995,1.175"
id="path5725"
style="fill:#5a5758;fill-opacity:1;fill-rule:nonzero;stroke:none" />
<path
d="m 305.76373,554.36943 c -0.185,0 -0.46875,0.13 -0.60375,0.2025 l 0,1.125 c 0.2025,0.0588 0.365,0.0763 0.51875,0.0763 0.32375,0 0.43625,-0.16625 0.43625,-0.7325 0,-0.5725 -0.1125,-0.67125 -0.35125,-0.67125 m -0.0362,1.8325 c -0.14875,0 -0.355,-0.0275 -0.5625,-0.1 l -0.005,0.005 0,0.7925 c 0,0.0487 -0.0125,0.09 -0.085,0.09 l -0.32,0 c -0.0712,0 -0.085,-0.0312 -0.085,-0.09 l 0,-2.85375 c 0,-0.0587 0.0225,-0.09 0.085,-0.09 l 0.32,0 c 0.0638,0 0.0813,0.035 0.0813,0.09 l 0,0.135 0.0138,0.009 c 0.16125,-0.1125 0.45,-0.27 0.71125,-0.27 0.58875,0 0.7425,0.445 0.7425,1.125 0,0.73375 -0.185,1.1575 -0.89625,1.1575"
id="path5729"
style="fill:#5a5758;fill-opacity:1;fill-rule:nonzero;stroke:none" />
<path
d="m 307.4016,554.85555 0.89125,0 c 0,-0.275 -0.0725,-0.54 -0.445,-0.54 -0.33375,0 -0.42375,0.2025 -0.44625,0.54 m -0.005,0.3375 c 0.0138,0.455 0.17625,0.58125 0.545,0.58125 0.1625,0 0.41375,-0.0325 0.585,-0.05 0.0813,-0.009 0.10875,-0.009 0.1225,0.0763 l 0.0263,0.14875 c 0.0138,0.0675 0.005,0.10375 -0.0762,0.14 -0.17625,0.0675 -0.50375,0.1125 -0.725,0.1125 -0.86,0 -0.98625,-0.54875 -0.98625,-1.135 0,-0.43625 0.0813,-1.15625 0.96,-1.15625 0.805,0 0.94875,0.5225 0.9625,1.0075 0.005,0.1625 -0.04,0.275 -0.22,0.275 l -1.19375,0 z"
id="path5733"
style="fill:#5a5758;fill-opacity:1;fill-rule:nonzero;stroke:none" />
<path
d="m 310.40323,555.15693 -0.54875,0 c -0.225,0 -0.37,0.0813 -0.37,0.37875 0,0.1975 0.0675,0.26125 0.28,0.26125 0.19375,0 0.4675,-0.11375 0.63875,-0.2125 l 0,-0.4275 z m 0.0275,0.7475 c -0.225,0.17125 -0.5275,0.2925 -0.82875,0.2925 -0.4775,0 -0.61625,-0.26125 -0.61625,-0.63875 -0.005,-0.5275 0.27875,-0.7525 0.84625,-0.7525 l 0.57625,0 0,-0.11625 c 0,-0.27 -0.1,-0.365 -0.46875,-0.365 -0.14875,0 -0.4325,0.0225 -0.6125,0.04 -0.09,0.0138 -0.1125,0.009 -0.125,-0.0537 l -0.0412,-0.16625 c -0.009,-0.0588 0.005,-0.095 0.10375,-0.135 0.19375,-0.0675 0.54875,-0.0987 0.76125,-0.0987 0.77875,0 0.8725,0.31875 0.8725,0.82375 l 0,0.86875 c 0,0.18375 0.0225,0.18875 0.1625,0.20625 0.0675,0.005 0.085,0.0187 0.085,0.0675 l 0,0.19 c 0,0.0488 -0.0312,0.08 -0.1075,0.0937 -0.0725,0.0138 -0.14375,0.0225 -0.21125,0.0225 -0.2125,0 -0.3425,-0.0625 -0.3875,-0.27375 l -0.009,-0.005 z"
id="path5737"
style="fill:#5a5758;fill-opacity:1;fill-rule:nonzero;stroke:none" />
<path
d="m 313.10785,556.16093 -0.32375,0 c -0.0588,0 -0.0863,-0.0275 -0.0863,-0.085 l 0.005,-1.265 c 0,-0.26625 -0.0625,-0.44125 -0.32375,-0.44125 -0.18,0 -0.495,0.14375 -0.6175,0.2025 l 0,1.50375 c 0,0.0538 -0.0225,0.085 -0.085,0.085 l -0.32,0 c -0.0625,0 -0.085,-0.0275 -0.085,-0.085 l 0,-2.03125 c 0,-0.0575 0.0225,-0.0888 0.085,-0.0888 l 0.32,0 c 0.0625,0 0.085,0.0312 0.085,0.0888 l 0,0.13625 c 0.005,0 0.01,0.004 0.0138,0.004 0.16625,-0.11625 0.48125,-0.27 0.75625,-0.27 0.6075,0 0.6625,0.40125 0.6625,0.855 l 0,1.30625 c 0,0.0538 -0.0188,0.085 -0.0863,0.085"
id="path5741"
style="fill:#5a5758;fill-opacity:1;fill-rule:nonzero;stroke:none" />
<path
d="m 297.80335,557.89043 c 0.22,0 0.585,0.0312 0.82375,0.13 0.0725,0.0325 0.0987,0.0688 0.085,0.14 l -0.04,0.185 c -0.0138,0.0538 -0.0362,0.0763 -0.1175,0.0675 -0.22,-0.0275 -0.49,-0.0587 -0.72375,-0.0587 -0.6125,0 -0.7025,0.495 -0.7025,1.08 0,0.59 0.1125,1.05375 0.7025,1.05375 0.26,0 0.48125,-0.0275 0.72375,-0.0588 0.0863,-0.009 0.10375,0.0138 0.1225,0.0725 l 0.035,0.17125 c 0.0187,0.0713 -0.004,0.1125 -0.0763,0.14375 -0.22,0.0937 -0.6125,0.135 -0.8325,0.135 -1.00375,0 -1.215,-0.7425 -1.215,-1.50875 0,-0.76875 0.18875,-1.5525 1.215,-1.5525"
id="path5745"
style="fill:#5a5758;fill-opacity:1;fill-rule:nonzero;stroke:none" />
<path
d="m 299.73385,559.0923 c -0.3825,0 -0.46875,0.24375 -0.46875,0.71125 0,0.4775 0.0863,0.71125 0.46375,0.71125 0.41,0 0.49125,-0.23 0.49125,-0.71125 0,-0.4775 -0.0763,-0.71125 -0.48625,-0.71125 m -0.005,1.855 c -0.90375,0 -0.9625,-0.6625 -0.9625,-1.175 0,-0.42375 0.0937,-1.1125 0.9625,-1.1125 0.87375,0 0.995,0.58125 0.995,1.1125 0,0.5125 -0.0625,1.175 -0.995,1.175"
id="path5749"
style="fill:#5a5758;fill-opacity:1;fill-rule:nonzero;stroke:none" />
<path
d="m 304.12648,560.91093 -0.32375,0 c -0.0637,0 -0.0863,-0.0275 -0.0863,-0.085 l 0,-1.27875 c 0,-0.33375 -0.08,-0.4275 -0.30625,-0.4275 -0.16625,0 -0.43625,0.13 -0.575,0.2025 0,0.045 0.004,0.12625 0.004,0.22875 l 0,1.275 c 0,0.0538 -0.0175,0.085 -0.085,0.085 l -0.32875,0 c -0.0587,0 -0.0763,-0.0275 -0.0763,-0.085 l 0,-1.30125 c 0,-0.275 -0.0725,-0.405 -0.2975,-0.405 -0.1575,0 -0.41,0.1125 -0.58125,0.2025 l 0,1.50375 c 0,0.0538 -0.0225,0.085 -0.085,0.085 l -0.32375,0 c -0.0588,0 -0.0813,-0.0275 -0.0813,-0.085 l 0,-2.03125 c 0,-0.0575 0.0225,-0.0888 0.0813,-0.0888 l 0.31875,0 c 0.0675,0 0.09,0.035 0.09,0.0888 l 0,0.13125 0.005,0.005 c 0.175,-0.1225 0.4225,-0.2575 0.67125,-0.26625 0.26,0 0.47625,0.0538 0.61625,0.315 0.225,-0.16625 0.50375,-0.315 0.7925,-0.315 0.59375,0 0.6525,0.3875 0.6525,0.8375 l 0,1.32375 c 0,0.0538 -0.0188,0.085 -0.0813,0.085"
id="path5753"
style="fill:#5a5758;fill-opacity:1;fill-rule:nonzero;stroke:none" />
<path
d="m 307.65447,560.91093 -0.32375,0 c -0.0637,0 -0.0863,-0.0275 -0.0863,-0.085 l 0,-1.27875 c 0,-0.33375 -0.08,-0.4275 -0.30625,-0.4275 -0.16625,0 -0.43625,0.13 -0.575,0.2025 0,0.045 0.004,0.12625 0.004,0.22875 l 0,1.275 c 0,0.0538 -0.0175,0.085 -0.085,0.085 l -0.32875,0 c -0.0587,0 -0.0763,-0.0275 -0.0763,-0.085 l 0,-1.30125 c 0,-0.275 -0.0725,-0.405 -0.2975,-0.405 -0.1575,0 -0.41,0.1125 -0.58125,0.2025 l 0,1.50375 c 0,0.0538 -0.0225,0.085 -0.085,0.085 l -0.32375,0 c -0.0588,0 -0.0813,-0.0275 -0.0813,-0.085 l 0,-2.03125 c 0,-0.0575 0.0225,-0.0888 0.0813,-0.0888 l 0.31875,0 c 0.0675,0 0.09,0.035 0.09,0.0888 l 0,0.13125 0.005,0.005 c 0.175,-0.1225 0.4225,-0.2575 0.67125,-0.26625 0.26,0 0.47625,0.0538 0.61625,0.315 0.225,-0.16625 0.50375,-0.315 0.7925,-0.315 0.59375,0 0.6525,0.3875 0.6525,0.8375 l 0,1.32375 c 0,0.0538 -0.0188,0.085 -0.0813,0.085"
id="path5757"
style="fill:#5a5758;fill-opacity:1;fill-rule:nonzero;stroke:none" />
<path
d="m 308.59422,560.82543 c 0,0.0488 -0.0175,0.085 -0.0813,0.085 l -0.32,0 c -0.0625,0 -0.09,-0.0263 -0.09,-0.085 l 0,-2.035 c 0,-0.0625 0.0275,-0.085 0.09,-0.085 l 0.32,0 c 0.0638,0 0.0813,0.0362 0.0813,0.085 l 0,2.035 z m -0.23875,-2.44375 c -0.23375,0 -0.265,-0.13125 -0.265,-0.26125 0,-0.14375 0.0488,-0.2575 0.265,-0.2575 0.22125,0 0.26625,0.10375 0.26625,0.2575 0,0.13875 -0.0412,0.26125 -0.26625,0.26125"
id="path5761"
style="fill:#5a5758;fill-opacity:1;fill-rule:nonzero;stroke:none" />
<path
d="m 309.71023,560.94705 c -0.225,0 -0.52625,-0.0312 -0.6975,-0.0987 -0.09,-0.0362 -0.10875,-0.0775 -0.095,-0.14875 l 0.0312,-0.14875 c 0.0138,-0.0725 0.045,-0.0762 0.1175,-0.0675 0.1975,0.0312 0.48625,0.0538 0.63875,0.0538 0.28875,0 0.40625,-0.0763 0.40625,-0.25625 0,-0.2075 -0.0775,-0.2525 -0.36125,-0.2925 -0.44125,-0.0638 -0.8275,-0.1575 -0.8275,-0.64875 0,-0.445 0.34125,-0.67875 0.84625,-0.67875 0.18375,0 0.495,0.0263 0.68375,0.0987 0.0763,0.0312 0.10875,0.0675 0.095,0.135 l -0.0362,0.16125 c -0.0138,0.0638 -0.04,0.0725 -0.12125,0.0638 -0.19375,-0.0225 -0.44625,-0.05 -0.6125,-0.05 -0.2875,0 -0.355,0.0812 -0.355,0.2525 0,0.175 0.1075,0.1975 0.3825,0.2425 0.4275,0.0637 0.81375,0.14875 0.81375,0.685 0,0.52625 -0.445,0.6975 -0.90875,0.6975"
id="path5765"
style="fill:#5a5758;fill-opacity:1;fill-rule:nonzero;stroke:none" />
<path
d="m 311.59573,560.94705 c -0.225,0 -0.52625,-0.0312 -0.6975,-0.0987 -0.09,-0.0362 -0.10875,-0.0775 -0.095,-0.14875 l 0.0312,-0.14875 c 0.0138,-0.0725 0.045,-0.0762 0.1175,-0.0675 0.1975,0.0312 0.48625,0.0538 0.63875,0.0538 0.28875,0 0.40625,-0.0763 0.40625,-0.25625 0,-0.2075 -0.0775,-0.2525 -0.36125,-0.2925 -0.44125,-0.0638 -0.8275,-0.1575 -0.8275,-0.64875 0,-0.445 0.34125,-0.67875 0.84625,-0.67875 0.18375,0 0.495,0.0263 0.68375,0.0987 0.0763,0.0312 0.10875,0.0675 0.095,0.135 l -0.0362,0.16125 c -0.0137,0.0638 -0.04,0.0725 -0.12125,0.0638 -0.19375,-0.0225 -0.44625,-0.05 -0.6125,-0.05 -0.2875,0 -0.355,0.0812 -0.355,0.2525 0,0.175 0.1075,0.1975 0.3825,0.2425 0.4275,0.0637 0.81375,0.14875 0.81375,0.685 0,0.52625 -0.445,0.6975 -0.90875,0.6975"
id="path5769"
style="fill:#5a5758;fill-opacity:1;fill-rule:nonzero;stroke:none" />
<path
d="m 313.29685,560.82543 c 0,0.0488 -0.0175,0.085 -0.0813,0.085 l -0.32,0 c -0.0625,0 -0.09,-0.0263 -0.09,-0.085 l 0,-2.035 c 0,-0.0625 0.0275,-0.085 0.09,-0.085 l 0.32,0 c 0.0638,0 0.0813,0.0362 0.0813,0.085 l 0,2.035 z m -0.23875,-2.44375 c -0.23375,0 -0.265,-0.13125 -0.265,-0.26125 0,-0.14375 0.0488,-0.2575 0.265,-0.2575 0.22125,0 0.26625,0.10375 0.26625,0.2575 0,0.13875 -0.0412,0.26125 -0.26625,0.26125"
id="path5773"
style="fill:#5a5758;fill-opacity:1;fill-rule:nonzero;stroke:none" />
<path
d="m 314.59735,559.0923 c -0.3825,0 -0.4675,0.24375 -0.4675,0.71125 0,0.4775 0.085,0.71125 0.4625,0.71125 0.41,0 0.49125,-0.23 0.49125,-0.71125 0,-0.4775 -0.0763,-0.71125 -0.48625,-0.71125 m -0.005,1.855 c -0.90375,0 -0.9625,-0.6625 -0.9625,-1.175 0,-0.42375 0.0937,-1.1125 0.9625,-1.1125 0.87375,0 0.995,0.58125 0.995,1.1125 0,0.5125 -0.0625,1.175 -0.995,1.175"
id="path5777"
style="fill:#5a5758;fill-opacity:1;fill-rule:nonzero;stroke:none" />
<path
d="m 317.66673,560.91093 -0.32375,0 c -0.0588,0 -0.0863,-0.0275 -0.0863,-0.085 l 0.005,-1.265 c 0,-0.26625 -0.0625,-0.44125 -0.32375,-0.44125 -0.18,0 -0.495,0.14375 -0.6175,0.2025 l 0,1.50375 c 0,0.0538 -0.0225,0.085 -0.085,0.085 l -0.32,0 c -0.0625,0 -0.085,-0.0275 -0.085,-0.085 l 0,-2.03125 c 0,-0.0575 0.0225,-0.0888 0.085,-0.0888 l 0.32,0 c 0.0625,0 0.085,0.0312 0.085,0.0888 l 0,0.13625 c 0.005,0 0.009,0.004 0.0138,0.004 0.16625,-0.11625 0.4825,-0.27 0.75625,-0.27 0.6075,0 0.6625,0.40125 0.6625,0.855 l 0,1.30625 c 0,0.0538 -0.0187,0.085 -0.0863,0.085"
id="path5781"
style="fill:#5a5758;fill-opacity:1;fill-rule:nonzero;stroke:none" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 30 KiB

View file

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

View file

Before

Width:  |  Height:  |  Size: 7.3 KiB

After

Width:  |  Height:  |  Size: 7.3 KiB

View file

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

View file

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 27 KiB

View file

@ -0,0 +1,158 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="149.71165mm"
height="149.71165mm"
viewBox="0 0 149.71165 149.71165"
version="1.1"
id="svg8"
inkscape:version="0.92.1 r"
sodipodi:docname="villasweb.svg"
inkscape:export-filename="/home/markus/Development/Projects/VILLASweb/doc/villasweb.svg.png"
inkscape:export-xdpi="21.299999"
inkscape:export-ydpi="21.299999">
<defs
id="defs2">
<linearGradient
inkscape:collect="always"
id="linearGradient4611">
<stop
style="stop-color:#00a2b0;stop-opacity:1"
offset="0"
id="stop4607" />
<stop
style="stop-color:#6ec5b0;stop-opacity:1"
offset="1"
id="stop4609" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4611"
id="linearGradient4613"
x1="65.497406"
y1="153.88686"
x2="65.497406"
y2="13.88037"
gradientUnits="userSpaceOnUse" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1.0941748"
inkscape:cx="96.131516"
inkscape:cy="285.10587"
inkscape:document-units="mm"
inkscape:current-layer="g5005"
showgrid="false"
inkscape:snap-smooth-nodes="true"
inkscape:snap-bbox="true"
inkscape:snap-bbox-edge-midpoints="true"
inkscape:bbox-nodes="true"
inkscape:object-paths="true"
inkscape:snap-intersection-paths="false"
inkscape:bbox-paths="false"
inkscape:snap-midpoints="true"
inkscape:window-width="1920"
inkscape:window-height="951"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:measure-start="37.9039,424.38"
inkscape:measure-end="101.386,461.031"
inkscape:snap-global="true" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Ebene 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(9.2667999,-9.6854979)">
<g
id="g5005"
transform="matrix(0.9623191,0,0,0.9623191,2.7484651,3.9385684)">
<path
inkscape:connector-curvature="0"
id="path4329"
d="M 65.519531,7.6875 C 30.952342,7.2288821 -1.7559504,32.928216 -9.0985572,66.77029 c -8.9441948,34.36253 9.91032274,73.19316 42.4331002,87.43912 31.90533,15.5955 73.697367,4.8306 94.125297,-24.21303 C 149.0773,101.82081 146.84579,58.724642 122.42805,32.933531 108.17012,16.922072 86.915542,7.695183 65.519531,7.6875 Z"
style="opacity:1;fill:none;fill-opacity:1;stroke:none;stroke-width:3.70000005;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
<path
sodipodi:type="star"
style="fill:none;stroke:url(#linearGradient4613);stroke-width:20.38569832;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4572"
sodipodi:sides="6"
sodipodi:cx="65.497406"
sodipodi:cy="83.983902"
sodipodi:r1="58.333843"
sodipodi:r2="50.518589"
sodipodi:arg1="-0.52359878"
sodipodi:arg2="-4.4017012e-09"
inkscape:flatsided="true"
inkscape:rounded="0"
inkscape:randomized="0"
d="m 116.016,54.81698 0,58.33384 -50.518594,29.16693 -50.51859,-29.16693 0,-58.333839 50.51859,-29.166922 z"
transform="matrix(0.83725065,0,0,0.85461295,10.659664,12.436674)" />
<path
sodipodi:type="star"
style="fill:#007da9;fill-opacity:1;stroke:none;stroke-width:17.67682076;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path4576-3"
sodipodi:sides="3"
sodipodi:cx="-80.89846"
sodipodi:cy="-21.019157"
sodipodi:r1="15.401051"
sodipodi:r2="7.7005253"
sodipodi:arg1="2.0943951"
sodipodi:arg2="3.1415927"
inkscape:flatsided="true"
inkscape:rounded="0"
inkscape:randomized="0"
d="m -88.598986,-7.6814564 0,-26.6754016 23.101576,13.337701 z"
transform="matrix(-1,0,0,-1.0094199,3.7691891,-0.07235845)"
inkscape:transform-center-x="3.7051813" />
<path
d="m 42.395834,161.35432 0,-26.6754 23.101576,13.3377 z"
inkscape:randomized="0"
inkscape:rounded="0"
inkscape:flatsided="true"
sodipodi:arg2="3.1415927"
sodipodi:arg1="2.0943951"
sodipodi:r2="7.7005253"
sodipodi:r1="15.401051"
sodipodi:cy="148.01662"
sodipodi:cx="50.096359"
sodipodi:sides="3"
id="path4593"
style="fill:#007da9;fill-opacity:1;stroke:none;stroke-width:17.67682076;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
sodipodi:type="star"
inkscape:transform-center-x="-3.7051807"
transform="matrix(1,0,0,1.0094199,-4.2717477,-1.5199394)"
inkscape:transform-center-y="1.8921547e-06" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.8 KiB

View file

@ -0,0 +1,91 @@
/**
* This file is part of VILLASweb.
*
* VILLASweb is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* VILLASweb is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with VILLASweb. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
import React from 'react';
import { Button } from 'react-bootstrap';
import { NavLink } from 'react-router-dom';
export function villasweb_welcome() {
let url = 'https://villas.fein-aachen.org/doc/web.html';
return (
<div >
<h1>Welcome!</h1>
<p>VILLASweb is a tool to configure real-time co-simulations and display simulation real-time data.
It enables the management and monitoring of simulators, models and simulations.</p>
<span className='solid-button'>
<Button key="learnmore" onClick={e => window.location = url }>Learn more</Button>
</span>
</div>)
}
export function villasweb_home(title, username, userid, role) {
return (
<div className="home-container">
<img style={{ height: 120, float: 'right' }} src={require('./img/villas_web.svg').default} alt="Logo VILLASweb" />
<h1>Home</h1>
<p>
Welcome to <b>{title}</b>!
</p>
<p>
You are logged in as user <b>{username}</b> with <b>ID {userid}</b> and role <b>{role}</b>.
</p>
<h3>Credits</h3>
<p>VILLASweb is an open source project developed by the <a href="http://acs.eonerc.rwth-aachen.de">Institute for Automation of Complex Power Systems</a> at <a href="https;//www.rwth-aachen.de">RWTH Aachen University</a>.</p>
<img height={60} src={require('./img/eonerc_rwth.svg').default} alt="Logo ACS" />
<ul>
<li><a href="mailto:stvogel@eonerc.rwth-aachen.de">Steffen Vogel</a></li>
<li><a href="mailto:sonja.happ@eonerc.rwth-aachen.de">Sonja Happ</a></li>
</ul>
<h3>Links</h3>
<ul>
<li><NavLink to="/api">VILLASweb API browser</NavLink></li>
<li><a href="http://fein-aachen.org/projects/villas-framework/">FEIN Aachen e.V. project page of VILLASframework</a></li>
<li><a href="https://villas.fein-aachen.org/doc/web.html">Documentation of VILLASweb</a></li>
<li><a href="https://git.rwth-aachen.de/acs/public/villas/web">Source Code of VILLASweb frontend</a></li>
<li><a href="https://git.rwth-aachen.de/acs/public/villas/web-backend-go">Source Code of VILLASweb backend</a></li>
</ul>
<h3>Funding</h3>
<p>The development of <a href="http://fein-aachen.org/projects/villas-framework/">VILLASframework</a> projects has received funding from</p>
<ul>
<p><a href="https://www.acs.eonerc.rwth-aachen.de/cms/E-ON-ERC-ACS/Forschung/Forschungsprojekte/Bildungsprojekte/~mikmu/SLEW-SECOND-LIFE-FOR-ENERGIEWENDE/">SLEW:</a> Second Life for Energiewende, an Exploratory Teaching Space project funded by RWTH Aachen University</p>
<p><a href="https://erigrid2.eu/">ERIgrid 2.0:</a> An EU Horizon 2020 research and innovation action project for connecting European Smart Grid Infrastructures (grant agreement No 870620)</p>
<p>
<img height={100} src={require('./img/european_commission.svg').default} alt="Logo EU" />
<img height={70} src={require('./img/erigrid2.png').default} alt="Logo ERIgrid 2.0" />
</p>
<p><a href="http://www.uel4-0.de/">Urban Energy Lab 4.0:</a> A project funded by EFRE.NRW (European Regional Development Fund) for the setup of a novel energy research infrastructure.</p>
<p>
<img height={70} src={require('./img/uel_efre.jpeg').default} alt="Logo UEL OP EFRE NRW" />
<img height={70} src={require('./img/uel.png').default} alt="Logo UEL" />
</p>
<p><a href="http://www.re-serve.eu">RESERVE:</a> An EU Horizon 2020 research and innovation project (grant agreement No 727481)</p>
<p>
<img height={100} src={require('./img/european_commission.svg').default} alt="Logo EU" />
<img height={70} src={require('./img/reserve.svg').default} alt="Logo RESERVE" />
</p>
<p><a href="http://www.jara.org/en/research/energy">JARA-ENERGY:</a> Jülich-Aachen Research Alliance (JARA) is an initiative of RWTH Aachen University and Forschungszentrum Jülich.</p>
</ul>
</div>)
}
export function villasweb_footer() {
return (
<footer className="app-footer">
Copyright &copy; {new Date().getFullYear()} - <a href="https://www.acs.eonerc.rwth-aachen.de">Institute for Automation of Complex Power Systems</a> - <a href="https://www.rwth-aachen.de">RWTH Aachen University</a>
</footer>
);
}

View file

@ -15,16 +15,23 @@
* along with VILLASweb. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
import React, { Component } from 'react';
class Footer extends Component {
render() {
return (
<footer className="app-footer">
Copyright &copy; {new Date().getFullYear()} - <a href="https://www.acs.eonerc.rwth-aachen.de">Institute for Automation of Complex Power Systems</a> - <a href="https://www.rwth-aachen.de">RWTH Aachen University</a>
</footer>
);
}
const villasweb_values = {
title: 'VILLASweb',
subtitle: 'ACS',
logo: 'villas_web.svg',
pages: {
home: true,
scenarios: true,
infrastructure: true,
account: true,
api: true,
},
style: {
background: '#6EA2B0',
highlights: '#527984',
maincolor: '#4d4d4d',
secondarytext: '#818181',
}
}
export default Footer;
export default villasweb_values;

View file

@ -18,49 +18,47 @@
import React from 'react';
import { Form } from 'react-bootstrap';
import Dialog from '../common/dialogs/dialog';
class NewDashboardDialog extends React.Component {
valid: false;
import Dialog from './dialog';
class NewDialog extends React.Component {
constructor(props) {
super(props);
this.state = {
name: ''
value: ''
}
}
onClose(canceled) {
if (canceled === false) {
if (this.valid) {
this.props.onClose(this.state);
}
this.props.onClose(this.state);
} else {
this.props.onClose();
}
}
handleChange(e) {
console.log(e)
this.setState({ [e.target.id]: e.target.value });
}
resetState() {
this.setState({ name: '' });
this.setState({ value: '' });
}
validateForm(target) {
// check all controls
var name = true;
var inputGiven = true;
if (this.state.name === '') {
name = false;
if (this.state.value === '') {
inputGiven = false;
}
this.valid = name;
this.valid = inputGiven;
// return state to control
if (target === 'name') return name ? "success" : "error";
if (target === 'value') return inputGiven ? "success" : "error";
return "success";
}
@ -68,17 +66,18 @@ class NewDashboardDialog extends React.Component {
render() {
return (
<Dialog
size="md"
show={this.props.show}
title="New Dashboard"
title={this.props.title}
buttonTitle="Add"
onClose={(c) => this.onClose(c)}
onReset={() => this.resetState()}
valid={this.valid}
>
<Form>
<Form.Group controlId="name" valid={this.validateForm('name')}>
<Form.Label>Name</Form.Label>
<Form.Control type="text" placeholder="Enter name" value={this.state.name} onChange={(e) => this.handleChange(e)} />
<Form.Group controlId="value" valid={this.validateForm('value')}>
<Form.Label>{this.props.inputLabel}</Form.Label>
<Form.Control type="text" placeholder={this.props.placeholder} value={this.state.value} onChange={(e) => this.handleChange(e)} />
<Form.Control.Feedback />
</Form.Group>
</Form>
@ -87,4 +86,4 @@ class NewDashboardDialog extends React.Component {
}
}
export default NewDashboardDialog;
export default NewDialog;

View file

@ -16,19 +16,25 @@
******************************************************************************/
import React from 'react';
import { Col, Button } from 'react-bootstrap';
import { Hidden } from 'react-grid-system'
import Icon from './icon';
import config from '../config';
import branding from '../branding/branding';
class Header extends React.Component {
render() {
let hasSubtitle = branding.getSubtitle();
return (
<header className="app-header">
<h1>{config.instance} - {config.subtitle}</h1>
<div>
{ hasSubtitle ?
<header className="app-header">
<h1>{branding.getTitle()} - {branding.getSubtitle()}</h1>
</header>
:
<header className="app-header">
<h1>{branding.getTitle()} </h1>
</header>
}
</div>
);
}
}
export default Header;
export default Header;

View file

@ -17,9 +17,9 @@
import React from 'react';
import config from '../config';
import { Redirect } from "react-router-dom";
import { NavLink } from 'react-router-dom';
import branding from '../branding/branding';
class Home extends React.Component {
@ -31,101 +31,16 @@ class Home extends React.Component {
}
render() {
let currentUser = JSON.parse(localStorage.getItem("currentUser"));
if (currentUser == null){
if (currentUser == null) {
console.log("HOME redirecting to logout/ login")
return (<Redirect to="/logout" />);
}
return (
<div className="home-container">
<img style={{height: 120, float: 'right'}} src={require('../img/villas_web.svg').default} alt="Logo VILLASweb" />
<h1>Home</h1>
<p>
{/*Welcome to <b>{config.instance}</b> hosted by <a href={"mailto:" + config.admin.mail}>{config.admin.name}</a>!<br />*/}
Welcome to <b>{config.instance}</b>!
</p>
<p>
You are logged in as user <b>{currentUser.username}</b> with <b>ID {currentUser.id}</b> and role <b>{currentUser.role}</b>.
</p>
{/*<h3>Data Model</h3>
<img height={400} src={require('../img/datamodel.png').default} alt="Datamodel VILLASweb" />
<h3>Terminology </h3>
<h5>Infrastructure Component</h5>
<ul>
<li>A component of research infrastructure</li>
<li>Category: for example simulator, gateway, amplifier, database, etc.</li>
<li>Type: for example RTDS, OpalRT, VILLASnode, Cassandra</li>
</ul>
<h5>Component Configuration</h5>
<ul>
<li>Input signals: Signals that can be modified in VILLASweb</li>
<li>Output signals: Signals that can be visualized on dashboards of VILLASweb</li>
<li>Parameters: Further configuration parameters of the infrastructure component</li>
</ul>
<h5>Dashboard</h5>
<ul>
<li>Visualize ongoing experiments in real-time</li>
<li>Interact with ongoing experiments in real-time</li>
</ul>
<h5>Scenario</h5>
<ul>
<li>A collection of component configurations and dashboards for a specific experiment</li>
<li>Users can have access to multiple scenarios</li>
</ul>*/}
<h3>Credits</h3>
<p>VILLASweb is an open source project developed by the <a href="http://acs.eonerc.rwth-aachen.de">Institute for Automation of Complex Power Systems</a> at <a href="https;//www.rwth-aachen.de">RWTH Aachen University</a>.</p>
<img height={60} src={require('../img/eonerc_rwth.svg').default} alt="Logo ACS" />
<ul>
<li><a href="mailto:stvogel@eonerc.rwth-aachen.de">Steffen Vogel</a></li>
<li><a href="mailto:sonja.happ@eonerc.rwth-aachen.de">Sonja Happ</a></li>
</ul>
<h3>Links</h3>
<ul>
<li><NavLink to="/api">VILLASweb API browser</NavLink></li>
<li><a href="http://fein-aachen.org/projects/villas-framework/">FEIN Aachen e.V. project page of VILLASframework</a></li>
<li><a href="https://villas.fein-aachen.org/doc/web.html">Documentation of VILLASweb</a></li>
<li><a href="https://git.rwth-aachen.de/acs/public/villas/web">Source Code of VILLASweb frontend</a></li>
<li><a href="https://git.rwth-aachen.de/acs/public/villas/web-backend-go">Source Code of VILLASweb backend</a></li>
</ul>
<h3>Funding</h3>
<p>The development of <a href="http://fein-aachen.org/projects/villas-framework/">VILLASframework</a> projects has received funding from</p>
<ul>
<p><a href="https://www.acs.eonerc.rwth-aachen.de/cms/E-ON-ERC-ACS/Forschung/Forschungsprojekte/Bildungsprojekte/~mikmu/SLEW-SECOND-LIFE-FOR-ENERGIEWENDE/">SLEW:</a> Second Life for Energiewende, an Exploratory Teaching Space project funded by RWTH Aachen University</p>
<p><a href="https://erigrid2.eu/">ERIgrid 2.0:</a> An EU Horizon 2020 research and innovation action project for connecting European Smart Grid Infrastructures (grant agreement No 870620)</p>
<p>
<img height={100} src={require('../img/european_commission.svg').default} alt="Logo EU" />
<img height={70} src={require('../img/erigrid2.png').default} alt="Logo ERIgrid 2.0" />
</p>
<p><a href="http://www.uel4-0.de/">Urban Energy Lab 4.0:</a> A project funded by EFRE.NRW (European Regional Development Fund) for the setup of a novel energy research infrastructure.</p>
<p>
<img height={70} src={require('../img/uel_efre.jpeg').default} alt="Logo UEL OP EFRE NRW" />
<img height={70} src={require('../img/uel.png').default} alt="Logo UEL" />
</p>
<p><a href="http://www.re-serve.eu">RESERVE:</a> An EU Horizon 2020 research and innovation project (grant agreement No 727481)</p>
<p>
<img height={100} src={require('../img/european_commission.svg').default} alt="Logo EU" />
<img height={70} src={require('../img/reserve.svg').default} alt="Logo RESERVE" />
</p>
<p><a href="http://www.jara.org/en/research/energy">JARA-ENERGY:</a> Jülich-Aachen Research Alliance (JARA) is an initiative of RWTH Aachen University and Forschungszentrum Jülich.</p>
</ul>
{
//<img height={70} src={require('../img/jara.svg').default} alt="Logo JARA" />
}
</div>
);
<div>
{branding.getHome(currentUser.username, currentUser.id, currentUser.role)}
</div>);
}
}

View file

@ -43,9 +43,9 @@ class IconButton extends React.Component {
button = btn;
} else {
button = <OverlayTrigger
key={this.props.ikey}
key={this.props.childKey}
placement={this.props.tipPlacement ? this.props.tipPlacement : 'top'}
overlay={<Tooltip id={`tooltip-${this.props.ikey}`}>{this.props.tooltip}</Tooltip>} >
overlay={<Tooltip id={`tooltip-${this.props.childKey}`}>{this.props.tooltip}</Tooltip>} >
{btn}
</OverlayTrigger>
}

View file

@ -28,9 +28,9 @@ class IconToggleButton extends React.Component {
let tooltip = this.props.checked ? this.props.tooltipChecked : this.props.tooltipUnchecked;
return <OverlayTrigger
key={this.props.ikey}
key={this.props.childKey}
placement={'top'}
overlay={<Tooltip id={`tooltip-${this.props.ikey}`}>{tooltip}</Tooltip>} >
overlay={<Tooltip id={`tooltip-${this.props.childKey}`}>{tooltip}</Tooltip>} >
<ButtonGroup toggle>
<ToggleButton
variant={this.props.variant ? this.props.variant : 'light'}

View file

@ -17,6 +17,7 @@
import React from 'react';
import { NavLink } from 'react-router-dom';
import branding from '../branding/branding';
import { Container } from 'flux/utils';
import LoginStore from '../user/login-store';
import AppDispatcher from './app-dispatcher';
@ -62,33 +63,67 @@ class SidebarMenu extends React.Component {
}
render() {
return (
<div className="menu">
<h2>Menu</h2>
const values = branding.values;
let links = []
if (values.links) {
Object.keys(values.links).forEach(key => {
links.push(<li key={key}><a href={values.links[key]} title={key}>{key}</a></li>);
})
}
var logoStyle = { width: 110, margin: 'auto' };
var logo = branding.getLogo(logoStyle);
{this.state.externalAuth ?
<ul>
<li><NavLink to="/home" activeClassName="active" title="Home">Home</NavLink></li>
<li><NavLink to="/scenarios" activeClassName="active" title="Scenarios">Scenarios</NavLink></li>
<li><NavLink to="/infrastructure" activeClassName="active" title="Infrastructure">Infrastructure</NavLink></li>
{ this.props.currentRole === 'Admin' ?
return (
<div className="menucontainer">
{ logo ?
<div className="menulogo">
{logo}
</div>
: ''
}
<div className="menu">
<h2>Menu</h2>
{this.state.externalAuth ?
<ul>
<li hidden={!values.pages.home}><NavLink to="/home" activeClassName="active" title="Home">Home</NavLink></li>
<li hidden={!values.pages.scenarios}><NavLink to="/scenarios" activeClassName="active" title="Scenarios">Scenarios</NavLink></li>
{this.props.currentRole === 'Admin' || values.pages.infrastructure ?
<li><NavLink to="/infrastructure" activeClassName="active" title="Infrastructure">Infrastructure</NavLink></li> : ''
}
{this.props.currentRole === 'Admin' ?
<li><NavLink to="/users" activeClassName="active" title="Users">Users</NavLink></li> : ''
}
<li><NavLink to="/account" title="Account">Account</NavLink></li>
<a onClick={this.logout.bind(this)} href={this.state.logoutLink}>Logout</a>
<li><NavLink to="/api" title="API Browser">API Browser</NavLink></li>
</ul>
: <ul>
<li><NavLink to="/home" activeClassName="active" title="Home">Home</NavLink></li>
<li><NavLink to="/scenarios" activeClassName="active" title="Scenarios">Scenarios</NavLink></li>
<li><NavLink to="/infrastructure" activeClassName="active" title="Infrastructure">Infrastructure</NavLink></li>
{ this.props.currentRole === 'Admin' ?
<li><NavLink to="/users" activeClassName="active" title="Users">Users</NavLink></li> : ''
}
<li hidden={!values.pages.account}><NavLink to="/account" title="Account">Account</NavLink></li>
<a onClick={this.logout.bind(this)} href={this.state.logoutLink}>Logout</a>
<li hidden={!values.pages.api}><NavLink to="/api" title="API Browser">API Browser</NavLink></li>
</ul>
: <ul>
<li hidden={!values.pages.home}><NavLink to="/home" activeClassName="active" title="Home">Home</NavLink></li>
<li hidden={!values.pages.scenarios}><NavLink to="/scenarios" activeClassName="active" title="Scenarios">Scenarios</NavLink></li>
{this.props.currentRole === 'Admin' || values.pages.infrastructure ?
<li><NavLink to="/infrastructure" activeClassName="active" title="Infrastructure">Infrastructure</NavLink></li> : ''
}
{this.props.currentRole === 'Admin' ?
<li><NavLink to="/users" activeClassName="active" title="Users">Users</NavLink></li> : ''
}
<li hidden={!values.pages.account}><NavLink to="/account" title="Account">Account</NavLink></li>
<li><NavLink to={this.state.logoutLink} title="Logout">Logout</NavLink></li>
<li hidden={!values.pages.api}> <NavLink to="/api" title="API Browser">API Browser</NavLink></li >
</ul >}
{
links.length > 0 ?
<div>
<br></br>
<h4> Links</h4>
<ul> {links} </ul>
</div>
: ''
}
<li><NavLink to="/account" title="Account">Account</NavLink></li>
<li><NavLink to={this.state.logoutLink} title="Logout">Logout</NavLink></li>
<li><NavLink to="/api" title="API Browser">API Browser</NavLink></li>
</ul>}
</div>
</div>
);
}

View file

@ -140,7 +140,7 @@ class CustomTable extends Component {
cell.push(
<IconButton
key={childkey++}
ikey={childkey++}
childKey={childkey++}
icon={'edit'}
disabled={child.props.onEdit == null || isLocked}
hidetooltip={isLocked}
@ -171,7 +171,7 @@ class CustomTable extends Component {
if (child.props.lockButton) {
cell.push(
<IconToggleButton
ikey={childkey++}
childKey={childkey++}
onChange={() => child.props.onChangeLock(index)}
checked={isLocked}
checkedIcon='lock'
@ -188,7 +188,7 @@ class CustomTable extends Component {
cell.push(
<IconButton
key={childkey++}
ikey={childkey++}
childKey={childkey++}
icon={'download'}
disabled={child.props.onExport == null}
tooltip={"Export"}
@ -202,7 +202,7 @@ class CustomTable extends Component {
cell.push(
<IconButton
key={childkey++}
ikey={childkey++}
childKey={childkey++}
icon={'wave-square'}
disabled={child.props.onAutoConf == null || child.props.locked }
hidetooltip={isLocked}
@ -217,7 +217,7 @@ class CustomTable extends Component {
cell.push(
<IconButton
key={childkey++}
ikey={childkey++}
childKey={childkey++}
icon={'copy'}
disabled={child.props.onDuplicate == null || child.props.locked}
hidetooltip={isLocked}
@ -232,7 +232,7 @@ class CustomTable extends Component {
cell.push(
<IconButton
key={childkey++}
ikey={childkey++}
childKey={childkey++}
icon={'file'}
disabled={child.props.onAddRemove == null || isLocked}
hidetooltip={isLocked}
@ -247,7 +247,7 @@ class CustomTable extends Component {
cell.push(
<IconButton
key={childkey++}
ikey={childkey++}
childKey={childkey++}
icon={'file-download'}
disabled={child.props.onDownloadAll == null}
tooltip={"Download All Files"}
@ -265,7 +265,7 @@ class CustomTable extends Component {
cell.push(
<IconButton
key={childkey++}
ikey={childkey++}
childKey={childkey++}
icon={'trash'}
disabled={child.props.onDelete == null || isLocked}
hidetooltip={isLocked}

View file

@ -15,11 +15,12 @@
* along with VILLASweb. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
import React, {Component} from "react";
import React, { Component } from "react";
import FileSaver from 'file-saver';
import IconButton from "../common/icon-button";
import Table from "../common/table";
import TableColumn from "../common/table-column";
import NewDialog from "../common/dialogs/new-dialog";
import DeleteDialog from "../common/dialogs/delete-dialog";
import AppDispatcher from "../common/app-dispatcher";
import NotificationsDataManager from "../common/data-managers/notifications-data-manager";
@ -37,21 +38,21 @@ class ConfigTable extends Component {
editConfigModal: false,
modalConfigData: {},
modalConfigIndex: 0,
newConfigModal: false,
deleteConfigModal: false,
importConfigModal: false,
newConfig: false,
selectedConfigs: [],
ExternalICInUse: false,
editOutputSignalsModal: false,
editInputSignalsModal: false,
editOutputSignalsModal: false,
editInputSignalsModal: false,
}
}
static getDerivedStateFromProps(props, state){
static getDerivedStateFromProps(props, state) {
let ExternalICInUse = false
for (let config of props.configs){
for (let config of props.configs) {
for (let component of props.ics) {
if ((config.icID === component.id) && (component.managedexternally === true)) {
ExternalICInUse = true;
@ -65,26 +66,27 @@ class ConfigTable extends Component {
};
}
addConfig() {
const config = {
scenarioID: this.props.scenario.id,
name: 'New Component Configuration',
icID: this.props.ics.length > 0 ? this.props.ics[0].id : null,
startParameters: {},
};
closeNewConfigModal(data) {
this.setState({ newConfigModal: false });
AppDispatcher.dispatch({
type: 'configs/start-add',
data: config,
token: this.props.sessionToken
});
this.setState({ newConfig: true });
if (data) {
const config = {
scenarioID: this.props.scenario.id,
name: data.value,
icID: this.props.ics.length > 0 ? this.props.ics[0].id : null,
startParameters: {},
};
AppDispatcher.dispatch({
type: 'configs/start-add',
data: config,
token: this.props.sessionToken
});
}
}
closeEditConfigModal(data) {
this.setState({ editConfigModal: false, newConfig: false });
this.setState({ editConfigModal: false });
if (data) {
AppDispatcher.dispatch({
@ -312,27 +314,27 @@ class ConfigTable extends Component {
{/*Component Configurations table*/}
<h2 style={this.props.tableHeadingStyle}>Component Configurations
<span className='icon-button'>
<IconButton
ikey={0}
tooltip='Add Component Configuration'
onClick={() => this.addConfig()}
icon='plus'
disabled={this.props.locked}
hidetooltip={this.props.locked}
buttonStyle={buttonStyle}
iconStyle={iconStyle}
/>
<IconButton
ikey={1}
tooltip='Import Component Configuration'
onClick={() => this.setState({ importConfigModal: true })}
icon='upload'
disabled={this.props.locked}
hidetooltip={this.props.locked}
buttonStyle={buttonStyle}
iconStyle={iconStyle}
/>
</span>
<IconButton
childKey={0}
tooltip='Add Component Configuration'
onClick={() => this.setState({ newConfigModal: true })}
icon='plus'
disabled={this.props.locked}
hidetooltip={this.props.locked}
buttonStyle={buttonStyle}
iconStyle={iconStyle}
/>
<IconButton
childKey={1}
tooltip='Import Component Configuration'
onClick={() => this.setState({ importConfigModal: true })}
icon='upload'
disabled={this.props.locked}
hidetooltip={this.props.locked}
buttonStyle={buttonStyle}
iconStyle={iconStyle}
/>
</span>
</h2>
<Table data={this.props.configs}>
<TableColumn
@ -404,9 +406,9 @@ class ConfigTable extends Component {
<ICAction
ics={this.props.ics}
configs={this.props.configs}
selectedConfigs = {this.state.selectedConfigs}
snapshotConfig = {(index) => this.copyConfig(index)}
token = {this.props.sessionToken}
selectedConfigs={this.state.selectedConfigs}
snapshotConfig={(index) => this.copyConfig(index)}
token={this.props.sessionToken}
actions={[
{ id: '0', title: 'Start', data: { action: 'start' } },
{ id: '1', title: 'Stop', data: { action: 'stop' } },
@ -432,6 +434,13 @@ class ConfigTable extends Component {
onClose={data => this.importConfig(data)}
ics={this.props.ics}
/>
<NewDialog
show={this.state.newConfigModal}
title="New Component Configuration"
inputLabel="Name"
placeholder="Enter name"
onClose={data => this.closeNewConfigModal(data)}
/>
<DeleteDialog
title="component configuration"
name={this.state.modalConfigData.name}

View file

@ -38,7 +38,7 @@ class DashboardButtonGroup extends React.Component {
if (locked) {
return <IconButton
key={buttonkey++}
ikey={buttonkey}
childKey={buttonkey}
icon={icon}
disabled={true}
hidetooltip={true}
@ -51,7 +51,7 @@ class DashboardButtonGroup extends React.Component {
} else {
return <IconButton
key={buttonkey++}
ikey={buttonkey}
childKey={buttonkey}
icon={icon}
tooltip={tooltip}
tipPlacement={'bottom'}

View file

@ -20,11 +20,11 @@ import FileSaver from 'file-saver';
import IconButton from "../common/icon-button";
import Table from "../common/table";
import TableColumn from "../common/table-column";
import NewDashboardDialog from "./new-dashboard";
import EditDashboardDialog from "./edit-dashboard";
import ImportDashboardDialog from "./import-dashboard";
import DeleteDialog from "../common/dialogs/delete-dialog";
import AppDispatcher from "../common/app-dispatcher";
import NewDialog from "../common/dialogs/new-dialog";
class DashboardTable extends Component {
@ -43,15 +43,15 @@ class DashboardTable extends Component {
closeNewDashboardModal(data) {
this.setState({ newDashboardModal: false });
if (data) {
// TODO: 'newDashboard' not used, check this
let newDashboard = data;
let newDashboard = {};
newDashboard["name"] = data.value;
// add default grid value and scenarioID
newDashboard["grid"] = 15;
newDashboard["scenarioID"] = this.props.scenario.id;
AppDispatcher.dispatch({
type: 'dashboards/start-add',
data,
data: newDashboard,
token: this.props.sessionToken,
});
}
@ -152,7 +152,7 @@ class DashboardTable extends Component {
<h2 style={this.props.tableHeadingStyle}>Dashboards
<span className='icon-button'>
<IconButton
ikey={0}
childKey={0}
tooltip='Add Dashboard'
onClick={() => this.setState({newDashboardModal: true})}
icon='plus'
@ -162,7 +162,7 @@ class DashboardTable extends Component {
iconStyle={iconStyle}
/>
<IconButton
ikey={1}
childKey={1}
tooltip='Import Dashboard'
onClick={() => this.setState({importDashboardModal: true})}
icon='upload'
@ -218,10 +218,14 @@ class DashboardTable extends Component {
/>
</Table>
<NewDashboardDialog
<NewDialog
show={this.state.newDashboardModal}
title="New Dashboard"
inputLabel="Name"
placeholder="Enter name"
onClose={data => this.closeNewDashboardModal(data)}
/>
<EditDashboardDialog
show={this.state.dashboardEditModal}
dashboard={this.state.modalDashboardData}

View file

@ -518,7 +518,7 @@ class Dashboard extends Component {
{this.state.dashboard.name}
<span className='icon-button'>
<IconToggleButton
ikey={0}
childKey={0}
checked={this.state.locked}
checkedIcon='lock'
uncheckedIcon='lock-open'

View file

@ -472,16 +472,20 @@ class InfrastructureComponents extends Component {
{this.state.currentUser.role === "Admin" ?
<span className='icon-button'>
<IconButton
ikey={1}
childKey={1}
tooltip='Add Infrastructure Component'
onClick={() => this.setState({newModal: true})}
icon='plus'
buttonStyle={buttonStyle}
iconStyle={iconStyle}
/>
<IconButton
ikey={1}
childKey={1}
tooltip='Import Infrastructure Component'
onClick={() => this.setState({importModal: true})}
icon='upload'
buttonStyle={buttonStyle}
iconStyle={iconStyle}
/>
</span>
: <span/>

BIN
src/img/ajax-loader.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

View file

@ -1,77 +0,0 @@
/**
* This file is part of VILLASweb.
*
* VILLASweb is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* VILLASweb is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with VILLASweb. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
import React from 'react';
import { Form } from 'react-bootstrap';
import Dialog from '../common/dialogs/dialog';
class NewResultDialog extends React.Component {
constructor(props) {
super(props);
this.state = {
ConfigSnapshots: '',
Description: '',
ResultFileIDs: [],
}
}
onClose(canceled) {
if (canceled === false) {
this.props.onClose(this.state);
} else {
this.props.onClose();
}
}
handleChange(e) {
this.setState({ [e.target.id]: e.target.value });
}
resetState() {
this.setState({
ConfigSnapshots: '',
Description: '',
ResultFileIDs: [],
});
}
render() {
return (
<Dialog
show={this.props.show}
title="New Result"
buttonTitle="Add"
onClose={(c) => this.onClose(c)}
onReset={() => this.resetState()}
valid={true}
>
<Form>
<Form.Group controlId="Description">
<Form.Label>Description</Form.Label>
<Form.Control type="text" placeholder="Enter description" value={this.state.Description} onChange={(e) => this.handleChange(e)} />
<Form.Control.Feedback />
</Form.Group>
</Form>
</Dialog>
);
}
}
export default NewResultDialog;

View file

@ -26,7 +26,7 @@ import TableColumn from "../common/table-column";
import DeleteDialog from "../common/dialogs/delete-dialog";
import EditResultDialog from "./edit-result";
import ResultConfigDialog from "./result-configs-dialog";
import NewResultDialog from "./new-result";
import NewDialog from "../common/dialogs/new-dialog";
class ResultTable extends Component {
@ -79,10 +79,13 @@ class ResultTable extends Component {
closeNewResultModal(data) {
this.setState({ newResultModal: false });
if (data) {
data["scenarioID"] = this.props.scenario.id;
let newResult = { ConfigSnapshots: '', ResultFileIDs: [] };
newResult["scenarioID"] = this.props.scenario.id;
newResult["Description"] = data.value;
AppDispatcher.dispatch({
type: 'results/start-add',
data,
data: newResult,
token: this.props.sessionToken,
});
}
@ -169,7 +172,7 @@ class ResultTable extends Component {
<h2 style={this.props.tableHeadingStyle}>Results
<span className='icon-button'>
<IconButton
ikey={1}
childKey={1}
tooltip='Add Result'
onClick={() => this.setState({ newResultModal: true })}
icon='plus'
@ -245,8 +248,11 @@ class ResultTable extends Component {
resultNo={this.state.modalResultConfigsIndex}
onClose={this.closeResultConfigSnapshots.bind(this)}
/>
<NewResultDialog
<NewDialog
show={this.state.newResultModal}
title="New Result"
inputLabel="Description"
placeholder="Enter description"
onClose={data => this.closeNewResultModal(data)}
/>
</div>

View file

@ -32,6 +32,7 @@ import User from "./user/user";
import LoginComplete from './user/login-complete'
class Root extends React.Component {
render() {
return (

View file

@ -134,7 +134,7 @@ class ScenarioUsersTable extends Component {
<InputGroup.Append>
<span className='icon-button'>
<IconButton
ikey={1}
childKey={1}
tooltip='Add User to Scenario'
onClick={() => this.addUser()}
icon='plus'

View file

@ -154,7 +154,7 @@ class Scenario extends React.Component {
return <div className='section'>
<div className='section-buttons-group-right'>
<IconButton
ikey="0"
childKey="0"
tooltip={tooltip}
onClick={this.onEditFiles.bind(this)}
icon="file"
@ -166,7 +166,7 @@ class Scenario extends React.Component {
{this.state.scenario.name}
<span className='icon-button'>
<IconToggleButton
ikey={0}
childKey={0}
onChange={() => this.onChangeLock()}
checked={this.state.scenario.isLocked}
checkedIcon='lock'

View file

@ -257,7 +257,7 @@ class Scenarios extends Component {
<h1>Scenarios
<span className='icon-button'>
<IconButton
ikey={0}
childKey={0}
tooltip='Add Scenario'
onClick={() => this.setState({ newModal: true })}
icon='plus'
@ -265,7 +265,7 @@ class Scenarios extends Component {
iconStyle={iconStyle}
/>
<IconButton
ikey={1}
childKey={1}
tooltip='Import Scenario'
onClick={() => this.setState({ importModal: true })}
icon='upload'

View file

@ -18,22 +18,36 @@
/**
* Application container
*/
:root {
--bg: #eceded;
--highlights: #527984;
--secondarytext: #818181;
--borderradius: 0px;
--mainfont: 16px 'Helvetica Neue', Helvetica, Arial, sans-serif;
--maincolor: #4d4d4d;
}
* {
color: var(--maincolor);
}
body {
background-color: #6EA2B0 !important;
background-color: var(--bg) !important;
}
.app {
height: 100vh;
color: #4d4d4d;
color: var(--maincolor);
border-radius: var(--borderradius);
font: 16px 'Helvetica Neue', Helvetica, Arial, sans-serif;
font: var(--mainfont);
hyphens: auto;
}
.app-header {
width: 100%;
color: #527984;
background-color: #fff;
}
@ -42,6 +56,7 @@ body {
margin: 0;
width: 100%;
text-align: center;
color: var(--highlights);
}
.btn-link {
@ -53,13 +68,11 @@ body {
margin-top: 20px;
padding-bottom: 10px;
color: var(--secondarytext);
text-align: center;
}
.app-footer a {
color: #4d4d4d;
text-decoration: underline;
}
@ -73,6 +86,8 @@ body {
.app-content {
padding: 15px 20px 20px 20px;
border-radius: var(--borderradius);
width: auto;
min-height: 300px;
@ -96,10 +111,30 @@ body {
/**
* Menus
*/
.menucontainer {
float: left;
flex-direction: column;
}
.menu {
padding: 20px;
margin-bottom: 20px;
width: 160px;
float: left;
border-radius: var(--borderradius);
background-color: #fff;
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2),
0 9px 18px 0 rgba(0, 0, 0, 0.1);
}
.menulogo {
padding-top: 20px;
padding-bottom: 20px;
text-align: center;
margin-bottom: 20px;
width: 160px;
border-radius: var(--borderradius);
background-color: #fff;
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2),
@ -107,7 +142,7 @@ body {
}
.menu a {
color: #4d4d4d;
color: var(--secondarytext);
text-decoration:none;
}
@ -157,7 +192,7 @@ body {
padding: 8px 8px 8px 32px;
text-decoration: none;
font-size: 25px;
color: #818181;
color: var(--secondarytext);
display: block;
transition: 0.3s;
}
@ -175,7 +210,7 @@ body {
margin-left: 50px;
text-decoration: none;
display: block;
color: #818181;
color: var(--secondarytext);
transition: 0.3s;
}
@ -204,33 +239,30 @@ body {
}
/**
* Login select
* Login form
*/
.login-select {
position: sticky;
width: 300px;
height: 150px;
top: 50%;
left: 50%;
margin-top: 50px;
margin-bottom: 100px;
transform: translate(-50%);
.login-parent {
display: flex;
max-width: 800px;
margin: 30px auto;
}
padding: 20px 20px;
.login-welcome {
float: right;
max-width: 400px;
padding: 15px 20px;
border-radius: var(--borderradius) 0px 0px var(--borderradius);
background-color: #a8c7cf;
background-color: #fff;
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2),
0 9px 18px 0 rgba(0, 0, 0, 0.1);
}
/**
* Login form
*/
.login-container {
float: left;
max-width: 400px;
margin: 30px auto;
border-radius: 0px var(--borderradius) var(--borderradius) 0px;
padding: 15px 20px;
background-color: #fff;
@ -253,7 +285,7 @@ hr {
}
.table th {
background-color: #527984;
background-color: var(--highlights);
color: #fff;
}
@ -402,23 +434,23 @@ hr {
}
.section-buttons-group-left .btn{
background-color: #527984;
border-color: #527984;
background-color: var(--highlights);
border-color: var(--highlights);
}
.section-buttons-group-left .btn:hover{
background-color: #31484f;
background-color: #31484f;
border-color: #31484f;
}
.drag-and-drop .btn{
color: #527984;
border-color: #527984;
color: var(--highlights);
border-color: var(--highlights);
}
.drag-and-drop .btn:hover{
color: #527984;
border-color: #527984;
color: var(--highlights);
border-color: var(--highlights);
}
@ -427,8 +459,8 @@ hr {
}
.solid-button .btn{
background-color: #527984;
border-color: #527984;
background-color: var(--highlights);
border-color: var(--highlights);
}
.solid-button .btn:hover{
@ -437,8 +469,8 @@ hr {
}
.solid-button .btn:disabled{
background-color: #527984;
border-color: #527984;
background-color: var(--highlights);
border-color: var(--highlights);
}
.icon-button .btn{
@ -452,7 +484,7 @@ hr {
}
.icon-color {
color: #527984;
color: var(--highlights);
}
.form-horizontal .form-group {

View file

@ -96,8 +96,8 @@ class LoginComplete extends React.Component {
} else {
return <div className="verticalhorizontal">
<img
style={{height: 300}}
src={require('../img/dog-waiting-bw.jpg').default}
style={{height: 80}}
src={require('../img/ajax-loader.gif').default}
alt="Waiting Dog" />
</div>;
}

View file

@ -23,10 +23,11 @@ import { Redirect } from 'react-router-dom';
import LoginForm from './login-form';
import Header from '../common/header';
import Footer from '../common/footer';
import NotificationsDataManager from '../common/data-managers/notifications-data-manager';
import LoginStore from './login-store'
import AppDispatcher from '../common/app-dispatcher';
import branding from '../branding/branding';
class Login extends React.Component {
constructor(props) {
@ -70,14 +71,19 @@ class Login extends React.Component {
<NotificationSystem ref="notificationSystem" />
<Header />
<div className="login-parent">
<div className="login-welcome">
{branding.getWelcome()}
</div>
<div className="login-container">
<NavbarBrand>Login</NavbarBrand>
<div className="login-container">
<NavbarBrand>Login</NavbarBrand>
<LoginForm loginMessage={this.state.loginMessage} config={this.state.config}/>
<LoginForm loginMessage={this.state.loginMessage} config={this.state.config} />
</div>
</div>
<Footer />
{branding.getFooter()}
</div>
);
}

View file

@ -17,15 +17,20 @@
import React from 'react';
import Dialog from '../common/dialogs/dialog';
import Config from '../config';
import { Container } from 'flux/utils';
import LoginStore from './login-store'
import _ from 'lodash';
class RecoverPassword extends React.Component {
constructor(props) {
super(props);
this.state = {
admin: Config.admin
static getStores() {
return [LoginStore]
}
static calculateState(prevState, props) {
return {
config: LoginStore.getState().config
}
}
@ -44,14 +49,14 @@ class RecoverPassword extends React.Component {
valid={true}
>
<div>
<div>Please contact:</div>
<div>{this.state.admin.name}</div>
<div>E-Mail:</div>
<a href={`mailto:${this.state.admin.mail}`}>{this.state.admin.mail}</a>
<h5>Please contact:</h5>
<div>{_.get(this.state.config, ['contact', 'name'])}</div>
<a href={`mailto:${_.get(this.state.config, ['contact', 'mail'])}`}>{_.get(this.state.config, ['contact', 'mail'])}</a>
</div>
</Dialog>
);
}
}
export default RecoverPassword;
let fluxContainerConverter = require('../common/FluxContainerConverter');
export default Container.create(fluxContainerConverter.convert(RecoverPassword));

View file

@ -0,0 +1,71 @@
/**
* This file is part of VILLASweb.
*
* VILLASweb is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* VILLASweb is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with VILLASweb. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
import React from 'react';
import { Table } from 'react-bootstrap';
import Dialog from '../common/dialogs/dialog';
class UsersToScenarioDialog extends React.Component {
valid = true;
onClose() {
if (this.props.onClose != null) {
this.props.onClose();
}
};
renderRow(value, key) {
return ( <tr>
<td>{key}</td>
<td>{value}</td>
</tr> );
}
renderData() {
let arr = [];
this.props.users.forEach((value, key) => {
arr.push(this.renderRow(value,key))
})
return arr;
}
render() {
return <Dialog
size='md'
show={this.props.show}
title={'Add to \'' + this.props.scenario + '\'?'}
buttonTitle='Confirm'
onClose={() => this.onClose()}
valid={true}
>
<Table size='sm' striped>
<thead>
<tr>
<th>ID</th>
<th>Name</th>
</tr>
</thead>
<tbody>
{ this.renderData() }
</tbody>
</Table>
</Dialog>;
}
}
export default UsersToScenarioDialog;

View file

@ -20,13 +20,16 @@ import { Container } from 'flux/utils';
import AppDispatcher from '../common/app-dispatcher';
import UsersStore from './users-store';
import ScenarioStore from '../scenario/scenario-store';
import Icon from '../common/icon';
import IconButton from '../common/icon-button';
import { Dropdown, DropdownButton } from 'react-bootstrap';
import Table from '../common/table';
import TableColumn from '../common/table-column';
import NewUserDialog from './new-user';
import EditUserDialog from './edit-user';
import UsersToScenarioDialog from './users-to-scenario';
import DeleteDialog from '../common/dialogs/delete-dialog';
import NotificationsDataManager from "../common/data-managers/notifications-data-manager";
@ -34,25 +37,25 @@ import NotificationsFactory from "../common/data-managers/notifications-factory"
class Users extends Component {
static getStores() {
return [ UsersStore ];
return [UsersStore, ScenarioStore];
}
static calculateState(prevState, props) {
let token = localStorage.getItem("token");
// If there is a token available and this method was called as a result of loading users
if (!prevState && token) {
AppDispatcher.dispatch({
type: 'users/start-load',
token: token
});
if (prevState == null) {
prevState = {};
}
return {
token: token,
token: localStorage.getItem("token"),
users: UsersStore.getState(),
scenarios: ScenarioStore.getState(),
usersToAdd: prevState.usersToAdd || new Map(),
selectedScenarioID: prevState.selectedScenarioID || null,
selectedScenario: prevState.selectedScenario || '',
newModal: false,
addUsersModal: false,
editModal: false,
deleteModal: false,
modalData: {},
@ -60,6 +63,19 @@ class Users extends Component {
};
}
componentDidMount() {
AppDispatcher.dispatch({
type: 'scenarios/start-load',
token: this.state.token
});
AppDispatcher.dispatch({
type: 'users/start-load',
token: this.state.token
});
}
closeNewModal(data) {
this.setState({ newModal: false });
@ -102,77 +118,137 @@ class Users extends Component {
}
}
onModalKeyPress = (event) => {
if (event.key === 'Enter') {
event.preventDefault();
this.confirmDeleteModal();
onUserChecked(user) {
let temp = this.state.usersToAdd;
const found = temp.get(user.id);
if (!found) {
temp.set(user.id, user.username);
} else {
temp.delete(user.id)
}
this.setState({ usersToAdd: temp });
}
setScenario(ID) {
let scenarioID = parseInt(ID, 10)
let scenario = this.state.scenarios.find(s => s.id === scenarioID);
this.setState({ selectedScenarioID: scenario.id, selectedScenario: scenario.name, addUsersModal: true })
};
closeAddUsersModal() {
this.state.usersToAdd.forEach((value, key) => {
AppDispatcher.dispatch({
type: 'scenarios/add-user',
data: this.state.selectedScenarioID,
username: value,
token: this.state.token
});
})
this.setState({ addUsersModal: false, selectedScenarioID: null })
}
modifyActiveColumn(active) {
return <Icon icon={active ? 'check' : 'times'} />
}
render() {
const buttonStyle = {
marginLeft: '10px',
}
const iconStyle = {
height: '30px',
width: '30px'
}
return <div>
<h1>Users
<h1>Users
<span className='icon-button'>
<IconButton
ikey={0}
tooltip='Add User'
onClick={() => this.setState({ newModal: true })}
icon='plus'
/>
</span>
</h1>
<IconButton
childKey={0}
tooltip='Add User'
onClick={() => this.setState({ newModal: true })}
icon='plus'
buttonStyle={buttonStyle}
iconStyle={iconStyle}
/>
</span>
</h1>
<Table data={this.state.users}>
{this.state.currentUser.role === "Admin" ?
<TableColumn
title='ID'
dataKey='id'
/>
: <></>
}
<Table data={this.state.users}>
{this.state.currentUser.role === "Admin" ?
<TableColumn
title='Username'
width='150'
dataKey='username'
title='ID'
dataKey='id'
/>
: <></>
}
{this.state.currentUser.role === "Admin" ?
<TableColumn
title='E-mail'
dataKey='mail'
title='Add'
checkbox
onChecked={(index, event) => this.onUserChecked(index, event)}
checkboxKey='checked'
width='30'
/>
<TableColumn
title='Role'
dataKey='role'
/>
<TableColumn
title='Active'
dataKey='active'
modifier={(active) => this.modifyActiveColumn(active)}
/>
<TableColumn
width='200'
align='right'
editButton
deleteButton
onEdit={index => this.setState({
editModal: true,
modalData: this.state.users[index]
})}
onDelete={index => this.setState({
deleteModal: true,
modalData: this.state.users[index]
})}
/>
</Table>
: <></>
}
<TableColumn
title='Username'
width='150'
dataKey='username'
/>
<TableColumn
title='E-mail'
dataKey='mail'
/>
<TableColumn
title='Role'
dataKey='role'
/>
<TableColumn
title='Active'
dataKey='active'
modifier={(active) => this.modifyActiveColumn(active)}
/>
<TableColumn
width='200'
align='right'
editButton
deleteButton
onEdit={index => this.setState({
editModal: true,
modalData: this.state.users[index]
})}
onDelete={index => this.setState({
deleteModal: true,
modalData: this.state.users[index]
})}
/>
</Table>
<span className='solid-button'>
<DropdownButton
title='Add to Scenario'
onSelect={(id) => this.setScenario(id)}
>
{this.state.scenarios.map(scenario => (
<Dropdown.Item key={scenario.id} eventKey={scenario.id}>{scenario.name}</Dropdown.Item>
))}
</DropdownButton>
</span>
<NewUserDialog show={this.state.newModal} onClose={(data) => this.closeNewModal(data)} />
<EditUserDialog show={this.state.editModal} onClose={(data) => this.closeEditModal(data)} user={this.state.modalData} />
<DeleteDialog title="user" name={this.state.modalData.username} show={this.state.deleteModal} onClose={(e) => this.closeDeleteModal(e)} />
</div>;
<UsersToScenarioDialog
show={this.state.addUsersModal}
users={this.state.usersToAdd}
scenario={this.state.selectedScenario}
onClose={() => this.closeAddUsersModal()}
/>
<NewUserDialog show={this.state.newModal} onClose={(data) => this.closeNewModal(data)} />
<EditUserDialog show={this.state.editModal} onClose={(data) => this.closeEditModal(data)} user={this.state.modalData} />
<DeleteDialog title="user" name={this.state.modalData.username} show={this.state.deleteModal} onClose={(e) => this.closeDeleteModal(e)} />
</div>;
}
}