aboutsummaryrefslogtreecommitdiff
path: root/front-end/src
diff options
context:
space:
mode:
Diffstat (limited to 'front-end/src')
-rw-r--r--front-end/src/App.vue2
-rw-r--r--front-end/src/components/Bookmarks.vue27
-rw-r--r--front-end/src/components/Login/PkiLogin.vue2
-rw-r--r--front-end/src/components/Settings.vue9
-rw-r--r--front-end/src/components/Settings/Bookmarks.vue33
-rw-r--r--front-end/src/components/Settings/PkiSettings.vue2
-rw-r--r--front-end/src/components/Settings/TotpSettings.vue2
-rw-r--r--front-end/src/components/global/PasswordPrompt.vue2
-rw-r--r--front-end/src/index.scss2
-rw-r--r--front-end/src/store/bookmarks.ts12
10 files changed, 65 insertions, 28 deletions
diff --git a/front-end/src/App.vue b/front-end/src/App.vue
index f63f9ca..01e91e7 100644
--- a/front-end/src/App.vue
+++ b/front-end/src/App.vue
@@ -36,7 +36,7 @@ const showIf = (tabId: TabId, active: TabId) => isEqual(tabId, active)
<title>{{ siteTitle }}</title>
</head>
<body>
- <div id="app" class="min-h-screen pb-16 text-gray-700 bg-gray-100 dark:bg-gray-900 dark:text-white sm:pb-0">
+ <div id="app" class="min-h-screen pb-16 text-gray-700 bg-gray-50 dark:bg-gray-900 dark:text-white sm:pb-0">
<div class="relative">
<div class="absolute z-50 right-10 top-10">
diff --git a/front-end/src/components/Bookmarks.vue b/front-end/src/components/Bookmarks.vue
index 34c31a8..93ddd73 100644
--- a/front-end/src/components/Bookmarks.vue
+++ b/front-end/src/components/Bookmarks.vue
@@ -1,7 +1,7 @@
<script setup lang="ts">
import { MaybeRef, Ref, computed, defineAsyncComponent, ref, shallowRef, watch } from 'vue';
import { useQuery, useStore } from '../store';
-import { get, set, formatTimeAgo, useToggle, useTimestamp, useFileDialog, asyncComputed, toReactive } from '@vueuse/core';
+import { get, set, formatTimeAgo, useToggle, useTimestamp, useFileDialog, asyncComputed, toReactive, useClipboard } from '@vueuse/core';
import { useVuelidate } from '@vuelidate/core';
import { required, maxLength, minLength, helpers } from '@vuelidate/validators';
import { apiCall, useConfirm, useGeneralToaster, useVuelidateWrapper, useWait } from '@vnuge/vnlib.browser';
@@ -22,6 +22,7 @@ const now = useTimestamp({interval: 1000});
const selectedTags = computed(() => store.bookmarks.tags);
const localSearch = shallowRef<string>(store.bookmarks.query);
const nextPageAvailable = computed(() => isEqual(bookmarks.value?.length, get(store.bookmarks.pages.currentPageSize)));
+const { copy } = useClipboard()
//Refresh on page load
store.bookmarks.refresh();
@@ -399,25 +400,6 @@ const upload = (() => {
</MenuItems>
</transition>
</Menu>
-
- <!-- Dropdown menu -->
- <div id="dropdown" class="z-10 hidden bg-white divide-y divide-gray-100 rounded-lg shadow w-44 dark:bg-gray-700">
- <ul class="py-2 text-sm text-gray-700 dark:text-gray-200" aria-labelledby="dropdownDefaultButton">
- <li>
- <a href="#" class="block px-4 py-2 hover:bg-gray-100 dark:hover:bg-gray-600 dark:hover:text-white">Dashboard</a>
- </li>
- <li>
- <a href="#" class="block px-4 py-2 hover:bg-gray-100 dark:hover:bg-gray-600 dark:hover:text-white">Settings</a>
- </li>
- <li>
- <a href="#" class="block px-4 py-2 hover:bg-gray-100 dark:hover:bg-gray-600 dark:hover:text-white">Earnings</a>
- </li>
- <li>
- <a href="#" class="block px-4 py-2 hover:bg-gray-100 dark:hover:bg-gray-600 dark:hover:text-white">Sign out</a>
- </li>
- </ul>
- </div>
-
</div>
</div>
<div class="grid flex-auto grid-cols-4 gap-8 mt-4 max-w-[60rem] mx-auto w-full">
@@ -457,6 +439,9 @@ const upload = (() => {
</span>
|
<span class="inline-flex gap-1.5">
+ <button class="text-xs text-gray-700 dark:text-gray-400" @click="copy(bm.Url)">
+ Copy
+ </button>
<button class="text-xs text-gray-700 dark:text-gray-400" @click="edit.editBookmark(bm)">
Edit
</button>
@@ -595,7 +580,7 @@ const upload = (() => {
<style scoped lang="scss">
input.search{
@apply ps-10 p-2.5 border block w-full text-sm rounded pe-10;
- @apply bg-gray-50 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500 border-gray-300 text-gray-900 focus:ring-blue-500 focus:border-blue-500 ;
+ @apply bg-white dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500 border-gray-300 text-gray-900 focus:ring-blue-500 focus:border-blue-500 ;
}
button.search{
diff --git a/front-end/src/components/Login/PkiLogin.vue b/front-end/src/components/Login/PkiLogin.vue
index 26528c4..4515062 100644
--- a/front-end/src/components/Login/PkiLogin.vue
+++ b/front-end/src/components/Login/PkiLogin.vue
@@ -39,7 +39,7 @@ const onSubmit = () => {
<textarea
id="message" rows="5"
v-model="otp"
- class="block p-2.5 w-full text-sm text-gray-900 bg-gray-50 rounded border border-gray-300 focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
+ class="block p-2.5 w-full text-sm text-gray-900 bg-transparent rounded border border-gray-300 focus:ring-blue-500 focus:border-blue-500 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
placeholder="Enter your OTP"
>
</textarea>
diff --git a/front-end/src/components/Settings.vue b/front-end/src/components/Settings.vue
index e03ae61..720c556 100644
--- a/front-end/src/components/Settings.vue
+++ b/front-end/src/components/Settings.vue
@@ -5,6 +5,7 @@ import Oauth2Apps from './Settings/Oauth2Apps.vue';
import PasswordReset from './Settings/PasswordReset.vue';
import PkiSettings from './Settings/PkiSettings.vue';
import TotpSettings from './Settings/TotpSettings.vue';
+import Bookmarks from './Settings/Bookmarks.vue';
const store = useStore();
const darkMode = useDark();
@@ -38,6 +39,14 @@ const darkMode = useDark();
</div>
</div>
+ <div class="">
+ <h3 class="text-xl font-bold">Boomarks</h3>
+
+ <div class="relative mt-4">
+ <Bookmarks />
+ </div>
+ </div>
+
<PasswordReset />
<div class="">
diff --git a/front-end/src/components/Settings/Bookmarks.vue b/front-end/src/components/Settings/Bookmarks.vue
new file mode 100644
index 0000000..68fa86b
--- /dev/null
+++ b/front-end/src/components/Settings/Bookmarks.vue
@@ -0,0 +1,33 @@
+<script setup lang="ts">
+import { apiCall, useWait } from '@vnuge/vnlib.browser';
+import { useStore } from '../../store';
+import { useObjectUrl, set } from '@vueuse/core';
+import { ref } from 'vue';
+
+const { bookmarks } = useStore();
+
+const blobUrl = ref<Blob>();
+const downloadAnchor = ref();
+const obj = useObjectUrl(blobUrl);
+const { waiting } = useWait()
+
+const downloadBookmarks = () => {
+ apiCall(async () => {
+ const htmlData = await bookmarks.api.downloadAll();
+ const blob = new Blob([htmlData], { type: 'text/html' });
+ set(blobUrl, blob);
+ downloadAnchor.value?.click();
+ });
+}
+
+</script>
+<template>
+ <div class="flex flex-row justify-start">
+ <div class="">
+ <button class="flex items-center btn light" :disabled="waiting" @click="downloadBookmarks()">
+ Download
+ </button>
+ </div>
+ </div>
+ <a ref="downloadAnchor" :href="obj" download="bookmarks.html" class="hidden"></a>
+</template> \ No newline at end of file
diff --git a/front-end/src/components/Settings/PkiSettings.vue b/front-end/src/components/Settings/PkiSettings.vue
index 5fa5c93..2564cf6 100644
--- a/front-end/src/components/Settings/PkiSettings.vue
+++ b/front-end/src/components/Settings/PkiSettings.vue
@@ -142,7 +142,7 @@ const onAddKey = async () => {
</div>
</div>
- <div class="relative mt-2 overflow-x-auto shadow-md sm:rounded">
+ <div class="relative mt-4 overflow-x-auto shadow-md sm:rounded">
<table class="w-full text-sm text-left text-gray-500 rtl:text-right dark:text-gray-400">
<thead class="text-xs text-gray-700 uppercase bg-gray-50 dark:bg-gray-700 dark:text-gray-400">
<tr>
diff --git a/front-end/src/components/Settings/TotpSettings.vue b/front-end/src/components/Settings/TotpSettings.vue
index 1d79914..0019a9d 100644
--- a/front-end/src/components/Settings/TotpSettings.vue
+++ b/front-end/src/components/Settings/TotpSettings.vue
@@ -114,7 +114,7 @@ const onVerifyOtp = async (code: string) => {
</span>
</div>
<div v-if="totpEnabled" class="flex">
- <button class="btn light">
+ <button class="btn light" @click="addOrUpdate()">
Regenerate
</button>
<button class="btn red" @click="disableTotp()">
diff --git a/front-end/src/components/global/PasswordPrompt.vue b/front-end/src/components/global/PasswordPrompt.vue
index d638c71..50024fb 100644
--- a/front-end/src/components/global/PasswordPrompt.vue
+++ b/front-end/src/components/global/PasswordPrompt.vue
@@ -79,7 +79,7 @@ onReveal(m => message.value = defaultTo(m, {}));
type="password"
id="password"
v-model.trim="v$.password.$model"
- class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
+ class="bg-transparent border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
placeholder="•••••••••"
required
>
diff --git a/front-end/src/index.scss b/front-end/src/index.scss
index fece9ee..5575eb3 100644
--- a/front-end/src/index.scss
+++ b/front-end/src/index.scss
@@ -16,7 +16,7 @@
}
.input {
- @apply bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded focus:ring-blue-500 focus:border-blue-500 block w-full p-2 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500;
+ @apply bg-transparent border border-gray-300 text-gray-900 text-sm rounded focus:ring-blue-500 focus:border-blue-500 block w-full p-2 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500;
&.dirty{
@apply bg-green-50 border-green-500 text-green-900 dark:text-green-400 placeholder-green-700 dark:placeholder-green-500 focus:ring-green-500 focus:border-green-500 dark:bg-gray-700 dark:border-green-500;
diff --git a/front-end/src/store/bookmarks.ts b/front-end/src/store/bookmarks.ts
index b6430f7..b0595e9 100644
--- a/front-end/src/store/bookmarks.ts
+++ b/front-end/src/store/bookmarks.ts
@@ -51,6 +51,7 @@ export interface BookmarkApi{
getTags: () => Promise<string[]>
delete: (bookmark: Bookmark | Bookmark[]) => Promise<void>
count: () => Promise<number>
+ downloadAll: () => Promise<string>
}
export interface BookmarkSearch{
@@ -140,6 +141,14 @@ const useBookmarkApi = (endpoint: MaybeRef<string>): BookmarkApi => {
return data.result;
}
+ const downloadAll = async () => {
+ //download the bookmarks as a html file
+ const { data } = await axios.get<string>(`${get(endpoint)}?export=true`, {
+ headers: { 'Content-Type': 'application/htlm' }
+ })
+ return data;
+ }
+
return {
list: listBookmarks,
add: addBookmark,
@@ -147,7 +156,8 @@ const useBookmarkApi = (endpoint: MaybeRef<string>): BookmarkApi => {
delete: deleteBookmark,
count: getItemsCount,
addMany,
- getTags
+ getTags,
+ downloadAll
}
}