Navigation bar => lit.
git-svn-id: https://www.unprompted.com/svn/projects/tildefriends/trunk@4267 ed5197a5-7fde-0310-b194-c3ffbd925b24
This commit is contained in:
parent
2926f855a1
commit
7b91a2ec37
218
core/client.js
218
core/client.js
@ -1,7 +1,6 @@
|
|||||||
import {LitElement, html} from '/static/lit/lit-all.min.js';
|
import {LitElement, html, css} from '/static/lit/lit-all.min.js';
|
||||||
|
|
||||||
let gSocket;
|
let gSocket;
|
||||||
let gCredentials;
|
|
||||||
let gPermissions;
|
let gPermissions;
|
||||||
|
|
||||||
let gCurrentFile;
|
let gCurrentFile;
|
||||||
@ -28,6 +27,106 @@ const k_api = {
|
|||||||
setHash: {args: ['hash'], func: api_setHash},
|
setHash: {args: ['hash'], func: api_setHash},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const k_global_style = css`
|
||||||
|
a:link {
|
||||||
|
color: #268bd2;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:visited {
|
||||||
|
color: #6c71c4;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover {
|
||||||
|
color: #859900;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:active {
|
||||||
|
color: #2aa198;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
class TfNavigationElement extends LitElement {
|
||||||
|
static get properties() {
|
||||||
|
return {
|
||||||
|
credentials: {type: Object},
|
||||||
|
permissions: {type: Object},
|
||||||
|
show_permissions: {type: Boolean},
|
||||||
|
status: {type: Object},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.permissions = {};
|
||||||
|
this.show_permissions = false;
|
||||||
|
this.status = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
toggle_edit(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
if (editing()) {
|
||||||
|
closeEditor();
|
||||||
|
} else {
|
||||||
|
edit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
reset_permission(key) {
|
||||||
|
send({action: "resetPermission", permission: key});
|
||||||
|
}
|
||||||
|
|
||||||
|
render_login() {
|
||||||
|
if (this?.credentials?.session?.name) {
|
||||||
|
return html`<a href="/login/logout?return=${url() + hash()}">logout ${this.credentials.session.name}</a>`;
|
||||||
|
} else {
|
||||||
|
return html`<a href="/login?return=${url() + hash()}">login</a>`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render_permissions() {
|
||||||
|
if (this.show_permissions) {
|
||||||
|
return html`
|
||||||
|
<div style="position: absolute; top: 0; padding: 0; margin: 0; z-index: 100; display: flex; justify-content: center; width: 100%">
|
||||||
|
<div style="background-color: #444; padding: 1em; margin: 0 auto; border-left: 4px solid #fff; border-right: 4px solid #fff; border-bottom: 4px solid #fff">
|
||||||
|
<div>This app has the following permissions:</div>
|
||||||
|
${Object.keys(this.permissions).map(key => html`
|
||||||
|
<div>
|
||||||
|
<span>${key}</span>: ${this.permissions[key] ? '✅ Allowed' : '❌ Denied'}
|
||||||
|
<button @click=${() => this.reset_permission(key)}>Reset</button>
|
||||||
|
</div>
|
||||||
|
`)}
|
||||||
|
<button @click=${() => this.show_permissions = false}>Close</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
let self = this;
|
||||||
|
return html`
|
||||||
|
<style>
|
||||||
|
* {
|
||||||
|
height: auto;
|
||||||
|
margin: 4px;
|
||||||
|
}
|
||||||
|
${k_global_style}
|
||||||
|
</style>
|
||||||
|
<span>😎</span>
|
||||||
|
<a accesskey="h" data-tip="Open home app." href="/" style="color: #fff">Tilde Friends</a>
|
||||||
|
<a accesskey="a" data-tip="Open apps list." href="/~core/apps/">apps</a>
|
||||||
|
<a accesskey="e" data-tip="Toggle the app editor." href="#" @click=${this.toggle_edit}>edit</a>
|
||||||
|
<a accesskey="p" data-tip="View and change permissions." href="#" @click=${() => self.show_permissions = !self.show_permissions}>🎛️</a>
|
||||||
|
<span style="display: inline-block; vertical-align: top; white-space: pre; color: ${this.status.color ?? kErrorColor}">${this.status.message}</span>
|
||||||
|
<span id="requests"></span>
|
||||||
|
${this.render_permissions()}
|
||||||
|
<span id="permissions"></span>
|
||||||
|
<span style="float: right">${this.render_login()}</span>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
customElements.define('tf-navigation', TfNavigationElement);
|
||||||
|
|
||||||
class TfFilesElement extends LitElement {
|
class TfFilesElement extends LitElement {
|
||||||
static get properties() {
|
static get properties() {
|
||||||
return {
|
return {
|
||||||
@ -68,6 +167,10 @@ class TfFilesElement extends LitElement {
|
|||||||
<style>
|
<style>
|
||||||
div.file {
|
div.file {
|
||||||
padding: 0.5em;
|
padding: 0.5em;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
div.file:hover {
|
||||||
|
background-color: #1a9188;
|
||||||
}
|
}
|
||||||
div.file::before {
|
div.file::before {
|
||||||
content: '📄 ';
|
content: '📄 ';
|
||||||
@ -145,14 +248,6 @@ function editing() {
|
|||||||
return document.getElementById("editPane").style.display != 'none';
|
return document.getElementById("editPane").style.display != 'none';
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggleEdit() {
|
|
||||||
if (editing()) {
|
|
||||||
closeEditor();
|
|
||||||
} else {
|
|
||||||
edit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function edit() {
|
function edit() {
|
||||||
if (editing()) {
|
if (editing()) {
|
||||||
return;
|
return;
|
||||||
@ -542,76 +637,12 @@ function api_setHash(hash) {
|
|||||||
window.location.hash = hash;
|
window.location.hash = hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
function hidePermissions() {
|
|
||||||
let permissions = document.getElementById('permissions_settings');
|
|
||||||
while (permissions.firstChild) {
|
|
||||||
permissions.removeChild(permissions.firstChild);
|
|
||||||
}
|
|
||||||
permissions.style.visibility = 'hidden';
|
|
||||||
}
|
|
||||||
|
|
||||||
function showPermissions() {
|
|
||||||
let permissions = document.getElementById('permissions_settings');
|
|
||||||
|
|
||||||
let container = document.createElement('div');
|
|
||||||
container.classList.add('permissions_contents');
|
|
||||||
|
|
||||||
let div = document.createElement('div');
|
|
||||||
div.appendChild(document.createTextNode('This app has the following permission:'));
|
|
||||||
for (let key of Object.keys(gPermissions || {})) {
|
|
||||||
let row = document.createElement('div');
|
|
||||||
|
|
||||||
let span = document.createElement('span');
|
|
||||||
span.appendChild(document.createTextNode(key));
|
|
||||||
row.appendChild(span);
|
|
||||||
|
|
||||||
span = document.createElement('span');
|
|
||||||
span.appendChild(document.createTextNode(': '));
|
|
||||||
row.appendChild(span);
|
|
||||||
|
|
||||||
span = document.createElement('span');
|
|
||||||
span.appendChild(document.createTextNode(gPermissions[key] ? '✅ Allowed' : '❌ Denied'));
|
|
||||||
row.appendChild(span);
|
|
||||||
|
|
||||||
span = document.createElement('span');
|
|
||||||
span.appendChild(document.createTextNode(' '));
|
|
||||||
row.appendChild(span);
|
|
||||||
|
|
||||||
let button = document.createElement('button');
|
|
||||||
button.innerText = 'Reset';
|
|
||||||
button.onclick = function() {
|
|
||||||
send({action: "resetPermission", permission: key});
|
|
||||||
};
|
|
||||||
row.appendChild(button);
|
|
||||||
div.appendChild(row);
|
|
||||||
}
|
|
||||||
container.appendChild(div);
|
|
||||||
|
|
||||||
div = document.createElement('div');
|
|
||||||
let button = document.createElement('button');
|
|
||||||
button.innerText = 'Close';
|
|
||||||
button.onclick = function() {
|
|
||||||
hidePermissions();
|
|
||||||
}
|
|
||||||
div.appendChild(button);
|
|
||||||
container.appendChild(div);
|
|
||||||
|
|
||||||
permissions.appendChild(container);
|
|
||||||
permissions.style.visibility = 'visible';
|
|
||||||
}
|
|
||||||
|
|
||||||
function _receive_websocket_message(message) {
|
function _receive_websocket_message(message) {
|
||||||
if (message && message.action == "session") {
|
if (message && message.action == "session") {
|
||||||
setStatusMessage("🟢 Executing...", kStatusColor);
|
setStatusMessage("🟢 Executing...", kStatusColor);
|
||||||
gCredentials = message.credentials;
|
document.getElementsByTagName('tf-navigation')[0].credentials = message.credentials;
|
||||||
updateLogin();
|
|
||||||
} else if (message && message.action == 'permissions') {
|
} else if (message && message.action == 'permissions') {
|
||||||
gPermissions = message.permissions;
|
document.getElementsByTagName('tf-navigation')[0].permissions = message.permissions ?? {};
|
||||||
let permissions = document.getElementById('permissions_settings');
|
|
||||||
if (permissions.firstChild) {
|
|
||||||
hidePermissions();
|
|
||||||
showPermissions();
|
|
||||||
}
|
|
||||||
} else if (message && message.action == "ready") {
|
} else if (message && message.action == "ready") {
|
||||||
setStatusMessage(null);
|
setStatusMessage(null);
|
||||||
if (window.location.hash) {
|
if (window.location.hash) {
|
||||||
@ -740,14 +771,7 @@ function keyEvent(event) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function setStatusMessage(message, color) {
|
function setStatusMessage(message, color) {
|
||||||
let node = document.getElementById("status");
|
document.getElementsByTagName('tf-navigation')[0].status = {message: message, color: color};
|
||||||
while (node.firstChild) {
|
|
||||||
node.removeChild(node.firstChild);
|
|
||||||
}
|
|
||||||
if (message) {
|
|
||||||
node.appendChild(document.createTextNode(message));
|
|
||||||
node.setAttribute("style", "display: inline-block; vertical-align: top; white-space: pre; color: " + (color || kErrorColor));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function send(value) {
|
function send(value) {
|
||||||
@ -760,23 +784,6 @@ function send(value) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateLogin() {
|
|
||||||
let login = document.getElementById("login");
|
|
||||||
while (login.firstChild) {
|
|
||||||
login.removeChild(login.firstChild);
|
|
||||||
}
|
|
||||||
|
|
||||||
let a = document.createElement("a");
|
|
||||||
if (gCredentials && gCredentials.session) {
|
|
||||||
a.appendChild(document.createTextNode("logout " + gCredentials.session.name));
|
|
||||||
a.setAttribute("href", "/login/logout?return=" + encodeURIComponent(url() + hash()));
|
|
||||||
} else {
|
|
||||||
a.appendChild(document.createTextNode("login"));
|
|
||||||
a.setAttribute("href", "/login?return=" + encodeURIComponent(url() + hash()));
|
|
||||||
}
|
|
||||||
login.appendChild(a);
|
|
||||||
}
|
|
||||||
|
|
||||||
function dragHover(event) {
|
function dragHover(event) {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
@ -1025,11 +1032,6 @@ window.addEventListener("load", function() {
|
|||||||
window.addEventListener("message", message, false);
|
window.addEventListener("message", message, false);
|
||||||
window.addEventListener("online", connectSocket);
|
window.addEventListener("online", connectSocket);
|
||||||
document.getElementById("name").value = window.location.pathname;
|
document.getElementById("name").value = window.location.pathname;
|
||||||
document.getElementById('edit_link').addEventListener('click', function(event) {
|
|
||||||
event.preventDefault();
|
|
||||||
toggleEdit();
|
|
||||||
});
|
|
||||||
document.getElementById('show_permissions_link').addEventListener('click', () => showPermissions());
|
|
||||||
document.getElementById('files_hide').addEventListener('click', () => hideFiles());
|
document.getElementById('files_hide').addEventListener('click', () => hideFiles());
|
||||||
document.getElementById('files_show').addEventListener('click', () => showFiles());
|
document.getElementById('files_show').addEventListener('click', () => showFiles());
|
||||||
document.getElementById('closeStats').addEventListener('click', () => closeStats());
|
document.getElementById('closeStats').addEventListener('click', () => closeStats());
|
||||||
@ -1038,11 +1040,11 @@ window.addEventListener("load", function() {
|
|||||||
document.getElementById('icon').addEventListener('click', () => changeIcon());
|
document.getElementById('icon').addEventListener('click', () => changeIcon());
|
||||||
document.getElementById('delete').addEventListener('click', () => deleteApp());
|
document.getElementById('delete').addEventListener('click', () => deleteApp());
|
||||||
document.getElementById('trace_button').addEventListener('click', function(event) {
|
document.getElementById('trace_button').addEventListener('click', function(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
trace();
|
trace();
|
||||||
});
|
});
|
||||||
document.getElementById('stats_button').addEventListener('click', function(event) {
|
document.getElementById('stats_button').addEventListener('click', function(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
toggleStats();
|
toggleStats();
|
||||||
});
|
});
|
||||||
document.getElementById('new_file_button').addEventListener('click', () => newFile());
|
document.getElementById('new_file_button').addEventListener('click', () => newFile());
|
||||||
|
@ -7,18 +7,7 @@
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
</head>
|
</head>
|
||||||
<body style="display: flex; flex-flow: column">
|
<body style="display: flex; flex-flow: column">
|
||||||
<div class="navigation">
|
<tf-navigation></tf-navigation>
|
||||||
<span>😎</span>
|
|
||||||
<a accesskey="h" data-tip="Open home app." href="/" style="color: #fff">Tilde Friends</a>
|
|
||||||
<a accesskey="a" data-tip="Open apps list." href="/~core/apps/">apps</a>
|
|
||||||
<a accesskey="e" data-tip="Toggle the app editor." href="#" id="edit_link">edit</a>
|
|
||||||
<a accesskey="p" data-tip="View and change permissions." href="#" id="show_permissions_link">🎛️</a>
|
|
||||||
<span id="status"></span>
|
|
||||||
<span id="requests"></span>
|
|
||||||
<span id="permissions_settings"></span>
|
|
||||||
<span id="permissions"></span>
|
|
||||||
<span id="login"></span>
|
|
||||||
</div>
|
|
||||||
<div id="content" class="hbox" style="flex: 1 1; width: 100%">
|
<div id="content" class="hbox" style="flex: 1 1; width: 100%">
|
||||||
<div id="statsPane" class="vbox" style="display: none; flex 1 1">
|
<div id="statsPane" class="vbox" style="display: none; flex 1 1">
|
||||||
<div class="hbox">
|
<div class="hbox">
|
||||||
@ -43,8 +32,8 @@
|
|||||||
<span id="files_hide">«</span>
|
<span id="files_hide">«</span>
|
||||||
<span id="files_show">»</span>
|
<span id="files_show">»</span>
|
||||||
</div>
|
</div>
|
||||||
<tf-files id="files_list"></tf-files>
|
|
||||||
<div id="files_content">
|
<div id="files_content">
|
||||||
|
<tf-files id="files_list"></tf-files>
|
||||||
<ul id="files"></ul>
|
<ul id="files"></ul>
|
||||||
<br>
|
<br>
|
||||||
<div><button id="new_file_button">New File</button></div>
|
<div><button id="new_file_button">New File</button></div>
|
||||||
|
@ -15,11 +15,6 @@ body {
|
|||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.navigation {
|
|
||||||
height: auto;
|
|
||||||
margin: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
a:link {
|
a:link {
|
||||||
color: #268bd2;
|
color: #268bd2;
|
||||||
}
|
}
|
||||||
@ -235,7 +230,7 @@ kbd {
|
|||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
#permissions, #permissions_settings {
|
#permissions {
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
display: block;
|
display: block;
|
||||||
|
Loading…
Reference in New Issue
Block a user