Refactored container list. Hover over effects. Frontend restyle.

This commit is contained in:
Sean Li 2015-01-30 12:11:41 -08:00
parent b79ae5c190
commit 011d6241cf
10 changed files with 528 additions and 325 deletions

View File

@ -12,12 +12,15 @@ var ContainerUtil = require('./ContainerUtil');
var docker = require('./docker');
var boot2docker = require('./boot2docker');
var ProgressBar = require('react-bootstrap/ProgressBar');
var Popover = require('react-bootstrap/Popover');
var ContainerDetails = React.createClass({
mixins: [Router.State, Router.Navigation],
_oldHeight: 0,
PAGE_LOGS: 'logs',
PAGE_SETTINGS: 'settings',
PAGE_PORTS: 'ports',
PAGE_VOLUMES: 'volumes',
getInitialState: function () {
return {
logs: [],
@ -77,7 +80,7 @@ var ContainerDetails = React.createClass({
var $viewPopover = $(this.getDOMNode()).find('.popover-view');
var $volumePopover = $(this.getDOMNode()).find('.popover-volume');
if ($viewDropdown && $volumeDropdown && $viewPopover && $volumePopover) {
/*if ($viewDropdown && $volumeDropdown && $viewPopover && $volumePopover) {
$viewPopover.offset({
top: $viewDropdown.offset().top + 32,
left: $viewDropdown.offset().left - ($viewPopover.outerWidth() / 2) + 14
@ -87,7 +90,7 @@ var ContainerDetails = React.createClass({
top: $volumeDropdown.offset().top + 32,
left: $volumeDropdown.offset().left + $volumeDropdown.outerWidth() - $volumePopover.outerWidth() / 2 - 20
});
}
}*/
},
init: function () {
var container = ContainerStore.container(this.getParams().name);
@ -127,12 +130,23 @@ var ContainerDetails = React.createClass({
page: this.PAGE_LOGS
});
},
showPorts: function () {
this.setState({
page: this.PAGE_PORTS
});
},
showVolumes: function () {
this.setState({
page: this.PAGE_VOLUMES
});
},
showSettings: function () {
this.setState({
page: this.PAGE_SETTINGS
});
},
handleView: function () {
console.log('CLICKED');
if (this.state.defaultPort) {
console.log(this.state.defaultPort);
exec(['open', this.state.ports[this.state.defaultPort].url], function (err) {
@ -160,11 +174,6 @@ var ContainerDetails = React.createClass({
console.log(err);
});
},
handleRestart: function () {
ContainerStore.restart(this.props.container.Name, function (err) {
console.log(err);
});
},
handleTerminal: function () {
var container = this.props.container;
var terminal = path.join(process.cwd(), 'resources', 'terminal').replace(/ /g, '\\\\ ');
@ -264,13 +273,15 @@ var ContainerDetails = React.createClass({
var state;
if (this.props.container.State.Running) {
state = <h2 className="status running">running</h2>;
state = <span className="status running">RUNNING</span>;
} else if (this.props.container.State.Restarting) {
state = <h2 className="status restarting">restarting</h2>;
state = <span className="status restarting">RESTARTING</span>;
} else if (this.props.container.State.Paused) {
state = <h2 className="status paused">paused</h2>;
state = <span className="status paused">PAUSED</span>;
} else if (this.props.container.State.Downloading) {
state = <h2 className="status">downloading</h2>;
state = <span className="status downloading">DOWNLOADING</span>;
} else {
state = <span className="status stopped">STOPPED</span>;
}
var button;
@ -359,54 +370,6 @@ var ContainerDetails = React.createClass({
var dropdownViewButtonClass = React.addons.classSet(assign({'dropdown-view': true}, dropdownClasses));
var dropdownVolumeButtonClass = React.addons.classSet(assign({'dropdown-volume': true}, dropdownClasses));
var body;
if (this.props.container.State.Downloading) {
body = (
<div className="details-progress">
<ProgressBar now={this.state.progress * 100} label="%(percent)s%" />
</div>
);
} else {
if (this.state.page === this.PAGE_LOGS) {
body = (
<div className="details-panel details-logs">
<div className="logs">
{logs}
</div>
</div>
);
} else {
body = (
<div className="details-panel">
<div className="settings">
<h3>Container Name</h3>
<div className="container-name">
<input id="input-container-name" type="text" className="line" placeholder="Container Name" defaultValue={this.props.container.Name}></input>
</div>
<a className="btn btn-action" onClick={this.handleSaveContainerName}>Save</a>
<h3>Environment Variables</h3>
<div className="env-vars-labels">
<div className="label-key">KEY</div>
<div className="label-val">VALUE</div>
</div>
<div className="env-vars">
{envVars}
{pendingEnvVars}
<div className="keyval-row">
<input id="new-env-key" type="text" className="key line"></input>
<input id="new-env-val" type="text" className="val line"></input>
<a onClick={this.handleAddPendingEnvVar} className="only-icon btn btn-positive small"><span className="icon icon-add-1"></span></a>
</div>
</div>
<a className="btn btn-action" onClick={this.handleSaveEnvVar}>Save</a>
<h3>Delete Container</h3>
<a className="btn btn-action" onClick={this.handleDeleteContainer}>Delete Container</a>
</div>
</div>
);
}
}
var ports = _.map(_.pairs(self.state.ports), function (pair, index, list) {
var key = pair[0];
var val = pair[1];
@ -430,31 +393,134 @@ var ContainerDetails = React.createClass({
);
});
var body;
if (this.props.container.State.Downloading) {
body = (
<div className="details-progress">
<ProgressBar now={this.state.progress * 100} label="%(percent)s%" />
</div>
);
} else {
if (this.state.page === this.PAGE_LOGS) {
body = (
<div className="details-panel details-logs">
<div className="logs">
{logs}
</div>
</div>
);
} else if (this.state.page === this.PAGE_PORTS) {
body = (
<div className="details-panel">
<div className="ports">
<h3>Configure Ports</h3>
<div className="table">
<div className="table-labels">
<div className="label-left">DOCKER PORT</div>
<div className="label-right">MAC PORT</div>
</div>
{ports}
</div>
</div>
</div>
);
} else if (this.state.page === this.PAGE_VOLUMES) {
body = (
<div className="details-panel">
<div className="volumes">
<h3>Configure Volumes</h3>
<div className="table">
<div className="table-labels">
<div className="label-left">DOCKER FOLDER</div>
<div className="label-right">MAC FOLDER</div>
</div>
{volumes}
</div>
</div>
</div>
);
} else {
body = (
<div className="details-panel">
<div className="settings">
<div className="settings-section">
<h3>Container Name</h3>
<div className="container-name">
<input id="input-container-name" type="text" className="line" placeholder="Container Name" defaultValue={this.props.container.Name}></input>
</div>
<a className="btn btn-action" onClick={this.handleSaveContainerName}>Save</a>
</div>
<div className="settings-section">
<h3>Environment Variables</h3>
<div className="env-vars-labels">
<div className="label-key">KEY</div>
<div className="label-val">VALUE</div>
</div>
<div className="env-vars">
{envVars}
{pendingEnvVars}
<div className="keyval-row">
<input id="new-env-key" type="text" className="key line"></input>
<input id="new-env-val" type="text" className="val line"></input>
<a onClick={this.handleAddPendingEnvVar} className="only-icon btn btn-positive small"><span className="icon icon-add-1"></span></a>
</div>
</div>
<a className="btn btn-action" onClick={this.handleSaveEnvVar}>Save</a>
</div>
<div className="settings-section">
<h3>Delete Container</h3>
<a className="btn btn-action" onClick={this.handleDeleteContainer}>Delete Container</a>
</div>
</div>
</div>
);
}
}
var tabLogsClasses = React.addons.classSet({
'tab': true,
'active': this.state.page === this.PAGE_LOGS,
disabled: this.props.container.State.Downloading
});
var tabPortsClasses = React.addons.classSet({
'tab': true,
'active': this.state.page === this.PAGE_PORTS,
disabled: this.props.container.State.Downloading
});
var tabVolumesClasses = React.addons.classSet({
'tab': true,
'active': this.state.page === this.PAGE_VOLUMES,
disabled: this.props.container.State.Downloading
});
var tabSettingsClasses = React.addons.classSet({
'tab': true,
'active': this.state.page === this.PAGE_SETTINGS,
disabled: this.props.container.State.Downloading
});
return (
<div className="details">
<div className="details-header">
<div className="details-header-info">
<h1>{this.props.container.Name}</h1>{state}<h2 className="image-label">Image</h2><h2 className="image">{this.props.container.Config.Image}</h2>
</div>
<h1>{this.props.container.Name}</h1><h2 className="image">{this.props.container.Config.Image}</h2>
<div className="details-header-actions">
<div className="action btn-group">
<a className={viewButtonClass} onClick={this.handleView}><span className="icon icon-preview-2"></span><span className="content">View</span></a>
<a className={dropdownViewButtonClass} onClick={this.handleViewDropdown}><span className="icon-dropdown icon icon-arrow-37"></span></a>
</div>
<div className="action">
<a className={dropdownVolumeButtonClass} onClick={this.handleVolumeDropdown}><span className="icon icon-folder-1"></span> <span className="content">Volumes</span> <span className="icon-dropdown icon icon-arrow-37"></span></a>
</div>
<div className="action">
<a className={buttonClass} onClick={this.handleRestart}><span className="icon icon-refresh"></span> <span className="content">Restart</span></a>
</div>
<div className="action">
<a className={buttonClass} onClick={this.handleTerminal}><span className="icon icon-window-code-3"></span> <span className="content">Terminal</span></a>
</div>
<div className="details-header-actions-rhs tabs btn-group">
<a className={textButtonClasses} onClick={this.showLogs}><span className="icon icon-text-wrapping-2"></span></a>
<a className={gearButtonClass} onClick={this.showSettings}><span className="icon icon-setting-gear"></span></a>
<span className="icon icon-preview-2 action-icon view-icon" onClick={this.handleView}></span>
<span className="icon icon-refresh action-icon" onClick={this.handleRestart}></span>
<span className="icon icon-window-code-3 action-icon" onClick={this.handleTerminal}></span>
</div>
</div>
<div className="details-subheader">
{state}
<div className="details-subheader-tabs">
<span className={tabLogsClasses} onClick={this.showLogs}>Logs</span>
<span className={tabPortsClasses} onClick={this.showPorts}>Ports</span>
<span className={tabVolumesClasses} onClick={this.showVolumes}>Volumes</span>
<span className={tabSettingsClasses} onClick={this.showSettings}>Settings</span>
</div>
</div>
{body}
<Popover className={popoverViewClasses} placement="bottom">
<div className="table ports">
<div className="table-labels">
@ -474,8 +540,6 @@ var ContainerDetails = React.createClass({
</div>
</Popover>
</div>
{body}
</div>
);
}
});

View File

@ -7,65 +7,16 @@ var Modal = require('react-bootstrap/Modal');
var RetinaImage = require('react-retina-image');
var ModalTrigger = require('react-bootstrap/ModalTrigger');
var ContainerModal = require('./ContainerModal.react');
var ContainerListItem = require('./ContainerListItem.react');
var Header = require('./Header.react');
var docker = require('./docker');
var ContainerList = React.createClass({
componentWillMount: function () {
this._start = Date.now();
},
render: function () {
var self = this;
var containers = this.props.containers.map(function (container) {
var downloadingImage = null, downloading = false;
var env = container.Config.Env;
if (env.length) {
var obj = _.object(env.map(function (e) {
return e.split('=');
}));
if (obj.KITEMATIC_DOWNLOADING) {
downloading = true;
}
downloadingImage = obj.KITEMATIC_DOWNLOADING_IMAGE || null;
}
var imageName = downloadingImage || container.Config.Image;
// Synchronize all animations
var style = {
WebkitAnimationDelay: (self._start - Date.now()) + 'ms'
};
var state;
if (downloading) {
state = <div className="state state-downloading"><div style={style} className="downloading-arrow"></div></div>;
} else if (container.State.Running && !container.State.Paused) {
state = <div className="state state-running"><div style={style} className="runningwave"></div></div>;
} else if (container.State.Restarting) {
state = <div className="state state-restarting" style={style}></div>;
} else if (container.State.Paused) {
state = <div className="state state-paused"></div>;
} else if (container.State.ExitCode) {
// state = <div className="state state-error"></div>;
state = <div className="state state-stopped"></div>;
} else {
state = <div className="state state-stopped"></div>;
}
return (
<Router.Link key={container.Name} data-container={name} to="container" params={{name: container.Name}}>
<li>
{state}
<div className="info">
<div className="name">
{container.Name}
</div>
<div className="image">
{imageName}
</div>
</div>
</li>
</Router.Link>
<ContainerListItem container={container} />
);
});
return (

View File

@ -0,0 +1,84 @@
var async = require('async');
var _ = require('underscore');
var $ = require('jquery');
var React = require('react/addons');
var Router = require('react-router');
var Modal = require('react-bootstrap/Modal');
var RetinaImage = require('react-retina-image');
var ModalTrigger = require('react-bootstrap/ModalTrigger');
var ContainerModal = require('./ContainerModal.react');
var Header = require('./Header.react');
var docker = require('./docker');
var ContainerListItem = React.createClass({
componentWillMount: function () {
this._start = Date.now();
},
handleItemMouseEnter: function () {
var $action = $(this.getDOMNode()).find('.action');
$action.show();
},
handleItemMouseLeave: function () {
var $action = $(this.getDOMNode()).find('.action');
$action.hide();
},
render: function () {
var self = this;
var container = this.props.container;
var downloadingImage = null, downloading = false;
var env = container.Config.Env;
if (env.length) {
var obj = _.object(env.map(function (e) {
return e.split('=');
}));
if (obj.KITEMATIC_DOWNLOADING) {
downloading = true;
}
downloadingImage = obj.KITEMATIC_DOWNLOADING_IMAGE || null;
}
var imageName = downloadingImage || container.Config.Image;
// Synchronize all animations
var style = {
WebkitAnimationDelay: (self._start - Date.now()) + 'ms'
};
var state;
if (downloading) {
state = <div className="state state-downloading"><div style={style} className="downloading-arrow"></div></div>;
} else if (container.State.Running && !container.State.Paused) {
state = <div className="state state-running"><div style={style} className="runningwave"></div></div>;
} else if (container.State.Restarting) {
state = <div className="state state-restarting" style={style}></div>;
} else if (container.State.Paused) {
state = <div className="state state-paused"></div>;
} else if (container.State.ExitCode) {
// state = <div className="state state-error"></div>;
state = <div className="state state-stopped"></div>;
} else {
state = <div className="state state-stopped"></div>;
}
return (
<Router.Link key={container.Name} data-container={name} to="container" params={{name: container.Name}}>
<li onMouseEnter={self.handleItemMouseEnter} onMouseLeave={self.handleItemMouseLeave}>
{state}
<div className="info">
<div className="name">
{container.Name}
</div>
<div className="image">
{imageName}
</div>
</div>
<div className="action">
<span className="icon icon-delete-3 btn-delete"></span>
</div>
</li>
</Router.Link>
);
}
});
module.exports = ContainerListItem;

View File

@ -79,10 +79,10 @@ var Containers = React.createClass({
<div className="containers-body">
<div className="sidebar">
<section className={sidebarHeaderClass}>
<h4>My Containers</h4>
<h4>Containers</h4>
<div className="create">
<ModalTrigger modal={<ContainerModal/>}>
<a className="btn btn-action only-icon"><span className="icon icon-add-1"></span></a>
<span className="btn-new icon icon-add-3"></span>
</ModalTrigger>
</div>
</section>

View File

@ -40,9 +40,9 @@ var Header = React.createClass({
return (
<div className="header no-drag">
<div className="buttons">
<div className="button button-close disabled"></div>
<div className="button button-minimize disabled"></div>
<div className="button button-fullscreenclose enabled" onClick={this.handleFullscreen}></div>
<div className="button button-close red disabled"></div>
<div className="button button-minimize yellow disabled"></div>
<div className="button button-fullscreenclose green enabled" onClick={this.handleFullscreen}></div>
</div>
</div>
);
@ -50,9 +50,9 @@ var Header = React.createClass({
return (
<div className="header">
<div className="buttons">
<div className="button button-close enabled" onClick={this.handleClose}></div>
<div className="button button-minimize enabled" onClick={this.handleMinimize}></div>
<div className="button button-fullscreen enabled" onClick={this.handleFullscreen}></div>
<div className="button button-close red enabled" onClick={this.handleClose}></div>
<div className="button button-minimize yellow enabled" onClick={this.handleMinimize}></div>
<div className="button button-fullscreen green enabled" onClick={this.handleFullscreen}></div>
</div>
</div>
);

View File

@ -13,99 +13,6 @@
flex-direction: column;
padding: 14px 14px 20px;
.table {
margin-bottom: 0;
.icon-arrow-right {
color: #aaa;
margin: 2px 9px 0;
flex: 0 auto;
min-width: 13px;
}
.btn {
min-width: 22px;
margin-left: 10px;
}
.table-labels {
flex: 1 auto;
display: flex;
font-size: 12px;
color: @gray-lightest;
.label-left {
flex: 0 auto;
min-width: 80px;
margin-right: 30px;
text-align: right;
}
.label-right {
flex: 1 auto;
display: inline-block;
width: 40%;
}
}
.table-values {
flex: 1 auto;
display: flex;
flex-direction: row;
margin: 8px 0;
.value-left {
text-align: right;
min-width: 80px;
flex: 0 auto;
}
.value-right {
flex: 1 auto;
-webkit-user-select: text;
width: 154px;
}
}
.table-new {
margin-top: 10px;
flex: 1 auto;
display: flex;
input {
padding: 0;
font-weight: 400;
}
input.new-left {
flex: 0 auto;
text-align: right;
min-width: 80px;
max-width: 80px;
}
.new-right-wrapper {
position: relative;
display: flex;
flex: 1 auto;
.new-right-placeholder {
position: absolute;
top: 3px;
left: 0;
font-weight: 400;
}
input.new-right {
flex: 1 auto;
height: 24px;
position :relative;
padding-left: 107px;
}
}
}
&.volumes {
.label-left {
min-width: 120px;
}
.value-left {
min-width: 120px;
}
.icon {
color: #aaa;
margin: 2px 9px 0;
}
}
}
.question {
margin: 12px 6px 6px;
}
@ -122,22 +29,26 @@
display: flex;
flex-direction: row;
padding: 0px;
.sidebar {
padding-top: 28px;
background-color: white;
display: flex;
flex-direction: column;
min-width: 280px;
min-width: 260px;
margin: 0;
box-sizing: border-box;
border-right: 1px solid #eee;
border-right: 1px solid #DCE2E2;
.sidebar-header {
flex: 0 auto;
min-width: 240px;
min-height: 42px;
min-height: 47px;
display: flex;
border-bottom: 1px solid transparent;
transition: border-bottom 0.25s;
padding: 0px 10px 0px 10px;
//padding: 0px 10px 0px 10px;
&.sep {
border-bottom: 1px solid #eee;
@ -146,27 +57,27 @@
h4 {
align-self: flex-start;
padding: 0 24px;
//padding: 0 24px;
padding-left: 26px;
margin: 14px 0 0;
display: inline-block;
font-size: 14px;
position: relative;
}
.create {
flex: 1 auto;
text-align: right;
/*.btn {
margin-top: 4px;
padding: 4px 7px;
font-size: 16px;
position: relative;
.icon {
position: relative;
top: 3px;
left: 1px;
margin-right: 20px;
margin-top: 3px;
.btn-new {
font-size: 24px;
color: @brand-action;
transition: all 0.25s;
&:hover {
color: darken(@brand-action, 10%);
}
}
}*/
}
}
@ -176,7 +87,7 @@
overflow-y: scroll;
overflow-x: hidden;
box-sizing: border-box;
max-width: 280px;
max-width: 260px;
&.sep {
border-top: 1px solid #eee;
@ -184,9 +95,7 @@
ul {
margin: 0;
min-width: 240px;
padding: 0;
margin-top: 4px;
display: flex;
flex-direction: column;
@ -195,23 +104,29 @@
color: inherit;
flex-shrink: 0;
cursor: default;
margin: 0px 3px 0px 8px;
outline: none;
padding: 4px 5px;
&.active {
li {
border-bottom: none;
border-radius: 40px;
background: @brand-primary;
background-image: linear-gradient(-180deg, #24B8EB 4%, #24A3EB 100%);
.name {
color: white;
}
.image {
color: white;
opacity: 0.9;
opacity: 0.8;
}
.btn-delete {
font-size: 24px;
color: white;
opacity: 0.8;
transition: all 0.25s;
&:hover {
opacity: 1;
color: white;
}
}
.state-running {
.at2x('running-white.png', 20px, 20px);
@ -244,7 +159,7 @@
li {
vertical-align: middle;
padding: 10px 16px 10px 16px;
padding: 10px 16px 10px 26px;
display: flex;
flex-direction: row;
@ -271,6 +186,23 @@
}
}
.action {
display: none;
flex: 1;
position: relative;
top: 5px;
text-align: right;
margin-right: 4px;
.btn-delete {
font-size: 24px;
color: @gray-lighter;
transition: all 0.25s;
&:hover {
color: @brand-action;
}
}
}
.state {
margin-top: 9px;
display: inline-block;
@ -370,16 +302,108 @@
display: flex;
flex-direction: column;
.details-subheader {
flex: 0 auto;
display: flex;
flex-direction: row;
position: relative;
border-bottom: 1px solid @gray-lightest;
background-color: white;
height: 32px;
padding: 8px 10px 10px 24px;
font-size: 12px;
color: @gray-normal;
.status {
font-weight: 500;
position: relative;
top: -2px;
&.running {
color: @brand-positive;
}
&.paused {
color: @gray-lighter;
}
&.stopped {
color: @gray-lighter;
}
}
.details-subheader-tabs {
flex: 1 auto;
text-align: right;
margin-right: 0px;
.tab {
margin-left: 20px;
padding: 3px 10px;
transition: all 0.25s;
&:hover {
color: @brand-action;
}
&.active {
background-color: lighten(@brand-action, 38%);
border-radius: 4px;
color: darken(@brand-action, 25%);
}
}
}
}
.details-header {
flex: 0 auto;
display: flex;
flex-direction: column;
padding: 4px 40px 10px 40px;
flex-direction: row;
padding: 31px 24px 18px 24px;
position: relative;
border-bottom: 1px solid #eee;
border-bottom: 1px solid #DCE2E2;
background-color: #F9F9f9;
height: 75px;
h1 {
margin: 0;
font-size: 20px;
font-weight: 300;
margin: 0;
color: @gray-darkest;
}
h2 {
&.status {
margin: 9px 0px 0px 12px;
font-weight: bold;
font-size: 10px;
&.running {
color: @brand-positive;
}
}
&.image {
flex: 1 auto;
margin: 7px 0px 0px 16px;
font-size: 12px;
color: @gray-normal;
font-weight: 300;
}
}
.details-header-actions {
flex: 0 auto;
flex: 1 auto;
text-align: right;
margin-top: -6px;
.action-icon {
font-size: 23px;
margin-left: 24px;
color: @gray-darker;
transition: all 0.25s;
&:hover {
color: @brand-action;
}
&.view-icon {
position: relative;
top: 2px;
font-size: 27px;
//color: @gray-darkest;
}
}
}
/*.details-header-actions {
flex: 1;
display: flex;
flex-direction: row;
margin-top: 24px;
@ -400,44 +424,7 @@
z-index: 0;
}
}
}
.details-header-info {
display: flex;
flex-direction: row;
a {
position: absolute;
right: 30px;
top: -4px;
}
h1 {
margin: 0;
font-size: 20px;
margin: 0;
color: @gray-darkest;
}
h2 {
&.status {
margin: 8px 0px 0px 16px;
text-transform: uppercase;
font-weight: bold;
font-size: 10px;
&.running {
color: @brand-positive;
}
}
&.image-label {
margin: 8px 0px 0px 30px;
font-size: 10px;
color: @gray-lighter;
}
&.image {
margin: 5px 0px 0px 16px;
font-size: 14px;
color: @gray-normal;
}
}
}
}*/
}
.details-progress {
@ -449,10 +436,11 @@
flex: 1;
overflow: auto;
.logs {
background-color: #FEFEFE;
-webkit-user-select: text;
font-family: Menlo;
font-size: 12px;
padding: 18px 35px;
padding: 20px 20px;
color: lighten(@gray-normal, 6%);
white-space: pre-wrap;
p {
@ -460,7 +448,110 @@
}
}
.settings {
padding: 18px 35px;
padding: 18px 38px;
.settings-section {
margin-bottom: 40px;
}
}
.ports {
padding: 18px 38px;
}
.volumes {
padding: 18px 38px;
}
.table {
margin-bottom: 0;
.icon-arrow-right {
color: #aaa;
margin: 2px 9px 0;
flex: 0 auto;
min-width: 13px;
}
.btn {
min-width: 22px;
margin-left: 10px;
}
.table-labels {
margin-top: 20px;
flex: 1 auto;
display: flex;
font-size: 12px;
color: @gray-lightest;
.label-left {
flex: 0 auto;
min-width: 80px;
margin-right: 30px;
text-align: right;
}
.label-right {
flex: 1 auto;
display: inline-block;
width: 40%;
}
}
.table-values {
flex: 1 auto;
display: flex;
flex-direction: row;
margin: 8px 0;
.value-left {
text-align: right;
min-width: 80px;
flex: 0 auto;
}
.value-right {
flex: 1 auto;
-webkit-user-select: text;
width: 40%;
}
}
.table-new {
margin-top: 10px;
flex: 1 auto;
display: flex;
input {
padding: 0;
font-weight: 400;
}
input.new-left {
flex: 0 auto;
text-align: right;
min-width: 80px;
max-width: 80px;
}
.new-right-wrapper {
position: relative;
display: flex;
flex: 1 auto;
.new-right-placeholder {
position: absolute;
top: 3px;
left: 0;
font-weight: 400;
}
input.new-right {
flex: 1 auto;
height: 24px;
position :relative;
padding-left: 107px;
}
}
}
&.volumes {
.label-left {
min-width: 120px;
}
.value-left {
min-width: 120px;
}
.icon {
color: #aaa;
margin: 2px 9px 0;
}
}
}
}
@ -477,6 +568,7 @@
color: @gray-lightest;
margin-left: 5px;
margin-bottom: 5px;
margin-top: 20px;
.label-key {
display: inline-block;
margin-right: 30px;

View File

@ -1,9 +1,10 @@
@import "bootstrap/bootstrap.less";
.header {
position: absolute;
min-width: 100%;
flex: 0;
min-height: 50px;
min-height: 30px;
-webkit-app-region: drag;
-webkit-user-select: none;
// border-bottom: 1px solid #efefef;
@ -15,8 +16,8 @@
.buttons {
display: inline-block;
position: relative;
top: 16px;
left: 20px;
top: 10px;
left: 15px;
&:hover {
.button-minimize.enabled {
@ -44,7 +45,18 @@
border-radius: 6px;
box-shadow: 0px 1px 1px 0px rgba(234,234,234,0.50);
-webkit-app-region: no-drag;
&.red {
background-color: #FF5F52;
border-color: #E33E32;
}
&.yellow {
background-color: #FFBE05;
border-color: #E2A100;
}
&.green {
background-color: #15CC35;
border-color: #17B230;
}
&.disabled {
border: 1px solid #E8EEEF;
}

View File

@ -17,7 +17,7 @@ html, body {
overflow: hidden;
-webkit-font-smoothing: antialiased;
-webkit-user-select: none;
font-family: 'Clear Sans', sans-serif;
font-family: "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
cursor: default;
img {
@ -25,7 +25,7 @@ html, body {
}
}
::-webkit-scrollbar {
/*::-webkit-scrollbar {
width: 13px;
}
@ -46,7 +46,7 @@ html, body {
&:hover {
background-color: rgba(0,0,0,0.25);
}
}
}*/
.question {
color: @gray-lightest;

View File

@ -12,7 +12,7 @@ h3 {
h4 {
font-size: 13px;
color: @gray-normal;
color: @gray-darker;
font-weight: 400;
}
@ -28,7 +28,7 @@ input[type="text"] {
color: @gray-normal;
font-weight: 300;
padding: 5px;
transition: all 0.1s;
transition: all 0.25s;
&:focus {
outline: 0;
border-bottom: 1px solid @brand-action;
@ -56,7 +56,7 @@ input[type="text"] {
// Mixin for generating new styles
.btn-styles(@btn-color: @gray-normal) {
transition: all 0.1s;
transition: all 0.25s;
.reset-filter(); // Disable gradients for IE9 because filter bleeds through rounded corners
border-color: @btn-color;
color: @btn-color;
@ -111,7 +111,7 @@ input[type="text"] {
// Common styles
.btn {
font-size: 12px;
font-size: 13px;
background-color: transparent;
color: @gray-normal;
border: 1px solid @gray-normal;
@ -119,8 +119,8 @@ input[type="text"] {
box-shadow: none;
font-weight: 400;
text-shadow: none;
padding: 6px 14px 6px 14px;
height: 32px;
padding: 4px 14px 4px 14px;
height: 28px;
cursor: default;
&.small {
@ -166,7 +166,7 @@ input[type="text"] {
&.only-icon {
padding: 6px 7px 6px 7px;
&.small {
padding: 2px 5px 3px 5px;
padding: 3px 5px 3px 5px;
}
}
}

View File

@ -1,6 +1,6 @@
@brand-primary: #24B8EB;
@brand-action: #24B8EB;
@brand-positive: #65E100;
@brand-positive: #16E568;
@brand-negative: #F47A45;
@gray-darkest: #253237;