diff --git a/src/components/ContainerHome.react.js b/src/components/ContainerHome.react.js
index 08016322d1..bcc2f07f25 100644
--- a/src/components/ContainerHome.react.js
+++ b/src/components/ContainerHome.react.js
@@ -2,6 +2,7 @@ var _ = require('underscore');
var $ = require('jquery');
var React = require('react/addons');
var Radial = require('./Radial.react');
+var ContainerProgress = require('./ContainerProgress.react');
var ContainerHomePreview = require('./ContainerHomePreview.react');
var ContainerHomeLogs = require('./ContainerHomeLogs.react');
var ContainerHomeFolders = require('./ContainerHomeFolders.react');
@@ -51,22 +52,29 @@ var ContainerHome = React.createClass({
);
} else if (this.props.container && this.props.container.State.Downloading) {
if (this.props.container.Progress !== undefined) {
- if (this.props.container.Progress > 0) {
- body = (
-
-
Downloading Image
-
-
- );
- } else {
- body = (
-
-
Downloading Image
-
-
- );
+
+ let fields = [];
+ let values = [];
+ let sum = 0.0;
+
+ for (let i = 0; i < this.props.container.Progress.amount; i++) {
+
+ values.push(Math.round(this.props.container.Progress.progress[i].value));
+ sum += this.props.container.Progress.progress[i].value;
}
+ sum = sum / this.props.container.Progress.amount;
+
+ fields.push({Math.round(sum*100)/100}%
)
+ fields.push();
+
+ body = (
+
+
Downloading Image
+ {fields}
+
+ );
+
} else if (this.props.container.State.Waiting) {
body = (
diff --git a/src/stores/ContainerStore.js b/src/stores/ContainerStore.js
index d3b63099a0..304fec7131 100644
--- a/src/stores/ContainerStore.js
+++ b/src/stores/ContainerStore.js
@@ -97,11 +97,15 @@ class ContainerStore {
this.setState({containers});
}
+ // Receives the name of the container and columns of progression
+ // A column represents progression for one or more layers
progress ({name, progress}) {
let containers = this.containers;
+
if (containers[name]) {
containers[name].Progress = progress;
}
+
this.setState({containers});
}
diff --git a/src/utils/DockerUtil.js b/src/utils/DockerUtil.js
index ccc6cb8644..f5315de6b9 100644
--- a/src/utils/DockerUtil.js
+++ b/src/utils/DockerUtil.js
@@ -178,9 +178,16 @@ export default {
delete this.placeholders[name];
localStorage.setItem('placeholders', JSON.stringify(this.placeholders));
this.createContainer(name, {Image: imageName});
- }, progress => {
+ },
+
+ // progress is actually the progression PER LAYER (combined in columns)
+ // not total because it's not accurate enough
+ progress => {
containerServerActions.progress({name, progress});
- }, () => {
+ },
+
+
+ () => {
containerServerActions.waiting({name, waiting: true});
});
},
@@ -310,7 +317,7 @@ export default {
stream.setEncoding('utf8');
stream.on('data', json => {
let data = JSON.parse(json);
- console.log(data);
+ // console.log(data);
if (data.status === 'pull' || data.status === 'untag' || data.status === 'delete') {
return;
@@ -344,6 +351,9 @@ export default {
return !existingIds.has(layerSize.Id);
});
+ console.log("existingIds:" + existingIds.size)
+ console.log("layersToDownload:" + layersToDownload.length)
+
this.client.pull(repository + ':' + tag, (err, stream) => {
if (err) {
callback(err);
@@ -351,16 +361,45 @@ export default {
}
stream.setEncoding('utf8');
+ // layerProgress contains progression infos for all layers
let layerProgress = layersToDownload.reduce(function (r, layer) {
if (_.findWhere(images, {Id: layer.Id})) {
- r[layer.Id] = 1;
+ // If the layer is already here, we set current and total to 1
+ r[layer.Id] = {current:1, total:1, column:-1};
} else {
- r[layer.Id] = 0;
+ // At this point, the total layer size is unknown
+ // so we set total to -1 to avoid displaying it
+ r[layer.Id] = {current:0, total:-1, column:-1};
}
return r;
}, {});
- let timeout = null;
+
+
+ let layersToLoad = _.keys(layerProgress).length;
+
+ console.log("nbLayers:" + layersToLoad)
+
+ // Split the loading in a few columns for more feedback
+ let columns = {};
+ columns.amount = 4; // arbitrary
+ columns.progress = []; // layerIDs, nbLayers, maxLayers, progress value
+ columns.toFill = 0; // the current column index, waiting for layer IDs to be displayed
+
+ for (let i = 0; i < columns.amount; i++)
+ {
+ let layerAmount = Math.ceil(layersToLoad / (columns.amount - i))
+ layersToLoad -= layerAmount;
+ columns.progress[i] = { layerIDs:[], nbLayers:0 , maxLayers:layerAmount , value:0.0 };
+ }
+
+
+
+ // scheduled to inform about progression at given interval
+ let tick = null;
+
+
+ // data is associated with one layer only (can be identified with id)
stream.on('data', str => {
var data = JSON.parse(str);
@@ -374,34 +413,79 @@ export default {
}
if (data.status === 'Already exists') {
- layerProgress[data.id] = 1;
+
+ //layerProgress[data.id].current = 1;
+ //layerProgress[data.id].total = 1;
+
} else if (data.status === 'Downloading') {
- let current = data.progressDetail.current;
- let total = data.progressDetail.total;
+
+ // aduermael: How total could be <= 0 ?
+
+ // if (data.progressDetail.total <= 0) {
+ // progressCallback(0);
+ // return;
+ // } else {
+
+ layerProgress[data.id].current = data.progressDetail.current;
+ layerProgress[data.id].total = data.progressDetail.total;
+
+ // Assign to a column if not done yet
+ if (layerProgress[data.id].column == -1)
+ {
+ // test if we can still add layers to that column
+ if (columns.progress[columns.toFill].nbLayers == columns.progress[columns.toFill].maxLayers) columns.toFill++;
+
+ layerProgress[data.id].column = columns.toFill;
+ columns.progress[columns.toFill].layerIDs.push(data.id);
+ columns.progress[columns.toFill].nbLayers++;
- if (total <= 0) {
- progressCallback(0);
- return;
- } else {
- layerProgress[data.id] = current / total;
}
+
+ //}
- let sum = _.values(layerProgress).reduce((pv, sv) => pv + sv, 0);
- let numlayers = _.keys(layerProgress).length;
+ if (!tick) {
+ tick = setInterval( function(){
+ // console.log(JSON.stringify(layerProgress))
- var totalProgress = sum / numlayers * 100;
+ // update values
+ for (let i = 0; i < columns.amount; i++)
+ {
+ columns.progress[i].value = 0.0;
+
+ // Start only if the column has accurate values for all layers
+ if (columns.progress[i].nbLayers == columns.progress[i].maxLayers)
+ {
+ let layer;
+ let totalSum = 0;
+ let currentSum = 0;
- if (!timeout) {
- progressCallback(totalProgress);
- timeout = setTimeout(() => {
- timeout = null;
- }, 100);
+ for (let j = 0; j < columns.progress[i].nbLayers; j++)
+ {
+ layer = layerProgress[columns.progress[i].layerIDs[j]];
+ totalSum += layer.total;
+ currentSum += layer.current;
+ }
+
+ if (totalSum > 0) columns.progress[i].value = 100.0 * currentSum / totalSum;
+ else columns.progress[i].value = 0.0;
+ }
+ }
+
+ progressCallback(columns);
+
+ },33);
}
}
+
});
+
stream.on('end', function () {
+
+ clearInterval(tick);
callback();
+
});
+
});
});
});