mirror of https://github.com/jenkinsci/jenkins.git
Update the design of notifications (#7049)
Co-authored-by: Tim Jacomb <timjacomb1@gmail.com> Co-authored-by: Tim Jacomb <21194782+timja@users.noreply.github.com> Co-authored-by: Alexander Brandes <mc.cache@web.de>
This commit is contained in:
parent
f04f407846
commit
42a4998045
|
@ -50,7 +50,7 @@ public class FormApply {
|
|||
public void generateResponse(StaplerRequest req, StaplerResponse rsp, Object node) throws IOException, ServletException {
|
||||
if (isApply(req)) {
|
||||
// if the submission is via 'apply', show a response in the notification bar
|
||||
applyResponse("notificationBar.show('" + Messages.HttpResponses_Saved() + "',notificationBar.OK)")
|
||||
applyResponse("notificationBar.show('" + Messages.HttpResponses_Saved() + "',notificationBar.SUCCESS)")
|
||||
.generateResponse(req, rsp, node);
|
||||
} else {
|
||||
rsp.sendRedirect(destination);
|
||||
|
|
|
@ -173,6 +173,7 @@ THE SOFTWARE.
|
|||
<script src="${resURL}/jsbundles/page-init.js" type="text/javascript"/>
|
||||
<!-- Sortable library used in drag & drop -->
|
||||
<script src="${resURL}/jsbundles/sortable-drag-drop.js" type="text/javascript"/>
|
||||
<script src="${resURL}/jsbundles/app.js" type="text/javascript" defer="true" />
|
||||
</head>
|
||||
<body id="jenkins" class="yui-skin-sam ${layoutType} jenkins-${h.version}" data-version="${h.version}" data-model-type="${it.class.name}">
|
||||
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
import Notifications from "@/components/notifications";
|
||||
|
||||
Notifications.init();
|
|
@ -0,0 +1,78 @@
|
|||
import * as Symbols from "@/util/symbols";
|
||||
import { createElementFromHtml } from "@/util/dom";
|
||||
|
||||
function init() {
|
||||
window.notificationBar = {
|
||||
OPACITY: 1,
|
||||
DELAY: 3000, // milliseconds to auto-close the notification
|
||||
div: null, // the main 'notification-bar' DIV
|
||||
token: null, // timer for cancelling auto-close
|
||||
defaultIcon: Symbols.INFO,
|
||||
defaultAlertClass: "jenkins-notification",
|
||||
|
||||
SUCCESS: {
|
||||
alertClass: "jenkins-notification jenkins-notification--success",
|
||||
icon: Symbols.SUCCESS,
|
||||
},
|
||||
WARNING: {
|
||||
alertClass: "jenkins-notification jenkins-notification--warning",
|
||||
icon: Symbols.WARNING,
|
||||
},
|
||||
ERROR: {
|
||||
alertClass: "jenkins-notification jenkins-notification--error",
|
||||
icon: Symbols.ERROR,
|
||||
sticky: true,
|
||||
},
|
||||
|
||||
init: function () {
|
||||
if (this.div == null) {
|
||||
this.div = document.createElement("div");
|
||||
this.div.id = "notification-bar";
|
||||
document.body.insertBefore(this.div, document.body.firstElementChild);
|
||||
const self = this;
|
||||
this.div.onclick = function () {
|
||||
self.hide();
|
||||
};
|
||||
} else {
|
||||
this.div.innerHTML = "";
|
||||
}
|
||||
},
|
||||
// cancel pending auto-hide timeout
|
||||
clearTimeout: function () {
|
||||
if (this.token) {
|
||||
window.clearTimeout(this.token);
|
||||
}
|
||||
this.token = null;
|
||||
},
|
||||
// hide the current notification bar, if it's displayed
|
||||
hide: function () {
|
||||
this.clearTimeout();
|
||||
this.div.classList.remove("jenkins-notification--visible");
|
||||
this.div.classList.add("jenkins-notification--hidden");
|
||||
},
|
||||
// show a notification bar
|
||||
show: function (text, options) {
|
||||
options = options || {};
|
||||
this.init();
|
||||
|
||||
this.div.appendChild(
|
||||
createElementFromHtml(options.icon || this.defaultIcon)
|
||||
);
|
||||
const message = this.div.appendChild(document.createElement("span"));
|
||||
message.appendChild(document.createTextNode(text));
|
||||
|
||||
this.div.className = options.alertClass || this.defaultAlertClass;
|
||||
this.div.classList.add("jenkins-notification--visible");
|
||||
|
||||
this.clearTimeout();
|
||||
const self = this;
|
||||
if (!options.sticky) {
|
||||
this.token = window.setTimeout(function () {
|
||||
self.hide();
|
||||
}, this.DELAY);
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export default { init };
|
|
@ -0,0 +1,4 @@
|
|||
export const INFO = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M256 56C145.72 56 56 145.72 56 256s89.72 200 200 200 200-89.72 200-200S366.28 56 256 56zm0 82a26 26 0 11-26 26 26 26 0 0126-26zm48 226h-88a16 16 0 010-32h28v-88h-16a16 16 0 010-32h32a16 16 0 0116 16v104h28a16 16 0 010 32z" fill='currentColor' /></svg>`;
|
||||
export const SUCCESS = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M256 48C141.31 48 48 141.31 48 256s93.31 208 208 208 208-93.31 208-208S370.69 48 256 48zm108.25 138.29l-134.4 160a16 16 0 01-12 5.71h-.27a16 16 0 01-11.89-5.3l-57.6-64a16 16 0 1123.78-21.4l45.29 50.32 122.59-145.91a16 16 0 0124.5 20.58z" fill='currentColor'/></svg>`;
|
||||
export const WARNING = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M449.07 399.08L278.64 82.58c-12.08-22.44-44.26-22.44-56.35 0L51.87 399.08A32 32 0 0080 446.25h340.89a32 32 0 0028.18-47.17zm-198.6-1.83a20 20 0 1120-20 20 20 0 01-20 20zm21.72-201.15l-5.74 122a16 16 0 01-32 0l-5.74-121.95a21.73 21.73 0 0121.5-22.69h.21a21.74 21.74 0 0121.73 22.7z" fill='currentColor'/></svg>`;
|
||||
export const ERROR = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M256 48C141.31 48 48 141.31 48 256s93.31 208 208 208 208-93.31 208-208S370.69 48 256 48zm0 319.91a20 20 0 1120-20 20 20 0 01-20 20zm21.72-201.15l-5.74 122a16 16 0 01-32 0l-5.74-121.94v-.05a21.74 21.74 0 1143.44 0z" fill='currentColor'/></svg>`;
|
|
@ -41,7 +41,7 @@
|
|||
|
||||
// Status icon colors
|
||||
--weather-icon-color: var(--primary);
|
||||
--unstable-build-icon-color: var(--notification-warning-icon-color);
|
||||
--unstable-build-icon-color: var(--orange);
|
||||
|
||||
// Background colors
|
||||
--background: var(--white);
|
||||
|
@ -76,31 +76,6 @@
|
|||
--breadcrumbs-text-color: #4d545d;
|
||||
--breadcrumbs-item-bg-color--hover: var(--light-grey);
|
||||
|
||||
// Alert banners
|
||||
// Default
|
||||
--alert-default-icon-color: #2196f3;
|
||||
--alert-default-bg-color: #d1ecf1;
|
||||
--alert-default-border-color: #bee5eb;
|
||||
--alert-default-color: #0c5464;
|
||||
|
||||
// Success
|
||||
--notification-success-icon-color: #4caf50;
|
||||
--notification-success-bg-color: #d4edda;
|
||||
--notification-success-border-color: #c3e6cb;
|
||||
--notification-success-color: var(--success);
|
||||
|
||||
// Warning
|
||||
--notification-warning-icon-color: #ff9800;
|
||||
--notification-warning-bg-color: #fff3cd;
|
||||
--notification-warning-border-color: #ffeeba;
|
||||
--notification-warning-color: #856404;
|
||||
|
||||
// Error
|
||||
--notification-error-icon-color: #f44336;
|
||||
--notification-error-bg-color: #f8d7da;
|
||||
--notification-error-border-color: #f5c6cb;
|
||||
--notification-error-color: #721c24;
|
||||
|
||||
// Alert call outs
|
||||
--alert-success-text-color: #155724;
|
||||
--alert-success-bg-color: #d4edda;
|
||||
|
|
|
@ -1170,96 +1170,7 @@ table.progress-bar.red td.progress-bar-done {
|
|||
background-color: #c00;
|
||||
}
|
||||
|
||||
/* ========================= notification bar ========================= */
|
||||
#notification-bar {
|
||||
width: 100%;
|
||||
position: fixed;
|
||||
text-align: center;
|
||||
left: 0;
|
||||
font-size: 1.75rem;
|
||||
z-index: 1000;
|
||||
border-bottom: 1px solid var(--black);
|
||||
line-height: 3.5rem;
|
||||
height: 3.5rem;
|
||||
display: block;
|
||||
will-change: opacity;
|
||||
}
|
||||
|
||||
#notification-bar .svg-icon {
|
||||
width: 35px;
|
||||
height: 35px;
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
|
||||
#notification-bar.notif-alert-default {
|
||||
background-color: var(--alert-default-bg-color);
|
||||
border-color: var(--alert-default-border-color);
|
||||
color: var(--alert-default-color);
|
||||
|
||||
.svg-icon {
|
||||
color: var(--alert-default-icon-color);
|
||||
}
|
||||
}
|
||||
|
||||
#notification-bar.notif-alert-success {
|
||||
background-color: var(--notification-success-bg-color);
|
||||
border-color: var(--notification-success-border-color);
|
||||
color: var(--notification-success-color);
|
||||
|
||||
.svg-icon {
|
||||
color: var(--notification-success-icon-color);
|
||||
}
|
||||
}
|
||||
|
||||
#notification-bar.notif-alert-warn {
|
||||
background-color: var(--notification-warning-bg-color);
|
||||
border-color: var(--notification-warning-border-color);
|
||||
color: var(--notification-warning-color);
|
||||
|
||||
.svg-icon {
|
||||
color: var(--notification-warning-icon-color);
|
||||
}
|
||||
}
|
||||
|
||||
#notification-bar.notif-alert-err {
|
||||
background-color: var(--notification-error-bg-color);
|
||||
border-color: var(--notification-error-border-color);
|
||||
color: var(--notification-error-color);
|
||||
|
||||
.svg-icon {
|
||||
color: var(--notification-error-icon-color);
|
||||
}
|
||||
}
|
||||
|
||||
#notification-bar.notif-alert-show {
|
||||
animation: fadein 350ms ease-out 1 normal forwards;
|
||||
}
|
||||
|
||||
#notification-bar.notif-alert-clear {
|
||||
animation: fadeout 350ms ease-in 1 normal forwards;
|
||||
}
|
||||
|
||||
@keyframes fadein {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeout {
|
||||
from {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
||||
/* Unknown */
|
||||
|
||||
@keyframes spin {
|
||||
from {
|
||||
|
|
|
@ -0,0 +1,124 @@
|
|||
.jenkins-notification {
|
||||
position: fixed;
|
||||
left: 1.2rem;
|
||||
bottom: 1.2rem;
|
||||
min-width: 321px;
|
||||
max-width: ~"min(600px, calc(100vw - 2.4rem))";
|
||||
display: grid;
|
||||
grid-template-columns: auto 1fr;
|
||||
grid-gap: 1.5ch;
|
||||
padding: 0.8rem;
|
||||
border-radius: 10px;
|
||||
font-weight: 500;
|
||||
line-height: 1.66;
|
||||
color: var(--text-color);
|
||||
box-shadow: 0 0 1px 1px rgba(darken(#024cb6, 50%), 0.075),
|
||||
0 10px 30px rgba(darken(#024cb6, 50%), 0.25), 0 0 30px 5px var(--background);
|
||||
will-change: opacity, transform;
|
||||
z-index: 999;
|
||||
cursor: pointer;
|
||||
transition: filter var(--standard-transition);
|
||||
backdrop-filter: brightness(2) blur(30px);
|
||||
|
||||
svg {
|
||||
width: 1.4rem;
|
||||
height: 1.4rem;
|
||||
}
|
||||
|
||||
&::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
border-radius: inherit;
|
||||
z-index: -1;
|
||||
background: var(--background);
|
||||
opacity: 0.3;
|
||||
}
|
||||
|
||||
@supports not (backdrop-filter: blur(15px)) {
|
||||
&::after {
|
||||
opacity: 0.9;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
filter: brightness(0.95);
|
||||
}
|
||||
|
||||
&:active {
|
||||
filter: brightness(0.9);
|
||||
}
|
||||
}
|
||||
|
||||
.jenkins-notification--success {
|
||||
color: var(--background);
|
||||
|
||||
&::after {
|
||||
background-color: var(--success-color);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.jenkins-notification--warning {
|
||||
color: var(--background);
|
||||
|
||||
&::after {
|
||||
background-color: var(--warning-color);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.jenkins-notification--error {
|
||||
color: var(--background);
|
||||
|
||||
&::after {
|
||||
background-color: var(--error-color);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.jenkins-notification--visible {
|
||||
animation: show-notification var(--elastic-transition) 1 normal forwards;
|
||||
|
||||
& > * {
|
||||
animation: show-notification-icon var(--elastic-transition) 1 normal
|
||||
forwards;
|
||||
}
|
||||
}
|
||||
|
||||
.jenkins-notification--hidden {
|
||||
animation: hide-notification 150ms ease-in 1 normal forwards;
|
||||
}
|
||||
|
||||
@keyframes show-notification {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(1.2rem);
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes show-notification-icon {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(0.3rem);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes hide-notification {
|
||||
from {
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 0;
|
||||
transform: scale(0.9);
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
|
@ -23,6 +23,7 @@
|
|||
@import url("./modules/buttons-deprecated");
|
||||
@import url("./modules/content-blocks");
|
||||
@import url("./modules/icons");
|
||||
@import url("./modules/notifications");
|
||||
@import url("./modules/page-footer");
|
||||
@import url("./modules/page-header");
|
||||
@import url("./modules/panes-and-bigtable");
|
||||
|
|
|
@ -2759,94 +2759,3 @@ var layoutUpdateCallback = {
|
|||
this.callbacks[i]();
|
||||
},
|
||||
};
|
||||
|
||||
// Notification bar
|
||||
// ==============================
|
||||
// this control displays a single line message at the top of the page, like StackOverflow does
|
||||
// see ui-samples for more details
|
||||
var notificationBar = {
|
||||
OPACITY: 1,
|
||||
DELAY: 3000, // milliseconds to auto-close the notification
|
||||
div: null, // the main 'notification-bar' DIV
|
||||
token: null, // timer for cancelling auto-close
|
||||
defaultIcon: "svg-sprite-action-symbol.svg#ic_info_24px",
|
||||
defaultAlertClass: "notif-alert-default",
|
||||
|
||||
OK: {
|
||||
// standard option values for typical OK notification
|
||||
icon: "svg-sprite-action-symbol.svg#ic_check_circle_24px",
|
||||
alertClass: "notif-alert-success",
|
||||
},
|
||||
WARNING: {
|
||||
// likewise, for warning
|
||||
icon: "svg-sprite-action-symbol.svg#ic_report_problem_24px",
|
||||
alertClass: "notif-alert-warn",
|
||||
},
|
||||
ERROR: {
|
||||
// likewise, for error
|
||||
icon: "svg-sprite-action-symbol.svg#ic_highlight_off_24px",
|
||||
alertClass: "notif-alert-err",
|
||||
sticky: true,
|
||||
},
|
||||
|
||||
init: function () {
|
||||
if (this.div == null) {
|
||||
this.div = document.createElement("div");
|
||||
YAHOO.util.Dom.setStyle(this.div, "opacity", 0);
|
||||
this.div.id = "notification-bar";
|
||||
document.body.insertBefore(this.div, document.body.firstElementChild);
|
||||
var self = this;
|
||||
this.div.onclick = function () {
|
||||
self.hide();
|
||||
};
|
||||
} else {
|
||||
this.div.innerHTML = "";
|
||||
}
|
||||
},
|
||||
// cancel pending auto-hide timeout
|
||||
clearTimeout: function () {
|
||||
if (this.token) window.clearTimeout(this.token);
|
||||
this.token = null;
|
||||
},
|
||||
// hide the current notification bar, if it's displayed
|
||||
hide: function () {
|
||||
this.clearTimeout();
|
||||
this.div.classList.remove("notif-alert-show");
|
||||
this.div.classList.add("notif-alert-clear");
|
||||
},
|
||||
// show a notification bar
|
||||
show: function (text, options) {
|
||||
options = options || {};
|
||||
this.init();
|
||||
var icon = this.div.appendChild(document.createElement("div"));
|
||||
icon.style.display = "inline-block";
|
||||
if (options.iconColor || this.defaultIconColor) {
|
||||
icon.style.color = options.iconColor || this.defaultIconColor;
|
||||
}
|
||||
var svg = icon.appendChild(
|
||||
document.createElementNS("http://www.w3.org/2000/svg", "svg")
|
||||
);
|
||||
svg.setAttribute("viewBox", "0 0 24 24");
|
||||
svg.setAttribute("focusable", "false");
|
||||
svg.setAttribute("class", "svg-icon");
|
||||
var use = svg.appendChild(
|
||||
document.createElementNS("http://www.w3.org/2000/svg", "use")
|
||||
);
|
||||
use.setAttribute(
|
||||
"href",
|
||||
rootURL + "/images/material-icons/" + (options.icon || this.defaultIcon)
|
||||
);
|
||||
var message = this.div.appendChild(document.createElement("span"));
|
||||
message.appendChild(document.createTextNode(text));
|
||||
|
||||
this.div.className = options.alertClass || this.defaultAlertClass;
|
||||
this.div.classList.add("notif-alert-show");
|
||||
|
||||
this.clearTimeout();
|
||||
var self = this;
|
||||
if (!options.sticky)
|
||||
this.token = window.setTimeout(function () {
|
||||
self.hide();
|
||||
}, this.DELAY);
|
||||
},
|
||||
};
|
||||
|
|
|
@ -30,6 +30,7 @@ module.exports = (env, argv) => ({
|
|||
path.join(__dirname, "src/main/js/config-tabbar.js"),
|
||||
path.join(__dirname, "src/main/js/config-tabbar.less"),
|
||||
],
|
||||
app: [path.join(__dirname, "src/main/js/app.js")],
|
||||
"keyboard-shortcuts": [
|
||||
path.join(__dirname, "src/main/js/keyboard-shortcuts.js"),
|
||||
],
|
||||
|
@ -178,6 +179,7 @@ module.exports = (env, argv) => ({
|
|||
},
|
||||
resolve: {
|
||||
alias: {
|
||||
"@": path.resolve(__dirname, "src/main/js"),
|
||||
// Needed to be able to register helpers at runtime
|
||||
handlebars: "handlebars/runtime",
|
||||
},
|
||||
|
|
Loading…
Reference in New Issue