Skip to content
This repository was archived by the owner on Jul 18, 2025. It is now read-only.
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 83 additions & 25 deletions src/components/ContainerSettingsVolumes.react.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,27 @@ import React from 'react/addons';
import electron from 'electron';
const remote = electron.remote;
const dialog = remote.dialog;
import {shell} from 'electron';
import { shell } from 'electron';
import util from '../utils/Util';
import metrics from '../utils/MetricsUtil';
import containerActions from '../actions/ContainerActions';

var ContainerSettingsVolumes = React.createClass({
getInitialState: function () {
let mounts = this.props.container.Mounts;
return {
dockerVol: '',
mounts: mounts
}
},
handleDockerVolChange: function (event) {
let input = event.target;
this.setState(prevState => ({
dockerVol: input.value
}));
},
handleChooseVolumeClick: function (dockerVol) {
dialog.showOpenDialog({properties: ['openDirectory', 'createDirectory']}, (filenames) => {
dialog.showOpenDialog({ properties: ['openDirectory', 'createDirectory'] }, (filenames) => {
if (!filenames) {
return;
}
Expand All @@ -28,43 +41,57 @@ var ContainerSettingsVolumes = React.createClass({

metrics.track('Choose Directory for Volume');

let mounts = _.clone(this.props.container.Mounts);
let mounts = _.clone(this.state.mounts);
let match = false;
_.each(mounts, m => {
if (m.Destination === dockerVol) {
m.Source = util.windowsToLinuxPath(directory);
m.Driver = null;
match = true;
}
});

let binds = mounts.map(m => {
return m.Source + ':' + m.Destination;
});

let hostConfig = _.extend(this.props.container.HostConfig, {Binds: binds});
// if this is a new volume
if (!match) {
if (!dockerVol) {
metrics.track('Added Volume Directory', {
from: 'settings'
});
dialog.showMessageBox({
type: 'error',
buttons: ['OK'],
message: 'Invalid docker folder path'
});
return;
}
mounts.push({
Destination: dockerVol,
Source: util.windowsToLinuxPath(directory),
Driver: null,
});
this.setState({ dockerVol: '' })
}

containerActions.update(this.props.container.Name, {Mounts: mounts, HostConfig: hostConfig});
this.setState(prevState => ({
dockerVol: prevState.dockerVol,
mounts: mounts
}));
});
},
handleRemoveVolumeClick: function (dockerVol) {
metrics.track('Removed Volume Directory', {
from: 'settings'
});

let mounts = _.clone(this.props.container.Mounts);
_.each(mounts, m => {
if (m.Destination === dockerVol) {
m.Source = null;
m.Driver = 'local';
}
let mounts = _.clone(this.state.mounts);
mounts = _.filter(mounts, m => {
return m.Destination != dockerVol;
});

let binds = mounts.map(m => {
return m.Source + ':' + m.Destination;
});

let hostConfig = _.extend(this.props.container.HostConfig, {Binds: binds});

containerActions.update(this.props.container.Name, {Mounts: mounts, HostConfig: hostConfig});
this.setState(prevState => ({
dockerVol: prevState.dockerVol,
mounts: mounts
}));
},
handleOpenVolumeClick: function (path) {
metrics.track('Opened Volume Directory', {
Expand All @@ -76,20 +103,47 @@ var ContainerSettingsVolumes = React.createClass({
shell.showItemInFolder(path);
}
},
handleSave: function () {
let mounts = this.state.mounts;
let binds = mounts.map(m => {
return m.Source + ':' + m.Destination;
});

let hostConfig = _.extend(this.props.container.HostConfig, { Binds: binds });
containerActions.update(this.props.container.Name, { Mounts: mounts, HostConfig: hostConfig });
},
render: function () {
if (!this.props.container) {
return false;
}

var isUpdating = (this.props.container.State.Updating);

var homeDir = util.isWindows() ? util.windowsToLinuxPath(util.home()) : util.home();
var mounts = _.map(this.props.container.Mounts, (m, i) => {
var mounts = _.map(_.union(this.state.mounts, [['', '']]), (m, i) => {
let source = m.Source, destination = m.Destination;
let icons;

if (!destination) {
destination = <input type="text" value={this.state.dockerVol} className="key line" onChange={this.handleDockerVolChange}></input>
}
if (!m.Source || (!util.isNative() && m.Source.indexOf(homeDir) === -1) || (m.Source.indexOf('/var/lib/docker/volumes') !== -1)) {
icons = (
<div>
<a className="only-icon btn btn-positive small" disabled={this.props.container.State.Updating} onClick={this.handleChooseVolumeClick.bind(this, m.Destination || this.state.dockerVol)}><span className="icon icon-add"></span></a>
</div>
)
source = (
<span className="value-right">No Folder</span>
);
} else {
let local = util.isWindows() ? util.linuxToWindowsPath(source) : source;
icons = (
<div>
<a className="only-icon btn btn-action small" onClick={this.handleRemoveVolumeClick.bind(this, m.Destination)}><span className="icon icon-delete"></span></a>
<a className="only-icon btn btn-action small" disabled={this.props.container.State.Updating} onClick={this.handleChooseVolumeClick.bind(this, destination)}><span className="icon icon-edit"></span></a>
</div>
);
source = (
<a className="value-right" onClick={this.handleOpenVolumeClick.bind(this, source)}>{local.replace(process.env.HOME, '~')}</a>
);
Expand All @@ -99,8 +153,7 @@ var ContainerSettingsVolumes = React.createClass({
<td>{destination}</td>
<td>{source}</td>
<td>
<a className="btn btn-action small" disabled={this.props.container.State.Updating} onClick={this.handleChooseVolumeClick.bind(this, destination)}>Change</a>
<a className="btn btn-action small" disabled={this.props.container.State.Updating} onClick={this.handleRemoveVolumeClick.bind(this, destination)}>Remove</a>
{icons}
</td>
</tr>
);
Expand All @@ -121,6 +174,11 @@ var ContainerSettingsVolumes = React.createClass({
{mounts}
</tbody>
</table>
<a className="btn btn-action"
disabled={isUpdating}
onClick={this.handleSave}>
Save
</a>
</div>
</div>
);
Expand Down