| 
									
										
										
										
											2022-11-28 02:19:36 +00:00
										 |  |  | import {LitElement, html} from './lit-core.min.js'; | 
					
						
							|  |  |  | import * as tfrpc from '/static/tfrpc.js'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class TodosElement extends LitElement { | 
					
						
							|  |  |  | 	static get properties() { | 
					
						
							|  |  |  | 		return { | 
					
						
							| 
									
										
										
										
											2024-02-24 11:09:34 -05:00
										 |  |  | 			lists: {type: Array}, | 
					
						
							| 
									
										
										
										
											2022-11-28 02:19:36 +00:00
										 |  |  | 		}; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	constructor() { | 
					
						
							|  |  |  | 		super(); | 
					
						
							|  |  |  | 		this.lists = []; | 
					
						
							|  |  |  | 		let self = this; | 
					
						
							| 
									
										
										
										
											2024-02-24 11:09:34 -05:00
										 |  |  | 		tfrpc.rpc | 
					
						
							|  |  |  | 			.todo_get_all() | 
					
						
							|  |  |  | 			.then(function (lists) { | 
					
						
							|  |  |  | 				self.lists = lists; | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 			.catch(function (error) { | 
					
						
							|  |  |  | 				console.log(error); | 
					
						
							|  |  |  | 			}); | 
					
						
							| 
									
										
										
										
											2022-11-28 02:19:36 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	async new_list() { | 
					
						
							|  |  |  | 		await tfrpc.rpc.todo_add('new list'); | 
					
						
							|  |  |  | 		await this.refresh(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	async refresh() { | 
					
						
							|  |  |  | 		this.lists = await tfrpc.rpc.todo_get_all(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	render() { | 
					
						
							|  |  |  | 		return html`
 | 
					
						
							|  |  |  | 			<div> | 
					
						
							|  |  |  | 				<div style="display: flex"> | 
					
						
							| 
									
										
										
										
											2024-02-24 11:09:34 -05:00
										 |  |  | 					${this.lists.map( | 
					
						
							|  |  |  | 						(x) => html`
 | 
					
						
							|  |  |  | 							<tf-todo-list | 
					
						
							|  |  |  | 								name=${x.name} | 
					
						
							|  |  |  | 								.items=${x.items} | 
					
						
							|  |  |  | 								@change=${this.refresh} | 
					
						
							|  |  |  | 							></tf-todo-list> | 
					
						
							|  |  |  | 						`
 | 
					
						
							|  |  |  | 					)} | 
					
						
							| 
									
										
										
										
											2022-11-28 02:19:36 +00:00
										 |  |  | 				</div> | 
					
						
							|  |  |  | 				<input type="button" @click=${this.new_list} value="+ List"></input> | 
					
						
							|  |  |  | 			</div>`; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class TodoListElement extends LitElement { | 
					
						
							|  |  |  | 	static get properties() { | 
					
						
							|  |  |  | 		return { | 
					
						
							|  |  |  | 			name: {type: String}, | 
					
						
							|  |  |  | 			items: {type: Array}, | 
					
						
							|  |  |  | 			editing: {type: Number}, | 
					
						
							|  |  |  | 			editing_name: {type: Boolean}, | 
					
						
							|  |  |  | 		}; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	constructor() { | 
					
						
							|  |  |  | 		super(); | 
					
						
							|  |  |  | 		this.items = []; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	save() { | 
					
						
							| 
									
										
										
										
											2022-12-24 18:50:01 +00:00
										 |  |  | 		let self = this; | 
					
						
							|  |  |  | 		console.log('saving', self.name, self.items); | 
					
						
							| 
									
										
										
										
											2024-02-24 11:09:34 -05:00
										 |  |  | 		tfrpc.rpc | 
					
						
							|  |  |  | 			.todo_set(self.name, self.items) | 
					
						
							|  |  |  | 			.then(function () { | 
					
						
							|  |  |  | 				console.log('saved', self.name, self.items); | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 			.catch(function (error) { | 
					
						
							|  |  |  | 				console.log(error); | 
					
						
							|  |  |  | 			}); | 
					
						
							| 
									
										
										
										
											2022-11-28 02:19:36 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	remove_item(item) { | 
					
						
							|  |  |  | 		let index = this.items.indexOf(item); | 
					
						
							| 
									
										
										
										
											2024-02-24 11:09:34 -05:00
										 |  |  | 		this.items = [].concat( | 
					
						
							|  |  |  | 			this.items.slice(0, index), | 
					
						
							|  |  |  | 			this.items.slice(index + 1) | 
					
						
							|  |  |  | 		); | 
					
						
							| 
									
										
										
										
											2022-11-28 02:19:36 +00:00
										 |  |  | 		this.save(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	handle_check(event, item) { | 
					
						
							|  |  |  | 		item.x = event.srcElement.checked; | 
					
						
							|  |  |  | 		this.save(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	input_blur(item) { | 
					
						
							|  |  |  | 		this.save(); | 
					
						
							|  |  |  | 		this.editing = undefined; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	input_change(event, item) { | 
					
						
							|  |  |  | 		item.text = event.srcElement.value; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	input_keydown(event, item) { | 
					
						
							|  |  |  | 		if (event.key === 'Enter' || event.key === 'Escape') { | 
					
						
							|  |  |  | 			item.text = event.srcElement.value; | 
					
						
							|  |  |  | 			this.editing = undefined; | 
					
						
							| 
									
										
										
										
											2022-12-24 18:50:01 +00:00
										 |  |  | 			this.save(); | 
					
						
							| 
									
										
										
										
											2022-11-28 02:19:36 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	updated() { | 
					
						
							|  |  |  | 		let edit = this.renderRoot.getElementById('edit'); | 
					
						
							|  |  |  | 		if (edit) { | 
					
						
							|  |  |  | 			edit.select(); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	render_item(item) { | 
					
						
							|  |  |  | 		let index = this.items.indexOf(item); | 
					
						
							|  |  |  | 		let self = this; | 
					
						
							|  |  |  | 		if (index === this.editing) { | 
					
						
							|  |  |  | 			return html`
 | 
					
						
							| 
									
										
										
										
											2024-02-24 11:09:34 -05:00
										 |  |  | 				<div><input type="checkbox" ?checked=${item.x} @change=${(x) => self.handle_check(x, item)}></input> | 
					
						
							| 
									
										
										
										
											2022-11-28 02:19:36 +00:00
										 |  |  | 				<input | 
					
						
							|  |  |  | 					id="edit" | 
					
						
							|  |  |  | 					type="text" | 
					
						
							|  |  |  | 					value=${item.text} | 
					
						
							| 
									
										
										
										
											2024-02-24 11:09:34 -05:00
										 |  |  | 					@change=${(event) => self.input_change(event, item)} | 
					
						
							|  |  |  | 					@keydown=${(event) => self.input_keydown(event, item)} | 
					
						
							|  |  |  | 					@blur=${(x) => self.input_blur(item)}></input> | 
					
						
							|  |  |  | 				<span @click=${(x) => self.remove_item(item)} style="cursor: pointer">❎</span></div> | 
					
						
							| 
									
										
										
										
											2022-11-28 02:19:36 +00:00
										 |  |  | 			`;
 | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			return html`
 | 
					
						
							| 
									
										
										
										
											2024-02-24 11:09:34 -05:00
										 |  |  | 				<div><input type="checkbox" ?checked=${item.x} @change=${(x) => self.handle_check(x, item)}></input> | 
					
						
							|  |  |  | 				<span @click=${(x) => (self.editing = index)}>${item.text || '(empty)'}</span> | 
					
						
							| 
									
										
										
										
											2022-11-28 02:19:36 +00:00
										 |  |  | 			`;
 | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	add_item() { | 
					
						
							|  |  |  | 		this.items = [].concat(this.items || [], [{text: 'new item'}]); | 
					
						
							|  |  |  | 		this.editing = this.items.length - 1; | 
					
						
							|  |  |  | 		this.save(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	async remove_list() { | 
					
						
							|  |  |  | 		if (confirm(`Are you sure you want to remove "${this.name}"?`)) { | 
					
						
							|  |  |  | 			await tfrpc.rpc.todo_remove(this.name); | 
					
						
							|  |  |  | 			this.dispatchEvent(new Event('change')); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	rename(new_name) { | 
					
						
							|  |  |  | 		let self = this; | 
					
						
							| 
									
										
										
										
											2024-02-24 11:09:34 -05:00
										 |  |  | 		return tfrpc.rpc | 
					
						
							|  |  |  | 			.todo_rename(this.name, new_name) | 
					
						
							|  |  |  | 			.then(function () { | 
					
						
							|  |  |  | 				self.dispatchEvent(new Event('change')); | 
					
						
							|  |  |  | 				self.editing_name = false; | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 			.catch(function (error) { | 
					
						
							|  |  |  | 				console.log(error); | 
					
						
							|  |  |  | 				alert(error.message); | 
					
						
							|  |  |  | 				self.editing_name = false; | 
					
						
							|  |  |  | 			}); | 
					
						
							| 
									
										
										
										
											2022-11-28 02:19:36 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	name_blur(new_name) { | 
					
						
							|  |  |  | 		this.rename(new_name); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	name_keydown(event, item) { | 
					
						
							|  |  |  | 		let self = this; | 
					
						
							|  |  |  | 		if (event.key == 'Enter' || event.key === 'Escape') { | 
					
						
							|  |  |  | 			let new_name = event.srcElement.value; | 
					
						
							|  |  |  | 			this.rename(new_name); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	render() { | 
					
						
							|  |  |  | 		let self = this; | 
					
						
							| 
									
										
										
										
											2024-02-24 11:09:34 -05:00
										 |  |  | 		let name = this.editing_name | 
					
						
							|  |  |  | 			? html`<input
 | 
					
						
							| 
									
										
										
										
											2022-11-28 02:19:36 +00:00
										 |  |  | 				type="text" | 
					
						
							|  |  |  | 				id="edit" | 
					
						
							| 
									
										
										
										
											2024-02-24 11:09:34 -05:00
										 |  |  | 				@keydown=${(event) => self.name_keydown(event)} | 
					
						
							|  |  |  | 				@blur=${(event) => self.name_blur(event.srcElement.value)} | 
					
						
							|  |  |  | 				value=${this.name}></input>` | 
					
						
							|  |  |  | 			: html`<h2 @click=${(x) => (this.editing_name = true)}>${this.name}</h2>`; | 
					
						
							| 
									
										
										
										
											2022-11-28 02:19:36 +00:00
										 |  |  | 		return html`
 | 
					
						
							| 
									
										
										
										
											2024-02-24 11:09:34 -05:00
										 |  |  | 			<div | 
					
						
							|  |  |  | 				style="border: 3px solid black; padding: 8px; margin: 8px; border-radius: 8px; background-color: #444" | 
					
						
							|  |  |  | 			> | 
					
						
							| 
									
										
										
										
											2022-11-28 02:19:36 +00:00
										 |  |  | 				${name} | 
					
						
							| 
									
										
										
										
											2024-02-24 11:09:34 -05:00
										 |  |  | 				${(this.items || []) | 
					
						
							|  |  |  | 					.filter((item) => !item.x) | 
					
						
							|  |  |  | 					.map((x) => self.render_item(x))} | 
					
						
							|  |  |  | 				${(this.items || []) | 
					
						
							|  |  |  | 					.filter((item) => item.x) | 
					
						
							|  |  |  | 					.map((x) => self.render_item(x))} | 
					
						
							| 
									
										
										
										
											2022-11-28 02:19:36 +00:00
										 |  |  | 				<button @click=${self.add_item}>+ Item</button> | 
					
						
							|  |  |  | 				<button @click=${self.remove_list}>- List</button> | 
					
						
							|  |  |  | 			</div> | 
					
						
							|  |  |  | 		`;
 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | customElements.define('tf-todo-list', TodoListElement); | 
					
						
							| 
									
										
										
										
											2024-02-24 11:09:34 -05:00
										 |  |  | customElements.define('tf-todos', TodosElement); |