Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Capture error handling #3618

Merged
merged 3 commits into from
Oct 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 21 additions & 17 deletions perma_web/frontend/components/CaptureError.vue
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ watch(
else if (errorMessage.includes("limit")) {
globalStore.linksRemaining = 0;
showUploadLink.value = false;
showGeneric.value = false;
}

else if (errorMessage.includes("subscription")) {
Expand All @@ -51,6 +52,11 @@ watch(
showUploadLink.value = false;
}

else if (errorMessage.includes("account needs attention")) {
showUploadLink.value = false;
showGeneric.value = false;
}

else if (errorMessage.includes("Not a valid URL")) {
showUploadLink.value = false;
}
Expand All @@ -65,24 +71,22 @@ defineExpose({
</script>

<template>

<div class="container cont-fixed">
<div id="error-container">
<p class="message-large">{{ errorMessage }} <span v-if="showLoginLink">
Please <a href='/login'>log in</a> to continue.
</span></p>
<p v-if="showGeneric" class="message">We’re unable to create your Perma Link.</p>
<template v-if="showUploadLink">
<template v-if="showDevPlayground">
<p>You can <button @click.prevent="handleOpen">upload your own
archive</button> or <a href="{{contact_url}}">contact
us about this error.</a></p>
</template>
<p v-else>You can <button id="upload-form-button">upload your own archive</button> or <a
href="/contact">contact us
about this error.</a></p>
<div id="error-container" role="alert" aria-live="assertive">
<p class="message">
{{ errorMessage }}
<template v-if="showLoginLink">Please <a href='/login'>log in</a> to continue.</template>
<template v-else-if="showGeneric">We’re unable to create your Perma Link.</template>
</p>
<template v-if="showUploadLink">
<template v-if="showDevPlayground">
<p>You can <button @click.prevent="handleOpen">upload your own
archive</button> or <a href="{{contact_url}}">contact
us about this error.</a></p>
</template>
</div>
<p v-else>You can <button id="upload-form-button">upload your own archive</button> or <a
href="/contact">contact us
about this error.</a></p>
</template>
</div>

<UploadForm
Expand Down
65 changes: 35 additions & 30 deletions perma_web/frontend/components/CreateLink.vue
Original file line number Diff line number Diff line change
Expand Up @@ -152,36 +152,45 @@ defineExpose({
<div class="container cont-full-bleed cont-sm-fixed">
<form class="form-priority" :class="{ '_isPrivate': globalStore.selectedFolder.isPrivate }" id="linker">
<fieldset class="form-priority-fieldset">
<input v-model="userLink" id="rawUrl" name="url"
class="text-input select-on-click form-priority-input" type="text"
placeholder="Paste your URL here." />
<div class="wrapper">
<button
@click.prevent="handleArchiveRequest"
class="btn btn-large btn-info _active-when-valid"
:class="{ '_isWorking': !isReady }"
id="addlink" type="submit"
>
<Spinner v-if="captureStatus === 'isValidating' || captureStatus === 'isQueued'" />
<ProgressBar v-if="captureStatus === 'isCapturing'" :progress="userLinkProgressBar" style="height: 32px"/>
{{ isReady ? "Create" : "Creating" }}
{{ globalStore.selectedFolder.isPrivate ? "Private" : "" }}
Perma Link
</button>
<p id="create-batch-links" v-if="isReady">
or
<div class="input-bar">
<input v-model="userLink" id="rawUrl" name="url"
class="text-input select-on-click form-priority-input" type="text"
placeholder="Paste your URL here." />
<div class="wrapper">
<button
@click.prevent="batchDialogRef.handleOpen"
class="c-button"
:class="globalStore.selectedFolder.isPrivate ? 'c-button--privateLink' : 'c-button--link'"
@click.prevent="handleArchiveRequest"
class="btn btn-large btn-info _active-when-valid"
:class="{ '_isWorking': !isReady }"
id="addlink" type="submit"
>
create multiple links
<Spinner v-if="captureStatus === 'isValidating' || captureStatus === 'isQueued'" />
<ProgressBar v-if="captureStatus === 'isCapturing'" :progress="userLinkProgressBar" style="height: 32px"/>
{{ isReady ? "Create" : "Creating" }}
{{ globalStore.selectedFolder.isPrivate ? "Private" : "" }}
Perma Link
</button>
</p>
<p id="create-batch-links" v-if="isReady">
or
<button
@click.prevent="batchDialogRef.handleOpen"
class="c-button"
:class="globalStore.selectedFolder.isPrivate ? 'c-button--privateLink' : 'c-button--link'"
>
create multiple links
</button>
</p>
</div>
</div>
<CaptureError
v-if="captureErrorMessage"
:errorMessage="captureErrorMessage"
:captureGUID="captureGUID"
/>
<LinkCount v-if="globalStore.userTypes.includes('individual')" />
<FolderSelect v-if="!globalStore.userTypes.includes('individual')" option="customSelect"
selectLabel="This Perma Link will be affiliated with" />
<div v-if="!globalStore.userTypes.includes('individual')" style="display: flex; align-items: center;">
<span class="label-affil" style="flex-shrink: 0; margin-right: 14px;">This Perma Link will be affiliated with</span>
<FolderSelect style="flex-grow: 1" />
</div>
</fieldset>
<p v-if="!isToolsReminderSuppressed" id="browser-tools-message" class="u-pb-150"
:class="globalStore.userTypes === 'individual' && 'limit-true'">
Expand All @@ -195,10 +204,6 @@ defineExpose({
</form><!--/#linker-->
</div><!-- cont-full-bleed cont-sm-fixed -->
</div><!-- container cont-full-bleed -->
<CaptureError
v-if="captureErrorMessage"
:errorMessage="captureErrorMessage"
:captureGUID="captureGUID"
/>

<CreateLinkBatch ref="batchDialogRef" />
</template>
71 changes: 46 additions & 25 deletions perma_web/frontend/components/CreateLinkBatch.vue
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
<script setup>
import { ref, watch, computed, onMounted, onBeforeUnmount, getCurrentInstance } from 'vue'
import { ref, computed, onMounted, onBeforeUnmount, getCurrentInstance } from 'vue'
import { useGlobalStore } from '../stores/globalStore'
import FolderSelect from './FolderSelect.vue';
import Spinner from './Spinner.vue';
import { fetchDataOrError } from '../lib/data';
import LinkBatchDetails from './LinkBatchDetails.vue'
import Dialog from './Dialog.vue';
import TextAreaInput from './forms/TextAreaInput.vue';
import BaseInput from './forms/BaseInput.vue';
import {
folderError,
missingUrlError,
getErrorFromNestedObject
getErrorFromNestedObject,
getErrorFromStatus,
defaultError
} from '../lib/errors';
import { useToast } from '../lib/notifications';
import { transitionalStates, validStates, showDevPlayground } from "../lib/consts";

const globalStore = useGlobalStore()
Expand All @@ -29,6 +32,9 @@ const targetFolderName = ref('')
const showBatchDetails = computed(() => batchCaptureStatus.value !== 'ready' && batchCaptureStatus.value !== 'isValidating')
const userSubmittedLinks = ref('')

const errors = ref({})
const globalErrors = ref()

let progressInterval;

const dialogRef = ref('')
Expand All @@ -51,6 +57,8 @@ const handleReset = () => {
batchCaptureJobs.value = []
batchDialogTitle.value = defaultDialogTitle
batchCaptureStatus.value = "ready"
errors.value = {}
globalErrors.value = null
}

const handleClose = () => {
Expand All @@ -72,6 +80,8 @@ const handleBatchCaptureRequest = async () => {
}

batchCaptureStatus.value = 'isValidating'
errors.value = {}
globalErrors.value = null

const formData = {
urls: userSubmittedLinks.value.split("\n").map(s => { return s.trim() }).filter(Boolean),
Expand All @@ -80,21 +90,30 @@ const handleBatchCaptureRequest = async () => {
}

if (!formData.urls.length) {
handleBatchError({ error: missingUrlError, errorType: 'urlError' })
return;
errors.value.userSubmittedLinks = [missingUrlError]
batchCaptureStatus.value = 'ready'
}
if (!formData.target_folder) {
handleBatchError({ error: folderError, errorType: 'folderSelectionError' })
return;
errors.value.folder = [folderError]
batchCaptureStatus.value = 'ready'
}

if (Object.keys(errors.value).length > 0) {
return
}

const { data, error } = await fetchDataOrError("/archives/batches/", {
const { data, error, response } = await fetchDataOrError("/archives/batches/", {
method: "POST",
data: formData
});

if (error) {
handleBatchError({ error, errorType: 'urlError' })
if (data) {
errors.value = data
} else {
globalErrors.value = response.status ? getErrorFromStatus(response.status) : defaultError
}
batchCaptureStatus.value = 'ready'
return;
}

Expand All @@ -119,9 +138,6 @@ const handleBatchCaptureRequest = async () => {
const handleBatchError = ({ error, errorType }) => {
clearInterval(progressInterval)
batchCaptureStatus.value = errorType

toggleToast(error)
handleClose()
}

const handleBatchDetailsFetch = async () => {
Expand Down Expand Up @@ -192,12 +208,6 @@ const handleBatchDetailsFetch = async () => {
}
};

const { addToast } = useToast();

const toggleToast = (errorMessage) => {
addToast(errorMessage, 'error');
}

onMounted(() => {
globalStore.components.batchDialog = getCurrentInstance().exposed
})
Expand Down Expand Up @@ -226,17 +236,28 @@ defineExpose({
</div>
<div class="modal-body">
<div id="batch-create-input" v-if="batchCaptureStatus === 'ready'">
<div class="form-group">
<FolderSelect selectLabel="These Perma Links will be affiliated with" />
</div>
<div class="form-group">
<textarea v-model="userSubmittedLinks" aria-label="Paste your URLs here (one URL per line)"
placeholder="Paste your URLs here (one URL per line)"></textarea>
</div>
<BaseInput
name="Folder"
description="These Perma Links will be affiliated with"
:error="errors.folder"
>
<FolderSelect />
</BaseInput>
<TextAreaInput
v-model="userSubmittedLinks"
name="URLs"
description="Paste your URLs here (one URL per line)"
placeholder="https://example.com"
id="userSubmittedLinks"
:error="errors.userSubmittedLinks"
/>
<div class="form-buttons">
<button class="btn" @click.prevent="handleBatchCaptureRequest">Create Links</button>
<button class="btn cancel" @click.prevent="handleClose">Cancel</button>
</div>
<p v-if="globalErrors" class="field-error">
Batch creation failed. {{ globalErrors }}
</p>
</div>

<div v-if="batchCaptureStatus === 'isValidating'" style="height: 200px;">
Expand Down
Loading
Loading