Skip to content

Commit d43a8d3

Browse files
committed
Init
1 parent c5c47ca commit d43a8d3

File tree

12 files changed

+154
-36
lines changed

12 files changed

+154
-36
lines changed

core/src/main/java/hudson/model/Computer.java

+5
Original file line numberDiff line numberDiff line change
@@ -1109,6 +1109,11 @@ public String getSearchUrl() {
11091109
return getUrl();
11101110
}
11111111

1112+
@Override
1113+
public String getSearchIcon() {
1114+
return this.getIconClassName();
1115+
}
1116+
11121117
/**
11131118
* {@link RetentionStrategy} associated with this computer.
11141119
*

core/src/main/java/hudson/model/Job.java

+5
Original file line numberDiff line numberDiff line change
@@ -519,6 +519,11 @@ public boolean supportsLogRotator() {
519519
return true;
520520
}
521521

522+
@Override
523+
public String getSearchIcon() {
524+
return "symbol-status-" + this.getIconColor().getIconName();
525+
}
526+
522527
@Override
523528
protected SearchIndexBuilder makeSearchIndex() {
524529
return super.makeSearchIndex().add(new SearchIndex() {

core/src/main/java/hudson/model/User.java

+6
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
import hudson.security.AccessControlled;
4545
import hudson.security.SecurityRealm;
4646
import hudson.security.UserMayOrMayNotExistException2;
47+
import hudson.tasks.UserAvatarResolver;
4748
import hudson.util.FormValidation;
4849
import hudson.util.RunList;
4950
import hudson.util.XStream2;
@@ -277,6 +278,11 @@ public String getId() {
277278
return "/user/" + Util.rawEncode(idStrategy().keyFor(id));
278279
}
279280

281+
@Override
282+
public String getSearchIcon() {
283+
return UserAvatarResolver.resolve(this, "48x48");
284+
}
285+
280286
/**
281287
* The URL of the user page.
282288
*/

core/src/main/java/hudson/model/View.java

+5
Original file line numberDiff line numberDiff line change
@@ -560,6 +560,11 @@ public String getSearchUrl() {
560560
return getUrl();
561561
}
562562

563+
@Override
564+
public String getSearchIcon() {
565+
return "symbol-jobs";
566+
}
567+
563568
/**
564569
* Returns the transient {@link Action}s associated with the top page.
565570
*

core/src/main/java/hudson/search/Search.java

+29-4
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@
4646
import jenkins.security.stapler.StaplerNotDispatchable;
4747
import jenkins.util.MemoryReductionUtil;
4848
import jenkins.util.SystemProperties;
49+
import org.jenkins.ui.symbol.Symbol;
50+
import org.jenkins.ui.symbol.SymbolRequest;
4951
import org.kohsuke.accmod.Restricted;
5052
import org.kohsuke.accmod.restrictions.NoExternalUse;
5153
import org.kohsuke.stapler.Ancestor;
@@ -157,9 +159,16 @@ public void doSuggestOpenSearch(StaplerRequest2 req, StaplerResponse2 rsp, @Quer
157159
*/
158160
public void doSuggest(StaplerRequest2 req, StaplerResponse2 rsp, @QueryParameter String query) throws IOException, ServletException {
159161
Result r = new Result();
160-
for (SuggestedItem item : getSuggestions(req, query))
161-
r.suggestions.add(new Item(item.getPath(), item.getUrl()));
162+
for (SuggestedItem item : getSuggestions(req, query)) {
163+
String symbolName = item.item.getSearchIcon();
162164

165+
if (symbolName == null || !symbolName.startsWith("symbol-")) {
166+
symbolName = "symbol-search";
167+
}
168+
169+
r.suggestions.add(new Item(item.getPath(), item.getUrl(), "",
170+
Symbol.get(new SymbolRequest.Builder().withRaw(symbolName).build())));
171+
}
163172
rsp.serveExposedBean(req, r, Flavor.JSON);
164173
}
165174

