mirror of
https://github.com/Ylianst/MeshCentral.git
synced 2025-02-12 02:51:50 +00:00
UI Toggle between Classic and Modern (#6763)
* [ENH] Add toggle switch for new MeshCentral UI in settings and top header of the classic UI * [ENH] Add toggle for new MeshCentral UI in settings and in top headbar of the modern UI * add showModernUIToggle and store uiviewmode in db --------- Co-authored-by: kambereBr <brunokambere@gmail.com>
This commit is contained in:
parent
1310c57397
commit
5734bcc33a
7 changed files with 114 additions and 4 deletions
|
@ -1173,6 +1173,11 @@
|
|||
"default": 2,
|
||||
"description": "Valid numbers are 1 and 2, changes the style of the login page and some secondary pages."
|
||||
},
|
||||
"showModernUIToggle": {
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"description": "When set to true, the user will be able to toggle between the modern and classic UI."
|
||||
},
|
||||
"title": {
|
||||
"type": "string",
|
||||
"default": "MeshCentral",
|
||||
|
|
|
@ -266,6 +266,16 @@ body {
|
|||
right: 3px;
|
||||
}
|
||||
|
||||
.textnewui {
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
padding-top: 5px;
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.LogoffLinkColor {
|
||||
color:white;
|
||||
}
|
||||
|
@ -2877,7 +2887,7 @@ nav .lbbuttonsel2 {
|
|||
width: 28px;
|
||||
}
|
||||
|
||||
.viewSelector3 {
|
||||
.viewSelector3, .uiSelector7 {
|
||||
margin-left: 2px;
|
||||
margin-top: 2px;
|
||||
background: url(../images/views.png) -56px 0px;
|
||||
|
@ -2977,6 +2987,13 @@ nav .lbbuttonsel2 {
|
|||
background-color: #AAA;
|
||||
}
|
||||
|
||||
.uiSelector_end {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
float: left;
|
||||
margin: 3px;
|
||||
}
|
||||
|
||||
.uiSelectorSel {
|
||||
background-color: #BBB;
|
||||
opacity: 0.8;
|
||||
|
|
|
@ -263,6 +263,16 @@ body {
|
|||
right: 3px;
|
||||
}
|
||||
|
||||
.textnewui {
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
padding-top: 5px;
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.LogoffLinkColor {
|
||||
color:white;
|
||||
}
|
||||
|
@ -2896,7 +2906,7 @@ a {
|
|||
width: 28px;
|
||||
}
|
||||
|
||||
.viewSelector3 {
|
||||
.viewSelector3, .uiSelector7 {
|
||||
margin-left: 2px;
|
||||
margin-top: 2px;
|
||||
background: url(../images/views.png) -56px 0px;
|
||||
|
@ -2996,6 +3006,13 @@ a {
|
|||
background-color: #AAA;
|
||||
}
|
||||
|
||||
.uiSelector_end {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
float: left;
|
||||
margin: 3px;
|
||||
}
|
||||
|
||||
.uiSelectorSel {
|
||||
background-color: #BBB;
|
||||
opacity: 0.8;
|
||||
|
|
|
@ -186,6 +186,7 @@
|
|||
"domains": {
|
||||
"": {
|
||||
"_siteStyle": 2,
|
||||
"_showModernUIToggle": true,
|
||||
"title": "MyServer",
|
||||
"title2": "Servername",
|
||||
"_titlePicture": "title-sample.png",
|
||||
|
|
|
@ -164,6 +164,9 @@
|
|||
<div id=notificationCount onclick="clickNotificationIcon()" class="unselectable" style="display: none;" title="Click to view current notifications">0</div>
|
||||
</div>
|
||||
<p id="logoutControl"><span id=logoutControlSpan class="logoncontrolspan"></span><span id=idleTimeoutNotify style="color:yellow"></span></p>
|
||||
<div class=textnewui id=textnewui onmouseup=toggleBootstrapUIMode() onkeypress="if (event.key=='Enter') { toggleBootstrapUIMode(); }">
|
||||
<b>Try the new MeshCentral UI</b>
|
||||
</div>
|
||||
</div>
|
||||
<div id="page_leftbar">
|
||||
<div style="height:16px"></div>
|
||||
|
@ -199,11 +202,13 @@
|
|||
<div tabindex=0 id=uiViewButton1 class=uiSelector onclick=userInterfaceSelectMenu(1) title="Left bar interface" onkeypress="if (event.key == 'Enter') userInterfaceSelectMenu(1)"><div class="uiSelector1"></div></div>
|
||||
<div tabindex=0 id=uiViewButton2 class=uiSelector onclick=userInterfaceSelectMenu(2) title="Top bar interface" onkeypress="if (event.key == 'Enter') userInterfaceSelectMenu(2)"><div class="uiSelector2"></div></div>
|
||||
<div tabindex=0 id=uiViewButton3 class=uiSelector onclick=userInterfaceSelectMenu(3) title="Fixed width interface" onkeypress="if (event.key == 'Enter') userInterfaceSelectMenu(3)"><div class="uiSelector3"></div></div>
|
||||
<div tabindex=0 id=uiViewButton7 class=uiSelector onclick=toggleBootstrapUIMode() title="Toggle Bootstrap UI" onkeypress="if (event.key == 'Enter') toggleBootstrapUIMode()"><div class="uiSelector7"></div></div>
|
||||
</td>
|
||||
<td>
|
||||
<div tabindex=0 id=uiViewButton6 class=uiSelector onclick="showNotes(false)" title="Personal Notes" onkeypress="if (event.key == 'Enter') showNotes(false)"><div class="uiSelector6"></div></div>
|
||||
<div tabindex=0 id=uiViewButton4 class=uiSelector onclick=toggleNightMode() title="Toggle night mode" onkeypress="if (event.key == 'Enter') toggleNightMode()"><div class="uiSelector4"></div></div>
|
||||
<div tabindex=0 id=uiViewButton5 class=uiSelector onclick=toggleFooterBarMode() title="Toggle footer bar" onkeypress="if (event.key == 'Enter') toggleFooterBarMode()"><div class="uiSelector5"></div></div>
|
||||
<div class=uiSelector_end> </div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
@ -1723,6 +1728,9 @@
|
|||
});
|
||||
}
|
||||
|
||||
// Show the modern ui switcher
|
||||
QV('textnewui', ((features2 & 0x40000000) == 0) ? false : true);
|
||||
|
||||
// Connect to the mesh server
|
||||
meshserver = MeshServerCreateControl(domainUrl);
|
||||
meshserver.onStateChanged = onStateChanged;
|
||||
|
@ -2183,6 +2191,24 @@
|
|||
QV('body', true);
|
||||
}
|
||||
|
||||
function saveUserInterfaceMode() {
|
||||
var nUiViewMode = 2;
|
||||
if (Q('ui1').checked) { nUiViewMode = 3; }
|
||||
if (getstore('uiViewMode', 2) != nUiViewMode) {
|
||||
putstore('uiViewMode', nUiViewMode);
|
||||
reload();
|
||||
}
|
||||
}
|
||||
|
||||
function toggleBootstrapUIMode() {
|
||||
if (xxdialogMode) return;
|
||||
var uiViewMode = getstore('uiViewMode', 2);
|
||||
var x = '<input type=radio id=ui0 name=uiradio value=2 ' + ((uiViewMode == 2)?'checked':'') + '><label for=ui0>' + "Classic" + '</label><br>';
|
||||
x += '<input type=radio id=ui1 name=uiradio value=3 ' + ((uiViewMode == 3)?'checked':'') + '><label for=ui1>' + "Modern" + '</label><br>';
|
||||
setDialogMode(2, "User Interface", 3, saveUserInterfaceMode, x);
|
||||
QV('uiMenu', false);
|
||||
}
|
||||
|
||||
function getNodeFromId(id) { if (nodes != null) { for (var i in nodes) { if (nodes[i]._id == id) return nodes[i]; } } return null; }
|
||||
function reload() {
|
||||
var x = window.location.href;
|
||||
|
|
|
@ -153,6 +153,9 @@
|
|||
<img id="topMenuIcon" class=noselect
|
||||
style="position:absolute;right:0;top:10px;color:#c8c8c8;font-size:44px;margin-right:8px;cursor:pointer;display:none"
|
||||
onclick=topMenu() src="/images/3bars-30.png" width=30 height=30 />
|
||||
<div class=textnewui id=textnewui onmouseup=toggleBootstrapUIMode() onkeypress="if (event.key=='Enter') { toggleBootstrapUIMode(); }">
|
||||
<b>Try the new MeshCentral UI</b>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar flex-column" id="page_leftbar">
|
||||
<div style="height:24px"></div>
|
||||
|
@ -190,6 +193,11 @@
|
|||
onkeypress="if (event.key == 'Enter') userInterfaceSelectMenu(3)">
|
||||
<div class="uiSelector3"></div>
|
||||
</div>
|
||||
<div tabindex=0 id=uiViewButton7 class=uiSelector
|
||||
onclick=toggleBootstrapUIMode() title="Toggle Modern UI"
|
||||
onkeypress="if (event.key == 'Enter') toggleBootstrapUIMode()">
|
||||
<div class="uiSelector7"></div>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<div tabindex=0 id=uiViewButton6 class=uiSelector onclick="showNotes(false)"
|
||||
|
@ -207,6 +215,7 @@
|
|||
onkeypress="if (event.key == 'Enter') toggleFooterBarMode()">
|
||||
<div class="uiSelector5"></div>
|
||||
</div>
|
||||
<div class=uiSelector_end> </div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
@ -2149,6 +2158,9 @@
|
|||
});
|
||||
}
|
||||
|
||||
// Show the modern ui switcher
|
||||
QV('textnewui', ((features2 & 0x40000000) == 0) ? false : true);
|
||||
|
||||
// Connect to the mesh server
|
||||
meshserver = MeshServerCreateControl(domainUrl);
|
||||
meshserver.onStateChanged = onStateChanged;
|
||||
|
@ -2622,6 +2634,31 @@
|
|||
QV('body', true);
|
||||
}
|
||||
|
||||
function saveUserInterfaceMode() {
|
||||
var nUiViewMode = 3;
|
||||
if (Q('ui0').checked) { nUiViewMode = 2; }
|
||||
if (getstore('uiViewMode', 3) != nUiViewMode) {
|
||||
putstore('uiViewMode', nUiViewMode);
|
||||
// Check if the URL includes 'sitestyle=' and remove it
|
||||
var url = new URL(window.location.href);
|
||||
if (url.searchParams.has('sitestyle')) {
|
||||
url.searchParams.delete('sitestyle');
|
||||
window.history.replaceState({}, document.title, url.toString());
|
||||
}
|
||||
reload();
|
||||
}
|
||||
}
|
||||
|
||||
function toggleBootstrapUIMode() {
|
||||
if (xxdialogMode) return;
|
||||
var uiViewMode = getstore('uiViewMode', 3);
|
||||
var x = '<div class=form-check><input type=radio class=form-check-input id=ui0 name=uiradio value=2 ' + ((uiViewMode == 2)?'checked':'') + '><label class=form-check-label for=ui0>' + "Classic" + '</label></div>';
|
||||
x += '<div class=form-check><input type=radio class=form-check-input id=ui1 name=uiradio value=3 ' + ((uiViewMode == 3)?'checked':'') + '><label class=form-check-label for=ui1>' + "Modern" + '</label></div>';
|
||||
setModalContent('xxAddAgent', "User Interface", x);
|
||||
showModal('xxAddAgentModal', 'idx_dlgOkButton', saveUserInterfaceMode);
|
||||
QV('uiMenu', false);
|
||||
}
|
||||
|
||||
function getNodeFromId(id) { if (nodes != null) { for (var i in nodes) { if (nodes[i]._id == id) return nodes[i]; } } return null; }
|
||||
function reload() {
|
||||
var x = window.location.href;
|
||||
|
|
11
webserver.js
11
webserver.js
|
@ -3184,8 +3184,14 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
|
|||
if (obj.parent.config.settings && obj.parent.config.settings.webrtcconfig && (typeof obj.parent.config.settings.webrtcconfig == 'object')) { webRtcConfig = encodeURIComponent(JSON.stringify(obj.parent.config.settings.webrtcconfig)).replace(/'/g, '%27'); }
|
||||
else if (args.webrtcconfig && (typeof args.webrtcconfig == 'object')) { webRtcConfig = encodeURIComponent(JSON.stringify(args.webrtcconfig)).replace(/'/g, '%27'); }
|
||||
|
||||
// Load default page style or new modern ui
|
||||
var uiViewMode = 'default';
|
||||
var webstateJSON = JSON.parse(webstate);
|
||||
if (webstateJSON && webstateJSON.uiViewMode == 3) { uiViewMode = 'default3'; }
|
||||
if (domain.sitestyle == 3) { uiViewMode = 'default3'; }
|
||||
if (req.query.sitestyle == 3) { uiViewMode = 'default3'; }
|
||||
// Refresh the session
|
||||
render(dbGetFunc.req, dbGetFunc.res, getRenderPage(((domain.sitestyle == 3) || (req.query.sitestyle == 3) ? 'default3' : 'default'), dbGetFunc.req, domain), getRenderArgs({
|
||||
render(dbGetFunc.req, dbGetFunc.res, getRenderPage(uiViewMode, dbGetFunc.req, domain), getRenderArgs({
|
||||
authCookie: authCookie,
|
||||
authRelayCookie: authRelayCookie,
|
||||
viewmode: viewmode,
|
||||
|
@ -3335,6 +3341,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
|
|||
if (domain.scrolltotop == true) { features2 += 0x08000000; } // Show the "Scroll to top" button
|
||||
if (domain.devicesearchbargroupname === true) { features2 += 0x10000000; } // Search bar will find by group name too
|
||||
if (((typeof domain.passwordrequirements != 'object') || (domain.passwordrequirements.duo2factor != false)) && (typeof domain.duo2factor == 'object') && (typeof domain.duo2factor.integrationkey == 'string') && (typeof domain.duo2factor.secretkey == 'string') && (typeof domain.duo2factor.apihostname == 'string')) { features2 += 0x20000000; } // using Duo for 2FA is allowed
|
||||
if (domain.showmodernuitoggle == true) { features2 += 0x40000000; } // Indicates that the new UI should be shown
|
||||
return { features: features, features2: features2 };
|
||||
}
|
||||
|
||||
|
@ -9045,7 +9052,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
|
|||
}
|
||||
|
||||
// Filter the user web site and only output state that we need to keep
|
||||
const acceptableUserWebStateStrings = ['webPageStackMenu', 'notifications', 'deviceView', 'nightMode', 'webPageFullScreen', 'search', 'showRealNames', 'sort', 'deskAspectRatio', 'viewsize', 'DeskControl', 'uiMode', 'footerBar','loctag','theme','lastThemes'];
|
||||
const acceptableUserWebStateStrings = ['webPageStackMenu', 'notifications', 'deviceView', 'nightMode', 'webPageFullScreen', 'search', 'showRealNames', 'sort', 'deskAspectRatio', 'viewsize', 'DeskControl', 'uiMode', 'footerBar','loctag','theme','lastThemes','uiViewMode'];
|
||||
const acceptableUserWebStateDesktopStrings = ['encoding', 'showfocus', 'showmouse', 'showcad', 'limitFrameRate', 'noMouseRotate', 'quality', 'scaling', 'agentencoding']
|
||||
obj.filterUserWebState = function (state) {
|
||||
if (typeof state == 'string') { try { state = JSON.parse(state); } catch (ex) { return null; } }
|
||||
|
|
Loading…
Reference in a new issue