mirror of
https://github.com/gravitational/teleport
synced 2024-10-22 10:13:21 +00:00
(web) Hooked up node screen with the API
This commit is contained in:
parent
16b0f15dc5
commit
59d5f43182
299
web/dist/app/app.js
vendored
299
web/dist/app/app.js
vendored
File diff suppressed because one or more lines are too long
6
web/dist/app/styles.js
vendored
6
web/dist/app/styles.js
vendored
File diff suppressed because one or more lines are too long
294
web/dist/app/vendor.js
vendored
294
web/dist/app/vendor.js
vendored
File diff suppressed because one or more lines are too long
8
web/dist/index.html
vendored
8
web/dist/index.html
vendored
|
@ -10,11 +10,11 @@
|
|||
<script src="/web/app/assets/js/jquery-validate-1.14.0.js"></script>
|
||||
<script src="/web/app/assets/js/bootstrap.js"></script>
|
||||
<script src="/web/app/assets/js/term.js"></script>
|
||||
<script src="/web/app/vendor.js?ver=0.11456421481641"></script>
|
||||
<script src="/web/app/styles.js?ver=0.11456421481641"></script>
|
||||
<script src="/web/app/vendor.js?ver=0.11456438265918"></script>
|
||||
<script src="/web/app/styles.js?ver=0.11456438265918"></script>
|
||||
</head>
|
||||
<body>
|
||||
<body class="grv">
|
||||
<div id="app"></div>
|
||||
</body>
|
||||
<script src="/web/app/app.js?ver=0.11456421481641"></script>
|
||||
<script src="/web/app/app.js?ver=0.11456438265918"></script>
|
||||
</html>
|
||||
|
|
|
@ -6,5 +6,6 @@ module.exports.$ = require('jQuery');
|
|||
module.exports.Dfd = module.exports.$.Deferred;
|
||||
module.exports.spyOn = module.exports.expect.spyOn;
|
||||
module.exports.reactor = require('app/reactor');
|
||||
module.exports.session = require('app/session');
|
||||
module.exports.api = require('app/services/api');
|
||||
require('app/modules');
|
||||
|
|
|
@ -12,12 +12,12 @@ describe('modules/nodes', function () {
|
|||
|
||||
describe('getters and actions', function () {
|
||||
beforeEach(function () {
|
||||
api.get.andReturn(Dfd().resolve([{id: 1, ip: '127.3.4.5:1000', count: 1, name: 'alex'}, {id: 2, ip: '227.1.1.5:1000', count: 4, name: 'martha'}]));
|
||||
api.get.andReturn(Dfd().resolve({ "nodes": [ { "addr": "127.0.0.1:8080", "hostname": "a.example.com", "labels": {"role": "mysql"}, "cmd_labels": { "db_status": { "command": "mysql -c status", "result": "master", "period": 1000000000 }} } ] }) );
|
||||
actions.fetchNodes();
|
||||
});
|
||||
|
||||
it('should handle "nodeInfos"', function () {
|
||||
var expected = [{"count":1,"ip":"127.3.4.5:1000","tags":["tag1","tag2","tag3"],"roles":["r1","r2","r3"]},{"count":4,"ip":"227.1.1.5:1000","tags":["tag1","tag2","tag3"],"roles":["r1","r2","r3"]}];
|
||||
var expected = [{"tags":[{"role":"role","value":"mysql"},{"role":"db_status","value":"master","tooltip":"mysql -c status"}],"ip":"127.0.0.1:8080"}]
|
||||
expect(reactor.evaluateToJS(getters.nodeListView)).toEqual(expected);
|
||||
});
|
||||
|
||||
|
|
23
web/src/app/__tests__/modules/userTest.js
Normal file
23
web/src/app/__tests__/modules/userTest.js
Normal file
|
@ -0,0 +1,23 @@
|
|||
var { reactor, expect, Dfd, spyOn } = require('./../');
|
||||
var {actions, getters} = require('app/modules/user');
|
||||
var {TLPT_RECEIVE_USER} = require('app/modules/user/actionTypes');
|
||||
|
||||
describe('modules/nodes', function () {
|
||||
|
||||
afterEach(function () {
|
||||
reactor.reset()
|
||||
})
|
||||
|
||||
describe('getters', function () {
|
||||
beforeEach(function () {
|
||||
var sample = {"type": "bearer", "token": "bearer token", "user": {"name": "alex", "allowed_logins": ["admin", "bob"]}, "expires_in": 20};
|
||||
reactor.dispatch(TLPT_RECEIVE_USER, sample.user);
|
||||
});
|
||||
|
||||
it('should return "user"', function () {
|
||||
var expected = {"name":"alex","logins":["admin","bob"]};
|
||||
expect(reactor.evaluateToJS(getters.user)).toEqual(expected);
|
||||
});
|
||||
|
||||
});
|
||||
})
|
|
@ -25,13 +25,14 @@ var auth = {
|
|||
},
|
||||
|
||||
ensureUser(){
|
||||
if(session.getUserData()){
|
||||
var userData = session.getUserData();
|
||||
if(userData){
|
||||
// refresh timer will not be set in case of browser refresh event
|
||||
if(auth._getRefreshTokenTimerId() === null){
|
||||
return auth._login().done(auth._startTokenRefresher);
|
||||
}
|
||||
|
||||
return $.Deferred().resolve();
|
||||
return $.Deferred().resolve(userData);
|
||||
}
|
||||
|
||||
return $.Deferred().reject();
|
||||
|
|
|
@ -5,9 +5,9 @@ var cfg = require('app/config');
|
|||
var App = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<div className="grv">
|
||||
<div className="grv-tlpt">
|
||||
<NavLeftBar/>
|
||||
<div className="row" style={{marginLeft: "70px"}}>
|
||||
<div className="row">
|
||||
<nav className="" role="navigation" style={{ marginBottom: 0 }}>
|
||||
<ul className="nav navbar-top-links navbar-right">
|
||||
<li>
|
||||
|
@ -24,7 +24,7 @@ var App = React.createClass({
|
|||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
<div style={{ 'marginLeft': '100px' }}>
|
||||
<div className="grv-page">
|
||||
{this.props.children}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -64,7 +64,7 @@ var Login = React.createClass({
|
|||
var isError = false;//this.state.userRequest.get('isError');
|
||||
|
||||
return (
|
||||
<div className="grv grv-login text-center">
|
||||
<div className="grv-login text-center">
|
||||
<div className="grv-logo-tprt"></div>
|
||||
<div className="grv-content grv-flex">
|
||||
<div className="grv-flex-column">
|
||||
|
|
|
@ -121,7 +121,7 @@ var Invite = React.createClass({
|
|||
}
|
||||
|
||||
return (
|
||||
<div className="grv grv-invite text-center">
|
||||
<div className="grv-invite text-center">
|
||||
<div className="grv-logo-tprt"></div>
|
||||
<div className="grv-content grv-flex">
|
||||
<div className="grv-flex-column">
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
var React = require('react');
|
||||
var reactor = require('app/reactor');
|
||||
var {getters, actions} = require('app/modules/nodes');
|
||||
var userGetters = require('app/modules/user/getters');
|
||||
var {Table, Column, Cell} = require('app/components/table.jsx');
|
||||
|
||||
const TextCell = ({rowIndex, data, columnKey, ...props}) => (
|
||||
|
@ -9,13 +10,58 @@ const TextCell = ({rowIndex, data, columnKey, ...props}) => (
|
|||
</Cell>
|
||||
);
|
||||
|
||||
const TagCell = ({rowIndex, data, columnKey, ...props}) => (
|
||||
<Cell {...props}>
|
||||
{ data[rowIndex].tags.map((item, index) =>
|
||||
(<span key={index} className="label label-default">
|
||||
{item.role} <li className="fa fa-long-arrow-right"></li>
|
||||
{item.value}
|
||||
</span>)
|
||||
) }
|
||||
</Cell>
|
||||
);
|
||||
|
||||
const LoginCell = ({user, ...props}) => {
|
||||
if(!user || user.logins.length === 0){
|
||||
return <Cell {...props} />;
|
||||
}
|
||||
|
||||
var $lis = [];
|
||||
|
||||
for(var i = 0; i < user.logins.length; i++){
|
||||
$lis.push(<li key={i}><a href="#" target="_blank">{user.logins[i]}</a></li>);
|
||||
}
|
||||
|
||||
return (
|
||||
<Cell {...props}>
|
||||
<div className="btn-group">
|
||||
<button type="button" className="btn btn-sm btn-primary">{user.logins[0]}</button>
|
||||
{
|
||||
$lis.length > 1 ? (
|
||||
<div className="btn-group">
|
||||
<button data-toggle="dropdown" className="btn btn-default btn-sm dropdown-toggle" aria-expanded="true">
|
||||
<span className="caret"></span>
|
||||
</button>
|
||||
<ul className="dropdown-menu">
|
||||
<li><a href="#" target="_blank">Logs</a></li>
|
||||
<li><a href="#" target="_blank">Logs</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
): null
|
||||
}
|
||||
</div>
|
||||
</Cell>
|
||||
)
|
||||
};
|
||||
|
||||
var Nodes = React.createClass({
|
||||
|
||||
mixins: [reactor.ReactMixin],
|
||||
|
||||
getDataBindings() {
|
||||
return {
|
||||
nodeRecords: getters.nodeListView
|
||||
nodeRecords: getters.nodeListView,
|
||||
user: userGetters.user
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -29,12 +75,12 @@ var Nodes = React.createClass({
|
|||
render: function() {
|
||||
var data = this.state.nodeRecords;
|
||||
return (
|
||||
<div>
|
||||
<div className="grv-nodes">
|
||||
<h1> Nodes </h1>
|
||||
<div className="">
|
||||
<div className="">
|
||||
<div className="">
|
||||
<Table rowCount={data.length}>
|
||||
<Table rowCount={data.length} className="grv-nodes-table">
|
||||
<Column
|
||||
columnKey="count"
|
||||
header={<Cell> Sessions </Cell> }
|
||||
|
@ -48,12 +94,12 @@ var Nodes = React.createClass({
|
|||
<Column
|
||||
columnKey="tags"
|
||||
header={<Cell></Cell> }
|
||||
cell={<TextCell data={data}/> }
|
||||
cell={<TagCell data={data}/> }
|
||||
/>
|
||||
<Column
|
||||
columnKey="roles"
|
||||
header={<Cell>Login as</Cell> }
|
||||
cell={<TextCell data={data}/> }
|
||||
cell={<LoginCell user={this.state.user}/> }
|
||||
/>
|
||||
</Table>
|
||||
</div>
|
||||
|
|
|
@ -22,7 +22,7 @@ var GrvTable = React.createClass({
|
|||
var rows = [];
|
||||
for(var i = 0; i < count; i ++){
|
||||
var cells = children.map((item, index)=>{
|
||||
return this.renderCell(item.props.cell, {rowIndex: i, key: i, isHeader: false, ...item.props});
|
||||
return this.renderCell(item.props.cell, {rowIndex: i, key: index, isHeader: false, ...item.props});
|
||||
})
|
||||
|
||||
rows.push(<tr key={i}>{cells}</tr>);
|
||||
|
@ -56,8 +56,10 @@ var GrvTable = React.createClass({
|
|||
children.push(child);
|
||||
});
|
||||
|
||||
var tableClass = 'table table-bordered ' + this.props.className;
|
||||
|
||||
return (
|
||||
<table className="table table-bordered">
|
||||
<table className={tableClass}>
|
||||
{this.renderHeader(children)}
|
||||
{this.renderBody(children)}
|
||||
</table>
|
||||
|
|
|
@ -5,7 +5,7 @@ let cfg = {
|
|||
baseUrl: window.location.origin,
|
||||
|
||||
api: {
|
||||
nodesPath: '/nodes',
|
||||
nodesPath: '/v1/webapi/sites/-current-/nodes',
|
||||
sessionPath: '/v1/webapi/sessions',
|
||||
invitePath: '/v1/webapi/users/invites/:inviteToken',
|
||||
createUserPath: '/v1/webapi/users',
|
||||
|
|
|
@ -2,6 +2,7 @@ var React = require('react');
|
|||
var render = require('react-dom').render;
|
||||
var { Router, Route, Redirect, IndexRoute, browserHistory } = require('react-router');
|
||||
var { App, Login, Nodes, Sessions, NewUser } = require('./components');
|
||||
var {ensureUser} = require('./modules/user/actions');
|
||||
var auth = require('./auth');
|
||||
var session = require('./session');
|
||||
var cfg = require('./config');
|
||||
|
@ -11,15 +12,6 @@ require('./modules');
|
|||
// init session
|
||||
session.init();
|
||||
|
||||
function requiresAuth(nextState, replace, cb) {
|
||||
auth.ensureUser()
|
||||
.done(()=> cb())
|
||||
.fail(()=>{
|
||||
replace({redirectTo: nextState.location.pathname }, cfg.routes.login);
|
||||
cb();
|
||||
});
|
||||
}
|
||||
|
||||
function handleLogout(nextState, replace, cb){
|
||||
auth.logout();
|
||||
// going back will hit requireAuth handler which will redirect it to the login page
|
||||
|
@ -31,8 +23,8 @@ render((
|
|||
<Route path={cfg.routes.login} component={Login}/>
|
||||
<Route path={cfg.routes.logout} onEnter={handleLogout}/>
|
||||
<Route path={cfg.routes.newUser} component={NewUser}/>
|
||||
|
||||
<Route path={cfg.routes.app} component={App} onEnter={requiresAuth}>
|
||||
<Route path={cfg.routes.app} component={App} onEnter={ensureUser} >
|
||||
<IndexRoute component={Nodes}/>
|
||||
<Route path={cfg.routes.nodes} component={Nodes}/>
|
||||
<Route path={cfg.routes.sessions} component={Sessions}/>
|
||||
</Route>
|
||||
|
|
|
@ -5,8 +5,8 @@ var cfg = require('app/config');
|
|||
|
||||
export default {
|
||||
fetchNodes(){
|
||||
api.get(cfg.api.nodes).done(nodes=>{
|
||||
reactor.dispatch(TLPT_RECEIVE_NODES, nodes);
|
||||
api.get(cfg.api.nodesPath).done(data=>{
|
||||
reactor.dispatch(TLPT_RECEIVE_NODES, data.nodes);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,17 +1,44 @@
|
|||
//var sort = require('app/common/sort');
|
||||
|
||||
const nodeListView = [ ['tlpt_nodes'], (nodes) =>{
|
||||
return nodes.valueSeq().map((item)=>{
|
||||
return nodes.map((item)=>{
|
||||
return {
|
||||
count: item.get('count'),
|
||||
ip: item.get('ip'),
|
||||
tags: ['tag1', 'tag2', 'tag3'],
|
||||
roles: ['r1', 'r2', 'r3']
|
||||
tags: getTags(item),
|
||||
ip: item.get('addr')
|
||||
}
|
||||
}).toJS();
|
||||
}
|
||||
];
|
||||
|
||||
function getTags(node){
|
||||
var allLabels = [];
|
||||
var labels = node.get('labels');
|
||||
|
||||
if(labels){
|
||||
labels.entrySeq().toArray().forEach(item=>{
|
||||
allLabels.push({
|
||||
role: item[0],
|
||||
value: item[1]
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
labels = node.get('cmd_labels');
|
||||
|
||||
if(labels){
|
||||
labels.entrySeq().toArray().forEach(item=>{
|
||||
allLabels.push({
|
||||
role: item[0],
|
||||
value: item[1].get('result'),
|
||||
tooltip: item[1].get('command')
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return allLabels;
|
||||
}
|
||||
|
||||
|
||||
export default {
|
||||
nodeListView
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ var { TLPT_RECEIVE_NODES } = require('./actionTypes');
|
|||
|
||||
export default Store({
|
||||
getInitialState() {
|
||||
return toImmutable({});
|
||||
return toImmutable([]);
|
||||
},
|
||||
|
||||
initialize() {
|
||||
|
@ -11,10 +11,6 @@ export default Store({
|
|||
}
|
||||
})
|
||||
|
||||
function receiveNodes(state, nodeArrayData){
|
||||
return state.withMutations(state => {
|
||||
nodeArrayData.forEach((item) => {
|
||||
state.set(item.id, toImmutable(item))
|
||||
})
|
||||
});
|
||||
function receiveNodes(state, nodeArray){
|
||||
return toImmutable(nodeArray);
|
||||
}
|
||||
|
|
|
@ -8,11 +8,27 @@ var cfg = require('app/config');
|
|||
|
||||
export default {
|
||||
|
||||
ensureUser(nextState, replace, cb){
|
||||
/*var userData = session.getUserData();
|
||||
reactor.dispatch(TLPT_RECEIVE_USER, userData.user);
|
||||
cb();*/
|
||||
|
||||
auth.ensureUser()
|
||||
.done((userData)=> {
|
||||
reactor.dispatch(TLPT_RECEIVE_USER, userData.user);
|
||||
cb();
|
||||
})
|
||||
.fail(()=>{
|
||||
replace({redirectTo: nextState.location.pathname }, cfg.routes.login);
|
||||
cb();
|
||||
});
|
||||
},
|
||||
|
||||
signUp({name, psw, token, inviteToken}){
|
||||
restApiActions.start(TRYING_TO_SIGN_UP);
|
||||
auth.signUp(name, psw, token, inviteToken)
|
||||
.done((user)=>{
|
||||
reactor.dispatch(TLPT_RECEIVE_USER, user);
|
||||
.done((sessionData)=>{
|
||||
reactor.dispatch(TLPT_RECEIVE_USER, sessionData.user);
|
||||
restApiActions.success(TRYING_TO_SIGN_UP);
|
||||
session.getHistory().push({pathname: cfg.routes.app});
|
||||
})
|
||||
|
@ -23,8 +39,8 @@ export default {
|
|||
|
||||
login({user, password, token}, redirect){
|
||||
auth.login(user, password, token)
|
||||
.done((user)=>{
|
||||
reactor.dispatch(TLPT_RECEIVE_USER, user);
|
||||
.done((sessionData)=>{
|
||||
reactor.dispatch(TLPT_RECEIVE_USER, sessionData.user);
|
||||
session.getHistory().push({pathname: redirect});
|
||||
})
|
||||
.fail(()=>{
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
const user = [ ['tlpt_user'], (currentUser) => {
|
||||
if(!currentUser){
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
name: currentUser.get('name'),
|
||||
logins: currentUser.get('allowed_logins').toJS()
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
export default {
|
||||
user
|
||||
}
|
|
@ -1,16 +1,3 @@
|
|||
module.exports.getters = require('./getters');
|
||||
module.exports.actions = require('./actions');
|
||||
module.exports.nodeStore = require('./userStore');
|
||||
|
||||
// nodes: [{"id":"x220","addr":"0.0.0.0:3022","hostname":"x220","labels":null,"cmd_labels":null}]
|
||||
|
||||
|
||||
// sessions: [{"id":"07630636-bb3d-40e1-b086-60b2cae21ac4","parties":[{"id":"89f762a3-7429-4c7a-a913-766493fe7c8a","site":"127.0.0.1:37514","user":"akontsevoy","server_addr":"0.0.0.0:3022","last_active":"2016-02-22T14:39:20.93120535-05:00"}]}]
|
||||
|
||||
/*
|
||||
let TodoRecord = Immutable.Record({
|
||||
id: 0,
|
||||
description: "",
|
||||
completed: false
|
||||
});
|
||||
*/
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
<script src="/web/app/vendor.js?ver=[VERSION]"></script>
|
||||
<script src="/web/app/styles.js?ver=[VERSION]"></script>
|
||||
</head>
|
||||
<body>
|
||||
<body class="grv">
|
||||
<div id="app"></div>
|
||||
</body>
|
||||
<script src="/web/app/app.js?ver=[VERSION]"></script>
|
||||
|
|
6
web/src/styles/bootstrap.scss
vendored
6
web/src/styles/bootstrap.scss
vendored
|
@ -28,15 +28,15 @@ $icon-font-path: "~bootstrap-sass/assets/fonts/bootstrap/";
|
|||
// Components
|
||||
|
||||
//@import "~bootstrap-sass/assets/stylesheets/bootstrap/component-animations";
|
||||
//@import "~bootstrap-sass/assets/stylesheets/bootstrap/dropdowns";
|
||||
//@import "~bootstrap-sass/assets/stylesheets/bootstrap/button-groups";
|
||||
@import "~bootstrap-sass/assets/stylesheets/bootstrap/dropdowns";
|
||||
@import "~bootstrap-sass/assets/stylesheets/bootstrap/button-groups";
|
||||
//@import "~bootstrap-sass/assets/stylesheets/bootstrap/input-groups";
|
||||
@import "~bootstrap-sass/assets/stylesheets/bootstrap/navs";
|
||||
@import "~bootstrap-sass/assets/stylesheets/bootstrap/navbar";
|
||||
//@import "~bootstrap-sass/assets/stylesheets/bootstrap/breadcrumbs";
|
||||
//@import "~bootstrap-sass/assets/stylesheets/bootstrap/pagination";
|
||||
//@import "~bootstrap-sass/assets/stylesheets/bootstrap/pager";
|
||||
//@import "~bootstrap-sass/assets/stylesheets/bootstrap/labels";
|
||||
@import "~bootstrap-sass/assets/stylesheets/bootstrap/labels";
|
||||
//@import "~bootstrap-sass/assets/stylesheets/bootstrap/badges";
|
||||
//@import "~bootstrap-sass/assets/stylesheets/bootstrap/jumbotron";
|
||||
//@import "~bootstrap-sass/assets/stylesheets/bootstrap/thumbnails";
|
||||
|
|
|
@ -1,41 +1,34 @@
|
|||
@import "grv-invite";
|
||||
@import "grv-login";
|
||||
@import "grv-logo";
|
||||
@import "grv-nodes";
|
||||
|
||||
.grv-logo-tprt{
|
||||
color: white;
|
||||
margin-top: 5%;
|
||||
margin: 0 auto;
|
||||
width: 67px;
|
||||
height: 70px;
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
background-image: url("/web/app/assets/img/grv-tlpt-logo.png");
|
||||
}
|
||||
|
||||
.grv-google-auth{
|
||||
text-align: initial;
|
||||
position: relative;
|
||||
margin: 15px 0 0 0;
|
||||
padding: 0 0 0 70px;
|
||||
|
||||
.grv-google-auth-icon{
|
||||
position: absolute;
|
||||
left: 15px;
|
||||
height: 40px;
|
||||
width: 40px;
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
background-image: url("/web/app/assets/img/authenticator-icon.png");
|
||||
}
|
||||
}
|
||||
|
||||
.grv {
|
||||
min-width: 1024px;
|
||||
|
||||
background-color: white;
|
||||
|
||||
#app{
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.grv-spinner.sk-spinner-three-bounce{
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
}
|
||||
|
||||
nav{
|
||||
height: 100%;
|
||||
background-color: #293846;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.grv-page{
|
||||
margin-left: 60px;
|
||||
padding: 0 15px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.grv-flex{
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
.grv-invite{
|
||||
|
||||
margin-top: 5%;
|
||||
background-color: #2f4050;
|
||||
padding-top: 5%;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
position: fixed;
|
||||
overflow: auto;
|
||||
|
||||
.grv-content{
|
||||
padding: 15px;
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
.grv-login{
|
||||
|
||||
margin-top: 5%;
|
||||
background-color: #2f4050;
|
||||
padding-top: 5%;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
position: fixed;
|
||||
overflow: auto;
|
||||
|
||||
.grv-content{
|
||||
padding: 15px;
|
||||
|
|
27
web/src/styles/grv-logo.scss
Normal file
27
web/src/styles/grv-logo.scss
Normal file
|
@ -0,0 +1,27 @@
|
|||
.grv-logo-tprt{
|
||||
color: white;
|
||||
margin-top: 5%;
|
||||
margin: 0 auto;
|
||||
width: 67px;
|
||||
height: 70px;
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
background-image: url("/web/app/assets/img/grv-tlpt-logo.png");
|
||||
}
|
||||
|
||||
.grv-google-auth{
|
||||
text-align: initial;
|
||||
position: relative;
|
||||
margin: 15px 0 0 0;
|
||||
padding: 0 0 0 70px;
|
||||
|
||||
.grv-google-auth-icon{
|
||||
position: absolute;
|
||||
left: 15px;
|
||||
height: 40px;
|
||||
width: 40px;
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
background-image: url("/web/app/assets/img/authenticator-icon.png");
|
||||
}
|
||||
}
|
9
web/src/styles/grv-nodes.scss
Normal file
9
web/src/styles/grv-nodes.scss
Normal file
|
@ -0,0 +1,9 @@
|
|||
.grv-nodes{
|
||||
|
||||
.grv-nodes-table{
|
||||
.label {
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue