Skip to content

Commit 71ed156

Browse files
committed
Merge pull request adobe#3944 from adobe/nj/issue-3906
Show message and disable search box when no extensions are installed
2 parents 6eeea16 + e873873 commit 71ed156

File tree

4 files changed

+80
-3
lines changed

4 files changed

+80
-3
lines changed

src/extensibility/ExtensionManagerDialog.js

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,17 @@ define(function (require, exports, module) {
4242
* Show a dialog that allows the user to browse and manage extensions.
4343
*/
4444
function _showDialog() {
45-
var $dlg, view;
45+
var $dlg, view, $search, $searchClear;
46+
47+
function updateSearch() {
48+
if (view.model.filterSet.length === 0) {
49+
$search.attr("disabled", "disabled");
50+
$searchClear.attr("disabled", "disabled");
51+
} else {
52+
$search.removeAttr("disabled");
53+
$searchClear.removeAttr("disabled");
54+
}
55+
}
4656

4757
// Open the dialog.
4858
Dialogs.showModalDialogUsingTemplate(
@@ -53,6 +63,8 @@ define(function (require, exports, module) {
5363

5464
// Create the view.
5565
$dlg = $(".extension-manager-dialog");
66+
$search = $(".search", $dlg);
67+
$searchClear = $(".search-clear", $dlg);
5668
view = new ExtensionManagerView();
5769
view.initialize(ExtensionManagerViewModel.SOURCE_INSTALLED)
5870
.done(function () {
@@ -62,17 +74,25 @@ define(function (require, exports, module) {
6274
$dlg.on("input", ".search", function (e) {
6375
view.filter($(this).val());
6476
}).on("click", ".search-clear", function (e) {
65-
$(".search", $dlg).val("");
77+
$search.val("");
6678
view.filter("");
6779
});
80+
81+
// Disable the search field when there are no items in the view.
82+
$(view.model).on("change", function () {
83+
updateSearch();
84+
});
6885

6986
// Handle the install button.
7087
$(".extension-manager-dialog .install-from-url")
7188
.click(function () {
7289
CommandManager.execute(Commands.FILE_INSTALL_EXTENSION);
7390
});
7491

75-
$dlg.find(".search").focus();
92+
updateSearch();
93+
if (!$search.attr("disabled")) {
94+
$dlg.find(".search").focus();
95+
}
7696
});
7797
}
7898

src/extensibility/ExtensionManagerView.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,9 @@ define(function (require, exports, module) {
6262
this._itemTemplate = Mustache.compile(itemTemplate);
6363
this._itemViews = {};
6464
this.$el = $("<div class='extension-list'/>");
65+
this._$emptyMessage = $("<div class='empty-message'/>")
66+
.append(Strings.NO_EXTENSIONS)
67+
.appendTo(this.$el);
6568
this._$table = $("<table class='table'/>").appendTo(this.$el);
6669

6770
// Show the busy spinner and access the registry.
@@ -93,6 +96,12 @@ define(function (require, exports, module) {
9396
*/
9497
ExtensionManagerView.prototype.model = null;
9598

99+
/**
100+
* @type {jQueryObject}
101+
* Element showing a message when there are no extensions.
102+
*/
103+
ExtensionManagerView.prototype._$emptyMessage = null;
104+
96105
/**
97106
* @private
98107
* @type {jQueryObject}
@@ -128,6 +137,7 @@ define(function (require, exports, module) {
128137
.on("change", function (e, id) {
129138
var extensions = self.model.extensions,
130139
$oldItem = self._itemViews[id];
140+
self._checkNoExtensions();
131141
if (self.model.filterSet.indexOf(id) === -1) {
132142
// This extension is not in the filter set. Remove it from the view if we
133143
// were rendering it previously.
@@ -224,6 +234,20 @@ define(function (require, exports, module) {
224234
return $(this._itemTemplate(context));
225235
};
226236

237+
/**
238+
* @private
239+
* Checks if there are no extensions, and if so shows the "no extensions" message.
240+
*/
241+
ExtensionManagerView.prototype._checkNoExtensions = function () {
242+
if (this.model.filterSet.length === 0) {
243+
this._$emptyMessage.css("display", "block");
244+
this._$table.css("display", "none");
245+
} else {
246+
this._$table.css("display", "");
247+
this._$emptyMessage.css("display", "none");
248+
}
249+
};
250+
227251
/**
228252
* @private
229253
* Renders the extension entry table based on the model's current filter set. Will create
@@ -232,6 +256,7 @@ define(function (require, exports, module) {
232256
ExtensionManagerView.prototype._render = function () {
233257
var self = this,
234258
$item;
259+
this._checkNoExtensions();
235260
this._$table.empty();
236261
this.model.filterSet.forEach(function (id) {
237262
var $item = self._itemViews[id];

src/styles/brackets_patterns_override.less

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -509,9 +509,17 @@
509509
width: 15px;
510510
height: 16px;
511511
z-index: 1;
512+
513+
&:disabled {
514+
opacity: 0.3;
515+
cursor: default;
516+
}
512517
}
513518
.search-clear:active {
514519
opacity: 0.5;
520+
&:disabled {
521+
opacity: 0.3;
522+
}
515523
}
516524
}
517525
.modal-body {
@@ -521,6 +529,15 @@
521529
overflow-y: scroll;
522530
padding: 0;
523531

532+
.empty-message {
533+
display: none;
534+
position: absolute;
535+
top: 50%;
536+
width: 100%;
537+
margin-top: -1em;
538+
text-align: center;
539+
}
540+
524541
.extension-list {
525542
td {
526543
height: 2em;
@@ -646,6 +663,11 @@ input, textarea {
646663
border: 1px solid @tc-gray-component-focused-border;
647664
box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.12), 0 0 0 2px #6fb5f1;
648665
}
666+
667+
&:disabled {
668+
opacity: 0.3;
669+
cursor: default;
670+
}
649671
}
650672

651673
/* Twipsy tooltips */

test/spec/ExtensionManager-test.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -765,11 +765,21 @@ define(function (require, exports, module) {
765765
}
766766
});
767767
});
768+
769+
it("should show the 'no extensions' message when there are no extensions installed", function () {
770+
setupViewWithMockData(ExtensionManagerViewModel.SOURCE_INSTALLED);
771+
runs(function () {
772+
expect($(".empty-message", view.$el).css("display")).not.toBe("none");
773+
expect($("table", view.$el).css("display")).toBe("none");
774+
});
775+
});
768776

769777
it("should show only items that are already installed and have a remove button for each", function () {
770778
mockLoadExtensions(["user/mock-extension-3", "user/mock-extension-4", "user/mock-legacy-extension"]);
771779
setupViewWithMockData(ExtensionManagerViewModel.SOURCE_INSTALLED);
772780
runs(function () {
781+
expect($(".empty-message", view.$el).css("display")).toBe("none");
782+
expect($("table", view.$el).css("display")).not.toBe("none");
773783
CollectionUtils.forEach(mockRegistry, function (item) {
774784
var $button = $("button.remove[data-extension-id=" + item.metadata.name + "]", view.$el);
775785
if (item.metadata.name === "mock-extension-3" ||

0 commit comments

Comments
 (0)