@@ -259,19 +268,35 @@ public static class Item {
259268

260269
private final String url;
261270

271+
public final String icon;
272+
273+
public final String iconXml;
274+
262275
public Item(String name) {
263-
this(name, null);
276+
this(name, null, null, null);
264277
}
265278

266-
public Item(String name, String url) {
279+
public Item(String name, String url, String icon, String iconXml) {
267280
this.name = name;
268281
this.url = url;
282+
this.icon = icon;
283+
this.iconXml = iconXml;
269284
}
270285

271286
@Exported
272287
public String getUrl() {
273288
return url;
274289
}
290+
291+
@Exported
292+
public String getIcon() {
293+
return icon;
294+
}
295+
296+
@Exported
297+
public String getIconXml() {
298+
return iconXml;
299+
}
275300
}
276301

277302
private enum Mode {

core/src/main/java/hudson/search/SearchItem.java

+9
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
package hudson.search;
2626

2727
import hudson.model.Build;
28+
import org.jenkins.ui.icon.IconSpec;
2829

2930
/**
3031
* Represents an item reachable from {@link SearchIndex}.
@@ -54,6 +55,14 @@ public interface SearchItem {
5455

5556
String getSearchUrl();
5657

58+
default String getSearchIcon() {
59+
if (this instanceof IconSpec) {
60+
return ((IconSpec) this).getIconClassName();
61+
}
62+
63+
return "symbol-search";
64+
}
65+
5766
/**
5867
* Returns the {@link SearchIndex} to further search sub items inside this item.
5968
*

core/src/main/java/jenkins/model/Jenkins.java

+24-3
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@
147147
import hudson.scm.RepositoryBrowser;
148148
import hudson.scm.SCM;
149149
import hudson.search.CollectionSearchIndex;
150+
import hudson.search.SearchIndex;
150151
import hudson.search.SearchIndexBuilder;
151152
import hudson.search.SearchItem;
152153
import hudson.security.ACL;
@@ -2345,9 +2346,29 @@ public String getSearchUrl() {
23452346
@Override
23462347
public SearchIndexBuilder makeSearchIndex() {
23472348
SearchIndexBuilder builder = super.makeSearchIndex();
2348-
if (hasPermission(ADMINISTER)) {
2349-
builder.add("manage", Messages.ManageJenkinsAction_DisplayName());
2350-
}
2349+
2350+
this.actions.stream().filter(e -> e.getIconFileName() != null).forEach(action -> builder.add(new SearchItem() {
2351+
@Override
2352+
public String getSearchName() {
2353+
return action.getDisplayName();
2354+
}
2355+
2356+
@Override
2357+
public String getSearchUrl() {
2358+
return action.getUrlName();
2359+
}
2360+
2361+
@Override
2362+
public String getSearchIcon() {
2363+
return action.getIconFileName();
2364+
}
2365+
2366+
@Override
2367+
public SearchIndex getSearchIndex() {
2368+
return SearchIndex.EMPTY;
2369+
}
2370+
}));
2371+
23512372
builder.add(new CollectionSearchIndex<TopLevelItem>() {
23522373
@Override
23532374
protected SearchItem get(String key) { return getItemByFullName(key, TopLevelItem.class); }

src/main/js/components/command-palette/datasources.js

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { LinkResult } from "./models";
22
import Search from "@/api/search";
3-
import * as Symbols from "./symbols";
43

54
export const JenkinsSearchSource = {
65
execute(query) {
@@ -18,7 +17,7 @@ export const JenkinsSearchSource = {
1817
rsp.json().then((data) => {
1918
return data["suggestions"].slice().map((e) =>
2019
LinkResult({
21-
icon: Symbols.SEARCH,
20+
icon: e.iconXml,
2221
label: e.name,
2322
url: correctAddress(e.url),
2423
}),

src/main/js/components/command-palette/index.js

+16-2
Original file line numberDiff line numberDiff line change
@@ -94,18 +94,23 @@ function init() {
9494
}
9595

9696
searchResultsContainer.style.height = searchResults.offsetHeight + "px";
97+
debouncedSpinner.cancel();
9798
commandPaletteSearchBarContainer.classList.remove(
9899
"jenkins-search--loading",
99100
);
100101
});
101102
}
102103

104+
const debouncedSpinner = debounce(() => {
105+
commandPaletteSearchBarContainer.classList.add("jenkins-search--loading");
106+
}, 150);
107+
103108
const debouncedLoad = debounce(() => {
104109
renderResults();
105110
}, 150);
106111

107112
commandPaletteInput.addEventListener("input", () => {
108-
commandPaletteSearchBarContainer.classList.add("jenkins-search--loading");
113+
debouncedSpinner();
109114
debouncedLoad();
110115
});
111116

@@ -119,7 +124,16 @@ function init() {
119124
}
120125

121126
function hideCommandPalette() {
122-
commandPalette.close();
127+
commandPalette.setAttribute("closing", "");
128+
129+
commandPalette.addEventListener(
130+
"animationend",
131+
() => {
132+
commandPalette.removeAttribute("closing");
133+
commandPalette.close();
134+
},
135+
{ once: true },
136+
);
123137
}
124138

125139
function itemMouseEnter(item) {

src/main/js/components/command-palette/symbols.js

-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/main/scss/components/_command-palette.scss

+49-24
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,5 @@
11
@use "../abstracts/mixins";
22

3-
.jenkins-command-palette__dialog {
4-
&::backdrop {
5-
background: var(--command-palette-backdrop-background);
6-
backdrop-filter: contrast(0.7) brightness(0.9) saturate(1.25) blur(3px);
7-
animation: jenkins-modal-backdrop-animate-in 0.3s;
8-
}
9-
}
10-
113
.jenkins-command-palette__dialog {
124
background: none;
135
border: none;
@@ -17,6 +9,41 @@
179
max-width: 100vw !important;
1810
margin: 0 !important;
1911
padding: 0 !important;
12+
user-select: none;
13+
14+
&::backdrop {
15+
background: var(--command-palette-backdrop-background);
16+
backdrop-filter: contrast(0.7) brightness(0.9) saturate(1.25) blur(3px);
17+
animation: jenkins-dialog-backdrop-animate-in 0.1s linear;
18+
}
19+
20+
&[open] {
21+
animation: command-palette-animate-in 0.1s cubic-bezier(0, 0.68, 0.5, 1.5);
22+
}
23+
24+
&[closing] {
25+
animation: command-palette-animate-out 0.1s linear;
26+
27+
&::backdrop {
28+
animation: jenkins-dialog-backdrop-animate-out 0.1s linear;
29+
}
30+
}
31+
}
32+
33+
@keyframes command-palette-animate-in {
34+
from {
35+
translate: 0 4px;
36+
scale: 98.5%;
37+
opacity: 0;
38+
transform: rotateX(30deg);
39+
}
40+
}
41+
42+
@keyframes command-palette-animate-out {
43+
to {
44+
scale: 98.5%;
45+
opacity: 0;
46+
}
2047
}
2148

2249
.jenkins-command-palette__wrapper {
@@ -40,9 +67,7 @@
4067
--search-bar-height: 3rem !important;
4168

4269
background: transparent;
43-
box-shadow:
44-
0 0 0 20px transparent,
45-
var(--command-palette-inset-shadow);
70+
box-shadow: var(--command-palette-inset-shadow);
4671
margin-bottom: 1.5rem;
4772
border-radius: 1rem;
4873
transition: var(--standard-transition);
@@ -71,7 +96,8 @@
7196
border-radius: 1rem;
7297
backdrop-filter: var(--command-palette-results-backdrop-filter);
7398
box-shadow: var(--command-palette-inset-shadow);
74-
height: 0;
99+
// If set to 0, Safari won't always show the backdrop-filter
100+
height: 1px;
75101
transition: height var(--standard-transition);
76102
overflow: hidden;
77103
will-change: height;
@@ -83,8 +109,8 @@
83109
padding: 0.5rem;
84110

85111
&__heading {
86-
font-weight: 600;
87-
font-size: 0.85rem;
112+
font-weight: 500;
113+
font-size: 0.875rem;
88114
margin: 0;
89115
padding: 0.75rem 0.75rem 0.625rem;
90116
color: var(--text-color-secondary);
@@ -113,8 +139,7 @@
113139
justify-content: flex-start;
114140
background: transparent;
115141
padding: 0.75rem;
116-
border-radius: 0.66rem;
117-
font-weight: 600;
142+
border-radius: 0.5rem;
118143
cursor: pointer;
119144
color: var(--text-color) !important;
120145
transition: var(--standard-transition);
@@ -132,17 +157,17 @@
132157
display: flex;
133158
align-items: center;
134159
justify-content: center;
135-
width: 1.4rem;
136-
height: 1.4rem;
137-
margin-right: 12.5px;
160+
width: 1.375rem;
161+
height: 1.375rem;
162+
margin-right: 0.75rem;
138163
overflow: hidden;
139164
pointer-events: none;
140165
color: var(--text-color);
141166

142167
svg,
143168
img {
144-
width: 1.2rem;
145-
height: 1.2rem;
169+
width: 1.25rem;
170+
height: 1.25rem;
146171
}
147172
}
148173

@@ -163,10 +188,10 @@
163188
}
164189

165190
&__info {
166-
font-weight: 600;
167-
font-size: 0.85rem;
191+
font-size: 0.875rem;
168192
margin: 0;
169-
padding: 12.5px 12.5px 10px;
193+
padding: 0 14px;
194+
line-height: 46px;
170195
color: var(--text-color);
171196

172197
span {
Loading

0 commit comments

Comments
 (0)