First commit
This commit is contained in:
77
hugo/public/bookmarks/add/index.html
Normal file
77
hugo/public/bookmarks/add/index.html
Normal file
@@ -0,0 +1,77 @@
|
||||
<!DOCTYPE html>
|
||||
<html class="no-js" lang="de">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="x-ua-compatible" content="ie=edge">
|
||||
<title>Add Bookmark :: alphabreed</title>
|
||||
<meta name="author" content="Stefan Mühlinghaus">
|
||||
<meta name="viewport" content="initial-scale=1, user-scalable=no">
|
||||
<link rel="icon" type="image/vnd.microsoft.icon" href="/img/favicon.ico">
|
||||
<link rel="preload" href="/css/bookmarks.css" as="style">
|
||||
<link rel="stylesheet" href="/css/bookmarks.css">
|
||||
<script>(function(H){H.className=H.className.replace(/\bno-js\b/,'js')})(document.documentElement)</script>
|
||||
<script defer src="/js/alpine-alphabreed.js"></script>
|
||||
<script defer src="/js/alpine-3.15.3.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<main x-data="{
|
||||
store: null,
|
||||
categories: [],
|
||||
name: '',
|
||||
url: '',
|
||||
categoryId: '',
|
||||
newcategory: '',
|
||||
async saveBookmark() {
|
||||
if (!this.categoryId)
|
||||
this.categoryId = this.categories[0].id;
|
||||
if (!this.name || !this.url || (!this.categoryId && !this.newcategory))
|
||||
return;
|
||||
if (this.newcategory)
|
||||
this.categoryId = await this.store.createBookmarkCategory(this.newcategory);
|
||||
const result = await this.store.createBookmark(
|
||||
this.categoryId, this.name, this.url
|
||||
);
|
||||
if (result)
|
||||
window.close();
|
||||
},
|
||||
async init() {
|
||||
this.store = Alpine.store('alphabreed');
|
||||
this.store.backUrl = '/bookmarks/add/';
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
this.name = params.get('name') || '';
|
||||
this.url = params.get('url') || '';
|
||||
|
||||
const tokenOK = await this.store.checkToken();
|
||||
if (tokenOK)
|
||||
this.categories = await this.store.getBookmarkCategories();
|
||||
}
|
||||
}">
|
||||
<div id="addcontent">
|
||||
<div class="field textfield">
|
||||
<label for="bookmarkname">Bookmark name</label>
|
||||
<input id="bookmarkname" type="text" x-model="name">
|
||||
</div>
|
||||
<div class="field textfield">
|
||||
<label for="bookmarkurl">URL</label>
|
||||
<input id="bookmarkurl" type="text" x-model="url">
|
||||
</div>
|
||||
<div class="field selectfield">
|
||||
<label for="bookmarkcategory">Category</label>
|
||||
<select id="bookmarkcategory" x-model="categoryId">
|
||||
<template x-for="category in categories" :key="category.id">
|
||||
<option :value="category.id" x-text="category.name" :selected="category.id == categoryId">
|
||||
</template>
|
||||
</select>
|
||||
</div>
|
||||
<div class="field textfield">
|
||||
<label for="bookmarknewcategory">New category</label>
|
||||
<input id="bookmarknewcategory" type="text" x-model="newcategory">
|
||||
</div>
|
||||
<div class="field buttons">
|
||||
<button @click="saveBookmark()">Save</button>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
191
hugo/public/bookmarks/index.html
Normal file
191
hugo/public/bookmarks/index.html
Normal file
@@ -0,0 +1,191 @@
|
||||
<!DOCTYPE html>
|
||||
<html class="no-js" lang="de">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="x-ua-compatible" content="ie=edge">
|
||||
<title>Bookmarks :: alphabreed</title>
|
||||
<meta name="author" content="Stefan Mühlinghaus">
|
||||
<meta name="viewport" content="initial-scale=1, user-scalable=no">
|
||||
<link rel="icon" type="image/vnd.microsoft.icon" href="/img/favicon.ico">
|
||||
<link rel="preload" href="/css/bookmarks.css" as="style">
|
||||
<link rel="stylesheet" href="/css/bookmarks.css">
|
||||
<script>(function(H){H.className=H.className.replace(/\bno-js\b/,'js')})(document.documentElement)</script>
|
||||
<script defer src="/js/alpine-alphabreed.js"></script>
|
||||
<script defer src="/js/alpine-3.15.3.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<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>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user