summaryrefslogtreecommitdiffstatsabout
diff options
context:
space:
mode:
authorMaciej Bendkowski2012-08-08 11:14:26 (EDT)
committer Malgorzata Janczarska2012-08-08 12:24:46 (EDT)
commit64508a794ce763d9e6feae14d8ee6c68e0e102c3 (patch)
tree598a09d309c563686a44fc33ce5d2fe0d4a9bccc
parent7dd49d05845ce038db386bf1726d6d36c7ff935b (diff)
downloadorg.eclipse.orion.client-64508a794ce763d9e6feae14d8ee6c68e0e102c3.zip
org.eclipse.orion.client-64508a794ce763d9e6feae14d8ee6c68e0e102c3.tar.gz
org.eclipse.orion.client-64508a794ce763d9e6feae14d8ee6c68e0e102c3.tar.bz2
Bug 384955 - Show content on git repository(ries) in a more dynamic wayv20120808-1624
-rw-r--r--bundles/org.eclipse.orion.client.core/web/orion/dynamicContent.js226
-rw-r--r--bundles/org.eclipse.orion.client.git/web/orion/git/gitRepositoryExplorer.js193
2 files changed, 340 insertions, 79 deletions
diff --git a/bundles/org.eclipse.orion.client.core/web/orion/dynamicContent.js b/bundles/org.eclipse.orion.client.core/web/orion/dynamicContent.js
new file mode 100644
index 0000000..5a0506c
--- /dev/null
+++ b/bundles/org.eclipse.orion.client.core/web/orion/dynamicContent.js
@@ -0,0 +1,226 @@
+/*******************************************************************************
+ * @license
+ * Copyright (c) 2012 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License v1.0
+ * (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution
+ * License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html).
+ *
+ * Contributors: IBM Corporation - initial API and implementation
+ ******************************************************************************/
+ define(['dojo', 'dijit'], function(dojo, dijit){
+
+ /**
+ * Default progress indicator in form of a simple spinner.
+ *
+ * @param id [required] unique identifier, e.g. the row number in which the spinner is created
+ * @param anchor [required] father DOM node for the created spinner
+ *
+ * @returns ProgressSpinner object
+ */
+ function ProgressSpinner(id, anchor){
+ if(id === undefined){ throw new Error("Missing reqired argument: id"); }
+ if(anchor === undefined){ throw new Error("Missing reqired argument: anchor"); }
+
+ this._id = id;
+ this._anchor = anchor;
+
+ // we add a prefix for the id label
+ this._prefix = "progressSpinner:";
+ }
+
+ ProgressSpinner.prototype = {
+
+ /**
+ * [interface] starts the progress indicator
+ */
+ start: function(){
+ dojo.create("img", {"id":this._prefix+this._id, "src":"/images/none.png", "class":"progressPane_running"}, this._anchor);
+ },
+
+ /**
+ * [interface] stops the progress indicator
+ */
+ stop: function(){
+ dojo.destroy(dojo.byId(this._prefix+this._id));
+ },
+
+ /**
+ * [interface] renders the progress indicator after an population error
+ */
+ error: function(err){
+ var indicator = dojo.byId(this._prefix+this._id);
+ indicator.src = "/images/problem.gif";
+ dojo.removeAttr(indicator, "class");
+
+ new dijit.Tooltip({
+ connectId: [this._prefix+this._id],
+ label: err
+ });
+ }
+ };
+
+ // add constructor
+ ProgressSpinner.prototype.constructor = ProgressSpinner;
+
+ /**
+ * Dynamic content model which handles the population logic
+ *
+ * @param objects [required] collection of objects to be populated
+ * @param populate [required] population function (i), which populates the i-th object in the collection
+ *
+ * @returns DynamicContentModel object
+ */
+ function DynamicContentModel(objects, populate){
+ if(!objects) { throw new Error("Missing reqired argument: objects"); }
+ if(!populate) { throw new Error("Missing reqired argument: populate"); }
+
+ this._objects = objects;
+ this._populate = populate;
+ }
+
+ DynamicContentModel.prototype = {
+
+ /**
+ * [interface] returns the object collection
+ */
+ getObjects : function(){
+ return this._objects;
+ },
+
+ /**
+ * [interface] returns the deferred for i-th element population
+ */
+ getDetails : function(i){
+ return this._populate(i);
+ }
+ };
+
+ // add constructor
+ DynamicContentModel.prototype.constructor = DynamicContentModel;
+
+ /**
+ * Dynamic content renderer which provides render methods.
+ * After being used in an explorer, the renderer gains access
+ * to the explorer through the explorer field
+ *
+ * @returns DynamicContentRenderer object
+ */
+ function DynamicContentRenderer(){ }
+
+ DynamicContentRenderer.prototype = {
+ // default progress indicator
+ progressIndicator : ProgressSpinner,
+
+ // default setup properties
+ setupProperties : {
+ //progress indicator list
+ progressIndicators : []
+ },
+
+ // default error handler
+ errorHandler : function(i, err){
+ this.explorer.progressIndicators[i].error(err);
+ }
+ };
+
+ // add constructor
+ DynamicContentRenderer.prototype.constructor = DynamicContentRenderer;
+
+ /**
+ * Dynamic content explorer which allows dynamic population and rendering of the given model
+ * @param model [required] dynamic content model to be explored
+ *
+ * @returns DynamicContentExplorer object
+ */
+ function DynamicContentExplorer(model){
+ if(!model) { throw new Error("Missing required argument: model"); }
+ this._model = model;
+
+ //default renderer
+ this.use(new DynamicContentRenderer());
+ }
+
+ DynamicContentExplorer.prototype = {
+ /**
+ * [interface] dynamically populates and renders the model.
+ */
+ render : function(){
+ var that = this;
+
+ //render initial data
+ if(this._initialRender){ this._initialRender(); }
+
+ //called if the i-th object is successfully populated
+ var populationSuccess = function(i){
+ return function(){
+ //after population work
+ that._renderAfterItemPopulation(i);
+
+ //stop indicator
+ that.progressIndicators[i].stop();
+ };
+ };
+
+ //called if the i-th object could not be successfully populated
+ var populationFailure = function(i){
+ return function(resp){
+ if(that._errorHandler) { that._errorHandler(i, resp); }
+ else { throw new Error(resp); }
+ };
+ };
+
+ for(var i=0; i<this._model.getObjects().length; i++){
+ //before population render work
+ this._renderBeforeItemPopulation(i);
+
+ //start indicator
+ this.progressIndicators[i].start();
+
+ //population
+ this._model.getDetails(i).then(
+ populationSuccess(i), populationFailure(i)
+ );
+ }
+
+ //cleanup render work
+ if(this._cleanupRender) { this._cleanupRender(); }
+ },
+
+ /**
+ * [interface] extends explorer functionality using the render functions in obj.
+ */
+ use : function(obj){
+ for(var field in obj){
+ if(field === "populateItem"){ this._populateItem = obj.populateItem.bind(obj); obj.explorer = this; }
+ else if(field === "renderBeforeItemPopulation"){ this._renderBeforeItemPopulation = obj.renderBeforeItemPopulation.bind(obj); obj.explorer = this; }
+ else if(field === "renderAfterItemPopulation"){ this._renderAfterItemPopulation = obj.renderAfterItemPopulation.bind(obj); obj.explorer = this; }
+ else if(field === "errorHandler"){ this._errorHandler = obj.errorHandler.bind(obj); obj.explorer = this; }
+ else if(field === "initialRender"){ this._initialRender = obj.initialRender.bind(obj); obj.explorer = this; }
+ else if(field === "cleanupRender"){ this._cleanupRender = obj.cleanupRender.bind(obj); obj.explorer = this; }
+
+ // inherit the progress indicator
+ else if(field === "progressIndicator"){ this.progressIndicator = obj.progressIndicator; obj.explorer = this; }
+
+ // inherit some setup properties
+ else if(field === "setupProperties"){
+ for(var property in obj.setupProperties){
+ this[property] = obj.setupProperties[property];
+ }
+
+ obj.explorer = this;
+ }
+ }
+ }
+ };
+
+ // add constructor
+ DynamicContentExplorer.prototype.constructor = DynamicContentExplorer;
+
+ return {
+ DynamicContentModel : DynamicContentModel,
+ DynamicContentExplorer : DynamicContentExplorer,
+ DynamicContentRenderer : DynamicContentRenderer,
+ ProgressSpinner : ProgressSpinner
+ };
+ }); \ No newline at end of file
diff --git a/bundles/org.eclipse.orion.client.git/web/orion/git/gitRepositoryExplorer.js b/bundles/org.eclipse.orion.client.git/web/orion/git/gitRepositoryExplorer.js
index ed2e487..37f7e7a 100644
--- a/bundles/org.eclipse.orion.client.git/web/orion/git/gitRepositoryExplorer.js
+++ b/bundles/org.eclipse.orion.client.git/web/orion/git/gitRepositoryExplorer.js
@@ -11,8 +11,8 @@
/*global define dijit console document Image */
-define(['i18n!git/nls/gitmessages', 'require', 'dojo', 'orion/commands', 'orion/section', 'orion/util', 'orion/PageUtil', 'orion/globalCommands', 'orion/git/gitCommands', 'orion/git/widgets/CommitTooltipDialog'],
- function(messages, require, dojo, mCommands, mSection, mUtil, PageUtil, mGlobalCommands, mGitCommands) {
+define(['i18n!git/nls/gitmessages', 'require', 'dojo', 'orion/commands', 'orion/section', 'orion/dynamicContent', 'orion/util', 'orion/PageUtil', 'orion/globalCommands', 'orion/git/gitCommands', 'orion/git/widgets/CommitTooltipDialog'],
+ function(messages, require, dojo, mCommands, mSection, mDynamicContent, mUtil, PageUtil, mGlobalCommands, mGitCommands) {
var exports = {};
exports.GitRepositoryExplorer = (function() {
@@ -227,36 +227,40 @@ exports.GitRepositoryExplorer = (function() {
// Git repo
- GitRepositoryExplorer.prototype.decorateRepositories = function(repositories, mode, deferred){
+ GitRepositoryExplorer.prototype.decorateRepository = function(repository, mode, deferred){
var that = this;
if (deferred == null){
deferred = new dojo.Deferred();
}
- if (repositories.length > 0) {
- this.registry.getService("orion.core.file").loadWorkspace(repositories[0].ContentLocation + "?parts=meta").then( //$NON-NLS-1$ //$NON-NLS-0$
+ if(!mode){
+ mode = "full";
+ }
+
+
+ this.registry.getService("orion.core.file").loadWorkspace(repository.ContentLocation + "?parts=meta").then( //$NON-NLS-1$ //$NON-NLS-0$
function(resp){
- repositories[0].Content = {};
+ repository.Content = {};
var path = "root / "; //$NON-NLS-0$
- if (resp.Parents != null)
+ if (resp.Parents !== null)
for (var i=resp.Parents.length; i>0; i--){
path += resp.Parents[i-1].Name + " / "; //$NON-NLS-0$
}
+
path += resp.Name;
-
- repositories[0].Content.Path = path;
+ repository.Content.Path = path;
if (mode !== "full"){ //$NON-NLS-0$
- that.decorateRepositories(repositories.slice(1), mode, deferred);
+ deferred.callback();
return;
}
- that.registry.getService("orion.git.provider").getGitStatus(repositories[0].StatusLocation).then( //$NON-NLS-0$
+ that.registry.getService("orion.git.provider").getGitStatus(repository.StatusLocation).then( //$NON-NLS-0$
function(resp){
- repositories[0].Status = resp;
+ repository.Status = resp;
- that.registry.getService("orion.git.provider").getGitBranch(repositories[0].BranchLocation).then( //$NON-NLS-0$
+ that.registry.getService("orion.git.provider").getGitBranch(repository.BranchLocation).then( //$NON-NLS-0$
function(resp){
var branches = resp.Children;
var currentBranch;
@@ -267,99 +271,136 @@ exports.GitRepositoryExplorer = (function() {
}
}
- if (!currentBranch || currentBranch.RemoteLocation[0] == null){
- that.decorateRepositories(repositories.slice(1), mode, deferred);
+ if (!currentBranch || currentBranch.RemoteLocation[0] === null){
+ deferred.callback();
return;
};
- var tracksRemoteBranch = (currentBranch.RemoteLocation.length == 1 && currentBranch.RemoteLocation[0].Children.length === 1);
+ var tracksRemoteBranch = (currentBranch.RemoteLocation.length === 1 && currentBranch.RemoteLocation[0].Children.length === 1);
if (tracksRemoteBranch && currentBranch.RemoteLocation[0].Children[0].CommitLocation){
that.registry.getService("orion.git.provider").getLog(currentBranch.RemoteLocation[0].Children[0].CommitLocation + "?page=1&pageSize=20", "HEAD").then( //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-0$
function(resp){
- repositories[0].CommitsToPush = resp.Children.length;
+ if(resp.Children === undefined) { repository.CommitsToPush = 0; }
+ else { repository.CommitsToPush = resp.Children.length; }
+ deferred.callback();
+ return;
+ }, function(resp){
+ deferred.errback();
+ return;
}
);
} else {
that.registry.getService("orion.git.provider").doGitLog(currentBranch.CommitLocation + "?page=1&pageSize=20").then( //$NON-NLS-1$ //$NON-NLS-0$
function(resp){
- repositories[0].CommitsToPush = resp.Children.length;
+ if(resp.Children === undefined) { repository.CommitsToPush = 0; }
+ else { repository.CommitsToPush = resp.Children.length; }
+ deferred.callback();
+ return;
+ }, function(resp){
+ deferred.errback();
+ return;
}
);
}
-
- that.decorateRepositories(repositories.slice(1), mode, deferred);
+ }, function(resp){
+ deferred.errback();
+ return;
}
);
+ }, function(resp){
+ deferred.errback();
+ return;
}
);
- }
+ }, function(resp){
+ deferred.errback();
+ return;
+ }
);
- } else {
- deferred.callback();
- }
return deferred;
};
GitRepositoryExplorer.prototype.displayRepositories = function(repositories, mode, links){
var that = this;
-
- var tableNode = dojo.byId( 'table' ); //$NON-NLS-0$
- dojo.empty( tableNode );
-
var progressService = this.registry.getService("orion.page.message"); //$NON-NLS-0$
- if (!repositories || repositories.length === 0){
- var titleWrapper = new mSection.Section(tableNode, {
- id: "repositorySection", //$NON-NLS-0$
- title: "Repository",
- iconClass: "gitImageSprite git-sprite-repository" //$NON-NLS-0$
- });
- titleWrapper.setTitle(mode === "full" ? messages["No Repositories"] : messages["Repository Not Found"]); //$NON-NLS-0$
- that.loadingDeferred.callback();
- progressService.setProgressMessage("");
- return;
- }
-
- var contentParent = dojo.create("div", {"role": "region", "class":"sectionTable"}, tableNode, "last");
- contentParent.innerHTML = '<list id="repositoryNode" class="mainPadding"></list>'; //$NON-NLS-0$
-
- this.decorateRepositories(repositories, mode).then(
- function(){
- for(var i=0; i<repositories.length;i++){
- that.renderRepository(repositories[i], i, repositories.length, mode, links);
+ var dynamicContentModel = new mDynamicContent.DynamicContentModel(repositories,
+ function(i){
+ return that.decorateRepository.bind(that)(repositories[i]);
+ }
+ );
+
+ var dcExplorer = new mDynamicContent.DynamicContentExplorer(dynamicContentModel);
+ var repositoryRenderer = {
+
+ initialRender : function(){
+ var tableNode = dojo.byId('table'); //$NON-NLS-0$
+ dojo.empty(tableNode);
+
+ if(!repositories || repositories.length === 0){
+ var titleWrapper = new mSection.Section(tableNode, {
+ id: "repositorySection", //$NON-NLS-0$
+ title: "Repository",
+ iconClass: "gitImageSprite git-sprite-repository" //$NON-NLS-0$
+ });
+ titleWrapper.setTitle(mode === "full" ? messages["No Repositories"] : messages["Repository Not Found"]); //$NON-NLS-0$
+ that.loadingDeferred.callback();
+ progressService.setProgressMessage("");
+ return;
}
+
+ var contentParent = dojo.create("div", {"role": "region", "class":"sectionTable"}, tableNode, "last");
+ contentParent.innerHTML = '<list id="repositoryNode" class="mainPadding"></list>'; //$NON-NLS-0$
+ },
+
+ cleanupRender : function(){
that.loadingDeferred.callback();
progressService.setProgressMessage("");
},
- function(){
- that.loadingDeferred.errback();
- progressService.setProgressMessage("");
+
+ renderBeforeItemPopulation : function(i){
+ var extensionListItem = dojo.create( "div", { "class":"sectionTableItem " + ((repositories.length === 1) ? "" : ((i % 2) ? "darkTreeTableRow" : "lightTreeTableRow"))}, dojo.byId("repositoryNode") ); //$NON-NLS-5$ //$NON-NLS-4$ //$NON-NLS-3$ //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-0$
+ var horizontalBox = dojo.create( "div", null, extensionListItem ); //$NON-NLS-0$
+
+ var detailsView = dojo.create( "div", { "class":"stretch" }, horizontalBox ); //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-0$
+ var title = dojo.create( "span", { "class":"gitMainDescription"}, detailsView ); //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-0$
+
+ if (links){
+ var link = dojo.create("a", {"class": "navlinkonpage", href: "/git/git-repository.html#" + repositories[i].Location}, title); //$NON-NLS-3$ //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-0$
+ dojo.place(document.createTextNode(repositories[i].Name), link);
+ } else { dojo.place(document.createTextNode(repositories[i].Name), title); }
+
+ //create indicator
+ this.explorer.progressIndicators[i] = new this.explorer.progressIndicator(i, title);
+
+ dojo.create("div", null, detailsView);
+ dojo.create("span", {"class" : "gitSecondaryDescription", innerHTML : (repositories[i].GitUrl != null ? "git url: " + repositories[i].GitUrl : messages["(no remote)"]) }, detailsView);
+ dojo.create("div", null, detailsView);
+ dojo.create("span", { "id" : "location"+i, "class":"gitSecondaryDescription" }, detailsView);
+
+ dojo.create("div", {"style" : "padding-top:10px"}, detailsView);
+ dojo.create("span", {"id":"workspaceState"+i, "class":"gitSecondaryDescription", "style" : "padding-left:10px"}, detailsView);
+ dojo.create("span", {"id":"commitsState"+i, "class":"gitSecondaryDescription", "style" : "padding-left:10px"}, detailsView);
+
+ if (mode === "full"){
+ var actionsArea = dojo.create( "div", {"id":"repositoryActionsArea", "class":"sectionTableItemActions" }, horizontalBox ); //$NON-NLS-4$ //$NON-NLS-3$ //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-0$
+ that.commandService.renderCommands(that.actionScopeId, actionsArea, repositories[i], that, "tool"); //$NON-NLS-0$
+ }
+ },
+
+ renderAfterItemPopulation : function(i){
+ that.renderRepository(repositories[i], i, repositories.length, mode, links);
}
- );
+ };
+
+ dcExplorer.use(repositoryRenderer);
+ dcExplorer.render();
};
GitRepositoryExplorer.prototype.renderRepository = function(repository, index, length, mode, links){
- var extensionListItem = dojo.create( "div", { "class":"sectionTableItem " + ((length == 1) ? "" : ((index % 2) ? "darkTreeTableRow" : "lightTreeTableRow"))}, dojo.byId("repositoryNode") ); //$NON-NLS-5$ //$NON-NLS-4$ //$NON-NLS-3$ //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-0$
- var horizontalBox = dojo.create( "div", null, extensionListItem ); //$NON-NLS-0$
-
- var detailsView = dojo.create( "div", { "class":"stretch" }, horizontalBox ); //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-0$
- var title = dojo.create( "span", { "class":"gitMainDescription"}, detailsView ); //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-0$
-
- if (links){
- link = dojo.create("a", {"class": "navlinkonpage", href: "/git/git-repository.html#" + repository.Location}, title); //$NON-NLS-3$ //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-0$
- dojo.place(document.createTextNode(repository.Name), link);
- } else {
- dojo.place(document.createTextNode(repository.Name), title);
- }
-
- dojo.create( "div", null, detailsView ); //$NON-NLS-0$
- var description = dojo.create( "span", { "class":"gitSecondaryDescription", //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-0$
- innerHTML: (repository.GitUrl != null ? "git url: " + repository.GitUrl : messages["(no remote)"]) }, detailsView );
- dojo.create( "div", null, detailsView ); //$NON-NLS-0$
- var description = dojo.create( "span", { "class":"gitSecondaryDescription", innerHTML: messages["location: "] + repository.Content.Path }, detailsView ); //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-0$
-
+ dojo.byId("location"+index).innerHTML = messages["location: "] + repository.Content.Path;
var status = repository.Status;
if (mode === "full"){ //$NON-NLS-0$
@@ -369,17 +410,11 @@ exports.GitRepositoryExplorer = (function() {
var workspaceState = ((unstaged > 0 || staged > 0)
? dojo.string.substitute(messages["${0} file(s) to stage and ${1} file(s) to commit."], [unstaged, staged])
: messages["Nothing to commit."]);
- dojo.create( "div", {"style":"padding-top:10px"}, detailsView ); //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-0$
- dojo.create( "span", { "class":"gitSecondaryDescription", "style":"padding-left:10px", innerHTML: workspaceState}, detailsView ); //$NON-NLS-4$ //$NON-NLS-3$ //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-0$
+
+ dojo.byId("workspaceState"+index).innerHTML = workspaceState;
var commitsState = repository.CommitsToPush;
- dojo.create( "span", { "class":"gitSecondaryDescription", "style":"padding-left:10px", //$NON-NLS-4$ //$NON-NLS-3$ //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-0$
- innerHTML: ((commitsState > 0 ) ? commitsState + messages[" commit(s) to push."] : messages["Nothing to push."])}, detailsView );
- }
-
- if (mode === "full"){
- var actionsArea = dojo.create( "div", {"id":"repositoryActionsArea", "class":"sectionTableItemActions" }, horizontalBox ); //$NON-NLS-4$ //$NON-NLS-3$ //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-0$
- this.commandService.renderCommands(this.actionScopeId, actionsArea, repository, this, "tool"); //$NON-NLS-0$
+ dojo.byId("commitsState"+index).innerHTML = ((commitsState > 0) ? commitsState + messages[" commit(s) to push."] : messages["Nothing to push."]);
}
};