Loading Gist

This commit is contained in:
Sidharth Vinod
2021-06-05 15:31:22 +05:30
parent aed37c19c7
commit cc3f4fabc2
8 changed files with 125 additions and 12 deletions
+4
View File
@@ -12,3 +12,7 @@
.action-btn {
@apply rounded p-2 bg-indigo-400 shadow flex-auto text-white hover:bg-indigo-500;
}
.input {
@apply flex-1 border-indigo-400 border-solid border-2 rounded;
}
+37 -6
View File
@@ -1,7 +1,8 @@
<script lang="ts">
import { goto } from '$app/navigation';
import Card from '$lib/components/card/card.svelte';
import type { State } from '$lib/types';
import { base64State, codeStore } from '$lib/util/state';
import { codeStore } from '$lib/util/state';
import { toBase64 } from 'js-base64';
import moment from 'moment';
@@ -103,11 +104,27 @@
);
};
const onCopyMarkdown = (event: Event) => {
event.target.select();
const onCopyMarkdown = () => {
document.getElementById('markdown').select();
document.execCommand('Copy');
};
let gistURL = '';
codeStore.subscribe((state) => {
if (state.loader?.type === 'gist') {
// @ts-ignore Gist will have url
gistURL = state.loader.config.url;
}
});
const loadGist = () => {
if (!gistURL) {
alert('Please enter a Gist URL first');
}
goto(`/edit?gist=${gistURL}`);
location.reload();
};
let iUrl: string;
let svgUrl: string;
let mdCode: string;
@@ -126,7 +143,7 @@
});
</script>
<Card title="Actions" isOpen={false}>
<Card title="Actions" isOpen={true}>
<div class="flex flex-wrap gap-2 m-2">
{#if isClipboardAvailable()}
<button class="action-btn w-full" on:click={onCopyClipboard}
@@ -160,8 +177,22 @@
</div>
<div class="w-full flex gap-2 items-center">
<label for="markdown">Copy Markdown</label>
<input class="flex-1" id="markdown" type="text" value={mdCode} on:click={onCopyMarkdown} />
<input class="input" id="markdown" type="text" value={mdCode} on:click={onCopyMarkdown} />
<label for="markdown">
<button class="btn text-white flex-auto" on:click={onCopyMarkdown}> Copy Markdown </button>
</label>
</div>
<div class="w-full flex gap-2 items-center">
<input
class="input"
id="gist"
type="text"
bind:value={gistURL}
placeholder="Enter Gist URL" />
<label for="gist">
<button class="btn text-white flex-auto" on:click={loadGist}> Load Gist </button>
</label>
</div>
</div>
</Card>
+4
View File
@@ -36,6 +36,10 @@ export interface GistLoaderConfig {
url: string;
}
export interface LoadingState {
loading: boolean;
message?: string;
}
export interface FileLoaderConfig {
codeURL: string;
configURL?: string;
+10 -2
View File
@@ -55,9 +55,15 @@ const getGistData = async (gistURL: string): Promise<GistData> => {
};
const getStateFromGist = (gist: GistData): State => {
const state = {
const state: State = {
...defaultState,
code: gist.code
code: gist.code,
loader: {
type: 'gist',
config: {
url: gist.url
}
}
};
gist.config && (state.mermaid = gist.config);
return state;
@@ -81,6 +87,8 @@ export const loadGistData = async (gistURL: string): Promise<State> => {
}
gistHistory.reverse();
const state = getStateFromGist(gistHistory.slice(-1).pop());
// @ts-ignore Ignore
state.loader.config.url = gistURL;
for (const gist of gistHistory) {
addHistoryEntry({
state: getStateFromGist(gist),
+7 -3
View File
@@ -7,7 +7,7 @@ const loaders: Record<string, Loader> = {
export const loadDataFromUrl = async (): Promise<void> => {
const searchParams = new URLSearchParams(window.location.search);
let state: State;
let state: State = defaultState;
let code: string, config: string;
const codeURL: string = searchParams.get('code');
const configURL: string = searchParams.get('config');
@@ -23,8 +23,12 @@ export const loadDataFromUrl = async (): Promise<void> => {
if (!code) {
for (const [key, value] of searchParams.entries()) {
if (key in loaders) {
state = await loaders[key](value);
break;
try {
state = await loaders[key](value);
break;
} catch (err) {
console.error(err);
}
}
}
} else {
+19
View File
@@ -0,0 +1,19 @@
import { writable, Writable } from 'svelte/store';
import type { LoadingState } from '$lib/types';
const defaultLoading: LoadingState = {
loading: false
};
export const loadingStateStore: Writable<LoadingState> = writable(defaultLoading);
export const initLoading = async <T>(message: string, task: Promise<T>): Promise<T> => {
loadingStateStore.set({
loading: true,
message
});
const result: T = await task;
loadingStateStore.set({
loading: false
});
return result;
};
+2 -1
View File
@@ -2,6 +2,7 @@ import type { State } from '$lib/types';
import { initURLSubscription, loadState, updateCodeStore } from './state';
import { analytics, initAnalytics } from './stats';
import { loadDataFromUrl } from './fileLoaders/loader';
import { initLoading } from './loading';
export const loadStateFromURL = (): void => {
loadState(window.location.hash.slice(1));
@@ -15,7 +16,7 @@ export const syncDiagram = (): void => {
export const initHandler = async (): Promise<void> => {
loadStateFromURL();
await loadDataFromUrl().catch(console.error);
await initLoading('Loading Gist...', loadDataFromUrl().catch(console.error));
syncDiagram();
initURLSubscription();
await initAnalytics();
+42
View File
@@ -2,6 +2,7 @@
import '../app.postcss';
import { base } from '$app/paths';
import { onMount } from 'svelte';
import { loadingStateStore } from '$lib/util/loading';
// This can be removed once https://github.com/sveltejs/kit/issues/1612 is fixed.
// Then move it into src and vite will bundle it automatically.
onMount(() => {
@@ -23,3 +24,44 @@
<main class="h-screen">
<slot />
</main>
{#if $loadingStateStore.loading}
<div
class="w-screen h-screen z-50 absolute left-0 top-0 bg-gray-600 opacity-50 flex align-middle justify-center">
<div class="text-indigo-100 text-4xl font-bold my-auto">
<div class="loader mx-auto" />
<div>{$loadingStateStore.message}</div>
</div>
</div>
{/if}
<style>
.loader {
border: 0.45em solid #f3f3f3;
border-radius: 50%;
border-top: 0.45em solid #6365f1;
width: 3em;
height: 3em;
-webkit-animation: spin 2s linear infinite; /* Safari */
animation: spin 2s linear infinite;
}
/* Safari */
@-webkit-keyframes spin {
0% {
-webkit-transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
}
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
</style>