Skip to content
This repository was archived by the owner on Sep 6, 2021. It is now read-only.

Added Extension Sorting capability according to downloads and last published date #13080

Merged
merged 6 commits into from
Feb 20, 2017
Merged
Show file tree
Hide file tree
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
3 changes: 3 additions & 0 deletions src/extensibility/ExtensionManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,9 @@ define(function (require, exports, module) {
_idsToDisable = {};

PreferencesManager.stateManager.definePreference(FOLDER_AUTOINSTALL, "object", undefined);
PreferencesManager.definePreference("extensions.sort", "string", "publishedDate", {
description: Strings.SORT_EXTENSION_METHOD
});

/**
* @private
Expand Down
25 changes: 24 additions & 1 deletion src/extensibility/ExtensionManagerDialog.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ define(function (require, exports, module) {
KeyEvent = require("utils/KeyEvent"),
ExtensionManager = require("extensibility/ExtensionManager"),
ExtensionManagerView = require("extensibility/ExtensionManagerView").ExtensionManagerView,
ExtensionManagerViewModel = require("extensibility/ExtensionManagerViewModel");
ExtensionManagerViewModel = require("extensibility/ExtensionManagerViewModel"),
PreferencesManager = require("preferences/PreferencesManager");

var dialogTemplate = require("text!htmlContent/extension-manager-dialog.html");

Expand Down Expand Up @@ -372,6 +373,11 @@ define(function (require, exports, module) {
if (models[_activeTabIndex]) {
$modalDlg.scrollTop(models[_activeTabIndex].scrollPos || 0);
clearSearch();
if (_activeTabIndex === 2) {
$(".ext-sort-group").hide();
} else {
$(".ext-sort-group").show();
}
}
}

Expand Down Expand Up @@ -460,6 +466,18 @@ define(function (require, exports, module) {
$modalDlg.scrollTop(0);
});
}).on("click", ".search-clear", clearSearch);

// Sort the extension list based on the current selected sorting criteria
$dlg.on("change", ".sort-extensions", function (e) {
var sortBy = $(this).val();
PreferencesManager.set("extensions.sort", sortBy);
models.forEach(function (model, index) {
if (index <= 1) {
model._setSortedExtensionList(ExtensionManager.extensions, index === 1);
views[index].filter($(".search").val());
}
});
});

// Disable the search field when there are no items in the model
models.forEach(function (model, index) {
Expand All @@ -480,6 +498,11 @@ define(function (require, exports, module) {
} else { // Otherwise show the first tab
$dlg.find(".nav-tabs a:first").tab("show");
}
if ($activeTab.hasClass("installed")) {
$(".ext-sort-group").hide();
} else {
$(".ext-sort-group").show();
}
});

// Handle the 'Install from URL' button.
Expand Down
5 changes: 4 additions & 1 deletion src/extensibility/ExtensionManagerView.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ define(function (require, exports, module) {
LanguageManager = require("language/LanguageManager"),
Mustache = require("thirdparty/mustache/mustache"),
PathUtils = require("thirdparty/path-utils/path-utils"),
itemTemplate = require("text!htmlContent/extension-manager-view-item.html");
itemTemplate = require("text!htmlContent/extension-manager-view-item.html"),
PreferencesManager = require("preferences/PreferencesManager");


/**
Expand Down Expand Up @@ -71,6 +72,7 @@ define(function (require, exports, module) {
this._$infoMessage = $("<div class='info-message'/>")
.appendTo(this.$el).html(this.model.infoMessage);
this._$table = $("<table class='table'/>").appendTo(this.$el);
$(".sort-extensions").val(PreferencesManager.get("extensions.sort"));

this.model.initialize().done(function () {
self._setupEventHandlers();
Expand Down Expand Up @@ -248,6 +250,7 @@ define(function (require, exports, module) {
var installWarningBase = context.requiresNewer ? Strings.EXTENSION_LATEST_INCOMPATIBLE_NEWER : Strings.EXTENSION_LATEST_INCOMPATIBLE_OLDER;
context.installWarning = StringUtils.format(installWarningBase, entry.registryInfo.versions[entry.registryInfo.versions.length - 1].version, latestVerCompatInfo.compatibleVersion);
}
context.downloadCount = entry.registryInfo.totalDownloads;
} else {
// We should only get here when viewing the Installed tab and some extensions don't exist in the registry
// (or registry is offline). These flags *should* always be ignored in that scenario, but just in case...
Expand Down
41 changes: 22 additions & 19 deletions src/extensibility/ExtensionManagerViewModel.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,11 @@ define(function (require, exports, module) {

var _ = require("thirdparty/lodash");

var ExtensionManager = require("extensibility/ExtensionManager"),
registry_utils = require("extensibility/registry_utils"),
EventDispatcher = require("utils/EventDispatcher"),
Strings = require("strings");
var ExtensionManager = require("extensibility/ExtensionManager"),
registry_utils = require("extensibility/registry_utils"),
EventDispatcher = require("utils/EventDispatcher"),
Strings = require("strings"),
PreferencesManager = require("preferences/PreferencesManager");

/**
* @private
Expand Down Expand Up @@ -292,6 +293,20 @@ define(function (require, exports, module) {
});
};

ExtensionManagerViewModel.prototype._setSortedExtensionList = function (extensions, isTheme) {
this.filterSet = this.sortedFullSet = registry_utils.sortRegistry(extensions, "registryInfo", PreferencesManager.get("extensions.sort"))
.filter(function (entry) {
if (!isTheme) {
return entry.registryInfo && !entry.registryInfo.metadata.theme;
} else {
return entry.registryInfo && entry.registryInfo.metadata.theme;
}
})
.map(function (entry) {
return entry.registryInfo.metadata.name;
});
};

/**
* The model for the ExtensionManagerView that is responsible for handling registry-based extensions.
* This extends ExtensionManagerViewModel.
Expand Down Expand Up @@ -329,13 +344,7 @@ define(function (require, exports, module) {
self.extensions = ExtensionManager.extensions;

// Sort the registry by last published date and store the sorted list of IDs.
self.sortedFullSet = registry_utils.sortRegistry(self.extensions, "registryInfo")
.filter(function (entry) {
return entry.registryInfo !== undefined && entry.registryInfo.metadata.theme === undefined;
})
.map(function (entry) {
return entry.registryInfo.metadata.name;
});
self._setSortedExtensionList(ExtensionManager.extensions, false);
self._setInitialFilter();
})
.fail(function () {
Expand Down Expand Up @@ -536,13 +545,7 @@ define(function (require, exports, module) {
self.extensions = ExtensionManager.extensions;

// Sort the registry by last published date and store the sorted list of IDs.
self.sortedFullSet = registry_utils.sortRegistry(self.extensions, "registryInfo")
.filter(function (entry) {
return entry.registryInfo !== undefined && entry.registryInfo.metadata.theme;
})
.map(function (entry) {
return entry.registryInfo.metadata.name;
});
self._setSortedExtensionList(ExtensionManager.extensions, true);
self._setInitialFilter();
})
.fail(function () {
Expand Down Expand Up @@ -570,4 +573,4 @@ define(function (require, exports, module) {
exports.RegistryViewModel = RegistryViewModel;
exports.ThemesViewModel = ThemesViewModel;
exports.InstalledViewModel = InstalledViewModel;
});
});
14 changes: 11 additions & 3 deletions src/extensibility/registry_utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ define(function (require, exports, module) {
* we should look at the top level of the object.
* @return {Array} Sorted array of registry entries.
*/
exports.sortRegistry = function (registry, subkey) {
exports.sortRegistry = function (registry, subkey, sortBy) {
function getPublishTime(entry) {
if (entry.versions) {
return new Date(entry.versions[entry.versions.length - 1].published).getTime();
Expand All @@ -136,8 +136,16 @@ define(function (require, exports, module) {
sortedEntries.push(registry[key]);
});
sortedEntries.sort(function (entry1, entry2) {
return getPublishTime((subkey && entry2[subkey]) || entry2) -
getPublishTime((subkey && entry1[subkey]) || entry1);
if (sortBy !== "publishedDate") {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a big deal, but in general I prefer if you spell out all cases:

if (sortBy === "downloadCount") {
} else if (sortBy === "publishedDate") {
} else {
  console.error("Unknown sortBy " + sortBy ". Defaults to....")
}

Or something like this.

if (entry1.registryInfo && entry2.registryInfo) {
return entry2.registryInfo.totalDownloads - entry1.registryInfo.totalDownloads;
} else {
return Number.NEGATIVE_INFINITY;
}
} else {
return getPublishTime((subkey && entry2[subkey]) || entry2) -
getPublishTime((subkey && entry1[subkey]) || entry1);
}
});

return sortedEntries;
Expand Down
5 changes: 5 additions & 0 deletions src/htmlContent/extension-manager-dialog.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@
<li><a href="#installed" class="installed" data-toggle="tab"><span class="notification"></span><img src="styles/images/extension-manager-installed.svg"/><br/>{{Strings.EXTENSIONS_INSTALLED_TITLE}}</a></li>
</ul>
<div>
<span class="sort-extensions-title ext-sort-group">{{Strings.EXTENSIONS_SORT_BY}}</span>
<select class="sort-extensions ext-sort-group">
<option value="publishedDate">{{Strings.EXTENSIONS_LAST_UPDATED}}</option>
<option value="downloadCount">{{Strings.EXTENSIONS_DOWNLOADS}}</option>
</select>
<button class="search-clear">&times;</button>
<input class="search" type="text" placeholder="{{EXTENSION_SEARCH_PLACEHOLDER}}">
</div>
Expand Down
5 changes: 4 additions & 1 deletion src/htmlContent/extension-manager-view-item.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
{{#hasVersionInfo}}
<span class="muted ext-date"> &mdash; {{lastVersionDate}}</span>
{{/hasVersionInfo}}
{{#downloadCount}}
<p title="{{downloadCount}} {{Strings.EXTENSIONS_DOWNLOADS}}"><img src="styles/images/download-icon.svg"/> {{downloadCount}}</p>
{{/downloadCount}}
</td>
<td class="ext-desc">
{{#showInstallButton}}
Expand Down Expand Up @@ -99,4 +102,4 @@
{{/isInstalled}}
</div>
</td>
</tr>
</tr>
4 changes: 4 additions & 0 deletions src/nls/root/strings.js
Original file line number Diff line number Diff line change
Expand Up @@ -503,6 +503,7 @@ define({
"INSTALL_CANCELED" : "Installation canceled.",
"VIEW_COMPLETE_DESCRIPTION" : "View complete description",
"VIEW_TRUNCATED_DESCRIPTION" : "View truncated description",
"SORT_EXTENSION_METHOD" : "Sort Extensions using downloadCount or publishedDate",
// These must match the error codes in ExtensionsDomain.Errors.* :
"INVALID_ZIP_FILE" : "The downloaded content is not a valid zip file.",
"MISSING_PACKAGE_JSON" : "The package has no package.json file.",
Expand Down Expand Up @@ -579,6 +580,9 @@ define({
"EXTENSIONS_AVAILABLE_TITLE" : "Available",
"EXTENSIONS_THEMES_TITLE" : "Themes",
"EXTENSIONS_UPDATES_TITLE" : "Updates",
"EXTENSIONS_SORT_BY" : "Sort By",
"EXTENSIONS_LAST_UPDATED" : "Last Updated",
"EXTENSIONS_DOWNLOADS" : "Downloads",

"INLINE_EDITOR_NO_MATCHES" : "No matches available.",
"INLINE_EDITOR_HIDDEN_MATCHES" : "All matches are collapsed. Expand the files listed at right to view matches.",
Expand Down
11 changes: 11 additions & 0 deletions src/styles/brackets_patterns_override.less
Original file line number Diff line number Diff line change
Expand Up @@ -1183,6 +1183,17 @@ a[href^="http"] {
opacity: 0.3;
}
}
.sort-extensions-title {
float: left;
margin-right: 5px;
margin-top: 5px;
}
.sort-extensions {
float: left;
margin-right: 10px;
width: auto;
padding-right: 18px;
}
}
.modal-body {
height: 400px;
Expand Down
19 changes: 19 additions & 0 deletions src/styles/images/download-icon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
30 changes: 20 additions & 10 deletions test/spec/ExtensionManager-test-files/mockRegistry.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@
"published": "2013-04-10T18:21:27.058Z",
"brackets": ">0.20.0"
}
]
],
"totalDownloads": 10
},
"long-desc-extension": {
"metadata": {
Expand All @@ -42,7 +43,8 @@
"version": "1.0.0",
"published": "2013-04-10T18:26:20.553Z"
}
]
],
"totalDownloads": 184
},
"mock-extension-1": {
"metadata": {
Expand All @@ -65,7 +67,8 @@
"version": "1.0.0",
"published": "2013-04-11T18:26:20.553Z"
}
]
],
"totalDownloads": 190
},
"mock-extension-2": {
"metadata": {
Expand All @@ -79,7 +82,8 @@
"version": "1.0.0",
"published": "2013-04-11T18:26:20.553Z"
}
]
],
"totalDownloads": 88
},
"mock-extension-3": {
"metadata": {
Expand All @@ -93,7 +97,8 @@
"version": "1.0.0",
"published": "2013-04-11T18:26:20.553Z"
}
]
],
"totalDownloads": 34
},
"mock-extension-4": {
"metadata": {
Expand All @@ -107,7 +112,8 @@
"version": "1.0.0",
"published": "2013-04-11T18:26:20.553Z"
}
]
],
"totalDownloads": 20
},
"malicious-script-extension": {
"metadata": {
Expand All @@ -122,7 +128,8 @@
"version": "1.0.0",
"published": "2013-04-10T18:26:24.956Z"
}
]
],
"totalDownloads": 781
},
"select-parent": {
"metadata": {
Expand All @@ -147,7 +154,8 @@
"published": "2013-04-10T18:26:47.580Z",
"brackets": ">0.22.0"
}
]
],
"totalDownloads": 101
},
"basic-valid-extension": {
"metadata": {
Expand All @@ -165,7 +173,8 @@
"version": "3.0.0",
"published": "2013-04-10T18:29:11.907Z"
}
]
],
"totalDownloads": 130
},
"everyscrub": {
"metadata": {
Expand All @@ -179,6 +188,7 @@
"version": "0.23.0",
"published": "2013-04-11T17:22:38.033Z"
}
]
],
"totalDownloads": 101
}
}
Loading