176 lines
6.0 KiB
HTML
176 lines
6.0 KiB
HTML
---
|
|
title: "Bookmarks"
|
|
---
|
|
<main x-data="{
|
|
store: null,
|
|
categories: [],
|
|
openCategoryId: '',
|
|
slideInOpen: false,
|
|
showFavletCode: false,
|
|
editCategory: null,
|
|
editBookmark: null,
|
|
host: '',
|
|
async updateBookmarks() {
|
|
const result = await this.store.getBookmarks();
|
|
const grouped = Object.groupBy(result, (bookmark) => bookmark.expand.category.id);
|
|
this.categories = Object.values(grouped).map((group) => {
|
|
const category = group[0].expand.category;
|
|
return {
|
|
id: category.id,
|
|
name: category.name,
|
|
bookmarks: group.map((bookmark) => ({
|
|
category: category.id,
|
|
id: bookmark.id,
|
|
name: bookmark.name,
|
|
url: bookmark.url
|
|
}))
|
|
};
|
|
});
|
|
this.categories.sort((a, b) => a.name.localeCompare(b.name));
|
|
},
|
|
openCategory(id, element) {
|
|
if (this.openCategoryId == id) {
|
|
this.openCategoryId = '';
|
|
return;
|
|
}
|
|
this.openCategoryId = id;
|
|
element.scrollIntoView(true);
|
|
},
|
|
async saveCategory() {
|
|
if (!this.editCategory || !this.editCategory.name)
|
|
return;
|
|
await this.store.updateBookmarkCategory(
|
|
this.editCategory.id, this.editCategory.name
|
|
);
|
|
this.slideInOpen = false;
|
|
await this.updateBookmarks();
|
|
},
|
|
async deleteCategory() {
|
|
if (!this.editCategory)
|
|
return;
|
|
await this.store.deleteBookmarkCategory(this.editCategory.id);
|
|
this.slideInOpen = false;
|
|
await this.updateBookmarks();
|
|
},
|
|
async saveBookmark() {
|
|
let categoryId = this.editBookmark.category || this.categories[0].id;
|
|
if (!this.editBookmark || !this.editBookmark.name || !this.editBookmark.url || (!categoryId && !this.editBookmark.newcategory))
|
|
return;
|
|
if (this.editBookmark.newcategory)
|
|
categoryId = await this.store.createBookmarkCategory(this.editBookmark.newcategory);
|
|
if (this.editBookmark.id) {
|
|
await this.store.updateBookmark(
|
|
this.editBookmark.id,
|
|
categoryId,
|
|
this.editBookmark.name,
|
|
this.editBookmark.url
|
|
);
|
|
}
|
|
else {
|
|
await this.store.createBookmark(
|
|
categoryId,
|
|
this.editBookmark.name,
|
|
this.editBookmark.url
|
|
);
|
|
}
|
|
this.slideInOpen = false;
|
|
this.openCategoryId = categoryId;
|
|
await this.updateBookmarks();
|
|
},
|
|
async deleteBookmark() {
|
|
if (!this.editBookmark)
|
|
return;
|
|
await this.store.deleteBookmark(this.editBookmark.id);
|
|
this.slideInOpen = false;
|
|
await this.updateBookmarks();
|
|
},
|
|
async init() {
|
|
this.store = Alpine.store('alphabreed');
|
|
this.store.backUrl = '/bookmarks/';
|
|
this.host = window.location.protocol + '//' + window.location.host;
|
|
const tokenOK = await this.store.checkToken();
|
|
if (tokenOK)
|
|
this.updateBookmarks();
|
|
}
|
|
}">
|
|
<p><button @click="editBookmark = {}; editCategory = null; showFavletCode = false; slideInOpen = true;">+ Bookmark</button></p>
|
|
<span id="favlet" @click="showFavletCode = true; editCategory = null; editBookmark = null; slideInOpen = true;">Generate Favlet code</span>
|
|
<div class="categories">
|
|
<template x-for="category in categories" :key="category.id">
|
|
<div class="category" :class="{'open': category.id == openCategoryId}">
|
|
<h1>
|
|
<span class="title" x-text="category.name" @click="openCategory(category.id, $el)"></span>
|
|
<span class="badge" x-text="category.bookmarks.length"></span>
|
|
<span class="edit" @click="editCategory = Object.assign({}, category); editBookmark = null; showFavletCode = false; slideInOpen = true;">✎</span>
|
|
</h1>
|
|
<ul class="bookmarks">
|
|
<template x-for="bookmark in category.bookmarks" :key="bookmark.id">
|
|
<li class="bookmark">
|
|
<div class="editicon" @click="editBookmark = Object.assign({}, bookmark); editCategory = null; showFavletCode = false; slideInOpen = true;">
|
|
<img :src="'https://www.google.com/s2/favicons?domain=' + encodeURIComponent(bookmark.url)">
|
|
</div>
|
|
<a class="link" :href="bookmark.url" target="_blank">
|
|
<span x-text="bookmark.name"></span>
|
|
</a>
|
|
</li>
|
|
</template>
|
|
</ul>
|
|
</div>
|
|
</template>
|
|
</div>
|
|
<div id="slidein" :class="{'open': slideInOpen}">
|
|
<span class="closer" @click="slideInOpen = false;"></span>
|
|
<div class="inner">
|
|
<template x-if="showFavletCode">
|
|
<div>
|
|
<p>Favlet code:</p>
|
|
<p class="favletcode" x-text='"javascript:(function(w,e){w.open(\""+host+"/bookmarks/add/?name=\"+e(document.title)+\"&url=\"+e(w.location.href),\"_blank\",\"height=500,width=500,location=0,menubar=0,scrollbars=0,status=0,titlebar=0,toolbar=0\")})(window,encodeURIComponent)"'></p>
|
|
</div>
|
|
</template>
|
|
<template x-if="editCategory">
|
|
<div>
|
|
<div class="field textfield">
|
|
<label for="categoryname">Category name</label>
|
|
<input id="categoryname" type="text" x-model="editCategory.name">
|
|
</div>
|
|
<div class="field buttons">
|
|
<button @click="saveCategory()">Save</button>
|
|
</div>
|
|
<div class="field buttons">
|
|
<button @click="deleteCategory()">Delete</button>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
<template x-if="editBookmark">
|
|
<div>
|
|
<div class="field textfield">
|
|
<label for="bookmarkname">Bookmark name</label>
|
|
<input id="bookmarkname" type="text" x-model="editBookmark.name">
|
|
</div>
|
|
<div class="field textfield">
|
|
<label for="bookmarkurl">URL</label>
|
|
<input id="bookmarkurl" type="text" x-model="editBookmark.url">
|
|
</div>
|
|
<div class="field selectfield">
|
|
<label for="bookmarkcategory">Category</label>
|
|
<select id="bookmarkcategory" x-model="editBookmark.category">
|
|
<template x-for="category in categories" :key="category.id">
|
|
<option :value="category.id" x-text="category.name" :selected="category.id == editBookmark.category">
|
|
</template>
|
|
</select>
|
|
</div>
|
|
<div class="field textfield">
|
|
<label for="bookmarknewcategory">New category</label>
|
|
<input id="bookmarknewcategory" type="text" x-model="editBookmark.newcategory">
|
|
</div>
|
|
<div class="field buttons">
|
|
<button @click="saveBookmark()">Save</button>
|
|
</div>
|
|
<div class="field buttons">
|
|
<button @click="deleteBookmark()">Delete</button>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
</div>
|
|
</div>
|
|
</main> |