add supabase editor
This commit is contained in:
1 parent
7c48643759
commit
58240ff520
6 files changed
+183
-5
No files matched your search
@@ -65,6 +65,7 @@ export default defineConfig({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
vite: {
|
vite: {
|
||||||
|
envDir: process.cwd(),
|
||||||
ssr: {
|
ssr: {
|
||||||
noExternal: [],
|
noExternal: [],
|
||||||
external: ["pdfjs-dist"], // don't bundle it for SSR — leave it browser-only
|
external: ["pdfjs-dist"], // don't bundle it for SSR — leave it browser-only
|
||||||
|
|||||||
@@ -100,6 +100,7 @@ import {
|
|||||||
watch,
|
watch,
|
||||||
} from "vue";
|
} from "vue";
|
||||||
import SentenceAudio, { IVoc } from "./SentenceAudio.vue";
|
import SentenceAudio, { IVoc } from "./SentenceAudio.vue";
|
||||||
|
import { supabase } from "../supabase.ts";
|
||||||
|
|
||||||
const { fmKey = "vocabulary" } = defineProps<{
|
const { fmKey = "vocabulary" } = defineProps<{
|
||||||
fmKey?: string;
|
fmKey?: string;
|
||||||
@@ -131,7 +132,7 @@ const example = computed(() => {
|
|||||||
|
|
||||||
const MAX_VOC = 5;
|
const MAX_VOC = 5;
|
||||||
|
|
||||||
const { frontmatter } = useData();
|
const { frontmatter, page } = useData();
|
||||||
|
|
||||||
const vocabulary: Record<string, IVoc[]> = {};
|
const vocabulary: Record<string, IVoc[]> = {};
|
||||||
|
|
||||||
@@ -148,7 +149,6 @@ for (const fk of fmKey.split(/[, ]+/g)) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
vChosenCats.value = [...vCats.value];
|
vChosenCats.value = [...vCats.value];
|
||||||
makeVList();
|
|
||||||
|
|
||||||
watch(isKoFirst, () => {
|
watch(isKoFirst, () => {
|
||||||
makeVList();
|
makeVList();
|
||||||
@@ -238,8 +238,46 @@ function updateCats(cat: string) {
|
|||||||
makeVList();
|
makeVList();
|
||||||
}
|
}
|
||||||
|
|
||||||
function onVContentSave() {
|
async function onVContentSave() {
|
||||||
const newV = { ko: v.value.ko, ...JSON.parse(vEditContent.value) };
|
const oldV = v.value;
|
||||||
|
const newV = { ko: oldV.ko, ...JSON.parse(vEditContent.value) };
|
||||||
|
|
||||||
|
let key = "";
|
||||||
|
let vKey = oldV.ko;
|
||||||
|
|
||||||
|
Object.entries(vocabulary).map(([k, vs]) => {
|
||||||
|
const vCount = new Map<string, number>();
|
||||||
|
|
||||||
|
vs.map((v, i_vs) => {
|
||||||
|
let vK = v.ko;
|
||||||
|
let i = vCount.get(v.ko) || 0;
|
||||||
|
if (i) {
|
||||||
|
vK = vK + `(${i})`;
|
||||||
|
}
|
||||||
|
vCount.set(v.ko, i + 1);
|
||||||
|
|
||||||
|
if (oldV.ko === v.ko && oldV.en === v.en) {
|
||||||
|
key = k;
|
||||||
|
vKey = vK;
|
||||||
|
|
||||||
|
vocabulary[k][i_vs] = newV;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
if (supabase && key) {
|
||||||
|
const user_id = await supabase.auth.getUser().then((r) => r.data.user?.id);
|
||||||
|
|
||||||
|
await supabase.from("quiz").upsert(
|
||||||
|
{
|
||||||
|
url: page.value.filePath,
|
||||||
|
key,
|
||||||
|
v: vKey,
|
||||||
|
data: newV,
|
||||||
|
user_id,
|
||||||
|
},
|
||||||
|
{ onConflict: "url,key,v,user_id" },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const newVList = [...vList.value];
|
const newVList = [...vList.value];
|
||||||
newVList[vIndex.value] = newV;
|
newVList[vIndex.value] = newV;
|
||||||
@@ -259,8 +297,40 @@ function onModalClickOutside(ev: MouseEvent) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(async () => {
|
||||||
document.addEventListener("click", onModalClickOutside);
|
document.addEventListener("click", onModalClickOutside);
|
||||||
|
|
||||||
|
if (supabase) {
|
||||||
|
await supabase
|
||||||
|
.from("quiz")
|
||||||
|
.select<any, { v: string; data: IVoc }>("v,data")
|
||||||
|
.eq("url", page.value.filePath)
|
||||||
|
.then((r) => {
|
||||||
|
if (!r.data?.length) return;
|
||||||
|
|
||||||
|
const replacement = new Map<string, IVoc>();
|
||||||
|
for (const { v, data } of r.data) {
|
||||||
|
replacement.set(v, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.entries(vocabulary).map(([k, vs]) => {
|
||||||
|
const vCount = new Map<string, number>();
|
||||||
|
|
||||||
|
vocabulary[k] = vs.map((v) => {
|
||||||
|
let vKey = v.ko;
|
||||||
|
let i = vCount.get(v.ko) || 0;
|
||||||
|
if (i) {
|
||||||
|
vKey = vKey + `(${i})`;
|
||||||
|
}
|
||||||
|
vCount.set(v.ko, i + 1);
|
||||||
|
|
||||||
|
return replacement.get(vKey) || v;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
makeVList();
|
||||||
});
|
});
|
||||||
|
|
||||||
onBeforeUnmount(() => {
|
onBeforeUnmount(() => {
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import VocabQuiz from "./components/VocabQuiz.vue";
|
|||||||
import YouTube from "./components/YouTube.vue";
|
import YouTube from "./components/YouTube.vue";
|
||||||
|
|
||||||
import type { Theme } from "vitepress";
|
import type { Theme } from "vitepress";
|
||||||
|
import { signIn } from "./supabase.ts";
|
||||||
export default {
|
export default {
|
||||||
extends: DefaultTheme,
|
extends: DefaultTheme,
|
||||||
Layout: () => {
|
Layout: () => {
|
||||||
@@ -32,3 +33,8 @@ export default {
|
|||||||
// app.component("PDF", PDF);
|
// app.component("PDF", PDF);
|
||||||
},
|
},
|
||||||
} satisfies Theme;
|
} satisfies Theme;
|
||||||
|
|
||||||
|
//@ts-ignore
|
||||||
|
if (import.meta.env.SSR) {
|
||||||
|
signIn();
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
import { createClient } from "@supabase/supabase-js";
|
||||||
|
|
||||||
|
const {
|
||||||
|
VITE_SUPABASE_URL,
|
||||||
|
VITE_SUPABASE_PUBLISHABLE_KEY,
|
||||||
|
VITE_SUPABASE_USER,
|
||||||
|
VITE_SUPABASE_USER_PASSWORD,
|
||||||
|
} =
|
||||||
|
//@ts-ignore
|
||||||
|
import.meta.env;
|
||||||
|
|
||||||
|
export const supabase = [
|
||||||
|
VITE_SUPABASE_URL,
|
||||||
|
VITE_SUPABASE_PUBLISHABLE_KEY,
|
||||||
|
VITE_SUPABASE_USER,
|
||||||
|
VITE_SUPABASE_USER_PASSWORD,
|
||||||
|
].every((v) => v)
|
||||||
|
? createClient(VITE_SUPABASE_URL, VITE_SUPABASE_PUBLISHABLE_KEY)
|
||||||
|
: null;
|
||||||
|
|
||||||
|
export async function signIn() {
|
||||||
|
if (!supabase) return;
|
||||||
|
await supabase.auth.signInWithPassword({
|
||||||
|
email: VITE_SUPABASE_USER,
|
||||||
|
password: VITE_SUPABASE_USER_PASSWORD,
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -25,6 +25,7 @@
|
|||||||
"vue": "^3.5.39"
|
"vue": "^3.5.39"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@supabase/supabase-js": "^2.110.5",
|
||||||
"pdfjs-dist": "^5.7.284",
|
"pdfjs-dist": "^5.7.284",
|
||||||
"tauri-plugin-tts-api": "^0.1.11"
|
"tauri-plugin-tts-api": "^0.1.11"
|
||||||
}
|
}
|
||||||
|
|||||||
Generated
+73
@@ -8,6 +8,9 @@ importers:
|
|||||||
|
|
||||||
.:
|
.:
|
||||||
dependencies:
|
dependencies:
|
||||||
|
'@supabase/supabase-js':
|
||||||
|
specifier: ^2.110.5
|
||||||
|
version: 2.110.5
|
||||||
pdfjs-dist:
|
pdfjs-dist:
|
||||||
specifier: ^5.7.284
|
specifier: ^5.7.284
|
||||||
version: 5.7.284
|
version: 5.7.284
|
||||||
@@ -458,6 +461,33 @@ packages:
|
|||||||
'@shikijs/vscode-textmate@10.0.2':
|
'@shikijs/vscode-textmate@10.0.2':
|
||||||
resolution: {integrity: sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==}
|
resolution: {integrity: sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==}
|
||||||
|
|
||||||
|
'@supabase/auth-js@2.110.5':
|
||||||
|
resolution: {integrity: sha512-QSlI5CNeEefHP95/GbeMhNgr8aHEHiXFh8c1IWthYyI9ZzBwEigYzJFCw4Ff+GkL8OK9tArBmGGv6rpg5zLXSw==}
|
||||||
|
engines: {node: '>=22.0.0'}
|
||||||
|
|
||||||
|
'@supabase/functions-js@2.110.5':
|
||||||
|
resolution: {integrity: sha512-nuQuoIoEGT8ukrwr6THlY5v50bSMJ2rqti1FFsGyDaC98POLmcFQVFFh23PVPhRsKWUxrFc0MpmEoHKa7CY4mg==}
|
||||||
|
engines: {node: '>=22.0.0'}
|
||||||
|
|
||||||
|
'@supabase/phoenix@0.4.4':
|
||||||
|
resolution: {integrity: sha512-Gt0pqoXuIqX/8dvG0OKp/wMCobXNH3klNbUPBNyOfN0YA1IswrM3HyWFMOPk1Jy+BRaIyDPcFx4jLBwHNmlyfQ==}
|
||||||
|
|
||||||
|
'@supabase/postgrest-js@2.110.5':
|
||||||
|
resolution: {integrity: sha512-eObfgBjxLPzFakwMpUmsv8nuNPOhoDhzzN8cwvEvGkxkmuRIZcOCYH9+DRbpKnxh7tgsBZW+KWtaZI2j98b2/g==}
|
||||||
|
engines: {node: '>=22.0.0'}
|
||||||
|
|
||||||
|
'@supabase/realtime-js@2.110.5':
|
||||||
|
resolution: {integrity: sha512-VtOZxw5jfrc37KgIfFdp9SOFJjtvJ0qU+gT8CPQjL7cqy4DJlaTXacw5aBBogLZksqAI0YN67qhlDaMKFwfOuw==}
|
||||||
|
engines: {node: '>=22.0.0'}
|
||||||
|
|
||||||
|
'@supabase/storage-js@2.110.5':
|
||||||
|
resolution: {integrity: sha512-7GkOZlrYknVGVPyijoDbu5OXGvQ2oQ6dkU0juAkIMPZ9QgtmJ8IPrxe76zGSbmzbaC1GdKw7pqeXEi2HT67sbA==}
|
||||||
|
engines: {node: '>=22.0.0'}
|
||||||
|
|
||||||
|
'@supabase/supabase-js@2.110.5':
|
||||||
|
resolution: {integrity: sha512-cAO1Nm+CCogRNVXN93bBkh0vjOdLM5e6J9gB/cHV9Lqni/gEmN2HJFrnn4NI33GYIfmlh4Wbm6siH+XXRgpexA==}
|
||||||
|
engines: {node: '>=22.0.0'}
|
||||||
|
|
||||||
'@tauri-apps/api@2.11.1':
|
'@tauri-apps/api@2.11.1':
|
||||||
resolution: {integrity: sha512-M2FPuYND2m+wh5hfW9ZpSdxMPdEJovPBWwoHJmwUpysTYNHaOkVFN419m/K0LIgjb/7KU2vBgsUepJWugQCvAA==}
|
resolution: {integrity: sha512-M2FPuYND2m+wh5hfW9ZpSdxMPdEJovPBWwoHJmwUpysTYNHaOkVFN419m/K0LIgjb/7KU2vBgsUepJWugQCvAA==}
|
||||||
|
|
||||||
@@ -730,6 +760,10 @@ packages:
|
|||||||
html-void-elements@3.0.0:
|
html-void-elements@3.0.0:
|
||||||
resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==}
|
resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==}
|
||||||
|
|
||||||
|
iceberg-js@0.8.1:
|
||||||
|
resolution: {integrity: sha512-1dhVQZXhcHje7798IVM+xoo/1ZdVfzOMIc8/rgVSijRK38EDqOJoGula9N/8ZI5RD8QTxNQtK/Gozpr+qUqRRA==}
|
||||||
|
engines: {node: '>=20.0.0'}
|
||||||
|
|
||||||
magic-string@0.30.21:
|
magic-string@0.30.21:
|
||||||
resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==}
|
resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==}
|
||||||
|
|
||||||
@@ -829,6 +863,9 @@ packages:
|
|||||||
trim-lines@3.0.1:
|
trim-lines@3.0.1:
|
||||||
resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==}
|
resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==}
|
||||||
|
|
||||||
|
tslib@2.8.1:
|
||||||
|
resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
|
||||||
|
|
||||||
unist-util-is@6.0.1:
|
unist-util-is@6.0.1:
|
||||||
resolution: {integrity: sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==}
|
resolution: {integrity: sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==}
|
||||||
|
|
||||||
@@ -1186,6 +1223,38 @@ snapshots:
|
|||||||
|
|
||||||
'@shikijs/vscode-textmate@10.0.2': {}
|
'@shikijs/vscode-textmate@10.0.2': {}
|
||||||
|
|
||||||
|
'@supabase/auth-js@2.110.5':
|
||||||
|
dependencies:
|
||||||
|
tslib: 2.8.1
|
||||||
|
|
||||||
|
'@supabase/functions-js@2.110.5':
|
||||||
|
dependencies:
|
||||||
|
tslib: 2.8.1
|
||||||
|
|
||||||
|
'@supabase/phoenix@0.4.4': {}
|
||||||
|
|
||||||
|
'@supabase/postgrest-js@2.110.5':
|
||||||
|
dependencies:
|
||||||
|
tslib: 2.8.1
|
||||||
|
|
||||||
|
'@supabase/realtime-js@2.110.5':
|
||||||
|
dependencies:
|
||||||
|
'@supabase/phoenix': 0.4.4
|
||||||
|
tslib: 2.8.1
|
||||||
|
|
||||||
|
'@supabase/storage-js@2.110.5':
|
||||||
|
dependencies:
|
||||||
|
iceberg-js: 0.8.1
|
||||||
|
tslib: 2.8.1
|
||||||
|
|
||||||
|
'@supabase/supabase-js@2.110.5':
|
||||||
|
dependencies:
|
||||||
|
'@supabase/auth-js': 2.110.5
|
||||||
|
'@supabase/functions-js': 2.110.5
|
||||||
|
'@supabase/postgrest-js': 2.110.5
|
||||||
|
'@supabase/realtime-js': 2.110.5
|
||||||
|
'@supabase/storage-js': 2.110.5
|
||||||
|
|
||||||
'@tauri-apps/api@2.11.1': {}
|
'@tauri-apps/api@2.11.1': {}
|
||||||
|
|
||||||
'@tauri-apps/cli-darwin-arm64@2.11.4':
|
'@tauri-apps/cli-darwin-arm64@2.11.4':
|
||||||
@@ -1438,6 +1507,8 @@ snapshots:
|
|||||||
|
|
||||||
html-void-elements@3.0.0: {}
|
html-void-elements@3.0.0: {}
|
||||||
|
|
||||||
|
iceberg-js@0.8.1: {}
|
||||||
|
|
||||||
magic-string@0.30.21:
|
magic-string@0.30.21:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@jridgewell/sourcemap-codec': 1.5.5
|
'@jridgewell/sourcemap-codec': 1.5.5
|
||||||
@@ -1577,6 +1648,8 @@ snapshots:
|
|||||||
|
|
||||||
trim-lines@3.0.1: {}
|
trim-lines@3.0.1: {}
|
||||||
|
|
||||||
|
tslib@2.8.1: {}
|
||||||
|
|
||||||
unist-util-is@6.0.1:
|
unist-util-is@6.0.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/unist': 3.0.3
|
'@types/unist': 3.0.3
|
||||||
|
|||||||
Reference in new issue
Block a user