Browse Source

bring back popup panel access from logger

Popup panel is now tab selector-bound, rather than logger
entry-bound.

Additonally, start migrating toward svg-based icons rather than
font-based icons.
pull/2/head
Raymond Hill 6 years ago
parent
commit
c6e29be792
No known key found for this signature in database GPG Key ID: 25E1490B761470C2
  1. 18
      src/css/common.css
  2. 135
      src/css/logger-ui.css
  3. 34
      src/img/fontawesome/LICENSE.txt
  4. 16
      src/img/fontawesome/fontawesome-defs.svg
  5. 168
      src/js/logger-ui.js
  6. 24
      src/logger-ui.html

18
src/css/common.css

@ -30,6 +30,24 @@
vertical-align: baseline;
display: inline-block;
}
.fa-icon {
align-self: center;
background-color: transparent;
border: border: 1px solid transparent;
display: inline-block;
height: 1.2em;
vertical-align: middle;
width: 1.2em;
}
.fa-icon:hover {
background-color: #eee;
}
.fa-icon.disabled {
fill: #888;
opacity: 0.4;
stroke: #fff;
pointer-events: none;
}
body {
font-size: 14px;

135
src/css/logger-ui.css

@ -9,6 +9,12 @@ body {
padding: 0;
width: 100%;
}
.fa-icon {
cursor: pointer;
height: 1.5em;
padding: 0.5em 1em;
width: 1.5em;
}
#toolbar {
background-color: white;
border: 0;
@ -23,42 +29,73 @@ body {
width: 100%;
z-index: 10;
}
#toolbar .button {
background-color: white;
border: none;
box-sizing: border-box;
-moz-box-sizing: border-box;
cursor: pointer;
display: inline-block;
font-size: 150%;
margin: 0;
padding: 8px;
}
#toolbar .button.disabled {
opacity: 0.2;
pointer-events: none;
}
#toolbar .button:hover {
background-color: #eee;
}
#toolbar > div {
display: flex;
padding: 0.5em;
white-space: nowrap;
}
#toolbar > div:first-of-type {
font-size: 120%;
}
#toolbar > div > * {
vertical-align: middle;
}
#pageSelector {
width: 28em;
margin-right: 0.5em;
padding: 0.2em 0;
}
body #compactViewToggler.button:before {
content: '\f102';
@keyframes popupPanelShow {
from { opacity: 0; }
to { opacity: 1; }
}
#popupPanelContainer {
background: white;
border: 1px solid gray;
display: none;
overflow: hidden;
position: fixed;
right: 0;
/*top: 0;*/
z-index: 2000;
}
body.popupPanelOn #popupPanelContainer {
animation-duration: 0.25s;
animation-name: popupPanelShow;
display: block;
}
#popupPanelContainer.hide {
width: 6em !important;
}
#popupPanelContainer > div {
background: #888;
border: 0;
display: none;
text-align: right;
}
#popupPanelContainer > div > span {
color: #ccc;
cursor: pointer;
display: inline-block;
font: 14px FontAwesome;
padding: 3px;
}
#popupPanelContainer > div > span:hover {
color: white;
}
#popupPanelContainer > iframe {
border: 0;
padding: 0;
margin: 0;
width: 100%;
}
#popupPanelContainer.hide > iframe {
display: none;
}
#popupPanelButton > use {
transform: scaleY(0.4);
}
body.compactView #compactViewToggler.button:before {
content: '\f103';
body.popupPanelOn #popupPanelButton > use {
transform: scaleY(1);
}
body.compactView #compactViewToggler {
transform: rotateZ(180deg);
}
#filterButton {
opacity: 0.25;
@ -189,7 +226,7 @@ body.compactView #content tr:not(.vExpanded) td {
position: fixed;
top: 0;
width: 100vw;
z-index: 1000;
z-index: 5000;
}
.modalDialog > .dialog {
background-color: white;
@ -218,46 +255,20 @@ body.compactView #content tr:not(.vExpanded) td {
justify-content: space-around;
margin-left: 0.5em;
}
.ruleEditorToolbar button {
background-color: white;
border: 0;
color: black;
cursor: pointer;
margin: 0;
padding: 0.2em;
position: relative;
}
.ruleEditorToolbar button:hover {
background-color: #eee;
}
.ruleEditorToolbar button.disabled {
color: #ccc;
}
.ruleEditorToolbar button.fa {
font: 1.7em FontAwesome;
min-width: 1.5em;
}
.ruleEditorToolbar button > span.badge {
background-color: rgba(240,240,240,0.75);
bottom: 1px;
color: #000;
display: inline-block;
.ruleEditorToolbar .fa-icon > .badge {
font-family: sans-serif;
font-size: 40%;
padding: 1px 1px;
font-size: 80%;
pointer-events: none;
position: absolute;
right: 1px;
}
.ruleEditorToolbar button.disabled > span.badge {
.ruleEditorToolbar .fa-icon.disabled > .badge {
display: none;
}
button.scopeRel {
color: #24c;
.fa-icon.scopeRel {
fill: #24c;
}
body[data-scope="*"] button.scopeRel {
color: #000;
body[data-scope="*"] .fa-icon.scopeRel {
fill: #000;
}
.ruleWidgets {

34
src/img/fontawesome/LICENSE.txt

@ -0,0 +1,34 @@
Font Awesome Free License
-------------------------
Font Awesome Free is free, open source, and GPL friendly. You can use it for
commercial projects, open source projects, or really almost whatever you want.
Full Font Awesome Free license: https://fontawesome.com/license/free.
# Icons: CC BY 4.0 License (https://creativecommons.org/licenses/by/4.0/)
In the Font Awesome Free download, the CC BY 4.0 license applies to all icons
packaged as SVG and JS file types.
# Fonts: SIL OFL 1.1 License (https://scripts.sil.org/OFL)
In the Font Awesome Free download, the SIL OLF license applies to all icons
packaged as web and desktop font files.
# Code: MIT License (https://opensource.org/licenses/MIT)
In the Font Awesome Free download, the MIT license applies to all non-font and
non-icon files.
# Attribution
Attribution is required by MIT, SIL OLF, and CC BY licenses. Downloaded Font
Awesome Free files already contain embedded comments with sufficient
attribution, so you shouldn't need to do anything additional when using these
files normally.
We've kept attribution comments terse, so we ask that you do not actively work
to remove them from files, especially code. They're a great way for folks to
learn about Font Awesome.
# Brand Icons
All brand icons are trademarks of their respective owners. The use of these
trademarks does not indicate endorsement of the trademark holder by Font
Awesome, nor vice versa. **Please do not use brand logos for any purpose except
to represent the company, product, or service to which they refer.**

16
src/img/fontawesome/fontawesome-defs.svg

@ -0,0 +1,16 @@
<!--
Font Awesome Free 5.3.1 by @fontawesome - https://fontawesome.com
License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
-->
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="display: none;">
<defs>
<symbol id="fa-icon_angle-double-down" viewBox="0 0 320 512"><path d="M143 256.3L7 120.3c-9.4-9.4-9.4-24.6 0-33.9l22.6-22.6c9.4-9.4 24.6-9.4 33.9 0l96.4 96.4 96.4-96.4c9.4-9.4 24.6-9.4 33.9 0L313 86.3c9.4 9.4 9.4 24.6 0 33.9l-136 136c-9.4 9.5-24.6 9.5-34 .1zm34 192l136-136c9.4-9.4 9.4-24.6 0-33.9l-22.6-22.6c-9.4-9.4-24.6-9.4-33.9 0L160 352.1l-96.4-96.4c-9.4-9.4-24.6-9.4-33.9 0L7 278.3c-9.4 9.4-9.4 24.6 0 33.9l136 136c9.4 9.5 24.6 9.5 34 .1z"/></symbol>
<symbol id="fa-icon_angle-double-up" viewBox="0 0 320 512"><path d="M177 255.7l136 136c9.4 9.4 9.4 24.6 0 33.9l-22.6 22.6c-9.4 9.4-24.6 9.4-33.9 0L160 351.9l-96.4 96.4c-9.4 9.4-24.6 9.4-33.9 0L7 425.7c-9.4-9.4-9.4-24.6 0-33.9l136-136c9.4-9.5 24.6-9.5 34-.1zm-34-192L7 199.7c-9.4 9.4-9.4 24.6 0 33.9l22.6 22.6c9.4 9.4 24.6 9.4 33.9 0l96.4-96.4 96.4 96.4c9.4 9.4 24.6 9.4 33.9 0l22.6-22.6c9.4-9.4 9.4-24.6 0-33.9l-136-136c-9.2-9.4-24.4-9.4-33.8 0z"/></symbol>
<symbol id="fa-icon_eraser" viewBox="0 0 512 512"><path d="M497.941 273.941c18.745-18.745 18.745-49.137 0-67.882l-160-160c-18.745-18.745-49.136-18.746-67.883 0l-256 256c-18.745 18.745-18.745 49.137 0 67.882l96 96A48.004 48.004 0 0 0 144 480h356c6.627 0 12-5.373 12-12v-40c0-6.627-5.373-12-12-12H355.883l142.058-142.059zm-302.627-62.627l137.373 137.373L265.373 416H150.628l-80-80 124.686-124.686z"/></symbol>
<symbol id="fa-icon_filter" viewBox="0 0 512 512"><path d="M487.976 0H24.028C2.71 0-8.047 25.866 7.058 40.971L192 225.941V432c0 7.831 3.821 15.17 10.237 19.662l80 55.98C298.02 518.69 320 507.493 320 487.98V225.941l184.947-184.97C520.021 25.896 509.338 0 487.976 0z"/></symbol>
<symbol id="fa-icon_lock" viewBox="0 0 448 512"><path d="M400 224h-24v-72C376 68.2 307.8 0 224 0S72 68.2 72 152v72H48c-26.5 0-48 21.5-48 48v192c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48V272c0-26.5-21.5-48-48-48zm-104 0H152v-72c0-39.7 32.3-72 72-72s72 32.3 72 72v72z"/></symbol>
<symbol id="fa-icon_sync-alt" viewBox="0 0 512 512"><path d="M370.72 133.28C339.458 104.008 298.888 87.962 255.848 88c-77.458.068-144.328 53.178-162.791 126.85-1.344 5.363-6.122 9.15-11.651 9.15H24.103c-7.498 0-13.194-6.807-11.807-14.176C33.933 94.924 134.813 8 256 8c66.448 0 126.791 26.136 171.315 68.685L463.03 40.97C478.149 25.851 504 36.559 504 57.941V192c0 13.255-10.745 24-24 24H345.941c-21.382 0-32.09-25.851-16.971-40.971l41.75-41.749zM32 296h134.059c21.382 0 32.09 25.851 16.971 40.971l-41.75 41.75c31.262 29.273 71.835 45.319 114.876 45.28 77.418-.07 144.315-53.144 162.787-126.849 1.344-5.363 6.122-9.15 11.651-9.15h57.304c7.498 0 13.194 6.807 11.807 14.176C478.067 417.076 377.187 504 256 504c-66.448 0-126.791-26.136-171.315-68.685L48.97 471.03C33.851 486.149 8 475.441 8 454.059V320c0-13.255 10.745-24 24-24z"/></symbol>
<symbol id="fa-icon_th" viewBox="0 0 512 512"><path d="M149.333 56v80c0 13.255-10.745 24-24 24H24c-13.255 0-24-10.745-24-24V56c0-13.255 10.745-24 24-24h101.333c13.255 0 24 10.745 24 24zm181.334 240v-80c0-13.255-10.745-24-24-24H205.333c-13.255 0-24 10.745-24 24v80c0 13.255 10.745 24 24 24h101.333c13.256 0 24.001-10.745 24.001-24zm32-240v80c0 13.255 10.745 24 24 24H488c13.255 0 24-10.745 24-24V56c0-13.255-10.745-24-24-24H386.667c-13.255 0-24 10.745-24 24zm-32 80V56c0-13.255-10.745-24-24-24H205.333c-13.255 0-24 10.745-24 24v80c0 13.255 10.745 24 24 24h101.333c13.256 0 24.001-10.745 24.001-24zm-205.334 56H24c-13.255 0-24 10.745-24 24v80c0 13.255 10.745 24 24 24h101.333c13.255 0 24-10.745 24-24v-80c0-13.255-10.745-24-24-24zM0 376v80c0 13.255 10.745 24 24 24h101.333c13.255 0 24-10.745 24-24v-80c0-13.255-10.745-24-24-24H24c-13.255 0-24 10.745-24 24zm386.667-56H488c13.255 0 24-10.745 24-24v-80c0-13.255-10.745-24-24-24H386.667c-13.255 0-24 10.745-24 24v80c0 13.255 10.745 24 24 24zm0 160H488c13.255 0 24-10.745 24-24v-80c0-13.255-10.745-24-24-24H386.667c-13.255 0-24 10.745-24 24v80c0 13.255 10.745 24 24 24zM181.333 376v80c0 13.255 10.745 24 24 24h101.333c13.255 0 24-10.745 24-24v-80c0-13.255-10.745-24-24-24H205.333c-13.255 0-24 10.745-24 24z"/></symbol>
<symbol id="fa-icon_times" viewBox="0 0 352 512"><path d="M242.72 256l100.07-100.07c12.28-12.28 12.28-32.19 0-44.48l-22.24-22.24c-12.28-12.28-32.19-12.28-44.48 0L176 189.28 75.93 89.21c-12.28-12.28-32.19-12.28-44.48 0L9.21 111.45c-12.28 12.28-12.28 32.19 0 44.48L109.28 256 9.21 356.07c-12.28 12.28-12.28 32.19 0 44.48l22.24 22.24c12.28 12.28 32.2 12.28 44.48 0L176 322.72l100.07 100.07c12.28 12.28 32.2 12.28 44.48 0l22.24-22.24c12.28-12.28 12.28-32.19 0-44.48L242.72 256z"/></symbol>
</defs>
</svg>

168
src/js/logger-ui.js

@ -537,32 +537,39 @@ var readLogBufferAsync = function() {
/******************************************************************************/
var tabIdFromPageSelector = function() {
let tabId = parseInt(document.getElementById('pageSelector').value, 10);
return isNaN(tabId) === false ? tabId : 0;
};
var pageSelectorChanged = function() {
let style = document.getElementById('tabFilterer');
let tabId = document.getElementById('pageSelector').value;
let tabId = tabIdFromPageSelector();
let sheet = style.sheet;
while ( sheet.cssRules.length !== 0 ) {
sheet.deleteRule(0);
}
if ( tabId.length !== 0 ) {
if ( tabId !== 0 ) {
sheet.insertRule(
'#content table tr:not([data-tabid="' + tabId + '"]) { display: none; }',
0
);
}
uDom('#refresh').toggleClass('disabled', /^\d+$/.test(tabId) === false);
document.getElementById('reloadTab').classList.toggle('disabled', tabId <= 0);
document.getElementById('popupPanelButton').classList.toggle('disabled', tabId === 0);
popupPanel.update();
};
/******************************************************************************/
var reloadTab = function(ev) {
let tabId = document.getElementById('pageSelector').value;
if ( /^\d+$/.test(tabId) === false ) { return; }
let tabId = tabIdFromPageSelector();
if ( tabId <= 0 ) { return; }
vAPI.messaging.send(
'default',
{
what: 'forceReloadTab',
tabId: parseInt(tabId, 10),
tabId: tabId,
bypassCache: ev && (ev.ctrlKey || ev.metaKey || ev.shiftKey)
}
);
@ -592,6 +599,135 @@ var onMaxEntriesChanged = function() {
/******************************************************************************/
var popupPanel = (function() {
let tabId = 0;
let popupObserver = null;
let timer;
let resizePopup = function() {
if ( timer !== undefined ) {
cancelAnimationFrame(timer);
timer = undefined;
}
let container = document.getElementById('popupPanelContainer');
let popup = container.querySelector('iframe');
if ( popup === null ) { return; }
let popupBody = popup.contentWindow.document.body;
if (
popupBody.clientWidth !== 0 &&
container.clientWidth !== popupBody.clientWidth
) {
container.style.setProperty('width', popupBody.clientWidth + 'px');
}
popup.style.removeProperty('height');
if (
popupBody.clientHeight !== 0 &&
popup.clientHeight !== popupBody.clientHeight
) {
popup.style.setProperty('height', popupBody.clientHeight + 'px');
}
let ph = document.documentElement.clientHeight;
let crect = container.getBoundingClientRect();
if ( crect.height > ph ) {
popup.style.setProperty('height', 'calc(' + ph + 'px - 1.8em)');
}
// Adjust width for presence/absence of vertical scroll bar which may
// have appeared as a result of last operation.
let cw = container.clientWidth;
let dw = popup.contentWindow.document.documentElement.clientWidth;
if ( cw !== dw ) {
container.style.setProperty('width', 2 * cw - dw + 'px');
}
};
let onResizeRequested = function() {
let popup = document.querySelector('#popupPanelContainer iframe');
if ( popup === null ) { return; }
let popupBody = popup.contentWindow.document.body;
if ( popupBody.hasAttribute('data-resize-popup') === false ) { return; }
popupBody.removeAttribute('data-resize-popup');
if ( timer === undefined ) {
timer = requestAnimationFrame(( ) => {
timer = undefined;
resizePopup();
});
}
};
let onLoad = function() {
resizePopup();
let popup = document.querySelector('#popupPanelContainer iframe');
if ( popup === null ) { return; }
let popupBody = popup.contentDocument.body;
popupBody.removeAttribute('data-resize-popup');
if ( popupObserver === null ) {
popupObserver = new MutationObserver(onResizeRequested);
}
popupObserver.observe(popupBody, {
attributes: true,
attributesFilter: [ 'data-resize-popup' ]
});
document.body.classList.add('popupPanelOn');
};
let start = function() {
let newTabId = tabIdFromPageSelector();
if ( newTabId === 0 ) {
return stop();
}
if ( newTabId === tabId ) { return; }
tabId = newTabId;
let container = document.getElementById('popupPanelContainer');
let popup = container.querySelector('iframe');
if ( popup === null ) {
popup = document.createElement('iframe');
popup.addEventListener('load', onLoad);
}
if ( popupObserver !== null ) {
popupObserver.disconnect();
}
popup.setAttribute('src', 'popup.html?tabId=' + tabId);
if ( popup.parentNode === null ) {
container.appendChild(popup);
}
};
let stop = function() {
document.body.classList.remove('popupPanelOn');
popupObserver.disconnect();
popupObserver = null;
let popup = document.querySelector('#popupPanelContainer iframe');
if ( popup !== null ) {
popup.removeEventListener('load', onLoad);
removeSelf(popup);
}
tabId = 0;
};
return {
get tabId() {
return tabId;
},
toggle: function(state) {
if ( state === undefined ) {
state = tabId === 0;
}
if ( state === false ) {
stop();
} else {
start();
}
},
update: function() {
if ( tabId !== 0 ) {
start();
}
}
};
})();
/******************************************************************************/
var rowFilterer = (function() {
var filters = [];
@ -728,7 +864,6 @@ var rowFilterer = (function() {
};
})();
/******************************************************************************/
/******************************************************************************/
var ruleEditor = (function() {
@ -817,9 +952,9 @@ var ruleEditor = (function() {
addListener(ruleWidgets, 'mouseenter', attachRulePicker, 0b11);
addListener(ruleWidgets, 'mouseleave', removeRulePicker, 0b11);
addListener(ruleActionPicker, 'click', rulePickerHandler, 0b11);
addListener(ruleEditorNode.querySelector('.buttonReload'), 'click', reload);
addListener(ruleEditorNode.querySelector('.buttonRevertScope'), 'click', revert);
addListener(ruleEditorNode.querySelector('.buttonPersist'), 'click', persist);
addListener(ruleEditorNode.querySelector('#matrixReloadButton'), 'click', reload);
addListener(ruleEditorNode.querySelector('#matrixRevertButton'), 'click', revert);
addListener(ruleEditorNode.querySelector('#matrixPersistButton'), 'click', persist);
document.body.appendChild(ruleEditorNode);
};
@ -854,14 +989,14 @@ var ruleEditor = (function() {
}
let dirty = diffCount !== 0;
ruleEditorNode
.querySelector('.buttonPersist .badge')
.querySelector('#matrixPersistButton .badge')
.textContent = dirty ? diffCount : '';
ruleEditorNode
.querySelector('.buttonRevertScope')
.querySelector('#matrixRevertButton')
.classList
.toggle('disabled', !dirty);
ruleEditorNode
.querySelector('.buttonPersist')
.querySelector('#matrixPersistButton')
.classList
.toggle('disabled', !dirty);
}
@ -1000,7 +1135,9 @@ var ruleEditor = (function() {
node.removeEventListener(type, handler, options);
}
listeners = [];
ruleEditorNode.querySelector('.buttonReload').removeEventListener('click', reload);
ruleEditorNode
.querySelector('#matrixReloadButton')
.removeEventListener('click', reload);
removeSelf(ruleEditorNode);
};
@ -1080,7 +1217,8 @@ window.addEventListener('beforeunload', releaseView);
readLogBuffer();
uDom('#pageSelector').on('change', pageSelectorChanged);
uDom('#refresh').on('click', reloadTab);
uDom('#reloadTab').on('click', reloadTab);
uDom('#popupPanelButton').on('click', ( ) => popupPanel.toggle());
uDom('#compactViewToggler').on('click', toggleCompactView);
uDom('#clean').on('click', cleanBuffer);
uDom('#clear').on('click', clearBuffer);

24
src/logger-ui.html

@ -15,19 +15,23 @@
<div>
<select id="pageSelector">
<option value="" data-i18n="statsPageDetailedAllPages">
<option value="tab_bts" data-i18n="statsPageDetailedBehindTheScenePage">
<option value="-1" data-i18n="statsPageDetailedBehindTheScenePage">
</select>
<span id="refresh" class="button disabled fa">&#xf021;</span>
<svg id="reloadTab" class="fa-icon disabled"><use xlink:href="/img/fontawesome/fontawesome-defs.svg#fa-icon_sync-alt"></use></svg>
<svg id="popupPanelButton" class="fa-icon disabled"><use xlink:href="/img/fontawesome/fontawesome-defs.svg#fa-icon_th"></use></svg>
</div>
<div>
<span id="compactViewToggler" class="button fa"></span>
<span id="clean" class="button fa disabled">&#xf00d;</span>
<span id="clear" class="button fa disabled">&#xf12d;</span>
<span id="filterButton" class="button fa">&#xf0b0;</span><input id="filterInput" type="text" placeholder="loggerFilterInputPlaceholder">
<svg id="compactViewToggler" class="fa-icon"><use xlink:href="/img/fontawesome/fontawesome-defs.svg#fa-icon_angle-double-up"></use></svg>
<svg id="clean" class="fa-icon disabled"><use xlink:href="/img/fontawesome/fontawesome-defs.svg#fa-icon_times"></use></svg>
<svg id="clear" class="fa-icon disabled"><use xlink:href="/img/fontawesome/fontawesome-defs.svg#fa-icon_eraser"></use></svg>
<svg id="filterButton" class="fa-icon"><use xlink:href="/img/fontawesome/fontawesome-defs.svg#fa-icon_filter"></use></svg>
<input id="filterInput" type="text" placeholder="loggerFilterInputPlaceholder">
<input id="maxEntries" type="text" size="5" title="loggerMaxEntriesTip">
</div>
</div>
<div id="popupPanelContainer"></div>
<div id="content">
<style id="tabFilterer"></style>
<table>
@ -36,8 +40,6 @@
</table>
</div>
<div style="display: none;">
<div id="emphasizeTemplate"><span><span></span><b></b><span></span></span></div>
<div id="hiddenTemplate"><span style="display:none;"></span></div>
@ -47,14 +49,14 @@
<span class="scope" id="specificScope"><span>&nbsp;</span></span><!--
--><span class="scope" id="globalScope" data-scope="*" data-i18n-tip="matrixGlobalScopeTip"><span><span>&#x2217;</span></span></span>
<div class="ruleEditorToolbar">
<button type="button" class="buttonReload fa tip-anchor-right" data-i18n-tip="matrixReloadButton">&#xf021;</button>
<svg id="matrixReloadButton" class="fa-icon" tip-anchor-right data-i18n-tip="matrixReloadButton"><use xlink:href="/img/fontawesome/fontawesome-defs.svg#fa-icon_sync-alt"></use></svg>
</div>
</section>
<section>
<div class="ruleWidgets"></div>
<div class="ruleEditorToolbar">
<button type="button" class="buttonRevertScope fa scopeRel tip-anchor-right" tabindex="-1" data-i18n-tip="matrixRevertButtonTip">&#xf12d;</button>
<button type="button" class="buttonPersist fa scopeRel tip-anchor-right" data-i18n-tip="matrixPersistButtonTip">&#xf023;<span class="badge"></span></button>
<svg id="matrixRevertButton" class="fa-icon scopeRel" tip-anchor-right data-i18n-tip="matrixRevertButtonTip"><use xlink:href="/img/fontawesome/fontawesome-defs.svg#fa-icon_eraser"></use></svg>
<svg id="matrixPersistButton" class="fa-icon scopeRel" tip-anchor-right data-i18n-tip="matrixPersistButtonTip"><use xlink:href="/img/fontawesome/fontawesome-defs.svg#fa-icon_lock"></use><text class="badge" x="100%" y="100%"></text></svg>
</section>
</section>
</div>

Loading…
Cancel
Save