Exposing setting the index page in the admin app and added a crude emoji picker, finally.
git-svn-id: https://www.unprompted.com/svn/projects/tildefriends/trunk@3966 ed5197a5-7fde-0310-b194-c3ffbd925b24
This commit is contained in:
		| @@ -1 +1 @@ | |||||||
| {"type":"tildefriends-app","files":{"app.js":"&ONpfDPCOakAWKWw0vPwQGPqMPbFNxZR/DOhIEQtK7Ac=.sha256","index.html":"&D3JwdPXy/QsLXkmwNDrBFXdzxfqO1/JGxfqEArnS5v4=.sha256","lit.min.js":"&3FfrVflmGr0n4lvN0GriN1Qz1lEw31SbZxRSJrcXR28=.sha256","script.js":"&hgxmXRvzwz27iH2BATFq20aLX4rtvL/AI/5QJV487XM=.sha256"}} | {"type":"tildefriends-app","files":{"app.js":"&srACRivbm0ZbvlMOAQ/9mhdcu++LLh6ckcRoRLvewjU=.sha256","index.html":"&D3JwdPXy/QsLXkmwNDrBFXdzxfqO1/JGxfqEArnS5v4=.sha256","lit.min.js":"&3FfrVflmGr0n4lvN0GriN1Qz1lEw31SbZxRSJrcXR28=.sha256","script.js":"&yTGrKjg1U/F9wt/60ySlg4N+qewVoaRUqqWQWkHi1Q0=.sha256"}} | ||||||
| @@ -4,9 +4,16 @@ tfrpc.register(function delete_user(user) { | |||||||
| 	return core.deleteUser(user); | 	return core.deleteUser(user); | ||||||
| }); | }); | ||||||
|  |  | ||||||
|  | tfrpc.register(function global_settings_set(key, value) { | ||||||
|  | 	return core.globalSettingsSet(key, value); | ||||||
|  | }); | ||||||
|  |  | ||||||
| async function main() { | async function main() { | ||||||
| 	let data = {users: {}, granted: await core.allPermissionsGranted()}; | 	let data = { | ||||||
| 	print(JSON.stringify(data)); | 		users: {}, | ||||||
|  | 		granted: await core.allPermissionsGranted(), | ||||||
|  | 		index: await core.globalSettingsGet('index'), | ||||||
|  | 	}; | ||||||
| 	for (let user of await core.users()) { | 	for (let user of await core.users()) { | ||||||
| 		data.users[user] = await core.permissionsForUser(user); | 		data.users[user] = await core.permissionsForUser(user); | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -11,9 +11,22 @@ function delete_user(user) { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | function global_settings_set(key, value) { | ||||||
|  | 	tfrpc.rpc.global_settings_set(key, value).then(function() { | ||||||
|  | 		alert(`Set "${key}" to "${value}".`); | ||||||
|  | 	}).catch(function(error) { | ||||||
|  | 		alert(`Failed to set "${key}": ${JSON.stringify(error, null, 2)}.`); | ||||||
|  | 	}); | ||||||
|  | } | ||||||
|  |  | ||||||
| window.addEventListener('load', function() { | window.addEventListener('load', function() { | ||||||
| 	const permission_template = (permission) => | 	const permission_template = (permission) => | ||||||
| 		html` <code>${permission}</code>`; | 		html` <code>${permission}</code>`; | ||||||
|  | 	const input_template = (key, value) => html` | ||||||
|  | 		<label ?for=${'gs_' + key}>${key}: </label> | ||||||
|  | 		<input type="text" value="${value}" ?id=${'gs_' + key}></input> | ||||||
|  | 		<button @click=${(e) => global_settings_set(key, e.srcElement.previousElementSibling.value)}>Set</button> | ||||||
|  | 	`; | ||||||
| 	const user_template = (user, permissions) => html` | 	const user_template = (user, permissions) => html` | ||||||
| 		<li> | 		<li> | ||||||
| 			<button @click=${(e) => delete_user(user)}> | 			<button @click=${(e) => delete_user(user)}> | ||||||
| @@ -24,8 +37,15 @@ window.addEventListener('load', function() { | |||||||
| 		</li> | 		</li> | ||||||
| 	`; | 	`; | ||||||
| 	const users_template = (users) => | 	const users_template = (users) => | ||||||
| 		html`<ul> | 		html`<h2>Users</h2> | ||||||
| 			${users.map(u => user_template(u[0], u[1]))} | 		<ul> | ||||||
|  | 			${Object.entries(users).map(u => user_template(u[0], u[1]))} | ||||||
| 		</ul>`; | 		</ul>`; | ||||||
| 	render(users_template(Object.entries(g_data.users)), document.body); | 	const page_template = (data) => | ||||||
|  | 		html`<div> | ||||||
|  | 		<h2>Global Settings</h2> | ||||||
|  | 		${input_template('index', data.index)} | ||||||
|  | 		${users_template(data.users)} | ||||||
|  | 		</div>`; | ||||||
|  | 	render(page_template(g_data), document.body); | ||||||
| }); | }); | ||||||
| @@ -1 +1 @@ | |||||||
| {"type":"tildefriends-app","files":{"app.js":"&7dCNJFk5RMHTWZC2qR8/UzjS22bXn7ZsPS6L/LIgUOg=.sha256","index.html":"&c+LsaIXIVMFXYjv5PkbgwjzxQ967QYRER5yy0YgpnZo=.sha256","vue-material.js":"&K5cdLqXYCENPak/TCINHQhyJhpS4G9DlZHGwoh/LF2g=.sha256","tf-user.js":"&cI/JLy83mOngcqYCEP8Vej8urDvAQAV1WxFsL67/K3M=.sha256","tf-message.js":"&JVARtJEQkq3XjjL0Jv/NUDkO2WZnXGIqkWsqYvTPXBI=.sha256","tf.js":"&MBqdk+3/ojaycNh92vOngTgvWk6h24vl8Q67MU4KZdI=.sha256","commonmark.min.js":"&EP0OeR9zyLwZannz+0ga4s9AGES2RLvvIIQYHqqV6+k=.sha256","vue.js":"&g1wvA+yHl1sVC+eufTsg9If7ZeVyMTBU+h0tks7ZNzE=.sha256","vue-material-theme-default-dark.css":"&RP2nr+2CR18BpHHw5ST9a5GJUCOG9n0G2kuGkcQioWE=.sha256","vue-material.min.css":"&kGbUM2QgFSyHZRzqQb0b+0S3EVIlZ0AXpdiAVjIhou8=.sha256","roboto.css":"&jJv43Om673mQO5JK0jj7714s5E+5Yrf82H6LcDx7wUs=.sha256","material-icons.css":"&a28PdcVvgq/DxyIvJAx/e+ZOEtOuHnr3kjLWKyzH11M=.sha256","tf-shared.js":"&LXyUSm6zSakN/ghJlZ1Qg2VJfV5alhN0gl8F7txIIOU=.sha256","style.css":"&qegBNCrVUihxffRUxGFuG/6u+0Y6d18zHtfNHBZtZ04=.sha256"}} | {"type":"tildefriends-app","files":{"app.js":"&7dCNJFk5RMHTWZC2qR8/UzjS22bXn7ZsPS6L/LIgUOg=.sha256","index.html":"&c+LsaIXIVMFXYjv5PkbgwjzxQ967QYRER5yy0YgpnZo=.sha256","vue-material.js":"&K5cdLqXYCENPak/TCINHQhyJhpS4G9DlZHGwoh/LF2g=.sha256","tf-user.js":"&cI/JLy83mOngcqYCEP8Vej8urDvAQAV1WxFsL67/K3M=.sha256","tf-message.js":"&qFKclMumLUufurbQyh2MrjwBG6E9w3L7HLfpelzmxzc=.sha256","tf.js":"&MBqdk+3/ojaycNh92vOngTgvWk6h24vl8Q67MU4KZdI=.sha256","commonmark.min.js":"&EP0OeR9zyLwZannz+0ga4s9AGES2RLvvIIQYHqqV6+k=.sha256","vue.js":"&g1wvA+yHl1sVC+eufTsg9If7ZeVyMTBU+h0tks7ZNzE=.sha256","vue-material-theme-default-dark.css":"&RP2nr+2CR18BpHHw5ST9a5GJUCOG9n0G2kuGkcQioWE=.sha256","vue-material.min.css":"&kGbUM2QgFSyHZRzqQb0b+0S3EVIlZ0AXpdiAVjIhou8=.sha256","roboto.css":"&jJv43Om673mQO5JK0jj7714s5E+5Yrf82H6LcDx7wUs=.sha256","material-icons.css":"&a28PdcVvgq/DxyIvJAx/e+ZOEtOuHnr3kjLWKyzH11M=.sha256","tf-shared.js":"&LXyUSm6zSakN/ghJlZ1Qg2VJfV5alhN0gl8F7txIIOU=.sha256","style.css":"&qegBNCrVUihxffRUxGFuG/6u+0Y6d18zHtfNHBZtZ04=.sha256","emojis.json":"&h3P4pez+AI4aYdsN0dJ3pbUEFR0276t9AM20caj/W/s=.sha256","emojis.js":"&OkagZLqq/yuT7B/6vYzAhpzphnPZsofQChAOVy6ZZFY=.sha256"}} | ||||||
							
								
								
									
										70
									
								
								apps/cory/ssb/emojis.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								apps/cory/ssb/emojis.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,70 @@ | |||||||
|  | let g_emojis; | ||||||
|  |  | ||||||
|  | function get_emojis() { | ||||||
|  | 	if (g_emojis) { | ||||||
|  | 		return Promise.resolve(g_emojis); | ||||||
|  | 	} | ||||||
|  | 	return fetch('emojis.json').then(function(result) { | ||||||
|  | 		g_emojis = result.json(); | ||||||
|  | 		return g_emojis; | ||||||
|  | 	}); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | export function picker(callback, anchor) { | ||||||
|  | 	get_emojis().then(function(json) { | ||||||
|  | 		let existing = document.getElementById('emoji_picker'); | ||||||
|  | 		if (existing) { | ||||||
|  | 			existing.parentElement.removeChild(existing); | ||||||
|  | 			return; | ||||||
|  | 		} | ||||||
|  | 		let div = document.createElement('div'); | ||||||
|  | 		div.id = 'emoji_picker'; | ||||||
|  | 		div.style.color = '#000'; | ||||||
|  | 		div.style.background = '#fff'; | ||||||
|  | 		div.style.border = '1px solid #000'; | ||||||
|  | 		div.style.display = 'block'; | ||||||
|  | 		div.style.position = 'absolute'; | ||||||
|  | 		div.style.maxWidth = '16em'; | ||||||
|  | 		div.style.maxHeight = '16em'; | ||||||
|  | 		div.style.overflow = 'scroll'; | ||||||
|  | 		div.style.fontWeight = 'bold'; | ||||||
|  | 		div.style.cursor = 'pointer'; | ||||||
|  | 		Object.entries(json).forEach(function(row) { | ||||||
|  | 			let header = document.createElement('div'); | ||||||
|  | 			header.appendChild(document.createTextNode(row[0])); | ||||||
|  | 			div.appendChild(header); | ||||||
|  | 			for (let entry of row[1]) { | ||||||
|  | 				let emoji = document.createElement('span'); | ||||||
|  | 				const k_size = '1.25em'; | ||||||
|  | 				emoji.style.width = k_size; | ||||||
|  | 				emoji.style.maxWidth = k_size; | ||||||
|  | 				emoji.style.minWidth = k_size; | ||||||
|  | 				emoji.style.height = k_size; | ||||||
|  | 				emoji.style.maxHeight = k_size; | ||||||
|  | 				emoji.style.minHeight = k_size; | ||||||
|  | 				emoji.style.display = 'inline-block'; | ||||||
|  | 				emoji.style.overflow = 'hidden'; | ||||||
|  | 				emoji.onclick = function() { | ||||||
|  | 					callback(entry); | ||||||
|  | 					div.parentElement.removeChild(div); | ||||||
|  | 				} | ||||||
|  | 				emoji.appendChild(document.createTextNode(entry.emoji)); | ||||||
|  | 				div.appendChild(emoji); | ||||||
|  | 			} | ||||||
|  | 		}); | ||||||
|  | 		document.body.appendChild(div); | ||||||
|  | 		if (anchor) { | ||||||
|  | 			let rect = anchor.getBoundingClientRect(); | ||||||
|  | 			if (rect.top < window.clientHeight / 2) { | ||||||
|  | 				div.style.top = rect.bottom + 'px'; | ||||||
|  | 			} else { | ||||||
|  | 				div.style.top = (rect.top - div.clientHeight) + 'px'; | ||||||
|  | 			} | ||||||
|  | 			if (rect.left < window.clientWidth / 2) { | ||||||
|  | 				div.style.left = rect.left + 'px'; | ||||||
|  | 			} else { | ||||||
|  | 				div.style.left = (rect.left - div.clientWidth) + 'px'; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	}); | ||||||
|  | } | ||||||
							
								
								
									
										15115
									
								
								apps/cory/ssb/emojis.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15115
									
								
								apps/cory/ssb/emojis.json
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1,5 +1,7 @@ | |||||||
|  | import * as tfrpc from '/static/tfrpc.js'; | ||||||
| import * as tfshared from './tf-shared.js'; | import * as tfshared from './tf-shared.js'; | ||||||
| import * as tf from './tf.js'; | import * as tf from './tf.js'; | ||||||
|  | import * as emojis from './emojis.js'; | ||||||
|  |  | ||||||
| Vue.component('tf-message', { | Vue.component('tf-message', { | ||||||
| 	props: ['message', 'messages', 'votes'], | 	props: ['message', 'messages', 'votes'], | ||||||
| @@ -46,24 +48,26 @@ Vue.component('tf-message', { | |||||||
| 			tf.g_data.reply_root = this.content_json.root || this.message.id; | 			tf.g_data.reply_root = this.content_json.root || this.message.id; | ||||||
| 			tf.g_data.reply_branch = this.message.id; | 			tf.g_data.reply_branch = this.message.id; | ||||||
| 		}, | 		}, | ||||||
| 		vote: function(event) { | 		vote: function(emoji) { | ||||||
| 			var reaction = event.srcElement.innerText; | 			let reaction = emoji.emoji; | ||||||
| 			var message = this.message.id; | 			var message = this.message.id; | ||||||
| 			if (confirm('Are you sure you want to react with ' + reaction + ' to ' + message + '?')) { | 			if (confirm('Are you sure you want to react with ' + reaction + ' to ' + message + '?')) { | ||||||
| 				window.parent.postMessage( | 				tfrpc.rpc.appendMessage({ | ||||||
| 					{ |  | ||||||
| 						appendMessage: { |  | ||||||
| 					type: 'vote', | 					type: 'vote', | ||||||
| 					vote: { | 					vote: { | ||||||
| 						link: message, | 						link: message, | ||||||
| 						value: 1, | 						value: 1, | ||||||
| 						expression: reaction, | 						expression: reaction, | ||||||
| 					}, | 					}, | ||||||
| 						}, | 				}).catch(function(error) { | ||||||
| 					}, | 					alert(error?.message); | ||||||
| 					'*'); | 				}); | ||||||
| 			} | 			} | ||||||
| 		}, | 		}, | ||||||
|  | 		show_emoji_picker: function(event) { | ||||||
|  | 			let self = this; | ||||||
|  | 			emojis.picker(x => self.vote(x), event.srcElement); | ||||||
|  | 		}, | ||||||
| 		show_message: function() { | 		show_message: function() { | ||||||
| 			window.parent.postMessage({ | 			window.parent.postMessage({ | ||||||
| 				action: 'setHash', | 				action: 'setHash', | ||||||
| @@ -167,10 +171,7 @@ Vue.component('tf-message', { | |||||||
| 			<md-icon>reply</md-icon> | 			<md-icon>reply</md-icon> | ||||||
| 		</md-button> | 		</md-button> | ||||||
| 		<md-menu> | 		<md-menu> | ||||||
| 			<md-menu-content> | 			<md-button class="md-icon-button" @click="show_emoji_picker"> | ||||||
| 				<md-menu-item @click="vote">Like</md-menu-item> |  | ||||||
| 			</md-menu-content> |  | ||||||
| 			<md-button class="md-icon-button" md-menu-trigger> |  | ||||||
| 				<md-icon>thumb_up</md-icon> | 				<md-icon>thumb_up</md-icon> | ||||||
| 			</md-button> | 			</md-button> | ||||||
| 		</md-menu> | 		</md-menu> | ||||||
|   | |||||||
							
								
								
									
										11
									
								
								core/core.js
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								core/core.js
									
									
									
									
									
								
							| @@ -240,6 +240,15 @@ async function getProcessBlob(blobId, key, options) { | |||||||
| 				} | 				} | ||||||
| 			}; | 			}; | ||||||
| 			if (process.credentials?.permissions?.administration) { | 			if (process.credentials?.permissions?.administration) { | ||||||
|  | 				imports.core.globalSettingsGet = function(key) { | ||||||
|  | 					return gGlobalSettings[key]; | ||||||
|  | 				}; | ||||||
|  | 				imports.core.globalSettingsSet = function(key, value) { | ||||||
|  | 					print('Setting', key, value); | ||||||
|  | 					gGlobalSettings[key] = value; | ||||||
|  | 					setGlobalSettings(gGlobalSettings); | ||||||
|  | 					print('Done.'); | ||||||
|  | 				}; | ||||||
| 				imports.core.deleteUser = function(user) { | 				imports.core.deleteUser = function(user) { | ||||||
| 					return imports.core.permissionTest('delete_user').then(function() { | 					return imports.core.permissionTest('delete_user').then(function() { | ||||||
| 						let db = new Database('auth'); | 						let db = new Database('auth'); | ||||||
| @@ -258,7 +267,7 @@ async function getProcessBlob(blobId, key, options) { | |||||||
| 							db.set('users', users); | 							db.set('users', users); | ||||||
| 						} | 						} | ||||||
| 					}); | 					}); | ||||||
| 				} | 				}; | ||||||
| 			} | 			} | ||||||
| 			if (options.api) { | 			if (options.api) { | ||||||
| 				imports.app = {}; | 				imports.app = {}; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user