зеркало из https://github.com/docker/kitematic.git
Change unique container key to name from Id
This commit is contained in:
Родитель
fa41982603
Коммит
f34e23b7a0
|
@ -8,8 +8,8 @@ var Link = Router.Link;
|
|||
var RouteHandler = Router.RouteHandler;
|
||||
var Convert = require('ansi-to-html');
|
||||
var convert = new Convert();
|
||||
var ContainerStore = require('./ContainerStore.js');
|
||||
var docker = require('./docker.js');
|
||||
var ContainerStore = require('./ContainerStore');
|
||||
var docker = require('./docker');
|
||||
|
||||
var ContainerDetails = React.createClass({
|
||||
mixins: [Router.State],
|
||||
|
@ -18,12 +18,12 @@ var ContainerDetails = React.createClass({
|
|||
logs: []
|
||||
};
|
||||
},
|
||||
componentWillMount: function () {
|
||||
componentWillReceiveProps: function () {
|
||||
this.update();
|
||||
var self = this;
|
||||
var logs = [];
|
||||
var index = 0;
|
||||
docker.client().getContainer(this.getParams().Id).logs({
|
||||
docker.client().getContainer(this.getParams().name).logs({
|
||||
follow: false,
|
||||
stdout: true,
|
||||
timestamps: true
|
||||
|
@ -40,7 +40,50 @@ var ContainerDetails = React.createClass({
|
|||
});
|
||||
stream.on('end', function (buf) {
|
||||
self.setState({logs: logs});
|
||||
docker.client().getContainer(self.getParams().Id).logs({
|
||||
docker.client().getContainer(self.getParams().name).logs({
|
||||
follow: true,
|
||||
stdout: true,
|
||||
timestamps: true,
|
||||
tail: 0
|
||||
}, function (err, stream) {
|
||||
stream.setEncoding('utf8');
|
||||
stream.on('data', function (buf) {
|
||||
// Every other message is a header
|
||||
if (index % 2 === 1) {
|
||||
var time = buf.substr(0,buf.indexOf(' '));
|
||||
var msg = buf.substr(buf.indexOf(' ')+1);
|
||||
logs.push(convert.toHtml(self._escapeHTML(msg)));
|
||||
self.setState({logs: logs});
|
||||
}
|
||||
index += 1;
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
componentWillMount: function () {
|
||||
this.update();
|
||||
var self = this;
|
||||
var logs = [];
|
||||
var index = 0;
|
||||
docker.client().getContainer(this.getParams().name).logs({
|
||||
follow: false,
|
||||
stdout: true,
|
||||
timestamps: true
|
||||
}, function (err, stream) {
|
||||
stream.setEncoding('utf8');
|
||||
stream.on('data', function (buf) {
|
||||
// Every other message is a header
|
||||
if (index % 2 === 1) {
|
||||
var time = buf.substr(0,buf.indexOf(' '));
|
||||
var msg = buf.substr(buf.indexOf(' ')+1);
|
||||
logs.push(convert.toHtml(self._escapeHTML(msg)));
|
||||
}
|
||||
index += 1;
|
||||
});
|
||||
stream.on('end', function (buf) {
|
||||
self.setState({logs: logs});
|
||||
docker.client().getContainer(self.getParams().name).logs({
|
||||
follow: true,
|
||||
stdout: true,
|
||||
timestamps: true,
|
||||
|
@ -68,9 +111,9 @@ var ContainerDetails = React.createClass({
|
|||
ContainerStore.removeChangeListener(this.update);
|
||||
},
|
||||
update: function () {
|
||||
var containerId = this.getParams().Id;
|
||||
var containerName = this.getParams().name;
|
||||
this.setState({
|
||||
container: ContainerStore.containers()[containerId]
|
||||
container: ContainerStore.containers()[containerName]
|
||||
});
|
||||
},
|
||||
_escapeHTML: function (html) {
|
||||
|
|
|
@ -3,7 +3,7 @@ var Router = require('react-router');
|
|||
var Modal = require('react-bootstrap/Modal');
|
||||
var RetinaImage = require('react-retina-image');
|
||||
var $ = require('jquery');
|
||||
var ContainerStore = require('./ContainerStore.js');
|
||||
var ContainerStore = require('./ContainerStore');
|
||||
|
||||
var ContainerModal = React.createClass({
|
||||
getInitialState: function () {
|
||||
|
@ -28,7 +28,6 @@ var ContainerModal = React.createClass({
|
|||
if (query === this.state.query) {
|
||||
return;
|
||||
}
|
||||
|
||||
clearTimeout(this.timeout);
|
||||
var self = this;
|
||||
this.timeout = setTimeout(function () {
|
||||
|
@ -37,7 +36,8 @@ var ContainerModal = React.createClass({
|
|||
},
|
||||
handleClick: function (event) {
|
||||
var name = event.target.getAttribute('name');
|
||||
ContainerStore.create(name);
|
||||
ContainerStore.create(name, 'latest', function (err, containerName) {
|
||||
});
|
||||
},
|
||||
render: function () {
|
||||
var top = this.state.results.splice(0, 7);
|
||||
|
|
|
@ -42,6 +42,7 @@ var ContainerStore = assign(EventEmitter.prototype, {
|
|||
docker.client().getEvents(function (err, stream) {
|
||||
stream.setEncoding('utf8');
|
||||
stream.on('data', function (data) {
|
||||
console.log(data);
|
||||
|
||||
// TODO: Make
|
||||
self.update(function (err) {
|
||||
|
@ -69,10 +70,9 @@ var ContainerStore = assign(EventEmitter.prototype, {
|
|||
}
|
||||
var containers = {};
|
||||
results.map(function (r) {
|
||||
containers[r.Id] = r;
|
||||
containers[r.Name.replace('/', '')] = r;
|
||||
});
|
||||
self._containers = containers;
|
||||
console.log(containers);
|
||||
self.emit('change');
|
||||
callback(null);
|
||||
});
|
||||
|
@ -157,6 +157,10 @@ var ContainerStore = assign(EventEmitter.prototype, {
|
|||
}
|
||||
}
|
||||
},
|
||||
// Returns all shoes
|
||||
containers: function() {
|
||||
return this._containers;
|
||||
},
|
||||
create: function (repository, tag, callback) {
|
||||
|
||||
console.log('create', repository, tag);
|
||||
|
@ -182,6 +186,8 @@ var ContainerStore = assign(EventEmitter.prototype, {
|
|||
}
|
||||
console.log('Placeholder container created.');
|
||||
docker.client().pull(imageName, function (err, stream) {
|
||||
console.log(containerName);
|
||||
callback(null, containerName);
|
||||
stream.setEncoding('utf8');
|
||||
stream.on('data', function (data) {
|
||||
console.log(data);
|
||||
|
@ -197,6 +203,7 @@ var ContainerStore = assign(EventEmitter.prototype, {
|
|||
} else {
|
||||
// If not then directly create the container
|
||||
self._createContainer(imageName, containerName, function () {
|
||||
callback(null, containerName);
|
||||
console.log('done');
|
||||
});
|
||||
}
|
||||
|
@ -205,19 +212,15 @@ var ContainerStore = assign(EventEmitter.prototype, {
|
|||
// Pull image
|
||||
// When image is done pulling then
|
||||
},
|
||||
|
||||
// Returns all shoes
|
||||
containers: function() {
|
||||
return this._containers;
|
||||
logs: function (containerName) {
|
||||
return logs[containerId];
|
||||
},
|
||||
|
||||
addChangeListener: function(callback) {
|
||||
this.on('change', callback);
|
||||
},
|
||||
|
||||
removeChangeListener: function(callback) {
|
||||
this.removeListener('change', callback);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
module.exports = ContainerStore;
|
||||
|
|
|
@ -1,20 +1,18 @@
|
|||
var React = require('react');
|
||||
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.js');
|
||||
var ContainerStore = require('./ContainerStore.js');
|
||||
var Route = Router.Route;
|
||||
var NotFoundRoute = Router.NotFoundRoute;
|
||||
var DefaultRoute = Router.DefaultRoute;
|
||||
var ContainerModal = require('./ContainerModal.react');
|
||||
var ContainerStore = require('./ContainerStore');
|
||||
var Header = require('./Header.react');
|
||||
var async = require('async');
|
||||
var _ = require('underscore');
|
||||
var docker = require('./docker');
|
||||
|
||||
var Link = Router.Link;
|
||||
var RouteHandler = Router.RouteHandler;
|
||||
var Navigation= Router.Navigation;
|
||||
var Header = require('./Header.react.js');
|
||||
var async = require('async');
|
||||
var _ = require('underscore');
|
||||
var docker = require('./docker.js');
|
||||
|
||||
var ContainerList = React.createClass({
|
||||
mixins: [Navigation],
|
||||
|
@ -22,15 +20,12 @@ var ContainerList = React.createClass({
|
|||
return {
|
||||
containers: []
|
||||
};
|
||||
},
|
||||
handleClick: function () {
|
||||
|
||||
},
|
||||
componentDidMount: function () {
|
||||
this.update();
|
||||
ContainerStore.addChangeListener(this.update);
|
||||
if (this.state.containers.length > 0) {
|
||||
this.transitionTo('container', {Id: this.state.containers[0].Id});
|
||||
if (this.state.active) {
|
||||
this.transitionTo('container', {name: this.state.active});
|
||||
}
|
||||
},
|
||||
componentWillMount: function () {
|
||||
|
@ -43,8 +38,16 @@ var ContainerList = React.createClass({
|
|||
var containers = _.values(ContainerStore.containers()).sort(function (a, b) {
|
||||
return a.Name.localeCompare(b.Name);
|
||||
});
|
||||
var state = {};
|
||||
if (!this.state.active && containers.length > 0) {
|
||||
state.active = containers[0].Name.replace('/', '');
|
||||
}
|
||||
state.containers = containers;
|
||||
this.setState(state);
|
||||
},
|
||||
handleClick: function (containerId) {
|
||||
this.setState({
|
||||
containers: containers
|
||||
active: containerId
|
||||
});
|
||||
},
|
||||
render: function () {
|
||||
|
@ -85,8 +88,9 @@ var ContainerList = React.createClass({
|
|||
} else {
|
||||
state = <div className="state state-stopped"></div>;
|
||||
}
|
||||
|
||||
return (
|
||||
<Link key={container.Id} to="container" params={{Id: container.Id}} onClick={this.handleClick}>
|
||||
<Link key={container.Name.replace('/', '')} to="container" params={{name: container.Name.replace('/', '')}} onClick={self.handleClick.bind(self, container.Id)}>
|
||||
<li>
|
||||
{state}
|
||||
<div className="info">
|
||||
|
@ -126,9 +130,6 @@ var Containers = React.createClass({
|
|||
});
|
||||
}
|
||||
},
|
||||
handleClick: function () {
|
||||
ContainerStore.create('dockerfile/ghost', 'latest', 'testghost');
|
||||
},
|
||||
render: function () {
|
||||
var sidebarHeaderClass = 'sidebar-header';
|
||||
if (this.state.sidebarOffset) {
|
||||
|
@ -140,7 +141,7 @@ var Containers = React.createClass({
|
|||
<div className="containers-body">
|
||||
<div className="sidebar">
|
||||
<section className={sidebarHeaderClass}>
|
||||
<h3 onClick={this.handleClick}>containers</h3>
|
||||
<h3>containers</h3>
|
||||
<div className="create">
|
||||
<ModalTrigger modal={<ContainerModal/>}>
|
||||
<div className="wrapper">
|
||||
|
|
24
app/main.js
24
app/main.js
|
@ -1,12 +1,6 @@
|
|||
var React = require('react');
|
||||
var Router = require('react-router');
|
||||
var RetinaImage = require('react-retina-image');
|
||||
var Route = Router.Route;
|
||||
var NotFoundRoute = Router.NotFoundRoute;
|
||||
var DefaultRoute = Router.DefaultRoute;
|
||||
var Link = Router.Link;
|
||||
var RouteHandler = Router.RouteHandler;
|
||||
|
||||
var Raven = require('raven');
|
||||
var async = require('async');
|
||||
var docker = require('./docker.js');
|
||||
|
@ -15,7 +9,13 @@ var Setup = require('./Setup.react');
|
|||
var Containers = require('./Containers.react');
|
||||
var ContainerDetails = require('./ContainerDetails.react');
|
||||
var ContainerStore = require('./ContainerStore.js');
|
||||
var Radial = require('./Radial.react');
|
||||
var Radial = require('./Radial.react.js');
|
||||
|
||||
var Route = Router.Route;
|
||||
var NotFoundRoute = Router.NotFoundRoute;
|
||||
var DefaultRoute = Router.DefaultRoute;
|
||||
var Link = Router.Link;
|
||||
var RouteHandler = Router.RouteHandler;
|
||||
|
||||
var NoContainers = React.createClass({
|
||||
render: function () {
|
||||
|
@ -38,7 +38,7 @@ var App = React.createClass({
|
|||
var routes = (
|
||||
<Route name="app" path="/" handler={App}>
|
||||
<Route name="containers" handler={Containers}>
|
||||
<Route name="container" path=":Id" handler={ContainerDetails}>
|
||||
<Route name="container" path=":name" handler={ContainerDetails}>
|
||||
</Route>
|
||||
<DefaultRoute handler={NoContainers}/>
|
||||
</Route>
|
||||
|
@ -48,17 +48,19 @@ var routes = (
|
|||
</Route>
|
||||
);
|
||||
|
||||
Router.run(routes, function (Handler) {
|
||||
boot2docker.ip(function (err, ip) {
|
||||
boot2docker.ip(function (err, ip) {
|
||||
if (!err) {
|
||||
docker.setHost(ip);
|
||||
ContainerStore.init(function () {
|
||||
Router.run(routes, function (Handler) {
|
||||
React.render(<Handler/>, document.body);
|
||||
});
|
||||
});
|
||||
} else {
|
||||
Router.run(routes, function (Handler) {
|
||||
React.render(<Handler/>, document.body);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
if (process.env.NODE_ENV !== 'development') {
|
||||
|
|
|
@ -1,71 +1,3 @@
|
|||
@import "bootstrap/bootstrap.less";
|
||||
@import "clearsans.less";
|
||||
@import "theme.less";
|
||||
@import "icons.less";
|
||||
@import "retina.less";
|
||||
@import "setup.less";
|
||||
@import "radial.less";
|
||||
|
||||
.buttons {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
top: 16px;
|
||||
left: 20px;
|
||||
|
||||
&:hover {
|
||||
.button-minimize.enabled {
|
||||
.at2x('minimize.png', 10px, 10px);
|
||||
}
|
||||
.button-close.enabled {
|
||||
.at2x('close.png', 10px, 10px);
|
||||
}
|
||||
.button-fullscreen.enabled {
|
||||
.at2x('fullscreen.png', 10px, 10px);
|
||||
}
|
||||
.button-fullscreenclose.enabled {
|
||||
.at2x('fullscreenclose.png', 10px, 10px);
|
||||
}
|
||||
}
|
||||
|
||||
.button {
|
||||
box-sizing: border-box;
|
||||
display: inline-block;
|
||||
background: white;
|
||||
margin-right: 9px;
|
||||
height: 12px;
|
||||
width: 12px;
|
||||
border: 1px solid #CCD3D5;
|
||||
border-radius: 6px;
|
||||
box-shadow: 0px 1px 1px 0px rgba(234,234,234,0.50);
|
||||
-webkit-app-region: no-drag;
|
||||
|
||||
&.disabled {
|
||||
border: 1px solid #E8EEEF;
|
||||
}
|
||||
|
||||
&.enabled:hover {
|
||||
box-shadow: 0px 1px 1px 0px rgba(195,198,201,0.50);
|
||||
}
|
||||
|
||||
&.enabled:hover:active {
|
||||
cursor: default;
|
||||
-webkit-filter: brightness(92%);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.header {
|
||||
min-width: 100%;
|
||||
flex: 0;
|
||||
min-height: 48px;
|
||||
-webkit-app-region: drag;
|
||||
-webkit-user-select: none;
|
||||
|
||||
&.no-drag {
|
||||
-webkit-app-region: no-drag;
|
||||
}
|
||||
}
|
||||
|
||||
.containers {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
|
@ -78,20 +10,21 @@
|
|||
.sidebar {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-width: 240px;
|
||||
min-width: 260px;
|
||||
margin: 0;
|
||||
box-sizing: border-box;
|
||||
border-right: 1px solid #eee;
|
||||
|
||||
.sidebar-header {
|
||||
flex: 0 auto;
|
||||
min-width: 240px;
|
||||
min-width: 260px;
|
||||
display: flex;
|
||||
border-bottom: 1px solid transparent;
|
||||
transition: border-bottom 0.25s;
|
||||
|
||||
&.sep {
|
||||
border-bottom: 1px solid #eee;
|
||||
box-shadow: 0px 2px 3px 0px rgba(0,0,0,0.03);
|
||||
}
|
||||
|
||||
h3 {
|
||||
|
@ -148,7 +81,7 @@
|
|||
ul {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
min-width: 240px;
|
||||
min-width: 260px;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
|
@ -163,23 +96,18 @@
|
|||
flex-shrink: 0;
|
||||
cursor: default;
|
||||
|
||||
/*&:hover {
|
||||
&.active {
|
||||
background: #eee;
|
||||
border-bottom: none;
|
||||
|
||||
&:hover {
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
text-decoration: none;
|
||||
cursor: default;
|
||||
background: @brand-primary;
|
||||
|
||||
li {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
li > .info > .name {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
li > .info > .image {
|
||||
color: #fff;
|
||||
}
|
||||
}*/
|
||||
&:focus {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
@ -187,10 +115,8 @@
|
|||
|
||||
li {
|
||||
vertical-align: middle;
|
||||
|
||||
margin: 14px 24px 0px;
|
||||
border-bottom: 1px solid #efefef;
|
||||
padding-bottom: 14px;
|
||||
margin: 16px 24px 0px;
|
||||
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
@ -198,18 +124,18 @@
|
|||
|
||||
.info {
|
||||
font-size: 13px;
|
||||
margin-left: 12px;
|
||||
margin-left: 16px;
|
||||
.name {
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
font-size: 13px;
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
color: #555;
|
||||
}
|
||||
.image {
|
||||
color: #999;
|
||||
font-size: 10px;
|
||||
font-size: 12px;
|
||||
font-weight: 400;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
|
@ -218,7 +144,7 @@
|
|||
}
|
||||
|
||||
.state {
|
||||
margin-top: 8px;
|
||||
margin-top: 9px;
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
min-width: 20px;
|
||||
|
@ -349,200 +275,3 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
html, body {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
user-select: none;
|
||||
font-family: 'Clear Sans', sans-serif;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar {
|
||||
width: 13px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
margin: 3px;
|
||||
-webkit-border-radius: 5px;
|
||||
border-radius: 5px;
|
||||
background: none;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
border: 3px solid rgba(0, 0, 0, 0);
|
||||
background-clip: padding-box;
|
||||
width: 7px;
|
||||
border-radius: 8px;
|
||||
background-color: rgba(0,0,0,0.2);
|
||||
}
|
||||
|
||||
.create-modal {
|
||||
@modal-padding: 32px;
|
||||
@search-width: 372px;
|
||||
@custom-width: 270px;
|
||||
.modal-dialog {
|
||||
margin-top: 8%;
|
||||
width: calc(@modal-padding + @search-width + 2 * @modal-padding + @custom-width);
|
||||
}
|
||||
.modal-content {
|
||||
//box-shadow: 0 3px 15px rgba(0, 0, 0, 0.2);
|
||||
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.10);
|
||||
border: none; //1px solid #ccc;
|
||||
height: 610px;
|
||||
}
|
||||
.modal-body {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
padding: 32px 32px;
|
||||
|
||||
.title {
|
||||
color: #CCD3D5;
|
||||
font-weight: 400;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
aside.custom {
|
||||
flex: 0 auto;
|
||||
padding-left: 32px;
|
||||
min-width: 270px;
|
||||
}
|
||||
|
||||
section.search {
|
||||
flex: 0 auto;
|
||||
min-width: 404px;
|
||||
padding-right: 32px;
|
||||
border-right: 1px solid #eee;
|
||||
|
||||
.question {
|
||||
a {
|
||||
color: #CCD3D5;
|
||||
}
|
||||
font-size: 10px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
input {
|
||||
border-radius: 20px;
|
||||
font-size: 13px;
|
||||
height: 38px;
|
||||
padding: 8px 16px;
|
||||
font-weight: 400;
|
||||
color: #666;
|
||||
|
||||
&:focus {
|
||||
box-shadow: none;
|
||||
border-color: #bbb;
|
||||
}
|
||||
|
||||
&::-webkit-input-placeholder {
|
||||
color: #ddd;
|
||||
font-weight: 300;
|
||||
}
|
||||
}
|
||||
|
||||
.results {
|
||||
overflow: auto;
|
||||
|
||||
.title {
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style: none;
|
||||
color: #555;
|
||||
padding: 0;
|
||||
|
||||
li {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
margin: 12px;
|
||||
border-bottom: 1px solid #eee;
|
||||
.info {
|
||||
.name {
|
||||
max-width: 278px;
|
||||
img {
|
||||
margin-right: 6px;
|
||||
margin-left: 2px;
|
||||
}
|
||||
font-size: 16px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
.stars {
|
||||
color: #A7A7A7;
|
||||
margin-top: 2px;
|
||||
|
||||
.star-count {
|
||||
font-size: 10px;
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
top: -3px;
|
||||
left: 1px;
|
||||
height: 17px;
|
||||
}
|
||||
|
||||
.icon {
|
||||
overflow: hidden;
|
||||
display: inline-block;
|
||||
font-size: 15px;
|
||||
height: 15px;
|
||||
}
|
||||
}
|
||||
flex: 0 auto;
|
||||
}
|
||||
.action {
|
||||
text-align: right;
|
||||
flex: 1 auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.modal-backdrop.in {
|
||||
background: rgba(227,230,230,0.95);
|
||||
opacity: 1;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
@-webkit-keyframes translatedownload {
|
||||
from {
|
||||
-webkit-transform: rotate(0deg);
|
||||
}
|
||||
to {
|
||||
-webkit-transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@-webkit-keyframes translatewave {
|
||||
from {
|
||||
-webkit-transform: translateX(0px);
|
||||
}
|
||||
to {
|
||||
-webkit-transform: translateX(20px);
|
||||
}
|
||||
}
|
||||
|
||||
@-webkit-keyframes translatedownload {
|
||||
0% {
|
||||
-webkit-transform: translateY(6px);
|
||||
opacity: 0;
|
||||
}
|
||||
25% {
|
||||
opacity: 1;
|
||||
-webkit-transform: translateY(6px);
|
||||
}
|
||||
50% {
|
||||
opacity: 1;
|
||||
-webkit-transform: translateY(20px);
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
-webkit-transform: translateY(20px);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
@import "bootstrap/bootstrap.less";
|
||||
|
||||
.header {
|
||||
min-width: 100%;
|
||||
flex: 0;
|
||||
min-height: 48px;
|
||||
-webkit-app-region: drag;
|
||||
-webkit-user-select: none;
|
||||
|
||||
&.no-drag {
|
||||
-webkit-app-region: no-drag;
|
||||
}
|
||||
|
||||
.buttons {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
top: 16px;
|
||||
left: 20px;
|
||||
|
||||
&:hover {
|
||||
.button-minimize.enabled {
|
||||
.at2x('minimize.png', 10px, 10px);
|
||||
}
|
||||
.button-close.enabled {
|
||||
.at2x('close.png', 10px, 10px);
|
||||
}
|
||||
.button-fullscreen.enabled {
|
||||
.at2x('fullscreen.png', 10px, 10px);
|
||||
}
|
||||
.button-fullscreenclose.enabled {
|
||||
.at2x('fullscreenclose.png', 10px, 10px);
|
||||
}
|
||||
}
|
||||
|
||||
.button {
|
||||
box-sizing: border-box;
|
||||
display: inline-block;
|
||||
background: white;
|
||||
margin-right: 9px;
|
||||
height: 12px;
|
||||
width: 12px;
|
||||
border: 1px solid #CCD3D5;
|
||||
border-radius: 6px;
|
||||
box-shadow: 0px 1px 1px 0px rgba(234,234,234,0.50);
|
||||
-webkit-app-region: no-drag;
|
||||
|
||||
&.disabled {
|
||||
border: 1px solid #E8EEEF;
|
||||
}
|
||||
|
||||
&.enabled:hover {
|
||||
box-shadow: 0px 1px 1px 0px rgba(195,198,201,0.50);
|
||||
}
|
||||
|
||||
&.enabled:hover:active {
|
||||
cursor: default;
|
||||
-webkit-filter: brightness(92%);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -17,24 +17,11 @@
|
|||
.btn-info,
|
||||
.btn-warning,
|
||||
.btn-danger {
|
||||
text-shadow: 0 -1px 0 rgba(0,0,0,.2);
|
||||
@shadow: inset 0 1px 0 rgba(255,255,255,.15), 0 1px 1px rgba(0,0,0,.075);
|
||||
.box-shadow(@shadow);
|
||||
|
||||
// Reset the shadow
|
||||
&:active,
|
||||
&.active {
|
||||
.box-shadow(inset 0 3px 5px rgba(0,0,0,.125));
|
||||
}
|
||||
|
||||
.badge {
|
||||
text-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
// Mixin for generating new styles
|
||||
.btn-styles(@btn-color: #555) {
|
||||
#gradient > .vertical(@start-color: @btn-color; @end-color: darken(@btn-color, 12%));
|
||||
.reset-filter(); // Disable gradients for IE9 because filter bleeds through rounded corners
|
||||
background-repeat: repeat-x;
|
||||
border-color: darken(@btn-color, 14%);
|
||||
|
@ -42,33 +29,35 @@
|
|||
&:hover,
|
||||
&:focus {
|
||||
background-color: darken(@btn-color, 12%);
|
||||
background-position: 0 -15px;
|
||||
}
|
||||
|
||||
&:active,
|
||||
&.active {
|
||||
background-color: darken(@btn-color, 12%);
|
||||
border-color: darken(@btn-color, 14%);
|
||||
}
|
||||
|
||||
&:disabled,
|
||||
&[disabled] {
|
||||
background-color: darken(@btn-color, 12%);
|
||||
background-image: none;
|
||||
}
|
||||
}
|
||||
|
||||
// Common styles
|
||||
.btn {
|
||||
border-radius: 25px;
|
||||
box-shadow: none;
|
||||
font-weight: 400;
|
||||
text-shadow: none;
|
||||
// Remove the gradient for the pressed/active state
|
||||
&:active,
|
||||
&.active {
|
||||
background-image: none;
|
||||
}
|
||||
|
||||
&:focus,
|
||||
&.focus {
|
||||
box-shadow: none;
|
||||
outline: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
// Apply the mixin to the buttons
|
||||
.btn-default { .btn-styles(@btn-default-bg); text-shadow: 0 1px 0 #fff; border-color: #ccc; }
|
||||
.btn-default { .btn-styles(@btn-default-bg); }
|
||||
.btn-primary { .btn-styles(@btn-primary-bg); }
|
||||
.btn-success { .btn-styles(@btn-success-bg); }
|
||||
.btn-info { .btn-styles(@btn-info-bg); }
|
||||
|
|
Загрузка…
Ссылка в новой задаче