Add option to mark if bookmark archive is public

This commit is contained in:
Radhi Fadlillah 2019-08-08 20:16:25 +07:00
parent 0324784c7c
commit 20e89216f0
18 changed files with 153 additions and 70 deletions

View file

@ -41,31 +41,32 @@ func OpenSQLiteDatabase(databasePath string) (*SQLiteDatabase, error) {
// Create tables
tx.MustExec(`CREATE TABLE IF NOT EXISTS account(
id INTEGER NOT NULL,
username TEXT NOT NULL,
password TEXT NOT NULL,
id INTEGER NOT NULL,
username TEXT NOT NULL,
password TEXT NOT NULL,
CONSTRAINT account_PK PRIMARY KEY(id),
CONSTRAINT account_username_UNIQUE UNIQUE(username))`)
tx.MustExec(`CREATE TABLE IF NOT EXISTS bookmark(
id INTEGER NOT NULL,
url TEXT NOT NULL,
title TEXT NOT NULL,
excerpt TEXT NOT NULL DEFAULT "",
author TEXT NOT NULL DEFAULT "",
modified TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
id INTEGER NOT NULL,
url TEXT NOT NULL,
title TEXT NOT NULL,
excerpt TEXT NOT NULL DEFAULT "",
author TEXT NOT NULL DEFAULT "",
public INTEGER NOT NULL DEFAULT 0,
modified TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT bookmark_PK PRIMARY KEY(id),
CONSTRAINT bookmark_url_UNIQUE UNIQUE(url))`)
tx.MustExec(`CREATE TABLE IF NOT EXISTS tag(
id INTEGER NOT NULL,
name TEXT NOT NULL,
id INTEGER NOT NULL,
name TEXT NOT NULL,
CONSTRAINT tag_PK PRIMARY KEY(id),
CONSTRAINT tag_name_UNIQUE UNIQUE(name))`)
tx.MustExec(`CREATE TABLE IF NOT EXISTS bookmark_tag(
bookmark_id INTEGER NOT NULL,
tag_id INTEGER NOT NULL,
tag_id INTEGER NOT NULL,
CONSTRAINT bookmark_tag_PK PRIMARY KEY(bookmark_id, tag_id),
CONSTRAINT bookmark_id_FK FOREIGN KEY(bookmark_id) REFERENCES bookmark(id),
CONSTRAINT tag_id_FK FOREIGN KEY(tag_id) REFERENCES tag(id))`)
@ -100,10 +101,11 @@ func (db *SQLiteDatabase) SaveBookmarks(bookmarks ...model.Bookmark) (result []m
// Prepare statement
stmtInsertBook, _ := tx.Preparex(`INSERT INTO bookmark
(id, url, title, excerpt, author, modified)
VALUES(?, ?, ?, ?, ?, ?)
(id, url, title, excerpt, author, public, modified)
VALUES(?, ?, ?, ?, ?, ?, ?)
ON CONFLICT(id) DO UPDATE SET
url = ?, title = ?, excerpt = ?, author = ?, modified = ?`)
url = ?, title = ?, excerpt = ?, author = ?,
public = ?, modified = ?`)
stmtInsertBookContent, _ := tx.Preparex(`INSERT OR IGNORE INTO bookmark_content
(docid, title, content, html)
@ -147,8 +149,8 @@ func (db *SQLiteDatabase) SaveBookmarks(bookmarks ...model.Bookmark) (result []m
// Save bookmark
stmtInsertBook.MustExec(book.ID,
book.URL, book.Title, book.Excerpt, book.Author, book.Modified,
book.URL, book.Title, book.Excerpt, book.Author, book.Modified)
book.URL, book.Title, book.Excerpt, book.Author, book.Public, book.Modified,
book.URL, book.Title, book.Excerpt, book.Author, book.Public, book.Modified)
stmtUpdateBookContent.MustExec(book.Title, book.Content, book.HTML, book.ID)
stmtInsertBookContent.MustExec(book.ID, book.Title, book.Content, book.HTML)
@ -206,6 +208,7 @@ func (db *SQLiteDatabase) GetBookmarks(opts GetBookmarksOptions) ([]model.Bookma
`b.title`,
`b.excerpt`,
`b.author`,
`b.public`,
`b.modified`,
`bc.content <> "" has_content`}
@ -407,7 +410,7 @@ func (db *SQLiteDatabase) DeleteBookmarks(ids ...int) (err error) {
func (db *SQLiteDatabase) GetBookmark(id int, url string) (model.Bookmark, bool) {
args := []interface{}{id}
query := `SELECT
b.id, b.url, b.title, b.excerpt, b.author, b.modified,
b.id, b.url, b.title, b.excerpt, b.author, b.public, b.modified,
bc.content, bc.html, bc.content <> "" has_content
FROM bookmark b
LEFT JOIN bookmark_content bc ON bc.docid = b.id

View file

@ -15,6 +15,7 @@ type Bookmark struct {
Title string `db:"title" json:"title"`
Excerpt string `db:"excerpt" json:"excerpt"`
Author string `db:"author" json:"author"`
Public int `db:"public" json:"public"`
Modified string `db:"modified" json:"modified"`
Content string `db:"content" json:"-"`
HTML string `db:"html" json:"html,omitempty"`

View file

@ -1 +1 @@
.bookmark{display:-webkit-box;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;flex-flow:column nowrap;min-width:0;border:1px solid var(--border);background-color:var(--contentBg);height:100%;position:relative}.bookmark:hover .bookmark-menu>a,.bookmark:focus .bookmark-menu>a{display:block}.bookmark.selected{background-color:var(--selectedBg)}.bookmark .bookmark-selector{position:absolute;top:0;left:0;width:100%;height:100%;z-index:9}.bookmark .bookmark-link{display:block;cursor:default}.bookmark .bookmark-link[href]{cursor:pointer}.bookmark .bookmark-link[href]:hover .title,.bookmark .bookmark-link[href]:focus .title{color:var(--main)}.bookmark .bookmark-link span.thumbnail{width:100%;height:200px;display:block;background-size:cover;background-repeat:no-repeat;background-position:center center;margin-bottom:8px;border-bottom:1px solid var(--border)}.bookmark .bookmark-link .id{color:var(--color);border:1px solid var(--border);background-color:var(--contentBg);font-size:.7em;font-weight:bold;left:-1px;top:-1px;position:absolute;padding:0 .3em;opacity:.7}.bookmark .bookmark-link .title{text-overflow:ellipsis;word-wrap:break-word;overflow:hidden;font-size:1.2em;line-height:1.3em;max-height:5.2em;font-weight:600;padding:0 16px;color:var(--color)}.bookmark .bookmark-link .title:first-child{margin-top:16px}.bookmark .bookmark-link .excerpt{color:var(--color);margin-top:8px;padding:0 16px;text-overflow:ellipsis;word-wrap:break-word;overflow:hidden;font-size:.9em;line-height:1.5em;max-height:10.5em}.bookmark .bookmark-tags{display:-webkit-box;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;flex-flow:row wrap;margin:4px 0 -4px;padding:0 8px}.bookmark .bookmark-tags a{margin:4px;padding:4px 8px;font-size:.8em;font-weight:600;border:1px solid var(--border);border-radius:4px;color:var(--colorLink);background-color:var(--contentBg)}.bookmark .bookmark-tags a:hover,.bookmark .bookmark-tags a:focus{color:var(--main)}.bookmark .bookmark-menu{padding:8px 16px 16px;display:-webkit-box;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;flex-flow:row nowrap;min-width:0;min-height:0;-webkit-box-align:center;align-items:center}.bookmark .bookmark-menu a{color:var(--colorLink);flex-shrink:0;opacity:.8;display:none;font-size:.9em}.bookmark .bookmark-menu a:not(:last-child){margin-right:12px}.bookmark .bookmark-menu a:hover,.bookmark .bookmark-menu a:focus{color:var(--main);opacity:1}.bookmark .bookmark-menu .url{-webkit-box-flex:1;flex:1 0;opacity:1;display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;line-height:21px}.bookmark .bookmark-menu .url:not([href]){cursor:default;color:var(--colorLink)}.bookmark.list{border-top-width:0;border-bottom-width:1px;padding:16px 24px 16px 100px}.bookmark.list:first-child{border-top-width:1px}.bookmark.list .bookmark-link span.thumbnail{position:absolute;top:0;left:0;width:100px;height:100%;margin-bottom:0;border-bottom:0;border-right:1px solid var(--border)}.bookmark.list .bookmark-link .title{margin:0;padding-left:24px}.bookmark.list .excerpt,.bookmark.list>.spacer{display:none}.bookmark.list .bookmark-tags{padding-left:16px;padding-right:0}.bookmark.list .bookmark-menu{padding:8px 0 0 24px;-webkit-box-align:end;align-items:flex-end}@media (max-width:600px){.bookmark.list{padding:8px 16px 8px 70px;border-width:0 !important;border-bottom-width:1px !important}.bookmark.list .bookmark-link span.thumbnail{width:70px}.bookmark.list .bookmark-link .title{font-size:1.1em;font-weight:500;padding-left:16px}.bookmark.list .bookmark-tags{padding-left:8px}.bookmark.list .bookmark-menu{padding-left:16px}.bookmark.list .bookmark-menu a:not(:first-of-type){display:none}}
.bookmark{display:-webkit-box;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;flex-flow:column nowrap;min-width:0;border:1px solid var(--border);background-color:var(--contentBg);height:100%;position:relative}.bookmark:hover .bookmark-menu>a,.bookmark:focus .bookmark-menu>a{display:block}.bookmark.selected{background-color:var(--selectedBg)}.bookmark.public .title::after{content:"\f06e";width:1.25em;text-align:center;font-weight:900;font-family:"Font Awesome 5 Free";margin-left:8px;font-size:14px}.bookmark .bookmark-selector{position:absolute;top:0;left:0;width:100%;height:100%;z-index:9}.bookmark .bookmark-link{display:block;cursor:default}.bookmark .bookmark-link[href]{cursor:pointer}.bookmark .bookmark-link[href]:hover .title,.bookmark .bookmark-link[href]:focus .title{color:var(--main)}.bookmark .bookmark-link span.thumbnail{width:100%;height:200px;display:block;background-size:cover;background-repeat:no-repeat;background-position:center center;margin-bottom:8px;border-bottom:1px solid var(--border)}.bookmark .bookmark-link .id{color:var(--color);border:1px solid var(--border);background-color:var(--contentBg);font-size:.7em;font-weight:bold;left:-1px;top:-1px;position:absolute;padding:0 .3em;opacity:.7}.bookmark .bookmark-link .title{text-overflow:ellipsis;word-wrap:break-word;overflow:hidden;font-size:1.2em;line-height:1.3em;max-height:5.2em;font-weight:600;padding:0 16px;color:var(--color)}.bookmark .bookmark-link .title:first-child{margin-top:16px}.bookmark .bookmark-link .excerpt{color:var(--color);margin-top:8px;padding:0 16px;text-overflow:ellipsis;word-wrap:break-word;overflow:hidden;font-size:.9em;line-height:1.5em;max-height:10.5em}.bookmark .bookmark-tags{display:-webkit-box;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;flex-flow:row wrap;margin:4px 0 -4px;padding:0 8px}.bookmark .bookmark-tags a{margin:4px;padding:4px 8px;font-size:.8em;font-weight:600;border:1px solid var(--border);border-radius:4px;color:var(--colorLink);background-color:var(--contentBg)}.bookmark .bookmark-tags a:hover,.bookmark .bookmark-tags a:focus{color:var(--main)}.bookmark .bookmark-menu{padding:8px 16px 16px;display:-webkit-box;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;flex-flow:row nowrap;min-width:0;min-height:0;-webkit-box-align:center;align-items:center}.bookmark .bookmark-menu a{color:var(--colorLink);flex-shrink:0;opacity:.8;display:none;font-size:.9em}.bookmark .bookmark-menu a:not(:last-child){margin-right:12px}.bookmark .bookmark-menu a:hover,.bookmark .bookmark-menu a:focus{color:var(--main);opacity:1}.bookmark .bookmark-menu .url{-webkit-box-flex:1;flex:1 0;opacity:1;display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;line-height:21px}.bookmark .bookmark-menu .url:not([href]){cursor:default;color:var(--colorLink)}.bookmark.list{border-top-width:0;border-bottom-width:1px;padding:16px 24px 16px 100px}.bookmark.list:first-child{border-top-width:1px}.bookmark.list .bookmark-link span.thumbnail{position:absolute;top:0;left:0;width:100px;height:100%;margin-bottom:0;border-bottom:0;border-right:1px solid var(--border)}.bookmark.list .bookmark-link .title{margin:0;padding-left:24px}.bookmark.list .excerpt,.bookmark.list>.spacer{display:none}.bookmark.list .bookmark-tags{padding-left:16px;padding-right:0}.bookmark.list .bookmark-menu{padding:8px 0 0 24px;-webkit-box-align:end;align-items:flex-end}@media (max-width:600px){.bookmark.list{padding:8px 16px 8px 70px;border-width:0 !important;border-bottom-width:1px !important}.bookmark.list .bookmark-link span.thumbnail{width:70px}.bookmark.list .bookmark-link .title{font-size:1.1em;font-weight:500;padding-left:16px}.bookmark.list .bookmark-tags{padding-left:8px}.bookmark.list .bookmark-menu{padding-left:16px}.bookmark.list .bookmark-menu a:not(:first-of-type){display:none}}

View file

@ -1 +1 @@
:root{--dialogHeaderBg:#292929;--colorDialogHeader:#FFF}.custom-dialog-overlay{display:-webkit-box;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;flex-flow:column nowrap;-webkit-box-align:center;align-items:center;-webkit-box-pack:center;justify-content:center;min-width:0;min-height:0;overflow:hidden;position:fixed;top:0;left:0;width:100vw;height:100vh;z-index:10001;background-color:rgba(0,0,0,0.6);padding:32px}.custom-dialog-overlay .custom-dialog{display:-webkit-box;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;flex-flow:column nowrap;width:100%;max-width:400px;min-height:0;max-height:100%;overflow:auto;background-color:var(--contentBg);font-size:16px}.custom-dialog-overlay .custom-dialog .custom-dialog-header{padding:16px;color:var(--colorDialogHeader);background-color:var(--dialogHeaderBg);font-weight:600;font-size:1em;text-transform:uppercase;border-bottom:1px solid var(--border)}.custom-dialog-overlay .custom-dialog .custom-dialog-body{padding:16px 16px 0;display:grid;max-height:100%;min-height:80px;min-width:0;overflow:auto;font-size:1em;grid-template-columns:max-content 1fr;-webkit-box-align:baseline;align-items:baseline;grid-gap:16px}.custom-dialog-overlay .custom-dialog .custom-dialog-body::after{content:"";display:block;min-height:1px;grid-column-end:-1;grid-column-start:1}.custom-dialog-overlay .custom-dialog .custom-dialog-body .custom-dialog-content{grid-column-end:-1;grid-column-start:1;color:var(--color);align-self:baseline}.custom-dialog-overlay .custom-dialog .custom-dialog-body>label{color:var(--color);padding:8px 0;font-size:1em}.custom-dialog-overlay .custom-dialog .custom-dialog-body>input[type="text"],.custom-dialog-overlay .custom-dialog .custom-dialog-body>textarea{color:var(--color);padding:8px;font-size:1em;border:1px solid var(--border);background-color:var(--contentBg);min-width:0}.custom-dialog-overlay .custom-dialog .custom-dialog-body .checkbox-field{color:var(--color);font-size:1em;display:-webkit-box;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;flex-flow:row nowrap;-webkit-box-pack:center;justify-content:center;cursor:pointer}.custom-dialog-overlay .custom-dialog .custom-dialog-body .checkbox-field:hover,.custom-dialog-overlay .custom-dialog .custom-dialog-body .checkbox-field:focus{text-decoration:underline;-webkit-text-decoration-color:var(--main);text-decoration-color:var(--main)}.custom-dialog-overlay .custom-dialog .custom-dialog-body .checkbox-field>input[type="checkbox"]{margin-right:8px}.custom-dialog-overlay .custom-dialog .custom-dialog-body>textarea{height:6em;min-height:37px;resize:vertical}.custom-dialog-overlay .custom-dialog .custom-dialog-body>.suggestion{position:absolute;display:block;padding:8px;background-color:var(--contentBg);border:1px solid var(--border);color:var(--color);font-size:.9em}.custom-dialog-overlay .custom-dialog .custom-dialog-footer{padding:16px;display:-webkit-box;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;flex-flow:row wrap;-webkit-box-pack:end;justify-content:flex-end;border-top:1px solid var(--border)}.custom-dialog-overlay .custom-dialog .custom-dialog-footer>a{padding:0 8px;font-size:.9em;font-weight:600;color:var(--color);text-transform:uppercase}.custom-dialog-overlay .custom-dialog .custom-dialog-footer>a:hover,.custom-dialog-overlay .custom-dialog .custom-dialog-footer>a:focus{outline:none;color:var(--main)}.custom-dialog-overlay .custom-dialog .custom-dialog-footer>i.fa-spinner.fa-spin{width:19px;line-height:19px;text-align:center;color:var(--color)}
:root{--dialogHeaderBg:#292929;--colorDialogHeader:#FFF}.custom-dialog-overlay{display:-webkit-box;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;flex-flow:column nowrap;-webkit-box-align:center;align-items:center;-webkit-box-pack:center;justify-content:center;min-width:0;min-height:0;overflow:hidden;position:fixed;top:0;left:0;width:100vw;height:100vh;z-index:10001;background-color:rgba(0,0,0,0.6);padding:32px}.custom-dialog-overlay .custom-dialog{display:-webkit-box;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;flex-flow:column nowrap;width:100%;max-width:400px;min-height:0;max-height:100%;overflow:auto;background-color:var(--contentBg);font-size:16px}.custom-dialog-overlay .custom-dialog .custom-dialog-header{padding:16px;color:var(--colorDialogHeader);background-color:var(--dialogHeaderBg);font-weight:600;font-size:1em;text-transform:uppercase;border-bottom:1px solid var(--border)}.custom-dialog-overlay .custom-dialog .custom-dialog-body{padding:16px 16px 0;display:grid;max-height:100%;min-height:80px;min-width:0;overflow:auto;font-size:1em;grid-template-columns:max-content 1fr;-webkit-box-align:baseline;align-items:baseline;grid-gap:16px}.custom-dialog-overlay .custom-dialog .custom-dialog-body::after{content:"";display:block;min-height:1px;grid-column-end:-1;grid-column-start:1}.custom-dialog-overlay .custom-dialog .custom-dialog-body .custom-dialog-content{grid-column-end:-1;grid-column-start:1;color:var(--color);align-self:baseline}.custom-dialog-overlay .custom-dialog .custom-dialog-body>label{color:var(--color);padding:8px 0;font-size:1em}.custom-dialog-overlay .custom-dialog .custom-dialog-body>input[type="text"],.custom-dialog-overlay .custom-dialog .custom-dialog-body>textarea{color:var(--color);padding:8px;font-size:1em;border:1px solid var(--border);background-color:var(--contentBg);min-width:0}.custom-dialog-overlay .custom-dialog .custom-dialog-body .checkbox-field{color:var(--color);font-size:1em;display:-webkit-box;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;flex-flow:row nowrap;padding:0;grid-column-start:1;grid-column-end:-1;cursor:pointer}.custom-dialog-overlay .custom-dialog .custom-dialog-body .checkbox-field:hover,.custom-dialog-overlay .custom-dialog .custom-dialog-body .checkbox-field:focus{text-decoration:underline;-webkit-text-decoration-color:var(--main);text-decoration-color:var(--main)}.custom-dialog-overlay .custom-dialog .custom-dialog-body .checkbox-field>input[type="checkbox"]{margin-right:8px}.custom-dialog-overlay .custom-dialog .custom-dialog-body>textarea{height:6em;min-height:37px;resize:vertical}.custom-dialog-overlay .custom-dialog .custom-dialog-body>.suggestion{position:absolute;display:block;padding:8px;background-color:var(--contentBg);border:1px solid var(--border);color:var(--color);font-size:.9em}.custom-dialog-overlay .custom-dialog .custom-dialog-footer{padding:16px;display:-webkit-box;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;flex-flow:row wrap;-webkit-box-pack:end;justify-content:flex-end;border-top:1px solid var(--border)}.custom-dialog-overlay .custom-dialog .custom-dialog-footer>a{padding:0 8px;font-size:.9em;font-weight:600;color:var(--color);text-transform:uppercase}.custom-dialog-overlay .custom-dialog .custom-dialog-footer>a:hover,.custom-dialog-overlay .custom-dialog .custom-dialog-footer>a:focus{outline:none;color:var(--main)}.custom-dialog-overlay .custom-dialog .custom-dialog-footer>i.fa-spinner.fa-spin{width:19px;line-height:19px;text-align:center;color:var(--color)}

File diff suppressed because one or more lines are too long

View file

@ -110,13 +110,15 @@
showId = (typeof opts.showId === "boolean") ? opts.showId : false,
listMode = (typeof opts.listMode === "boolean") ? opts.listMode : false,
nightMode = (typeof opts.nightMode === "boolean") ? opts.nightMode : false,
useArchive = (typeof opts.useArchive === "boolean") ? opts.useArchive : false;
useArchive = (typeof opts.useArchive === "boolean") ? opts.useArchive : false,
makePublic = (typeof opts.makePublic === "boolean") ? opts.makePublic : false;
this.displayOptions = {
showId: showId,
listMode: listMode,
nightMode: nightMode,
useArchive: useArchive,
makePublic: makePublic,
};
document.body.className = nightMode ? "night" : "";

View file

@ -1,5 +1,5 @@
var template = `
<div class="bookmark" :class="{list: listMode, selected: selected}">
<div class="bookmark" :class="{list: listMode, selected: selected, public: public >= 1}">
<a class="bookmark-selector"
v-if="editMode"
@click="selectBookmark">
@ -39,6 +39,7 @@ export default {
url: String,
title: String,
excerpt: String,
public: Number,
imageURL: String,
hasContent: Boolean,
hasArchive: Boolean,

View file

@ -6,7 +6,7 @@ var template = `
<slot>
<p class="custom-dialog-content">{{content}}</p>
<template v-for="(field,index) in formFields">
<label v-if="showLabel">{{field.label}} :</label>
<label v-if="showLabel && field.type !== 'check'">{{field.label}} :</label>
<textarea v-if="field.type === 'area'"
:style="{gridColumnEnd: showLabel ? null : 'span 2'}"
:placeholder="field.label"

View file

@ -8,6 +8,7 @@ export default {
listMode: false,
nightMode: false,
useArchive: false,
makePublic: false,
};
}
}

View file

@ -38,7 +38,14 @@ var template = `
@change="changePage">
</pagination-box>
<bookmark-item v-for="(book, index) in bookmarks"
v-bind="book"
:id="book.id"
:url="book.url"
:title="book.title"
:excerpt="book.excerpt"
:public="book.public"
:imageURL="book.imageURL"
:hasContent="book.hasContent"
:hasArchive="book.hasArchive"
:index="index"
:key="book.id"
:editMode="editMode"
@ -303,6 +310,11 @@ export default {
label: "Create archive",
type: "check",
value: this.displayOptions.useArchive,
}, {
name: "makePublic",
label: "Make archive publicly available",
type: "check",
value: this.displayOptions.makePublic,
}],
mainText: "OK",
secondText: "Cancel",
@ -330,6 +342,7 @@ export default {
url: data.url.trim(),
title: data.title.trim(),
excerpt: data.excerpt.trim(),
public: data.makePublic ? 1 : 0,
tags: tags,
createArchive: data.createArchive,
};
@ -396,6 +409,11 @@ export default {
value: strTags,
separator: ",",
dictionary: this.tags.map(tag => tag.name)
}, {
name: "makePublic",
label: "Make archive publicly available",
type: "check",
value: book.public >= 1,
}],
mainText: "OK",
secondText: "Cancel",
@ -419,6 +437,7 @@ export default {
book.url = data.url.trim();
book.title = data.title.trim();
book.excerpt = data.excerpt.trim();
book.public = data.makePublic ? 1 : 0;
book.tags = tags;
// Send data

View file

@ -21,6 +21,17 @@ var template = `
Create archive by default
</label>
</details>
<details open class="setting-group" id="setting-bookmarks">
<summary>Bookmarks</summary>
<label>
<input type="checkbox" v-model="displayOptions.useArchive" @change="saveSetting">
Create archive by default
</label>
<label>
<input type="checkbox" v-model="displayOptions.makePublic" @change="saveSetting">
Make archive publicly available by default
</label>
</details>
<details open class="setting-group" id="setting-accounts">
<summary>Accounts</summary>
<ul>
@ -67,6 +78,7 @@ export default {
listMode: this.displayOptions.listMode,
nightMode: this.displayOptions.nightMode,
useArchive: this.displayOptions.useArchive,
makePublic: this.displayOptions.makePublic,
});
},
loadAccounts() {

View file

@ -18,6 +18,16 @@
background-color: var(--selectedBg);
}
&.public .title::after {
content: "\f06e";
width: 1.25em;
text-align: center;
font-weight: 900;
font-family: "Font Awesome 5 Free";
margin-left: 8px;
font-size: 14px;
}
.bookmark-selector {
position: absolute;
top: 0;

View file

@ -89,7 +89,9 @@
font-size: 1em;
display: flex;
flex-flow: row nowrap;
justify-content: center;
padding: 0;
grid-column-start: 1;
grid-column-end: -1;
cursor: pointer;
&:hover,

View file

@ -707,7 +707,8 @@ a {
}
}
#setting-display {
#setting-display,
#setting-bookmarks {
display: flex;
flex-flow: column nowrap;

View file

@ -18,6 +18,7 @@
<link href="/css/stylesheet.css" rel="stylesheet">
<script src="/js/vue.min.js"></script>
<script src="/js/url.min.js"></script>
</head>
<body>
@ -86,7 +87,8 @@
return response;
})
.then(() => {
location.href = "/";
var dst = (new Url).query.dst;
location.href = dst || "/";
})
.catch(err => {
this.loading = false;
@ -105,9 +107,6 @@
mounted() {
// Load setting
this.loadSetting();
// Set initial URL
history.replaceState(null, "login", "login");
}
})
</script>

File diff suppressed because one or more lines are too long

View file

@ -414,6 +414,7 @@ func (h *handler) apiUpdateBookmark(w http.ResponseWriter, r *http.Request, ps h
book.URL = request.URL
book.Title = request.Title
book.Excerpt = request.Excerpt
book.Public = request.Public
// Set new tags
for i := range book.Tags {

View file

@ -7,6 +7,7 @@ import (
"html/template"
"io"
"net/http"
nurl "net/url"
"os"
"path"
fp "path/filepath"
@ -82,6 +83,21 @@ func (h *handler) serveBookmarkContent(w http.ResponseWriter, r *http.Request, p
panic(fmt.Errorf("Bookmark not found"))
}
// If it's not public, make sure session still valid
if bookmark.Public != 1 {
err = h.validateSession(r)
if err != nil {
urlQueries := nurl.Values{}
urlQueries.Set("dst", r.URL.Path)
redirectURL, _ := nurl.Parse("/login")
redirectURL.RawQuery = urlQueries.Encode()
redirectPage(w, r, redirectURL.String())
return
}
}
// Check if it has archive
archivePath := fp.Join(h.DataDir, "archive", strID)
if fileExists(archivePath) {
@ -144,6 +160,21 @@ func (h *handler) serveBookmarkArchive(w http.ResponseWriter, r *http.Request, p
panic(fmt.Errorf("Bookmark not found"))
}
// If it's not public, make sure session still valid
if bookmark.Public != 1 {
err = h.validateSession(r)
if err != nil {
urlQueries := nurl.Values{}
urlQueries.Set("dst", r.URL.Path)
redirectURL, _ := nurl.Parse("/login")
redirectURL.RawQuery = urlQueries.Encode()
redirectPage(w, r, redirectURL.String())
return
}
}
// Open archive, look in cache first
var archive *warc.Archive
cacheData, found := h.ArchiveCache.Get(strID)