-#
+#
# Copyright 2016 RIFT.IO Inc
#
# Licensed under the Apache License, Version 2.0 (the "License");
#
# Author(s): Kiran Kashalkar
# Creation Date: 08/18/2015
-#
+#
##
# DEPENDENCY ALERT
composer
config
debug
+ project_management
+ user_management
# goodbyworld
# helloworld
launchpad
+++ /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
+# 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(
+ project_management
+ DEPENDS skyquake
+ SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}
+ CONFIGURE_COMMAND echo
+ BUILD_COMMAND
+ ${CMAKE_CURRENT_BINARY_DIR}/project_management/project_management-build/scripts/build.sh
+ INSTALL_COMMAND
+ ${CMAKE_CURRENT_SOURCE_DIR}/scripts/install.sh
+ ${CMAKE_CURRENT_BINARY_DIR}/project_management/project_management-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
-# 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": "User Management",
- "dashboard": "./dashboard/dashboard.jsx",
- "order": 1,
- "priority":1,
- "routes": [
- {
- "label": "User Management Dashboard",
- "route": "user-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=user-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=user-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 UserManagementStore from './userMgmtStore.js';
-import SkyquakeComponent from 'widgets/skyquake_container/skyquakeComponent.jsx';
-import 'style/layout.scss';
-import './userMgmt.scss';
-import {Panel, PanelWrapper} from 'widgets/panel/panel';
-
-
-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 UserManagementDashboard extends React.Component {
- constructor(props) {
- super(props);
- this.Store = this.props.flux.stores.hasOwnProperty('UserManagementStore') ? this.props.flux.stores.UserManagementStore : this.props.flux.createStore(UserManagementStore);
- this.Store.getUsers();
- this.state = this.Store.getState();
- this.actions = this.state.actions;
- }
- componentDidUpdate() {
- let self = this;
- ReactDOM.findDOMNode(this.UserList).addEventListener('transitionend', this.onTransitionEnd, false);
- setTimeout(function() {
- let element = self[`user-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)
- }
- addUser = () => {
- this.actions.handleAddUser();
- }
- viewUser = (un, index) => {
- this.actions.viewUser(un, index);
- }
- editUser = () => {
- this.actions.editUser(false);
- }
- cancelEditUser = () => {
- this.actions.editUser(true)
- }
- closePanel = () => {
- this.actions.handleCloseUserPanel();
- }
- // updateUser = (e) => {
- // e.preventDefault();
- // e.stopPropagation();
-
- // this.Store.updateUser();
- // }
- deleteUser = (e) => {
- e.preventDefault();
- e.stopPropagation();
- this.Store.deleteUser({
- 'user-name': this.state['user-name'],
- 'user-domain': this.state['user-domain']
- });
- }
- createUser = (e) => {
- e.preventDefault();
- e.stopPropagation();
- if(this.state['new-password'] != this.state['confirm-password']) {
- this.props.actions.showNotification('Passwords do not match')
- } else {
- this.Store.createUser({
- 'user-name': this.state['user-name'],
- 'user-domain': this.state['user-domain'],
- 'password': this.state['new-password']
- // 'confirm-password': this.state['confirm-password']
- });
- }
- }
- updateUser = (e) => {
- let self = this;
- e.preventDefault();
- e.stopPropagation();
- let validatedPasswords = validatePasswordFields(this.state);
- if(validatedPasswords) {
- this.Store.updateUser(_.merge({
- 'user-name': this.state['user-name'],
- 'user-domain': this.state['user-domain'],
- 'password': this.state['new-password']
- }));
- }
- function validatePasswordFields(state) {
- let oldOne = state['old-password'];
- let newOne = state['new-password'];
- let confirmOne = state['confirm-password'];
- if(true) {
- if(oldOne == newOne) {
- self.props.actions.showNotification('Your new password must not match your old one');
- return false;
- }
- if(newOne != confirmOne) {
- self.props.actions.showNotification('Passwords do not match');
- return false;
- }
- return {
- // 'old-password': oldOne,
- 'new-password': newOne,
- 'confirm-password': confirmOne
- }
- } else {
- return {};
- }
- }
- }
- evaluateSubmit = (e) => {
- if (e.keyCode == 13) {
- if (this.props.isEdit) {
- this.updateUser(e);
- } else {
- this.createUser(e);
- }
- e.preventDefault();
- e.stopPropagation();
- }
- }
- 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.editUser} />
- </ButtonGroup>
- );
- if(!this.state.isReadOnly) {
- passwordSectionHTML = ( this.state.isEdit ?
- (
- <FormSection title="PASSWORD CHANGE">
- <Input label="NEW PASSWORD" type="password" value={state['new-password']} onChange={this.updateInput.bind(null, 'new-password')}/>
- <Input label="REPEAT NEW PASSWORD" type="password" value={state['confirm-password']} onChange={this.updateInput.bind(null, 'confirm-password')}/>
- </FormSection>
- ) :
- (
- <FormSection title="CREATE PASSWORD">
- <Input label="CREATE PASSWORD" type="password" value={state.newPassword} onChange={this.updateInput.bind(null, 'new-password')}/>
- <Input label="REPEAT PASSWORD" type="password" value={state.repeatNewPassword} onChange={this.updateInput.bind(null, 'confirm-password')}/>
- </FormSection>
- )
- );
- formButtonsHTML = (
- state.isEdit ?
- (
- <ButtonGroup className="buttonGroup">
- <Button label="Update" type="submit" onClick={this.updateUser} />
- <Button label="Delete" onClick={this.deleteUser} />
- <Button label="Cancel" onClick={this.cancelEditUser} />
- </ButtonGroup>
- )
- : (
- <ButtonGroup className="buttonGroup">
- <Button label="Create" type="submit" onClick={this.createUser} />
- </ButtonGroup>
- )
- )
- }
-
- html = (
- <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">
- <div className="userName">
- Username
- </div>
- <div>
- Domain
- </div>
- </div>
- {state.users && state.users.map((u, k) => {
- let platformRoles = [];
- for(let role in u.platformRoles) {
- platformRoles.push(<div>{`${role}: ${u.platformRoles[role]}`}</div>)
- }
- return (
- <div ref={(el) => this[`user-ref-${k}`] = el} className={`tableRow tableRow--data ${((self.state.activeIndex == k) && self.state.userOpen) ? 'tableRow--data-active' : ''}`} key={k}>
- <div
- className={`userName userName-header ${((self.state.activeIndex == k) && self.state.userOpen) ? 'activeUser' : ''}`}
- onClick={self.viewUser.bind(null, u, k)}>
- {u['user-name']}
- </div>
- <div>
- {u['user-domain']}
- </div>
-
-
- </div>
- )
- })}
- </Panel>
- <ButtonGroup className="buttonGroup" style={{margin: '0 0.5rem 0.5rem', background: '#ddd', paddingBottom: '0.5rem'}}>
- <Button label="Add User" onClick={this.addUser} />
- </ButtonGroup>
- </PanelWrapper>
- <PanelWrapper onKeyUp={this.evaluateSubmit}
- className={`userAdmin column`}>
- <Panel
- title={state.isEdit ? state['user-name'] : 'Create User'}
- style={{marginBottom: 0}}
- hasCloseButton={this.closePanel}
- no-corners>
- <FormSection title="USER INFO">
- {
- this.state.isEdit ?
- null
- : <Input readonly={state.isReadOnly} label="Username" value={state['user-name']} onChange={this.updateInput.bind(null, 'user-name')} />
- }
- <Input readonly={true} label="Domain" value={state['user-domain']} onChange={this.updateInput.bind(null, 'user-domain')}></Input>
-
- <Input type="radiogroup" readonly={state.isReadOnly} label="Disabled" value={state.disabled} options={[{value: true, label: 'YES'}, {value: false, label: 'NO'}]} onChange={this.disableChange} />
- </FormSection>
- <FormSection title="PLATFORM ROLES" style={{display:'none'}}>
- <Input label="Super Admin" onChange={this.platformChange.bind(null, 'super_admin')} checked={state.platformRoles.super_admin} type="checkbox" />
- <Input label="Platform Admin" onChange={this.platformChange.bind(null, 'platform_admin')} checked={state.platformRoles.platform_admin} type="checkbox" />
- <Input label="Platform Oper" onChange={this.platformChange.bind(null, 'platform_oper')} checked={state.platformRoles.platform_oper} type="checkbox" />
- </FormSection>
- <FormSection title="PROJECT ROLES" style={{display:'none'}}>
- <InputCollection
- inital={true}
- type='select'
- readonly={state.isReadOnly}
- options={state.projectRolesOptions}
- collection={state.projectRoles}
- onChange={this.updateProjectRole}
- AddItemFn={this.addProjectRole}
- RemoveItemFn={this.removeProjectRole}
- />
- </FormSection>
- {passwordSectionHTML}
-
- </Panel>
- {formButtonsHTML}
-
- </PanelWrapper>
-
-
- </PanelWrapper>
- );
- return html;
- }
-}
-// onClick={this.Store.update.bind(null, Account)}
-UserManagementDashboard.contextTypes = {
- router: React.PropTypes.object
-};
-
-UserManagementDashboard.defaultProps = {
- userList: [],
- selectedUser: {}
-}
-
-export default SkyquakeComponent(UserManagementDashboard);
-
-
-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/>)
- }
-}
-
-/**
- * AddItemFn:
- */
-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}`)
- }
-}
-
-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: ''
-}
+++ /dev/null
-/*
- * STANDARD_RIFT_IO_COPYRIGHT
- */
-
-/* If there's time this really needs to be rewritten. Ideally with smooth animations.*/
-@import "style/_colors.scss";
-
-.userManagement {
- max-width: 900px;
-
- .skyquakePanel-wrapper {
- overflow-x: hidden;
- }
- .userList {
-
- -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(.userName) {
- 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(.userName) {
- /* opacity: 0;*/
- /* width:0px;*/
- display:none;
- overflow:hidden;
- /* transition: all 600ms;*/
- }
- }
- }
- &.hideColumns {
- overflow:hidden;
- >div {
- overflow:hidden;
- }
- .tableRow>div:not(.userName) {
- width: 0px;
- /* transition: all 600ms;*/
- }
- .userName {
- &--header {
- /* display:none;*/
- }
- }
- }
- .userName {
- cursor:pointer;
- }
-
- }
-
- .userAdmin {
- -ms-flex: 1 1;
- flex: 1 1;
- width:auto;
- opacity:1;
- }
- &.userList-open {
- .userAdmin {
- -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;
- }
-}
-
-
-
-.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%;
- }
- &--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',
- 'viewUser',
- 'editUser',
- 'handleCloseUserPanel',
- 'handleHideColumns',
- 'getUsersSuccess',
- 'getUsersNotification',
- 'handleDisabledChange',
- 'handlePlatformRoleUpdate',
- 'handleAddUser',
- 'handleCreateUser',
- 'handleUpdateUser',
- 'updateUserSuccess',
- 'createUserSuccess',
- 'deleteUserSuccess'
- );
-}
+++ /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 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
- },
- updateUser: {
- remote: function(state, user) {
- return new Promise(function(resolve, reject) {
- $.ajax({
- url: `/user?api_server=${API_SERVER}`,
- type: 'PUT',
- data: user,
- 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 user.'
- }),
- success: Alt.actions.global.updateUserSuccess,
- loading: Alt.actions.global.showScreenLoader,
- error: Alt.actions.global.showNotification
- },
- deleteUser: {
- remote: function(state, user) {
- return new Promise(function(resolve, reject) {
- // setTimeout(function() {
- // resolve(true);
- // }, 1000)
- $.ajax({
- url: `/user/${user['user-name']}/${user['user-domain']}?api_server=${API_SERVER}`,
- type: 'DELETE',
- data: user,
- 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.deleteUserSuccess,
- loading: Alt.actions.global.showScreenLoader,
- error: Alt.actions.global.showNotification
- },
- createUser: {
- remote: function(state, user) {
-
- return new Promise(function(resolve, reject) {
- // setTimeout(function() {
- // resolve(true);
- // }, 1000)
- $.ajax({
- url: `/user?api_server=${API_SERVER}`,
- type: 'POST',
- data: user,
- 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.createUserSuccess,
- 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 mockUsers() {
- let data = [];
- let count = 10;
- for(let i = 0; i < 10; i++) {
- data.push({
- username: `Tester ${i}`,
- 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 UserManagementActions from './userMgmtActions.js';
-import UserManagementSource from './userMgmtSource.js';
-import _ from 'lodash';
-export default class UserManagementStore {
- constructor() {
- this.actions = UserManagementActions(this.alt);
- this.bindActions(this.actions);
- this.registerAsync(UserManagementSource);
- this.users = [];
- this['user-name'] = '';
- this['user-domain'] = 'system';
- this.disabled = false;
- this.platformRoles = {
- super_admin: false,
- platform_admin: false,
- platform_oper: false
- };
- this.projectRoles = ['Project:Role'];
- this.projectRolesOptions = ['Choose your adventure', 'Project:Role', 'Project:Another Role'];
- this.currentPassword = '';
- this['old-password'] = '';
- this['new-password'] = '';
- this['confirm-password'] = '';
-
- this.activeIndex = null;
- this.isReadOnly = true;
- this.userOpen = 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
- });
- }
- viewUser(data) {
- let user = data[0];
- let userIndex = data[1];
-
- let ActiveUser = {
- 'user-name': user['user-name'],
- 'user-domain': user['user-domain'],
- platformRoles: user.platformRoles || this.platformRoles,
- disabled: user.disabled || this.disabled,
- projectRoles: user.projectRoles || this.projectRoles
- }
- let state = _.merge({
- activeIndex: userIndex,
- userOpen: true,
- isEdit: true,
- isReadOnly: true
- }, ActiveUser);
- this.setState(state)
- }
- editUser(isEdit) {
- this.setState({
- isReadOnly: isEdit
- })
- }
- handleCloseUserPanel() {
- this.setState({
- userOpen: false,
- isEdit: false,
- isReadOnly: true
- })
- }
- handleHideColumns(e) {
- if(this.userOpen && 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
- })
- }
- resetUser() {
- let username = '';
- let domain = 'system';
- let disabled = false;
- let platformRoles = {
- super_admin: false,
- platform_admin: false,
- platform_oper: false
- };
- let projectRoles = [];
- let currentPassword = '';
- let oldPassword = '';
- let newPassword = '';
- let confirmPassword = '';
- return {
- 'user-name' : username,
- 'user-domain' : domain,
- disabled,
- platformRoles,
- projectRoles,
- currentPassword,
- 'old-password': oldPassword,
- 'new-password': newPassword,
- 'confirm-password': confirmPassword
- }
- }
- resetPassword() {
- let currentPassword = '';
- let oldPassword = '';
- let newPassword = '';
- let confirmPassword = '';
- return {
- currentPassword,
- 'old-password': oldPassword,
- 'new-password': newPassword,
- 'confirm-password': confirmPassword
- }
- }
- handleAddUser() {
- this.setState(_.merge( this.resetUser() ,
- {
- isEdit: false,
- userOpen: true,
- activeIndex: null,
- isReadOnly: false
- }
- ))
- }
- handleCreateUser() {
-
- }
- handleUpdateUser() {
-
- }
-
- getUsersSuccess(users) {
- this.alt.actions.global.hideScreenLoader.defer();
- this.setState({users});
- }
- updateUserSuccess() {
- this.alt.actions.global.hideScreenLoader.defer();
- let users = this.users || [];
- users[this.activeIndex] = {
- 'user-name': this['user-name'],
- 'user-domain': this['user-domain'],
- platformRoles: this.platformRoles,
- disabled: this.disabled,
- projectRoles: this.projectRoles
- }
- this.setState({
- users,
- isEdit: true,
- isReadOnly: true
- })
- }
- deleteUserSuccess() {
- this.alt.actions.global.hideScreenLoader.defer();
- let users = this.users;
- users.splice(this.activeIndex, 1);
- this.setState({users, userOpen: false})
- }
- createUserSuccess() {
- this.alt.actions.global.hideScreenLoader.defer();
- let users = this.users || [];
- users.push({
- 'user-name': this['user-name'],
- 'user-domain': this['user-domain'],
- platformRoles: this.platformRoles,
- disabled: this.disabled,
- projectRoles: this.projectRoles,
- });
- let newState = {
- users,
- isEdit: true,
- isReadOnly: true,
- activeIndex: users.length - 1
- };
- _.merge(newState, this.resetPassword())
- 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
+# 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(
+ user_management
+ DEPENDS skyquake
+ SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}
+ CONFIGURE_COMMAND echo
+ BUILD_COMMAND
+ ${CMAKE_CURRENT_BINARY_DIR}/user_management/user_management-build/scripts/build.sh
+ INSTALL_COMMAND
+ ${CMAKE_CURRENT_SOURCE_DIR}/scripts/install.sh
+ ${CMAKE_CURRENT_BINARY_DIR}/user_management/user_management-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": "User Management",
+ "dashboard": "./dashboard/dashboard.jsx",
+ "order": 1,
+ "priority":1,
+ "routes": [
+ {
+ "label": "User Management Dashboard",
+ "route": "user-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=user-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=user-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 UserManagementStore from './userMgmtStore.js';
+import SkyquakeComponent from 'widgets/skyquake_container/skyquakeComponent.jsx';
+import 'style/layout.scss';
+import './userMgmt.scss';
+import {Panel, PanelWrapper} from 'widgets/panel/panel';
+
+
+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 UserManagementDashboard extends React.Component {
+ constructor(props) {
+ super(props);
+ this.Store = this.props.flux.stores.hasOwnProperty('UserManagementStore') ? this.props.flux.stores.UserManagementStore : this.props.flux.createStore(UserManagementStore);
+ this.Store.getUsers();
+ this.state = this.Store.getState();
+ this.actions = this.state.actions;
+ }
+ componentDidUpdate() {
+ let self = this;
+ ReactDOM.findDOMNode(this.UserList).addEventListener('transitionend', this.onTransitionEnd, false);
+ setTimeout(function() {
+ let element = self[`user-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)
+ }
+ addUser = () => {
+ this.actions.handleAddUser();
+ }
+ viewUser = (un, index) => {
+ this.actions.viewUser(un, index);
+ }
+ editUser = () => {
+ this.actions.editUser(false);
+ }
+ cancelEditUser = () => {
+ this.actions.editUser(true)
+ }
+ closePanel = () => {
+ this.actions.handleCloseUserPanel();
+ }
+ // updateUser = (e) => {
+ // e.preventDefault();
+ // e.stopPropagation();
+
+ // this.Store.updateUser();
+ // }
+ deleteUser = (e) => {
+ e.preventDefault();
+ e.stopPropagation();
+ this.Store.deleteUser({
+ 'user-name': this.state['user-name'],
+ 'user-domain': this.state['user-domain']
+ });
+ }
+ createUser = (e) => {
+ e.preventDefault();
+ e.stopPropagation();
+ if(this.state['new-password'] != this.state['confirm-password']) {
+ this.props.actions.showNotification('Passwords do not match')
+ } else {
+ this.Store.createUser({
+ 'user-name': this.state['user-name'],
+ 'user-domain': this.state['user-domain'],
+ 'password': this.state['new-password']
+ // 'confirm-password': this.state['confirm-password']
+ });
+ }
+ }
+ updateUser = (e) => {
+ let self = this;
+ e.preventDefault();
+ e.stopPropagation();
+ let validatedPasswords = validatePasswordFields(this.state);
+ if(validatedPasswords) {
+ this.Store.updateUser(_.merge({
+ 'user-name': this.state['user-name'],
+ 'user-domain': this.state['user-domain'],
+ 'password': this.state['new-password']
+ }));
+ }
+ function validatePasswordFields(state) {
+ let oldOne = state['old-password'];
+ let newOne = state['new-password'];
+ let confirmOne = state['confirm-password'];
+ if(true) {
+ if(oldOne == newOne) {
+ self.props.actions.showNotification('Your new password must not match your old one');
+ return false;
+ }
+ if(newOne != confirmOne) {
+ self.props.actions.showNotification('Passwords do not match');
+ return false;
+ }
+ return {
+ // 'old-password': oldOne,
+ 'new-password': newOne,
+ 'confirm-password': confirmOne
+ }
+ } else {
+ return {};
+ }
+ }
+ }
+ evaluateSubmit = (e) => {
+ if (e.keyCode == 13) {
+ if (this.props.isEdit) {
+ this.updateUser(e);
+ } else {
+ this.createUser(e);
+ }
+ e.preventDefault();
+ e.stopPropagation();
+ }
+ }
+ 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.editUser} />
+ </ButtonGroup>
+ );
+ if(!this.state.isReadOnly) {
+ passwordSectionHTML = ( this.state.isEdit ?
+ (
+ <FormSection title="PASSWORD CHANGE">
+ <Input label="NEW PASSWORD" type="password" value={state['new-password']} onChange={this.updateInput.bind(null, 'new-password')}/>
+ <Input label="REPEAT NEW PASSWORD" type="password" value={state['confirm-password']} onChange={this.updateInput.bind(null, 'confirm-password')}/>
+ </FormSection>
+ ) :
+ (
+ <FormSection title="CREATE PASSWORD">
+ <Input label="CREATE PASSWORD" type="password" value={state.newPassword} onChange={this.updateInput.bind(null, 'new-password')}/>
+ <Input label="REPEAT PASSWORD" type="password" value={state.repeatNewPassword} onChange={this.updateInput.bind(null, 'confirm-password')}/>
+ </FormSection>
+ )
+ );
+ formButtonsHTML = (
+ state.isEdit ?
+ (
+ <ButtonGroup className="buttonGroup">
+ <Button label="Update" type="submit" onClick={this.updateUser} />
+ <Button label="Delete" onClick={this.deleteUser} />
+ <Button label="Cancel" onClick={this.cancelEditUser} />
+ </ButtonGroup>
+ )
+ : (
+ <ButtonGroup className="buttonGroup">
+ <Button label="Create" type="submit" onClick={this.createUser} />
+ </ButtonGroup>
+ )
+ )
+ }
+
+ html = (
+ <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">
+ <div className="userName">
+ Username
+ </div>
+ <div>
+ Domain
+ </div>
+ </div>
+ {state.users && state.users.map((u, k) => {
+ let platformRoles = [];
+ for(let role in u.platformRoles) {
+ platformRoles.push(<div>{`${role}: ${u.platformRoles[role]}`}</div>)
+ }
+ return (
+ <div ref={(el) => this[`user-ref-${k}`] = el} className={`tableRow tableRow--data ${((self.state.activeIndex == k) && self.state.userOpen) ? 'tableRow--data-active' : ''}`} key={k}>
+ <div
+ className={`userName userName-header ${((self.state.activeIndex == k) && self.state.userOpen) ? 'activeUser' : ''}`}
+ onClick={self.viewUser.bind(null, u, k)}>
+ {u['user-name']}
+ </div>
+ <div>
+ {u['user-domain']}
+ </div>
+
+
+ </div>
+ )
+ })}
+ </Panel>
+ <ButtonGroup className="buttonGroup" style={{margin: '0 0.5rem 0.5rem', background: '#ddd', paddingBottom: '0.5rem'}}>
+ <Button label="Add User" onClick={this.addUser} />
+ </ButtonGroup>
+ </PanelWrapper>
+ <PanelWrapper onKeyUp={this.evaluateSubmit}
+ className={`userAdmin column`}>
+ <Panel
+ title={state.isEdit ? state['user-name'] : 'Create User'}
+ style={{marginBottom: 0}}
+ hasCloseButton={this.closePanel}
+ no-corners>
+ <FormSection title="USER INFO">
+ {
+ this.state.isEdit ?
+ null
+ : <Input readonly={state.isReadOnly} label="Username" value={state['user-name']} onChange={this.updateInput.bind(null, 'user-name')} />
+ }
+ <Input readonly={true} label="Domain" value={state['user-domain']} onChange={this.updateInput.bind(null, 'user-domain')}></Input>
+
+ <Input type="radiogroup" readonly={state.isReadOnly} label="Disabled" value={state.disabled} options={[{value: true, label: 'YES'}, {value: false, label: 'NO'}]} onChange={this.disableChange} />
+ </FormSection>
+ <FormSection title="PLATFORM ROLES" style={{display:'none'}}>
+ <Input label="Super Admin" onChange={this.platformChange.bind(null, 'super_admin')} checked={state.platformRoles.super_admin} type="checkbox" />
+ <Input label="Platform Admin" onChange={this.platformChange.bind(null, 'platform_admin')} checked={state.platformRoles.platform_admin} type="checkbox" />
+ <Input label="Platform Oper" onChange={this.platformChange.bind(null, 'platform_oper')} checked={state.platformRoles.platform_oper} type="checkbox" />
+ </FormSection>
+ <FormSection title="PROJECT ROLES" style={{display:'none'}}>
+ <InputCollection
+ inital={true}
+ type='select'
+ readonly={state.isReadOnly}
+ options={state.projectRolesOptions}
+ collection={state.projectRoles}
+ onChange={this.updateProjectRole}
+ AddItemFn={this.addProjectRole}
+ RemoveItemFn={this.removeProjectRole}
+ />
+ </FormSection>
+ {passwordSectionHTML}
+
+ </Panel>
+ {formButtonsHTML}
+
+ </PanelWrapper>
+
+
+ </PanelWrapper>
+ );
+ return html;
+ }
+}
+// onClick={this.Store.update.bind(null, Account)}
+UserManagementDashboard.contextTypes = {
+ router: React.PropTypes.object
+};
+
+UserManagementDashboard.defaultProps = {
+ userList: [],
+ selectedUser: {}
+}
+
+export default SkyquakeComponent(UserManagementDashboard);
+
+
+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/>)
+ }
+}
+
+/**
+ * AddItemFn:
+ */
+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}`)
+ }
+}
+
+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: ''
+}
--- /dev/null
+/*
+ * STANDARD_RIFT_IO_COPYRIGHT
+ */
+
+/* If there's time this really needs to be rewritten. Ideally with smooth animations.*/
+@import "style/_colors.scss";
+
+.userManagement {
+ max-width: 900px;
+
+ .skyquakePanel-wrapper {
+ overflow-x: hidden;
+ }
+ .userList {
+
+ -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(.userName) {
+ 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(.userName) {
+ /* opacity: 0;*/
+ /* width:0px;*/
+ display:none;
+ overflow:hidden;
+ /* transition: all 600ms;*/
+ }
+ }
+ }
+ &.hideColumns {
+ overflow:hidden;
+ >div {
+ overflow:hidden;
+ }
+ .tableRow>div:not(.userName) {
+ width: 0px;
+ /* transition: all 600ms;*/
+ }
+ .userName {
+ &--header {
+ /* display:none;*/
+ }
+ }
+ }
+ .userName {
+ cursor:pointer;
+ }
+
+ }
+
+ .userAdmin {
+ -ms-flex: 1 1;
+ flex: 1 1;
+ width:auto;
+ opacity:1;
+ }
+ &.userList-open {
+ .userAdmin {
+ -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;
+ }
+}
+
+
+
+.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%;
+ }
+ &--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',
+ 'viewUser',
+ 'editUser',
+ 'handleCloseUserPanel',
+ 'handleHideColumns',
+ 'getUsersSuccess',
+ 'getUsersNotification',
+ 'handleDisabledChange',
+ 'handlePlatformRoleUpdate',
+ 'handleAddUser',
+ 'handleCreateUser',
+ 'handleUpdateUser',
+ 'updateUserSuccess',
+ 'createUserSuccess',
+ 'deleteUserSuccess'
+ );
+}
--- /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 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
+ },
+ updateUser: {
+ remote: function(state, user) {
+ return new Promise(function(resolve, reject) {
+ $.ajax({
+ url: `/user?api_server=${API_SERVER}`,
+ type: 'PUT',
+ data: user,
+ 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 user.'
+ }),
+ success: Alt.actions.global.updateUserSuccess,
+ loading: Alt.actions.global.showScreenLoader,
+ error: Alt.actions.global.showNotification
+ },
+ deleteUser: {
+ remote: function(state, user) {
+ return new Promise(function(resolve, reject) {
+ // setTimeout(function() {
+ // resolve(true);
+ // }, 1000)
+ $.ajax({
+ url: `/user/${user['user-name']}/${user['user-domain']}?api_server=${API_SERVER}`,
+ type: 'DELETE',
+ data: user,
+ 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.deleteUserSuccess,
+ loading: Alt.actions.global.showScreenLoader,
+ error: Alt.actions.global.showNotification
+ },
+ createUser: {
+ remote: function(state, user) {
+
+ return new Promise(function(resolve, reject) {
+ // setTimeout(function() {
+ // resolve(true);
+ // }, 1000)
+ $.ajax({
+ url: `/user?api_server=${API_SERVER}`,
+ type: 'POST',
+ data: user,
+ 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.createUserSuccess,
+ 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 mockUsers() {
+ let data = [];
+ let count = 10;
+ for(let i = 0; i < 10; i++) {
+ data.push({
+ username: `Tester ${i}`,
+ 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 UserManagementActions from './userMgmtActions.js';
+import UserManagementSource from './userMgmtSource.js';
+import _ from 'lodash';
+export default class UserManagementStore {
+ constructor() {
+ this.actions = UserManagementActions(this.alt);
+ this.bindActions(this.actions);
+ this.registerAsync(UserManagementSource);
+ this.users = [];
+ this['user-name'] = '';
+ this['user-domain'] = 'system';
+ this.disabled = false;
+ this.platformRoles = {
+ super_admin: false,
+ platform_admin: false,
+ platform_oper: false
+ };
+ this.projectRoles = ['Project:Role'];
+ this.projectRolesOptions = ['Choose your adventure', 'Project:Role', 'Project:Another Role'];
+ this.currentPassword = '';
+ this['old-password'] = '';
+ this['new-password'] = '';
+ this['confirm-password'] = '';
+
+ this.activeIndex = null;
+ this.isReadOnly = true;
+ this.userOpen = 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
+ });
+ }
+ viewUser(data) {
+ let user = data[0];
+ let userIndex = data[1];
+
+ let ActiveUser = {
+ 'user-name': user['user-name'],
+ 'user-domain': user['user-domain'],
+ platformRoles: user.platformRoles || this.platformRoles,
+ disabled: user.disabled || this.disabled,
+ projectRoles: user.projectRoles || this.projectRoles
+ }
+ let state = _.merge({
+ activeIndex: userIndex,
+ userOpen: true,
+ isEdit: true,
+ isReadOnly: true
+ }, ActiveUser);
+ this.setState(state)
+ }
+ editUser(isEdit) {
+ this.setState({
+ isReadOnly: isEdit
+ })
+ }
+ handleCloseUserPanel() {
+ this.setState({
+ userOpen: false,
+ isEdit: false,
+ isReadOnly: true
+ })
+ }
+ handleHideColumns(e) {
+ if(this.userOpen && 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
+ })
+ }
+ resetUser() {
+ let username = '';
+ let domain = 'system';
+ let disabled = false;
+ let platformRoles = {
+ super_admin: false,
+ platform_admin: false,
+ platform_oper: false
+ };
+ let projectRoles = [];
+ let currentPassword = '';
+ let oldPassword = '';
+ let newPassword = '';
+ let confirmPassword = '';
+ return {
+ 'user-name' : username,
+ 'user-domain' : domain,
+ disabled,
+ platformRoles,
+ projectRoles,
+ currentPassword,
+ 'old-password': oldPassword,
+ 'new-password': newPassword,
+ 'confirm-password': confirmPassword
+ }
+ }
+ resetPassword() {
+ let currentPassword = '';
+ let oldPassword = '';
+ let newPassword = '';
+ let confirmPassword = '';
+ return {
+ currentPassword,
+ 'old-password': oldPassword,
+ 'new-password': newPassword,
+ 'confirm-password': confirmPassword
+ }
+ }
+ handleAddUser() {
+ this.setState(_.merge( this.resetUser() ,
+ {
+ isEdit: false,
+ userOpen: true,
+ activeIndex: null,
+ isReadOnly: false
+ }
+ ))
+ }
+ handleCreateUser() {
+
+ }
+ handleUpdateUser() {
+
+ }
+
+ getUsersSuccess(users) {
+ this.alt.actions.global.hideScreenLoader.defer();
+ this.setState({users});
+ }
+ updateUserSuccess() {
+ this.alt.actions.global.hideScreenLoader.defer();
+ let users = this.users || [];
+ users[this.activeIndex] = {
+ 'user-name': this['user-name'],
+ 'user-domain': this['user-domain'],
+ platformRoles: this.platformRoles,
+ disabled: this.disabled,
+ projectRoles: this.projectRoles
+ }
+ this.setState({
+ users,
+ isEdit: true,
+ isReadOnly: true
+ })
+ }
+ deleteUserSuccess() {
+ this.alt.actions.global.hideScreenLoader.defer();
+ let users = this.users;
+ users.splice(this.activeIndex, 1);
+ this.setState({users, userOpen: false})
+ }
+ createUserSuccess() {
+ this.alt.actions.global.hideScreenLoader.defer();
+ let users = this.users || [];
+ users.push({
+ 'user-name': this['user-name'],
+ 'user-domain': this['user-domain'],
+ platformRoles: this.platformRoles,
+ disabled: this.disabled,
+ projectRoles: this.projectRoles,
+ });
+ let newState = {
+ users,
+ isEdit: true,
+ isReadOnly: true,
+ activeIndex: users.length - 1
+ };
+ _.merge(newState, this.resetPassword())
+ 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;