зеркало из https://github.com/docker/kitematic.git
- Added favorites feature for containers. (#3419)
- Fixed side-bar width css, added cursor: pointer to containers. Signed-off-by: Daniel Amram <danielamram0@gmail.com> - Added favorites feature for containers. - Fixed side-bar width css, added cursor: pointer to containers. Signed-off-by: Daniel Amram <danielamram0@gmail.com>
This commit is contained in:
Родитель
62746cfe04
Коммит
90b8d1fd03
|
@ -1,5 +1,6 @@
|
||||||
import alt from '../alt';
|
import alt from '../alt';
|
||||||
import dockerUtil from '../utils/DockerUtil';
|
import dockerUtil from '../utils/DockerUtil';
|
||||||
|
import _ from "underscore";
|
||||||
|
|
||||||
class ContainerActions {
|
class ContainerActions {
|
||||||
|
|
||||||
|
@ -42,6 +43,17 @@ class ContainerActions {
|
||||||
active (name) {
|
active (name) {
|
||||||
dockerUtil.active(name);
|
dockerUtil.active(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toggleFavorite (name) {
|
||||||
|
let favorites = JSON.parse(localStorage.getItem('containers.favorites'));
|
||||||
|
if (favorites.includes(name)) {
|
||||||
|
favorites = favorites.filter(favoriteName => favoriteName !== name);
|
||||||
|
} else {
|
||||||
|
favorites = [...favorites, name];
|
||||||
|
}
|
||||||
|
localStorage.setItem('containers.favorites', JSON.stringify(favorites));
|
||||||
|
this.dispatch({name});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default alt.createActions(ContainerActions);
|
export default alt.createActions(ContainerActions);
|
||||||
|
|
|
@ -17,7 +17,8 @@ class ContainerServerActions {
|
||||||
'kill',
|
'kill',
|
||||||
'stopped',
|
'stopped',
|
||||||
'log',
|
'log',
|
||||||
'logs'
|
'logs',
|
||||||
|
'toggleFavorite'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,13 +9,10 @@ import {OverlayTrigger, Tooltip} from 'react-bootstrap';
|
||||||
import containerActions from '../actions/ContainerActions';
|
import containerActions from '../actions/ContainerActions';
|
||||||
|
|
||||||
var ContainerListItem = React.createClass({
|
var ContainerListItem = React.createClass({
|
||||||
handleItemMouseEnter: function () {
|
toggleFavoriteContainer: function (e) {
|
||||||
var $action = $(this.getDOMNode()).find('.action');
|
e.preventDefault();
|
||||||
$action.show();
|
e.stopPropagation();
|
||||||
},
|
containerActions.toggleFavorite(this.props.container.Name);
|
||||||
handleItemMouseLeave: function () {
|
|
||||||
var $action = $(this.getDOMNode()).find('.action');
|
|
||||||
$action.hide();
|
|
||||||
},
|
},
|
||||||
handleDeleteContainer: function (e) {
|
handleDeleteContainer: function (e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
@ -108,6 +105,7 @@ var ContainerListItem = React.createClass({
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="action">
|
<div className="action">
|
||||||
|
<span className={container.Favorite ? 'btn circular favorite' : 'btn circular'} onClick={this.toggleFavoriteContainer}><span className="icon icon-favorite"></span></span>
|
||||||
<span className="btn circular" onClick={this.handleDeleteContainer}><span className="icon icon-delete"></span></span>
|
<span className="btn circular" onClick={this.handleDeleteContainer}><span className="icon icon-delete"></span></span>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
|
|
|
@ -32,17 +32,23 @@ var Containers = React.createClass({
|
||||||
|
|
||||||
sorted: function (containers) {
|
sorted: function (containers) {
|
||||||
return _.values(containers).sort(function (a, b) {
|
return _.values(containers).sort(function (a, b) {
|
||||||
if (a.State.Downloading && !b.State.Downloading) {
|
if (a.Favorite && !b.Favorite) {
|
||||||
return -1;
|
return -1;
|
||||||
} else if (!a.State.Downloading && b.State.Downloading) {
|
} else if (!a.Favorite && b.Favorite) {
|
||||||
return 1;
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
if (a.State.Running && !b.State.Running) {
|
if (a.State.Downloading && !b.State.Downloading) {
|
||||||
return -1;
|
return -1;
|
||||||
} else if (!a.State.Running && b.State.Running) {
|
} else if (!a.State.Downloading && b.State.Downloading) {
|
||||||
return 1;
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
return a.Name.localeCompare(b.Name);
|
if (a.State.Running && !b.State.Running) {
|
||||||
|
return -1;
|
||||||
|
} else if (!a.State.Running && b.State.Running) {
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
return a.Name.localeCompare(b.Name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -191,6 +191,16 @@ class ContainerStore {
|
||||||
this.emitChange();
|
this.emitChange();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toggleFavorite ({name}) {
|
||||||
|
let containers = this.containers;
|
||||||
|
|
||||||
|
if (containers[name]) {
|
||||||
|
containers[name].Favorite = !containers[name].Favorite;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setState({containers});
|
||||||
|
}
|
||||||
|
|
||||||
static generateName (repo) {
|
static generateName (repo) {
|
||||||
const base = _.last(repo.split('/'));
|
const base = _.last(repo.split('/'));
|
||||||
const names = _.keys(this.getState().containers);
|
const names = _.keys(this.getState().containers);
|
||||||
|
|
|
@ -262,6 +262,8 @@ var DockerUtil = {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
containerServerActions.allUpdated({containers: _.indexBy(containers.concat(_.values(this.placeholders)), 'Name')});
|
containerServerActions.allUpdated({containers: _.indexBy(containers.concat(_.values(this.placeholders)), 'Name')});
|
||||||
|
let favorites = JSON.parse(localStorage.getItem('containers.favorites')) || [];
|
||||||
|
favorites.forEach(name => containerServerActions.toggleFavorite({name}));
|
||||||
this.logs();
|
this.logs();
|
||||||
this.fetchAllImages();
|
this.fetchAllImages();
|
||||||
});
|
});
|
||||||
|
|
|
@ -137,8 +137,14 @@
|
||||||
height: 45px;
|
height: 45px;
|
||||||
border-top: 1px solid transparent;
|
border-top: 1px solid transparent;
|
||||||
border-bottom: 1px solid transparent;
|
border-bottom: 1px solid transparent;
|
||||||
|
& {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: @color-box-button;
|
background-color: @color-box-button;
|
||||||
|
.action .btn {
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.info {
|
.info {
|
||||||
margin-left: 1rem;
|
margin-left: 1rem;
|
||||||
|
@ -163,17 +169,29 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.action {
|
.action {
|
||||||
display: none;
|
display: block;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
position: relative;
|
position: relative;
|
||||||
top: 0.4rem;
|
top: 0.4rem;
|
||||||
text-align: right;
|
text-align: right;
|
||||||
.btn {
|
.btn {
|
||||||
|
visibility: hidden;
|
||||||
|
cursor: pointer;
|
||||||
border: 1px solid @gray-lighter;
|
border: 1px solid @gray-lighter;
|
||||||
|
margin-left: 2px;
|
||||||
.icon {
|
.icon {
|
||||||
color: @gray-lighter;
|
color: @gray-lighter;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.favorite {
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
.btn:hover {
|
||||||
|
border: 1px solid @gray-normal;
|
||||||
|
.icon {
|
||||||
|
color: @gray-normal;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.state {
|
.state {
|
||||||
margin-top: 0.6rem;
|
margin-top: 0.6rem;
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
|
|
||||||
@border-radius: 0.2rem;
|
@border-radius: 0.2rem;
|
||||||
|
|
||||||
@sidebar-width: 220px;
|
@sidebar-width: 230px;
|
||||||
@sidebar-text-overflow-width: 140px;
|
@sidebar-text-overflow-width: 140px;
|
||||||
|
|
||||||
@container-state-size: 20px;
|
@container-state-size: 20px;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче