| author | Maciej Bendkowski | 2012-08-08 11:14:26 (EDT) |
|---|---|---|
| committer | Malgorzata Janczarska | 2012-08-08 12:24:46 (EDT) |
| commit | 64508a794ce763d9e6feae14d8ee6c68e0e102c3 (patch) (side-by-side diff) | |
| tree | 598a09d309c563686a44fc33ce5d2fe0d4a9bccc | |
| parent | 7dd49d05845ce038db386bf1726d6d36c7ff935b (diff) | |
| download | org.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.js | 226 | ||||
| -rw-r--r-- | bundles/org.eclipse.orion.client.git/web/orion/git/gitRepositoryExplorer.js | 193 |
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 --- a/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."]); } }; |

