url encoding and decoding
This commit is contained in:
parent
b63ae715a2
commit
19106501aa
@ -41,6 +41,8 @@ div.copyable {
|
|||||||
span.contents {
|
span.contents {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
padding: 4px;
|
padding: 4px;
|
||||||
|
overflow: hidden;
|
||||||
|
text-align: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
span.copy {
|
span.copy {
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import {type Field, fields, type Specs} from "@/urlmaker/specs.ts";
|
|||||||
import Btn from "@/components/Btn.vue";
|
import Btn from "@/components/Btn.vue";
|
||||||
import Copyable from "@/components/Copyable.vue";
|
import Copyable from "@/components/Copyable.vue";
|
||||||
import EditUrlModal from "@/components/EditUrlModal.vue";
|
import EditUrlModal from "@/components/EditUrlModal.vue";
|
||||||
|
import {decodeUrl, encodeUrl} from "@/urlmaker";
|
||||||
|
|
||||||
const emptySpecs = fields.reduce((o, f) => {
|
const emptySpecs = fields.reduce((o, f) => {
|
||||||
o[f.name] = f.default;
|
o[f.name] = f.default;
|
||||||
@ -13,9 +14,9 @@ const emptySpecs = fields.reduce((o, f) => {
|
|||||||
const specs = reactive(emptySpecs);
|
const specs = reactive(emptySpecs);
|
||||||
const formValid = ref(false);
|
const formValid = ref(false);
|
||||||
|
|
||||||
watch(specs, (value, oldValue) => {
|
watch(specs, (value) => {
|
||||||
formValid.value = fields.every(field => (
|
formValid.value = fields.every(field => (
|
||||||
specs[field.name].length === 0 && !(field as Field).required || field.validate(specs[field.name]).ok
|
value[field.name].length === 0 && !(field as Field).required || field.validate(value[field.name]).ok
|
||||||
));
|
));
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -23,12 +24,33 @@ const existingLink = ref("");
|
|||||||
const link = ref("");
|
const link = ref("");
|
||||||
const editModalVisible = ref(false);
|
const editModalVisible = ref(false);
|
||||||
|
|
||||||
|
watch(existingLink, async (value) => {
|
||||||
|
if(!value) return;
|
||||||
|
existingLink.value = "";
|
||||||
|
try {
|
||||||
|
Object.assign(specs, await decodeUrl(value));
|
||||||
|
link.value = "";
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e);
|
||||||
|
alert(`Decoding error: ${e}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
async function generateLink() {
|
||||||
|
try {
|
||||||
|
link.value = await encodeUrl(specs);
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e);
|
||||||
|
alert(`Encoding error: ${e}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="wrapper">
|
<div class="wrapper">
|
||||||
<SpecsForm v-model="specs" class="specs-form"></SpecsForm>
|
<SpecsForm v-model="specs" class="specs-form"></SpecsForm>
|
||||||
<Btn :active="formValid">Generate link</Btn>
|
<Btn :active="formValid" @click="generateLink">Generate link</Btn>
|
||||||
<Btn :active="formValid">Screenshot</Btn>
|
<Btn :active="formValid">Screenshot</Btn>
|
||||||
<Btn @click="editModalVisible = true">Edit existing task</Btn>
|
<Btn @click="editModalVisible = true">Edit existing task</Btn>
|
||||||
<Copyable v-if="link" :contents="link" class="link-view"></Copyable>
|
<Copyable v-if="link" :contents="link" class="link-view"></Copyable>
|
||||||
|
|||||||
63
frontend/wizard-vue/src/urlmaker/index.ts
Normal file
63
frontend/wizard-vue/src/urlmaker/index.ts
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
import type {Specs} from "@/urlmaker/specs.ts";
|
||||||
|
|
||||||
|
const apiEndpoint = '/api/v1/render/';
|
||||||
|
|
||||||
|
export async function decodeUrl(url: string): Promise<Specs> {
|
||||||
|
const splitUrl = url.split(apiEndpoint);
|
||||||
|
if(splitUrl.length !== 2) {
|
||||||
|
throw 'Split failed';
|
||||||
|
}
|
||||||
|
let encodedData = splitUrl[1];
|
||||||
|
console.log('Data len=' + encodedData.length);
|
||||||
|
const m = encodedData.match(/(\d*):?([A-Za-z0-9+/=]+)/);
|
||||||
|
if(!m) {
|
||||||
|
throw 'Regex failed';
|
||||||
|
}
|
||||||
|
const version = m[1] ? parseInt(m[1]) : 0;
|
||||||
|
console.log('Decoding url using version: ' + version);
|
||||||
|
encodedData = m[2];
|
||||||
|
|
||||||
|
let buf = b64decode(encodedData);
|
||||||
|
if (version === 0) {
|
||||||
|
const jsonData = await decompress(buf);
|
||||||
|
return JSON.parse(jsonData);
|
||||||
|
}
|
||||||
|
throw 'Unknown version'
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function encodeUrl(specs: Specs): Promise<string> {
|
||||||
|
const jsonData = JSON.stringify(specs);
|
||||||
|
const buf = await compress(jsonData);
|
||||||
|
const encodedData = b64encode(buf);
|
||||||
|
console.log('Data len=' + encodedData.length);
|
||||||
|
const version = 0;
|
||||||
|
return `${document.location.origin}${apiEndpoint}${version}:${encodedData}`
|
||||||
|
}
|
||||||
|
|
||||||
|
function b64encode(buf: Uint8Array): string {
|
||||||
|
const b64str = btoa(String.fromCharCode.apply(null, buf));
|
||||||
|
return b64str.replaceAll('=', '');
|
||||||
|
}
|
||||||
|
|
||||||
|
function b64decode(s: string): Uint8Array {
|
||||||
|
return Uint8Array.from(atob(s), c => c.charCodeAt(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
async function compress(s: string): Promise<Uint8Array> {
|
||||||
|
let byteArray = new TextEncoder().encode(s);
|
||||||
|
let cs = new CompressionStream('deflate-raw');
|
||||||
|
let writer = cs.writable.getWriter();
|
||||||
|
writer.write(byteArray);
|
||||||
|
writer.close();
|
||||||
|
let response = new Response(cs.readable);
|
||||||
|
return new Uint8Array(await response.arrayBuffer());
|
||||||
|
}
|
||||||
|
|
||||||
|
async function decompress(buf: Uint8Array): Promise<string> {
|
||||||
|
let ds = new DecompressionStream('deflate-raw');
|
||||||
|
let writer = ds.writable.getWriter();
|
||||||
|
writer.write(buf);
|
||||||
|
writer.close();
|
||||||
|
let response = new Response(ds.readable);
|
||||||
|
return response.text();
|
||||||
|
}
|
||||||
@ -7,5 +7,10 @@
|
|||||||
{
|
{
|
||||||
"path": "./tsconfig.app.json"
|
"path": "./tsconfig.app.json"
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"compilerOptions": {
|
||||||
|
"lib": [
|
||||||
|
"es2021"
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user