--- /dev/null
+/*
+ *
+ * Copyright 2016 RIFT.IO Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+// DescriptorModelMeta API (NSD + VNFD)
+
+
+var ProjectManagement = {};
+var Promise = require('bluebird');
+var rp = require('request-promise');
+var Promise = require('promise');
+var constants = require('../../api_utils/constants');
+var utils = require('../../api_utils/utils');
+var _ = require('lodash');
+
+ProjectManagement.get = function(req) {
+ var self = this;
+ var api_server = req.query['api_server'];
+
+ return new Promise(function(resolve, reject) {
+ Promise.all([
+ rp({
+ uri: utils.confdPort(api_server) + '/api/operational/project',
+ method: 'GET',
+ headers: _.extend({}, constants.HTTP_HEADERS.accept.data, {
+ 'Authorization': req.get('Authorization')
+ }),
+ forever: constants.FOREVER_ON,
+ rejectUnauthorized: false,
+ resolveWithFullResponse: true
+ })
+ ]).then(function(result) {
+ var response = {};
+ response['data'] = {};
+ if (result[0].body) {
+ response['data']['project'] = JSON.parse(result[0].body)['rw-project:project'];
+ }
+ response.statusCode = constants.HTTP_RESPONSE_CODES.SUCCESS.OK
+
+ resolve(response);
+ }).catch(function(error) {
+ var response = {};
+ console.log('Problem with ProjectManagement.get', error);
+ response.statusCode = error.statusCode || 500;
+ response.errorMessage = {
+ error: 'Failed to get ProjectManagement' + error
+ };
+ reject(response);
+ });
+ });
+};
+ProjectManagement.create = function(req) {
+ var self = this;
+ var api_server = req.query['api_server'];
+ var data = req.body;
+ data = {
+ "project":[data]
+ }
+ return new Promise(function(resolve, reject) {
+ Promise.all([
+ rp({
+ uri: utils.confdPort(api_server) + '/api/config/project',
+ method: 'POST',
+ headers: _.extend({}, constants.HTTP_HEADERS.accept.data, {
+ 'Authorization': req.get('Authorization')
+ }),
+ forever: constants.FOREVER_ON,
+ json: data,
+ rejectUnauthorized: false,
+ resolveWithFullResponse: true
+ })
+ ]).then(function(result) {
+ var response = {};
+ response['data'] = {};
+ if (result[0].body) {
+ response['data'] = result[0].body;
+ }
+ response.statusCode = constants.HTTP_RESPONSE_CODES.SUCCESS.OK
+
+ resolve(response);
+ }).catch(function(error) {
+ var response = {};
+ console.log('Problem with ProjectManagement.create', error);
+ response.statusCode = error.statusCode || 500;
+ response.errorMessage = {
+ error: 'Failed to create user' + error
+ };
+ reject(response);
+ });
+ });
+};
+ProjectManagement.update = function(req) {
+ var self = this;
+ var api_server = req.query['api_server'];
+ var bodyData = req.body;
+ data = {
+ "project":[bodyData]
+ }
+ var updateTasks = [];
+
+ var updateUser = rp({
+ uri: utils.confdPort(api_server) + '/api/config/project',
+ method: 'PUT',
+ headers: _.extend({}, constants.HTTP_HEADERS.accept.data, {
+ 'Authorization': req.get('Authorization')
+ }),
+ forever: constants.FOREVER_ON,
+ json: data,
+ rejectUnauthorized: false,
+ resolveWithFullResponse: true
+ });
+ updateTasks.push(updateUser)
+ return new Promise(function(resolve, reject) {
+ Promise.all([
+ updateTasks
+ ]).then(function(result) {
+ var response = {};
+ response['data'] = {};
+ if (result[0].body) {
+ response['data'] = result[0].body;
+ }
+ response.statusCode = constants.HTTP_RESPONSE_CODES.SUCCESS.OK
+
+ resolve(response);
+ }).catch(function(error) {
+ var response = {};
+ console.log('Problem with ProjectManagement.update', error);
+ response.statusCode = error.statusCode || 500;
+ response.errorMessage = {
+ error: 'Failed to passwordChange user' + error
+ };
+ reject(response);
+ });
+ });
+};
+
+ProjectManagement.delete = function(req) {
+ var self = this;
+ var projectname = req.params.projectname;
+ var api_server = req.query["api_server"];
+ var requestHeaders = {};
+ var url = `${utils.confdPort(api_server)}/api/config/project/${projectname}`
+ return new Promise(function(resolve, reject) {
+ _.extend(requestHeaders,
+ constants.HTTP_HEADERS.accept.data,
+ constants.HTTP_HEADERS.content_type.data, {
+ 'Authorization': req.get('Authorization')
+ });
+ rp({
+ url: url,
+ method: 'DELETE',
+ headers: requestHeaders,
+ forever: constants.FOREVER_ON,
+ rejectUnauthorized: false,
+ }, function(error, response, body) {
+ if (utils.validateResponse('ProjectManagement.DELETE', error, response, body, resolve, reject)) {
+ return resolve({
+ statusCode: response.statusCode,
+ data: JSON.stringify(response.body)
+ });
+ };
+ });
+ })
+}
+module.exports = ProjectManagement;
--- /dev/null
+
+/*
+ *
+ * Copyright 2016 RIFT.IO Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/**
+ * inactivity routes module. Provides a RESTful API for this
+ * skyquake instance's inactivity state.
+ * @module framework/core/modules/routes/inactivity
+ * @author Laurence Maultsby <laurence.maultsby@riftio.com>
+ */
+
+var cors = require('cors');
+var bodyParser = require('body-parser');
+var Router = require('express').Router();
+var utils = require('../../api_utils/utils');
+var ProjectManagementAPI = require('../api/projectManagementAPI.js');
+
+Router.use(bodyParser.json());
+Router.use(cors());
+Router.use(bodyParser.urlencoded({
+ extended: true
+}));
+
+Router.get('/project', cors(), function(req, res) {
+ ProjectManagementAPI.get(req).then(function(response) {
+ utils.sendSuccessResponse(response, res);
+ }, function(error) {
+ utils.sendErrorResponse(error, res);
+ });
+});
+Router.post('/project', cors(), function(req, res) {
+ ProjectManagementAPI.create(req).then(function(response) {
+ utils.sendSuccessResponse(response, res);
+ }, function(error) {
+ utils.sendErrorResponse(error, res);
+ });
+});
+Router.put('/project', cors(), function(req, res) {
+ ProjectManagementAPI.update(req).then(function(response) {
+ utils.sendSuccessResponse(response, res);
+ }, function(error) {
+ utils.sendErrorResponse(error, res);
+ });
+});
+Router.delete('/project/:projectname', cors(), function(req, res) {
+ ProjectManagementAPI.delete(req).then(function(response) {
+ utils.sendSuccessResponse(response, res);
+ }, function(error) {
+ utils.sendErrorResponse(error, res);
+ });
+});
+
+module.exports = Router;
+
+
+
--- /dev/null
+import './formControls.jsx';
+
+import React from 'react'
+import SelectOption from 'widgets/form_controls/selectOption.jsx';
+import imgAdd from '../../../node_modules/open-iconic/svg/plus.svg'
+import imgRemove from '../../../node_modules/open-iconic/svg/trash.svg'
+import TextInput from 'widgets/form_controls/textInput.jsx';
+import Input from 'widgets/form_controls/input.jsx';
+
+export class FormSection extends React.Component {
+ render() {
+ let className = 'FormSection ' + this.props.className;
+ let html = (
+ <div
+ style={this.props.style}
+ className={className}
+ >
+ <div className="FormSection-title">
+ {this.props.title}
+ </div>
+ <div className="FormSection-body">
+ {this.props.children}
+ </div>
+ </div>
+ );
+ return html;
+ }
+}
+
+FormSection.defaultProps = {
+ className: ''
+}
+
+/**
+ * AddItemFn:
+ */
+export class InputCollection extends React.Component {
+ constructor(props) {
+ super(props);
+ this.collection = props.collection;
+ }
+ buildTextInput(onChange, v, i) {
+ return (
+ <Input
+ readonly={this.props.readonly}
+ style={{flex: '1 1'}}
+ key={i}
+ value={v}
+ onChange= {onChange.bind(null, i)}
+ />
+ )
+ }
+ buildSelectOption(initial, options, onChange, v, i) {
+ return (
+ <SelectOption
+ readonly={this.props.readonly}
+ key={`${i}-${v.replace(' ', '_')}`}
+ intial={initial}
+ defaultValue={v}
+ options={options}
+ onChange={onChange.bind(null, i)}
+ />
+ );
+ }
+ showInput() {
+
+ }
+ render() {
+ const props = this.props;
+ let inputType;
+ let className = "InputCollection";
+ if (props.className) {
+ className = `${className} ${props.className}`;
+ }
+ if (props.type == 'select') {
+ inputType = this.buildSelectOption.bind(this, props.initial, props.options, props.onChange);
+ } else {
+ inputType = this.buildTextInput.bind(this, props.onChange)
+ }
+ let html = (
+ <div className="InputCollection-wrapper">
+ {props.collection.map((v,i) => {
+ return (
+ <div key={i} className={className} >
+ {inputType(v, i)}
+ {
+ props.readonly ? null : <span onClick={props.RemoveItemFn.bind(null, i)} className="removeInput"><img src={imgRemove} />Remove</span>}
+ </div>
+ )
+ })}
+ { props.readonly ? null : <span onClick={props.AddItemFn} className="addInput"><img src={imgAdd} />Add</span>}
+ </div>
+ );
+ return html;
+ }
+}
+
+InputCollection.defaultProps = {
+ input: Input,
+ collection: [],
+ onChange: function(i, e) {
+ console.log(`
+ Updating with: ${e.target.value}
+ At index of: ${i}
+ `)
+ },
+ AddItemFn: function(e) {
+ console.log(`Adding a new item to collection`)
+ },
+ RemoveItemFn: function(i, e) {
+ console.log(`Removing item from collection at index of: ${i}`)
+ }
+}
--- /dev/null
+# RIFT_IO_STANDARD_CMAKE_COPYRIGHT_HEADER(BEGIN)
+# Author(s): Kiran Kashalkar
+# Creation Date: 08/18/2015
+# RIFT_IO_STANDARD_CMAKE_COPYRIGHT_HEADER(END)
+
+##
+# DEPENDENCY ALERT
+# The submodule dependencies must be specified in the
+# .gitmodules.dep file at the top level (supermodule) directory
+# If this submodule depends other submodules remember to update
+# the .gitmodules.dep
+##
+
+cmake_minimum_required(VERSION 2.8)
+
+##
+# Submodule specific includes will go here,
+# These are specified here, since these variables are accessed
+# from multiple sub directories. If the variable is subdirectory
+# specific it must be declared in the subdirectory.
+##
+
+rift_externalproject_add(
+ config
+ DEPENDS skyquake
+ SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}
+ CONFIGURE_COMMAND echo
+ BUILD_COMMAND
+ ${CMAKE_CURRENT_BINARY_DIR}/config/config-build/scripts/build.sh
+ INSTALL_COMMAND
+ ${CMAKE_CURRENT_SOURCE_DIR}/scripts/install.sh
+ ${CMAKE_CURRENT_BINARY_DIR}/config/config-build
+ ${CMAKE_INSTALL_PREFIX}/usr/share/rw.ui/skyquake
+ ${RIFT_SUBMODULE_INSTALL_PREFIX}/skyquake/${CMAKE_INSTALL_PREFIX}/usr/share/rw.ui/skyquake
+
+ BCACHE_COMMAND echo
+)
+
--- /dev/null
+{
+ "root": "public",
+ "name": "Project Management",
+ "dashboard": "./dashboard/dashboard.jsx",
+ "order": 1,
+ "priority":1,
+ "routes": [
+ {
+ "label": "Project Management Dashboard",
+ "route": "project-management",
+ "component": "./dashboard/dashboard.jsx",
+ "type": "internal"
+ }]
+}
--- /dev/null
+{
+ "name": "config",
+ "version": "1.0.0",
+ "description": "",
+ "main": "routes.js",
+ "scripts": {
+ "start": "rm -rf public/ && mkdir public && cd public && mkdir build && cp ../src/index.html ./ && node ../server.js"
+ },
+ "author": "RIFT.io",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "alt": "^0.18.3",
+ "bluebird": "^3.4.1",
+ "express": "^4.13.3",
+ "history": "^1.17.0",
+ "jquery": "^2.2.1",
+ "json-loader": "^0.5.4",
+ "lodash": "^4.10.0",
+ "normalizr": "^2.1.0",
+ "open-iconic": "^1.1.1",
+ "prismjs": "^1.4.1",
+ "react": "^0.14.8",
+ "react-breadcrumbs": "^1.3.9",
+ "react-crouton": "^0.2.7",
+ "react-dom": "^0.14.6",
+ "react-router": "^2.0.1",
+ "react-slick": "^0.11.1",
+ "react-tabs": "^0.5.3",
+ "react-treeview": "^0.4.2",
+ "request-promise": "^3.0.0",
+ "underscore": "^1.8.3"
+ },
+ "devDependencies": {
+ "babel-core": "^6.4.5",
+ "babel-loader": "^6.2.1",
+ "babel-polyfill": "^6.9.1",
+ "babel-preset-es2015": "^6.6.0",
+ "babel-preset-react": "^6.5.0",
+ "babel-preset-stage-0": "^6.3.13",
+ "babel-runtime": "^6.3.19",
+ "cors": "^2.7.1",
+ "css-loader": "^0.23.1",
+ "file-loader": "^0.8.5",
+ "html-webpack-plugin": "^2.9.0",
+ "http-proxy": "^1.12.0",
+ "loaders.css": "^0.1.2",
+ "node-sass": "^3.4.2",
+ "react-addons-css-transition-group": "^0.14.7",
+ "sass-loader": "^3.1.2",
+ "style-loader": "^0.13.0",
+ "webpack": "^1.3.0",
+ "webpack-dev-server": "^1.16.3"
+ }
+}
--- /dev/null
+/*
+ * STANDARD_RIFT_IO_COPYRIGHT
+ */
+
+var app = require('express').Router();
+var cors = require('cors');
+var utils = require('../../framework/core/api_utils/utils.js')
+ // Begin Accounts API
+
+ utils.passThroughConstructor(app);
+
+module.exports = app;
--- /dev/null
+#!/bin/bash
+
+# STANDARD_RIFT_IO_COPYRIGHT
+
+PLUGIN_NAME=project-management
+# change to the directory of this script
+THIS_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
+cd $THIS_DIR
+cd ..
+
+echo 'Building plugin '$PLUGIN_NAME
+echo 'Fetching third-party node_modules for '$PLUGIN_NAME
+npm install
+echo 'Fetching third-party node_modules for '$PLUGIN_NAME'...done'
+echo 'Packaging '$PLUGIN_NAME' using webpack'
+ui_plugin_cmake_build=true ./node_modules/.bin/webpack --progress --config webpack.production.config.js
+echo 'Packaging '$PLUGIN_NAME' using webpack... done'
+echo 'Building plugin '$PLUGIN_NAME'... done'
--- /dev/null
+#!/bin/bash
+
+# STANDARD_RIFT_IO_COPYRIGHT
+
+plugin=project-management
+source_dir=$1
+dest_dir=$2
+bcache_dir=$3
+
+# Create destination and build cache directories
+mkdir -p $dest_dir
+mkdir -p $bcache_dir
+
+# Create necessary directories under dest and cache dirs
+mkdir -p $dest_dir/framework
+mkdir -p $dest_dir/plugins
+mkdir -p $bcache_dir/framework
+mkdir -p $bcache_dir/plugins
+
+# Copy over built plugin's public folder, config.json, routes.js and api folder as per installed_plugins.txt
+mkdir -p $dest_dir/plugins/$plugin
+cp -Lrf $source_dir/public $dest_dir/plugins/$plugin/.
+cp -Lrf $source_dir/config.json $dest_dir/plugins/$plugin/.
+cp -Lrf $source_dir/routes.js $dest_dir/plugins/$plugin/.
+cp -Lrp $source_dir/api $dest_dir/plugins/$plugin/.
+tar -cf $dest_dir/plugins/$plugin/node_modules.tar node_modules package.json -C $source_dir
+#cp -Lrp $source_dir/node_modules $dest_dir/plugins/$plugin/.
+mkdir -p $bcache_dir/plugins/$plugin
+cp -Lrf $source_dir/public $bcache_dir/plugins/$plugin/.
+cp -Lrf $source_dir/config.json $bcache_dir/plugins/$plugin/.
+cp -Lrf $source_dir/routes.js $bcache_dir/plugins/$plugin/.
+cp -Lrp $source_dir/api $bcache_dir/plugins/$plugin/.
+tar -cf $bcache_dir/plugins/$plugin/node_modules.tar $source_dir/node_modules $source_dir/package.json
+#cp -Lrp $source_dir/node_modules $bcache_dir/plugins/$plugin/.
--- /dev/null
+/*
+ * STANDARD_RIFT_IO_COPYRIGHT
+ */
+
+var express = require('express');
+var path = require('path');
+var httpProxy = require('http-proxy');
+var bodyParser = require('body-parser');
+var cors = require('cors');
+var session = require('express-session');
+var proxy = httpProxy.createProxyServer();
+var app = express();
+
+var isProduction = process.env.NODE_ENV === 'production';
+var port = isProduction ? 8080 : 8888;
+var publicPath = path.resolve(__dirname, 'public');
+
+if (!isProduction) {
+
+ //Routes for local development
+ var lpRoutes = require('./routes.js');
+
+ app.use(express.static(publicPath));
+ app.use(session({
+ secret: 'ritio rocks',
+ }));
+ app.use(bodyParser.urlencoded({
+ extended: true
+ }));
+ app.use(bodyParser.json());
+ app.use(cors());
+ app.use('/', lpRoutes);
+ var bundle = require('./server/bundle.js');
+ bundle();
+
+ app.all('/build/*', function (req, res) {
+ proxy.web(req, res, {
+ target: 'http://localhost:8080'
+ });
+ });
+
+}
+proxy.on('error', function(e) {
+ console.log('Could not connect to proxy, please try again...');
+});
+
+app.listen(port, function () {
+ console.log('Server running on port ' + port);
+});
+
+app.get('/*')
--- /dev/null
+/*
+ * STANDARD_RIFT_IO_COPYRIGHT
+ */
+
+import React from 'react';
+import ReactDOM from 'react-dom';
+import AppHeader from 'widgets/header/header.jsx';
+import ProjectManagementStore from './projectMgmtStore.js';
+import SkyquakeComponent from 'widgets/skyquake_container/skyquakeComponent.jsx';
+import 'style/layout.scss';
+import './projectMgmt.scss';
+import {Panel, PanelWrapper} from 'widgets/panel/panel';
+import {InputCollection, FormSection} from 'widgets/form_controls/formControls.jsx';
+
+import TextInput from 'widgets/form_controls/textInput.jsx';
+import Input from 'widgets/form_controls/input.jsx';
+import Button, {ButtonGroup} from 'widgets/button/sq-button.jsx';
+import SelectOption from 'widgets/form_controls/selectOption.jsx';
+import 'widgets/form_controls/formControls.scss';
+import imgAdd from '../../node_modules/open-iconic/svg/plus.svg'
+import imgRemove from '../../node_modules/open-iconic/svg/trash.svg'
+
+class ProjectManagementDashboard extends React.Component {
+ constructor(props) {
+ super(props);
+ this.Store = this.props.flux.stores.hasOwnProperty('ProjectManagementStore') ? this.props.flux.stores.ProjectManagementStore : this.props.flux.createStore(ProjectManagementStore);
+ this.Store.getProjects();
+ this.Store.getUsers();
+ this.state = this.Store.getState();
+ this.actions = this.state.actions;
+ }
+ componentDidUpdate() {
+ let self = this;
+ ReactDOM.findDOMNode(this.projectList).addEventListener('transitionend', this.onTransitionEnd, false);
+ setTimeout(function() {
+ let element = self[`project-ref-${self.state.activeIndex}`]
+ element && !isElementInView(element) && element.scrollIntoView({block: 'end', behavior: 'smooth'});
+ })
+ }
+ componentWillMount() {
+ this.Store.listen(this.updateState);
+ }
+ componentWillUnmount() {
+ this.Store.unlisten(this.updateState);
+ }
+ updateState = (state) => {
+ this.setState(state);
+ }
+ updateInput = (key, e) => {
+ let property = key;
+ this.actions.handleUpdateInput({
+ [property]:e.target.value
+ })
+ }
+ disabledChange = (e) => {
+ this.actions.handleDisabledChange(e.target.checked);
+ }
+ platformChange = (platformRole, e) => {
+ this.actions.handlePlatformRoleUpdate(platformRole, e.currentTarget.checked);
+ }
+ addProjectRole = (e) => {
+ this.actions.handleAddProjectItem();
+ }
+ removeProjectRole = (i, e) => {
+ this.actions.handleRemoveProjectItem(i);
+ }
+ updateProjectRole = (i, e) => {
+ this.actions.handleUpdateProjectRole(i, e)
+ }
+ addProject = () => {
+ this.actions.handleAddProject();
+ }
+ viewProject = (un, index) => {
+ this.actions.viewProject(un, index);
+ }
+ editProject = () => {
+ this.actions.editProject(false);
+ }
+ cancelEditProject = () => {
+ this.actions.editProject(true)
+ }
+ closePanel = () => {
+ this.actions.handleCloseProjectPanel();
+ }
+
+ deleteProject = (e) => {
+ e.preventDefault();
+ e.stopPropagation();
+ this.Store.deleteProject({
+ 'name': this.state['name']
+ });
+ }
+ createProject = (e) => {
+ let self = this;
+ e.preventDefault();
+ e.stopPropagation();
+ let projectUsers = self.state.projectUsers;
+
+ //Remove null values from role
+ projectUsers.map((u) => {
+ u.role && u.role.map((r,i) => {
+ let role = {};
+ //you may add a user without a role or a keys, but if one is present then the other must be as well.
+ if(!r || ((r.role || r['keys']) && (!r.role || !r['keys']))) {
+ projectUsers.splice(i, 1);
+ } else {
+ return u;
+ }
+ })
+ })
+ this.Store.createProject({
+ 'name': self.state['name'],
+ 'description': self.state.description,
+ 'project-config' : {
+ 'user': projectUsers
+ }
+ });
+ }
+ updateProject = (e) => {
+ let self = this;
+ e.preventDefault();
+ e.stopPropagation();
+ let projectUsers = self.state.projectUsers;
+
+ //Remove null values from role
+ projectUsers.map((u) => {
+ u.role && u.role.map((r,i) => {
+ let role = {};
+ //you may add a user without a role or a keys, but if one is present then the other must be as well.
+ if(!r || ((r.role || r['keys']) && (!r.role || !r['keys']))) {
+ projectUsers.splice(i, 1);
+ } else {
+ return u;
+ }
+ })
+ })
+
+ this.Store.updateProject(_.merge({
+ 'name': self.state['name'],
+ 'description': self.state.description,
+ 'project-config' : {
+ 'user': projectUsers
+ }
+ }));
+ }
+ evaluateSubmit = (e) => {
+ if (e.keyCode == 13) {
+ if (this.props.isEdit) {
+ this.updateProject(e);
+ } else {
+ this.createProject(e);
+ }
+ e.preventDefault();
+ e.stopPropagation();
+ }
+ }
+ updateSelectedUser = (e) => {
+ this.setState({
+ selected
+ })
+ }
+ addUserToProject = (e) => {
+ this.actions.handleAddUser();
+ }
+ removeUserFromProject = (userIndex, e) => {
+ this.actions.handleRemoveUserFromProject(userIndex);
+ }
+ updateUserRoleInProject = (userIndex, roleIndex, e) => {
+ this.actions.handleUpdateUserRoleInProject({
+ userIndex,
+ roleIndex,
+ value: JSON.parse(e.target.value)
+ })
+ }
+ removeRoleFromUserInProject = (userIndex, roleIndex, e) => {
+ this.actions.handleRemoveRoleFromUserInProject({
+ userIndex,
+ roleIndex
+ })
+ }
+ addRoleToUserInProject = (userIndex, e) => {
+ this.actions.addRoleToUserInProject(userIndex);
+ }
+ onTransitionEnd = (e) => {
+ this.actions.handleHideColumns(e);
+ console.log('transition end')
+ }
+ disableChange = (e) => {
+ let value = e.target.value;
+ value = value.toUpperCase();
+ if (value=="TRUE") {
+ value = true;
+ } else {
+ value = false;
+ }
+ console.log(value)
+ }
+ render() {
+ let self = this;
+ let html;
+ let props = this.props;
+ let state = this.state;
+ let passwordSectionHTML = null;
+ let formButtonsHTML = (
+ <ButtonGroup className="buttonGroup">
+ <Button label="EDIT" type="submit" onClick={this.editProject} />
+ </ButtonGroup>
+ );
+ if(!this.state.isReadOnly) {
+ formButtonsHTML = (
+ state.isEdit ?
+ (
+ <ButtonGroup className="buttonGroup">
+ <Button label="Update" type="submit" onClick={this.updateProject} />
+ <Button label="Delete" onClick={this.deleteProject} />
+ <Button label="Cancel" onClick={this.cancelEditProject} />
+ </ButtonGroup>
+ )
+ : (
+ <ButtonGroup className="buttonGroup">
+ <Button label="Create" type="submit" onClick={this.createProject} />
+ </ButtonGroup>
+ )
+ )
+ }
+
+ html = (
+ <PanelWrapper className={`row projectManagement ${!this.state.projectOpen ? 'projectList-open' : ''}`} style={{'alignContent': 'center', 'flexDirection': 'row'}} >
+ <PanelWrapper ref={(div) => { this.projectList = div}} className={`column projectList expanded ${this.state.projectOpen ? 'collapsed ' : ' '} ${this.state.hideColumns ? 'hideColumns ' : ' '}`}>
+ <Panel title="Project List" style={{marginBottom: 0}} no-corners>
+ <div className="tableRow tableRow--header">
+ <div className="projectName">
+ projectName
+ </div>
+ <div>
+ Description
+ </div>
+ </div>
+ {state.projects && state.projects.map((u, k) => {
+ let platformRoles = [];
+ for(let role in u.platformRoles) {
+ platformRoles.push(<div>{`${role}: ${u.platformRoles[role]}`}</div>)
+ }
+ return (
+ <div ref={(el) => this[`project-ref-${k}`] = el} className={`tableRow tableRow--data ${((self.state.activeIndex == k) && self.state.projectOpen) ? 'tableRow--data-active' : ''}`} key={k}>
+ <div
+ className={`projectName projectName-header ${((self.state.activeIndex == k) && self.state.projectOpen) ? 'activeProject' : ''}`}
+ onClick={self.viewProject.bind(null, u, k)}>
+ {u['name']}
+ </div>
+ <div>
+ {u['description']}
+ </div>
+
+
+ </div>
+ )
+ })}
+ </Panel>
+ <ButtonGroup className="buttonGroup" style={{margin: '0 0.5rem 0.5rem', background: '#ddd', paddingBottom: '0.5rem'}}>
+ <Button label="Add Project" onClick={this.addProject} />
+ </ButtonGroup>
+ </PanelWrapper>
+ <PanelWrapper onKeyUp={this.evaluateSubmit}
+ className={`ProjectAdmin column`}>
+ <Panel
+ title={state.isEdit ? state['name'] : 'Create Project'}
+ style={{marginBottom: 0}}
+ hasCloseButton={this.closePanel}
+ no-corners>
+ <FormSection title="PROJECT INFO">
+ {
+ this.state.isEdit ?
+ null
+ : <Input readonly={state.isReadOnly} label="Name" value={state['name']} onChange={this.updateInput.bind(null, 'name')} />
+ }
+ <Input readonly={state.isReadOnly} type="textarea" label="Description" value={state['description']} onChange={this.updateInput.bind(null, 'description')}></Input>
+ </FormSection>
+ <FormSection title="USER ROLES">
+ <div className="tableRow tableRow--header">
+ <div className="projectName">
+ User Name
+ </div>
+ <div>
+ Role
+ </div>
+ </div>
+ {
+ state.projectUsers && state.projectUsers.map((u, k) => {
+ return (
+ <div ref={(el) => this[`project-ref-${k}`] = el} className={`tableRow tableRow--data projectUsers`} key={k}>
+ <div className="userName" style={state.isReadOnly ? {paddingTop: '0.25rem'} : {} }>{u['user-name']}</div>
+ <div>
+ {
+ u.role && u.role.map((r, l) => {
+ return (
+ <div key={l}>
+ <div style={{display: 'flex'}} className="selectRole">
+ <SelectOption
+ readonly={state.isReadOnly}
+ defaultValue={r.role}
+ options={state.roles}
+ onChange={self.updateUserRoleInProject.bind(self, k, l)}
+ />
+ {!state.isReadOnly ?
+ <span
+ className="removeInput"
+ onClick={self.removeRoleFromUserInProject.bind(self, k, l)}
+ >
+ <img src={imgRemove} />
+ Remove Role
+ </span>
+ : null
+ }
+
+ </div>
+ </div>
+ )
+ })
+ }
+ {!state.isReadOnly ?
+ <div className="buttonGroup">
+ <span className="addInput addRole" onClick={self.addRoleToUserInProject.bind(self, k)}><img src={imgAdd} />
+ Add Role
+ </span>
+ {
+ (!(u.role && u.role.length)) ?
+ <span
+ className="removeInput"
+ onClick={self.removeUserFromProject.bind(self, k)}
+ >
+ <img src={imgRemove} />
+ Remove User
+ </span> : null
+ }
+ </div>
+ : null
+ }
+ </div>
+ </div>
+ )
+ })
+ }
+ {
+ !state.isReadOnly ?
+ <div className="tableRow tableRow--header">
+ <div>
+ <div className="addUser">
+ <SelectOption
+ onChange={this.actions.handleSelectedUser}
+ defaultValue={state.selectedUser}
+ initial={true}
+ options={state.users && state.users.map((u) => {
+ return {
+ label: u['user-name'],
+ value: u
+ }
+ })}
+ />
+ <span className="addInput" onClick={this.addUserToProject}><img src={imgAdd} />
+ Add User
+ </span>
+ </div>
+ </div>
+ </div> : null
+ }
+
+ </FormSection>
+
+ </Panel>
+ {formButtonsHTML}
+
+ </PanelWrapper>
+
+
+ </PanelWrapper>
+ );
+ return html;
+ }
+}
+// onClick={this.Store.update.bind(null, Account)}
+ProjectManagementDashboard.contextTypes = {
+ router: React.PropTypes.object
+};
+
+ProjectManagementDashboard.defaultProps = {
+ projectList: [],
+ selectedProject: {}
+}
+
+export default SkyquakeComponent(ProjectManagementDashboard);
+
+
+function isElementInView(el) {
+ var rect = el && el.getBoundingClientRect() || {};
+
+ return (
+ rect.top >= 0 &&
+ rect.left >= 0 &&
+ rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && /*or $(window).height() */
+ rect.right <= (window.innerWidth || document.documentElement.clientWidth) /*or $(window).width() */
+ );
+}
+
+
+// isReadOnly={state.isReadOnly} disabled={state.disabled} onChange={this.disableChange}
+
+class isDisabled extends React.Component {
+ constructor(props) {
+ super(props);
+ }
+ render() {
+ let props = this.props;
+ return (<div/>)
+ }
+}
+
+
+
+
--- /dev/null
+/*
+ * STANDARD_RIFT_IO_COPYRIGHT
+ */
+
+/* If there's time this really needs to be rewritten. Ideally with smooth animations.*/
+@import "style/_colors.scss";
+
+.projectManagement {
+ max-width: 900px;
+
+ .skyquakePanel-wrapper {
+ overflow-x: hidden;
+ }
+ .projectList {
+
+ -ms-flex: 0 1 200px;
+ flex: 0 1 200px;
+
+ .activeUser {
+ font-weight:bold;
+ }
+
+ /* transition: all 2s;*/
+ &.expanded {
+ -ms-flex: 1 1 100%;
+ flex: 1 1 100%;
+ /* transition: all 300ms;*/
+ .tableRow>div:not(.projectName) {
+ opacity: 1;
+ /* width:auto;*/
+ /* transition: width 600ms;*/
+ /* transition: opacity 300ms;*/
+ }
+ &.collapsed {
+ -ms-flex: 0 1 200px;
+ flex: 0 1 200px;
+ /* transition: all 2s;*/
+ .tableRow>div:not(.projectName) {
+ /* opacity: 0;*/
+ /* width:0px;*/
+ display:none;
+ overflow:hidden;
+ /* transition: all 600ms;*/
+ }
+ }
+ }
+ &.hideColumns {
+ overflow:hidden;
+ >div {
+ overflow:hidden;
+ }
+ .tableRow>div:not(.projectName) {
+ width: 0px;
+ /* transition: all 600ms;*/
+ }
+ .projectName {
+ &--header {
+ /* display:none;*/
+ }
+ }
+ }
+ .projectName {
+ cursor:pointer;
+ }
+
+
+ }
+
+ .projectAdmin {
+ -ms-flex: 1 1;
+ flex: 1 1;
+ width:auto;
+ opacity:1;
+
+ textarea{
+ height: 100px;
+ }
+ }
+ &.projectList-open {
+ .projectAdmin {
+ -ms-flex: 0 1 0px;
+ flex: 0 1 0px;
+ opacity:0;
+ /* width: 0px;*/
+ display:none;
+ /* transition: opacity 300ms;*/
+ /* transition: width 600ms;*/
+
+ }
+ }
+ .buttonGroup {
+ margin: 0 0.5rem 0.5rem;
+ background: #ddd;
+ padding-bottom: 0.5rem;
+ padding: 0.5rem 0;
+ border-top: #d3d3d3 1px solid;
+ }
+ .addUser {
+ display:-ms-flexbox;
+ display:flex;
+ -ms-flex-direction:row;
+ flex-direction:row;
+ label {
+ -ms-flex: 0 1;
+ flex: 0 1;
+ width:150px;
+ select {
+ width:150px;
+ }
+ }
+ }
+ .projectUsers {
+ .userName {
+ -ms-flex-pack: start;
+ justify-content: flex-start;
+ padding-top: 0.75rem;
+ }
+ select {
+ margin-bottom:0.5rem;
+ }
+ .addRole {
+ margin:.25rem 0;
+ }
+ .buttonGroup {
+ display:-ms-flexbox;
+ display:flex;
+ }
+
+ }
+ .projectUsers.tableRow--data:hover {
+ background:none;
+ color: black;
+ }
+}
+
+
+
+.FormSection {
+ &-title {
+ color: #000;
+ background: lightgray;
+ padding: 0.5rem;
+ border-top: 1px solid #f1f1f1;
+ border-bottom: 1px solid #f1f1f1;
+ }
+ &-body {
+ padding: 0.5rem 0.75rem;
+ }
+ label {
+ -ms-flex: 1 0;
+ flex: 1 0;
+ }
+ /* label {*/
+ /* display: -ms-flexbox;*/
+ /* display: flex;*/
+ /* -ms-flex-direction: column;*/
+ /* flex-direction: column;*/
+ /* width: 100%;*/
+ /* margin: 0.5rem 0;*/
+ /* -ms-flex-align: start;*/
+ /* align-items: flex-start;*/
+ /* -ms-flex-pack: start;*/
+ /* justify-content: flex-start;*/
+ /* }*/
+ select {
+ font-size: 1rem;
+ min-width: 75%;
+ height: 35px;
+ }
+}
+
+
+.InputCollection {
+ display:-ms-flexbox;
+ display:flex;
+ -ms-flex-wrap: nowrap;
+ flex-wrap: nowrap;
+ -ms-flex-align: center;
+ align-items: center;
+ button {
+ padding: 0.25rem;
+ height: 1.5rem;
+ font-size: 0.75rem;
+ }
+ select {
+ min-width: 100%;
+ }
+ margin-bottom:0.5rem;
+ &-wrapper {
+
+ }
+}
+.tableRow {
+ display:-ms-flexbox;
+ display:flex;
+ -ms-flex-wrap: nowrap;
+ flex-wrap: nowrap;
+ padding: 0.25rem;
+ margin: .125rem 0;
+ >div {
+ padding:0.25rem 1rem 0.25rem 0;
+ -ms-flex: 1 1 33%;
+ flex: 1 1 33%;
+ display: -ms-flexbox;
+ display: flex;
+ -ms-flex-direction: column;
+ flex-direction: column;
+ -ms-flex-pack: center;
+ justify-content: center;
+ }
+ &--header {
+ font-weight:bold;
+ }
+ &--data {
+ &:hover:not(&-active) {
+ background:$neutral-dark-1;
+ }
+ &:hover, .activeUser, &-active{
+ cursor:pointer;
+ color:white;
+ }
+ .activeUser, &-active{
+ background: #00acee;
+ }
+ }
+}
+
+.addInput, .removeInput {
+ display:-ms-flexbox;
+ display:flex;
+ -ms-flex-align:center;
+ align-items:center;
+ margin-left: 1rem;
+
+ font-size:0.75rem;
+ text-transform:uppercase;
+ font-weight:bold;
+
+ cursor:pointer;
+ img {
+ height:0.75rem;
+ margin-right:0.5rem;
+ width:auto;
+ }
+ span {
+ color: #5b5b5b;
+ text-transform: uppercase;
+ }
+}
--- /dev/null
+/*
+ * STANDARD_RIFT_IO_COPYRIGHT
+ */
+module.exports = function(Alt) {
+ return Alt.generateActions(
+ 'handleUpdateInput',
+ 'handleAddProjectItem',
+ 'handleRemoveProjectItem',
+ 'handleUpdateProjectRole',
+ 'viewProject',
+ 'editProject',
+ 'handleCloseProjectPanel',
+ 'handleHideColumns',
+ 'handleSelectedUser',
+ 'handleSelectedRole',
+ 'handleAddUser',
+ 'handleRemoveUserFromProject',
+ 'getProjectsSuccess',
+ 'getUsersSuccess',
+ 'getProjectsNotification',
+ 'handleDisabledChange',
+ 'handlePlatformRoleUpdate',
+ 'handleAddProject',
+ 'handleCreateProject',
+ 'handleUpdateProject',
+ 'handleUpdateSelectedUser',
+ 'handleUpdateUserRoleInProject',
+ 'addRoleToUserInProject',
+ 'handleRemoveRoleFromUserInProject',
+ 'updateProjectSuccess',
+ 'createProjectSuccess',
+ 'deleteProjectSuccess'
+ );
+}
--- /dev/null
+/*
+ * STANDARD_RIFT_IO_COPYRIGHT
+ */
+import $ from 'jquery';
+var Utils = require('utils/utils.js');
+let API_SERVER = require('utils/rw.js').getSearchParams(window.location).api_server;
+let HOST = API_SERVER;
+let NODE_PORT = require('utils/rw.js').getSearchParams(window.location).api_port || ((window.location.protocol == 'https:') ? 8443 : 8000);
+let DEV_MODE = require('utils/rw.js').getSearchParams(window.location).dev_mode || false;
+
+if (DEV_MODE) {
+ HOST = window.location.protocol + '//' + window.location.hostname;
+}
+
+
+let Projects = mockProjects();
+let Users = mockUsers();
+
+
+module.exports = function(Alt) {
+ return {
+
+ getUsers: {
+ remote: function() {
+ return new Promise(function(resolve, reject) {
+ // setTimeout(function() {
+ // resolve(Users);
+ // }, 1000);
+ $.ajax({
+ url: `/user?api_server=${API_SERVER}`,
+ type: 'GET',
+ beforeSend: Utils.addAuthorizationStub,
+ success: function(data, textStatus, jqXHR) {
+ resolve(data.users);
+ }
+ }).fail(function(xhr){
+ //Authentication and the handling of fail states should be wrapped up into a connection class.
+ Utils.checkAuthentication(xhr.status);
+ });
+ });
+ },
+ interceptResponse: interceptResponse({
+ 'error': 'There was an error retrieving the resource orchestrator information.'
+ }),
+ success: Alt.actions.global.getUsersSuccess,
+ loading: Alt.actions.global.showScreenLoader,
+ error: Alt.actions.global.showNotification
+ },
+ getProjects: {
+ remote: function() {
+ return new Promise(function(resolve, reject) {
+ // setTimeout(function() {
+ // resolve(Projects);
+ // }, 1000)
+ $.ajax({
+ url: `/project?api_server=${API_SERVER}`,
+ type: 'GET',
+ beforeSend: Utils.addAuthorizationStub,
+ success: function(data, textStatus, jqXHR) {
+ resolve(data.project);
+ }
+ }).fail(function(xhr){
+ //Authentication and the handling of fail states should be wrapped up into a connection class.
+ Utils.checkAuthentication(xhr.status);
+ });
+ });
+ },
+ interceptResponse: interceptResponse({
+ 'error': 'There was an error retrieving the resource orchestrator information.'
+ }),
+ success: Alt.actions.global.getProjectsSuccess,
+ loading: Alt.actions.global.showScreenLoader,
+ error: Alt.actions.global.showNotification
+ },
+ updateProject: {
+ remote: function(state, project) {
+ return new Promise(function(resolve, reject) {
+ $.ajax({
+ url: `/project?api_server=${API_SERVER}`,
+ type: 'PUT',
+ data: project,
+ beforeSend: Utils.addAuthorizationStub,
+ success: function(data, textStatus, jqXHR) {
+ resolve(data);
+ }
+ }).fail(function(xhr){
+ //Authentication and the handling of fail states should be wrapped up into a connection class.
+ Utils.checkAuthentication(xhr.status);
+ });
+ });
+ },
+ interceptResponse: interceptResponse({
+ 'error': 'There was an error updating the project.'
+ }),
+ success: Alt.actions.global.updateProjectSuccess,
+ loading: Alt.actions.global.showScreenLoader,
+ error: Alt.actions.global.showNotification
+ },
+ deleteProject: {
+ remote: function(state, project) {
+ return new Promise(function(resolve, reject) {
+ // setTimeout(function() {
+ // resolve(true);
+ // }, 1000)
+ $.ajax({
+ url: `/project/${project['name']}?api_server=${API_SERVER}`,
+ type: 'DELETE',
+ beforeSend: Utils.addAuthorizationStub,
+ success: function(data, textStatus, jqXHR) {
+ resolve(data);
+ }
+ }).fail(function(xhr){
+ //Authentication and the handling of fail states should be wrapped up into a connection class.
+ Utils.checkAuthentication(xhr.status);
+ });
+ });
+ },
+ interceptResponse: interceptResponse({
+ 'error': 'There was an error deleting the user.'
+ }),
+ success: Alt.actions.global.deleteProjectSuccess,
+ loading: Alt.actions.global.showScreenLoader,
+ error: Alt.actions.global.showNotification
+ },
+ createProject: {
+ remote: function(state, project) {
+
+ return new Promise(function(resolve, reject) {
+ // setTimeout(function() {
+ // resolve(true);
+ // }, 1000)
+ $.ajax({
+ url: `/project?api_server=${API_SERVER}`,
+ type: 'POST',
+ data: project,
+ beforeSend: Utils.addAuthorizationStub,
+ success: function(data, textStatus, jqXHR) {
+ resolve(data);
+ }
+ }).fail(function(xhr){
+ //Authentication and the handling of fail states should be wrapped up into a connection class.
+ Utils.checkAuthentication(xhr.status);
+ });
+ });
+ },
+ interceptResponse: interceptResponse({
+ 'error': 'There was an error updating the account.'
+ }),
+ success: Alt.actions.global.createProjectSuccess,
+ loading: Alt.actions.global.showScreenLoader,
+ error: Alt.actions.global.showNotification
+ }
+ }
+}
+
+function interceptResponse (responses) {
+ return function(data, action, args) {
+ if(responses.hasOwnProperty(data)) {
+ return {
+ type: data,
+ msg: responses[data]
+ }
+ } else {
+ return data;
+ }
+ }
+}
+
+function mockProjects() {
+ let data = [];
+ let count = 10;
+ for(let i = 0; i < 3; i++) {
+ data.push({
+ name: `Test Project ${i}`,
+ description: 'Some description',
+ roles: ['Some-Role', 'Some-Other-Role'],
+ users: [
+ {
+ 'user-name': 'Some-User',
+ 'user-domain': 'system',
+ role: [
+ {
+ 'role': 'Some-Role',
+ 'key-set' : 'some key'
+ },
+ {
+ 'role': 'Some-Other-Role',
+ 'key-set' : 'some key'
+ }
+ ]
+ },
+ {
+ 'user-name': 'Some-User',
+ 'user-domain': 'system',
+ role: [
+ {
+ 'role': 'Some-Role',
+ 'key-set' : 'some key'
+ }
+ ]
+ }
+ ]
+ })
+ }
+ return data;
+}
+function mockUsers() {
+ let data = [];
+ let count = 10;
+ for(let i = 0; i < 10; i++) {
+ data.push({
+ 'user-name': `Tester ${i}`,
+ 'user-domain': 'Some Domain',
+ platformRoles: {
+ super_admin: true,
+ platform_admin: false,
+ platform_oper: false
+ },
+ disabled: false,
+ projectRoles: [
+ 'Project:Role'
+ ]
+ })
+ }
+ return data;
+}
--- /dev/null
+/*
+ * STANDARD_RIFT_IO_COPYRIGHT
+ */
+import ProjectManagementActions from './projectMgmtActions.js';
+import ProjectManagementSource from './projectMgmtSource.js';
+import _ from 'lodash';
+export default class ProjectManagementStore {
+ constructor() {
+ this.actions = ProjectManagementActions(this.alt);
+ this.bindActions(this.actions);
+ this.registerAsync(ProjectManagementSource);
+ this.projects = [];
+ this['name'] = '';
+ this['description'] = 'Some Description';
+ this.projectUsers = [];
+ this.selectedUser = null;
+ this.selectedRole = null;
+ this.roles = ['Assign a role', 'super_admin'];
+ this.users = [];
+ this.activeIndex = null;
+ this.isReadOnly = true;
+ this.projectOpen = false;
+ this.hideColumns = false;
+ this.isEdit = false;
+ // this.exportPublicMethods({})
+ }
+ /**
+ * [handleFieldUpdate description]
+ * @param {Object} data {
+ * [store_property] : [value]
+ * }
+ * @return {[type]} [description]
+ */
+ handleUpdateInput(data) {
+ this.setState(data);
+ }
+ handleAddProjectItem(item) {
+ let projectRoles = this.projectRoles;
+ projectRoles.push('');
+ this.setState({projectRoles});
+ }
+ handleRemoveProjectItem(i) {
+ let projectRoles = this.projectRoles;
+ projectRoles.splice(i, 1);
+ console.log('Removing', projectRoles)
+ this.setState({projectRoles});
+ }
+ handleUpdateProjectRole(data) {
+ let i = data[0];
+ let e = data[1];
+ let projectRoles = this.projectRoles
+ projectRoles[i] = JSON.parse(e.currentTarget.value);
+ this.setState({
+ projectRoles
+ });
+ }
+ viewProject(data) {
+ let project = data[0];
+ let projectIndex = data[1];
+
+ let ProjectUser = {
+ 'name': project['name'],
+ 'description': project['description'],
+ 'projectUsers': project['project-config'] && project['project-config']['user'] || []
+ }
+ let state = _.merge({
+ activeIndex: projectIndex,
+ projectOpen: true,
+ isEdit: true,
+ isReadOnly: true
+ }, ProjectUser);
+ this.setState(state)
+ }
+ editProject(isEdit) {
+ this.setState({
+ isReadOnly: isEdit
+ })
+ }
+ handleCloseProjectPanel() {
+ this.setState({
+ projectOpen: false,
+ isEdit: false,
+ isReadOnly: true
+ })
+ }
+ handleHideColumns(e) {
+ if(this.projectOpen && e.currentTarget.classList.contains('hideColumns')) {
+ this.setState({
+ hideColumns: true
+ })
+ } else {
+ this.setState({
+ hideColumns: false
+ })
+ }
+ }
+ handleDisabledChange(isDisabled){
+ this.setState({
+ disabled: isDisabled
+ })
+ }
+ handlePlatformRoleUpdate(data){
+ let platform_role = data[0];
+ let checked = data[1];
+ let platformRoles = this.platformRoles;
+ platformRoles[platform_role] = checked;
+ this.setState({
+ platformRoles
+ })
+ }
+ handleSelectedUser(event) {
+ this.setState({
+ selectedUser: JSON.parse(event.currentTarget.value)
+ })
+ }
+
+ handleSelectedRole(event) {
+ this.setState({
+ selectedRole: JSON.parse(event.currentTarget.value)
+ })
+ }
+ resetProject() {
+ let name = '';
+ let description = '';
+ return {
+ 'name' : name,
+ 'description' : description
+ }
+ }
+ handleAddProject() {
+ this.setState(_.merge( this.resetProject() ,
+ {
+ isEdit: false,
+ projectOpen: true,
+ activeIndex: null,
+ isReadOnly: false,
+ projectUsers: []
+ }
+ ))
+ }
+
+ handleUpdateSelectedUser(user) {
+ this.setState({
+ selectedUser: JSON.parse(user)
+ });
+ }
+ handleAddUser() {
+ let u = JSON.parse(this.selectedUser);
+ let r = this.selectedRole;
+ let projectUsers = this.projectUsers;
+ console.log('adding user')
+ projectUsers.push({
+ 'user-name': u['user-name'],
+ 'user-domain': u['user-domain'],
+ "role":[{
+ "role": r,
+ "keys": r
+ }
+ ]
+ })
+ this.setState({projectUsers})
+ }
+ handleUpdateUserRoleInProject(data) {
+ let {userIndex, roleIndex, value} = data;
+ let projectUsers = this.projectUsers;
+ projectUsers[userIndex].role[roleIndex].role = value;
+ projectUsers[userIndex].role[roleIndex]['keys'] = value;
+
+ }
+ addRoleToUserInProject(userIndex) {
+ let projectUsers = this.projectUsers;
+ if(!projectUsers[userIndex].role) {
+ projectUsers[userIndex].role = [];
+ }
+ projectUsers[userIndex].role.push({
+ 'role': null,
+ //temp until we get actual keys
+ 'keys' : 'some key'
+ });
+ this.setState({
+ projectUsers
+ })
+ }
+ handleRemoveRoleFromUserInProject (data) {
+ let {userIndex, roleIndex} = data;
+ let projectUsers = this.projectUsers;
+ projectUsers[userIndex].role.splice(roleIndex, 1);
+ this.setState({
+ projectUsers
+ })
+ }
+ handleRemoveUserFromProject (userIndex) {
+ let projectUsers = this.projectUsers;
+ projectUsers.splice(userIndex, 1);
+ this.setState({
+ projectUsers
+ })
+ }
+ getProjectsSuccess(projects) {
+ this.alt.actions.global.hideScreenLoader.defer();
+ this.setState({projects: projects});
+ }
+ getUsersSuccess(users) {
+ console.log(users)
+ this.alt.actions.global.hideScreenLoader.defer();
+ this.setState({users});
+ }
+ updateProjectSuccess() {
+ this.alt.actions.global.hideScreenLoader.defer();
+ let projects = this.projects || [];
+ projects[this.activeIndex] = {
+ 'name': this['name'],
+ 'description': this['description']
+ }
+ this.setState({
+ projects,
+ isEdit: true,
+ isReadOnly: true
+ })
+ }
+ deleteProjectSuccess() {
+ this.alt.actions.global.hideScreenLoader.defer();
+ let projects = this.projects;
+ projects.splice(this.activeIndex, 1);
+ this.setState({projects, projectOpen: false})
+ }
+ createProjectSuccess() {
+ this.alt.actions.global.hideScreenLoader.defer();
+ let projects = this.projects || [];
+ projects.push({
+ 'name': this['name'],
+ 'description': this['description']
+ });
+ let newState = {
+ projects,
+ isEdit: true,
+ isReadOnly: true,
+ activeIndex: projects.length - 1
+ };
+ _.merge(newState)
+ this.setState(newState);
+ }
+}
--- /dev/null
+/*
+ * STANDARD_RIFT_IO_COPYRIGHT
+ */
+import "babel-polyfill";
+import { render } from 'react-dom';
+import SkyquakeRouter from 'widgets/skyquake_container/skyquakeRouter.jsx';
+const config = require('json!../config.json');
+
+let context = require.context('./', true, /^\.\/.*\.jsx$/);
+let router = SkyquakeRouter(config, context);
+let element = document.querySelector('#app');
+
+render(router, element);
+
+
--- /dev/null
+/*
+ * STANDARD_RIFT_IO_COPYRIGHT
+ */
+var Webpack = require('webpack');
+var path = require('path');
+var nodeModulesPath = path.resolve(__dirname, 'node_modules');
+var buildPath = path.resolve(__dirname, 'public', 'build');
+var mainPath = path.resolve(__dirname, 'src', 'main.js');
+var uiPluginCmakeBuild = process.env.ui_plugin_cmake_build || false;
+var frameworkPath = uiPluginCmakeBuild?'../../../../skyquake/skyquake-build/framework':'../../framework';
+var HtmlWebpackPlugin = require('html-webpack-plugin');
+var CommonsPlugin = new require("webpack/lib/optimize/CommonsChunkPlugin")
+// Added to overcome node-sass bug https://github.com/iam4x/isomorphic-flux-boilerplate/issues/62
+process.env.UV_THREADPOOL_SIZE=64;
+var config = {
+ devtool: 'source-map',
+ entry: mainPath,
+ output: {
+ path: buildPath,
+ filename: 'bundle.js',
+ publicPath: "build/"
+ },
+ resolve: {
+ extensions: ['', '.js', '.jsx', '.css', '.scss'],
+ root: path.resolve(frameworkPath),
+ alias: {
+ 'widgets': path.resolve(frameworkPath) + '/widgets',
+ 'style': path.resolve(frameworkPath) + '/style',
+ 'utils': path.resolve(frameworkPath) + '/utils'
+ }
+ },
+ module: {
+ loaders: [{
+ test: /\.(jpe?g|png|gif|svg|ttf|otf|eot|svg|woff(2)?)(\?[a-z0-9]+)?$/i,
+ loader: "file-loader"
+ },
+ {
+ test: /\.(js|jsx)$/,
+ exclude: /react-treeview/,
+ loader: 'babel-loader',
+ query: {
+ presets: ["es2015", "stage-0", "react"]
+ }
+ }, {
+ test: /\.css$/,
+ loader: 'style!css'
+ }, {
+ test: /\.scss/,
+ loader: 'style!css!sass?includePaths[]='+ path.resolve(frameworkPath)
+ }
+ ]
+ },
+ plugins: [
+ new HtmlWebpackPlugin({
+ filename: '../index.html'
+ , templateContent: '<div id="app"></div>'
+ }),
+ new Webpack.optimize.CommonsChunkPlugin("vendor", "vendor.js", Infinity)
+ ]
+};
+module.exports = config;
+++ /dev/null
-/*
- * STANDARD_RIFT_IO_COPYRIGHT
- */
-
-var request = require('request');
-var Promise = require('bluebird');
-var rp = require('request-promise');
-var utils = require('../../../framework/core/api_utils/utils.js');
-var constants = require('../../../framework/core/api_utils/constants.js');
-var _ = require('underscore');
-var RO = {}
-RO.get = function(req) {
-return new Promise(function(resolve, reject) {
- var self = this;
- var api_server = req.query["api_server"];
- var requestHeaders = {};
- var url = utils.confdPort(api_server) + '/api/running/resource-orchestrator';
- _.extend(
- requestHeaders,
- id ? constants.HTTP_HEADERS.accept.data : constants.HTTP_HEADERS.accept.collection, {
- 'Authorization': req.get('Authorization')
- }
- );
-
- request({
- url: url + '?deep',
- type: 'GET',
- headers: requestHeaders,
- forever: constants.FOREVER_ON,
- rejectUnauthorized: false
- },
- function(error, response, body) {
- var data;
- if (utils.validateResponse('RO.get', error, response, body, resolve, reject)) {
- try {
- data = JSON.parse(response.body);
- if (!id) {
- data = data.collection;
- }
-
- data = data[objKey]
- } catch (e) {
- console.log('Problem with "' + type.toUpperCase() + '.get"', e);
- var err = {};
- err.statusCode = 500;
- err.errorMessage = {
- error: 'Problem with "' + type.toUpperCase() + '.get": ' + e
- }
- return reject(err);
- }
- return resolve({
- statusCode: response.statusCode,
- data: data
- });
- };
- });
- });
-}
-
-RO.update = updateAccount;
-
-function updateAccount(req) {
- var self = this;
- var api_server = req.query["api_server"];
- var data = req.body;
- var requestHeaders = {};
- var url = utils.confdPort(api_server) + '/api/config/resource-orchestrator';
- var method = 'PUT'
-
- return new Promise(function(resolve, reject) {
- _.extend(requestHeaders,
- constants.HTTP_HEADERS.accept.data,
- constants.HTTP_HEADERS.content_type.data, {
- 'Authorization': req.get('Authorization')
- });
- request({
- url: url,
- method: method,
- headers: requestHeaders,
- forever: constants.FOREVER_ON,
- rejectUnauthorized: false,
- json: data,
- }, function(error, response, body) {
- if (utils.validateResponse('RO.update', error, response, body, resolve, reject)) {
- return resolve({
- statusCode: response.statusCode,
- data: JSON.stringify(response.body)
- });
- };
- });
- })
-}
-
-module.exports = RO;
var app = require('express').Router();
var cors = require('cors');
var utils = require('../../framework/core/api_utils/utils.js')
-var ro = require('./api/ro.js')
// Begin Accounts API
- app.get('/resource-orchestrator', cors(), function(req, res) {
- ro.get(req).then(function(data) {
- utils.sendSuccessResponse(data, res);
- }, function(error) {
- utils.sendErrorResponse(error, res);
- });
- });
- app.put('/resource-orchestrator', cors(), function(req, res) {
- ro.update(req).then(function(data) {
- utils.sendSuccessResponse(data, res);
- }, function(error) {
- utils.sendErrorResponse(error, res);
- });
- })
utils.passThroughConstructor(app);
}
html = (
- <PanelWrapper className={`row userManagement ${!this.state.userOpen ? 'userList-open' : ''}`} style={{'alignContent': 'center', 'flexDirection': 'row'}} >
+ <PanelWrapper className={`row userManagement ${!this.state.userOpen ? 'userList-open' : ''}`} style={{'flexDirection': 'row'}} >
<PanelWrapper ref={(div) => { this.UserList = div}} className={`column userList expanded ${this.state.userOpen ? 'collapsed ' : ' '} ${this.state.hideColumns ? 'hideColumns ' : ' '}`}>
<Panel title="User List" style={{marginBottom: 0}} no-corners>
<div className="tableRow tableRow--header">
.userManagement {
max-width: 900px;
- -ms-flex-item-align:center;
- -ms-grid-row-align:center;
- align-self:center;
.skyquakePanel-wrapper {
overflow-x: hidden;
var configuration_routes = require('./framework/core/modules/routes/configuration');
var configurationAPI = require('./framework/core/modules/api/configuration');
var userManagement_routes = require('./framework/core/modules/routes/userManagement');
+ var projectManagement_routes = require('./framework/core/modules/routes/projectManagement');
/**
* Processing when a plugin is added or modified
* @param {string} plugin_name - Name of the plugin
//Configure user management route(s)
app.use(userManagement_routes);
+ //Configure project management route(s)
+ app.use(projectManagement_routes);
+
// app.get('/testme', function(req, res) {
// res.sendFile(__dirname + '/index.html');
// });