forked from cory/tildefriends
		
	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:
		
							
								
								
									
										214
									
								
								core/client.js
									
									
									
									
									
								
							
							
						
						
									
										214
									
								
								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());
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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;
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user