renaming, reordering, dropping firestore

This commit is contained in:
msramalho
2024-11-13 15:47:43 +01:00
parent 0b271e44ec
commit 50a257d6e8
12 changed files with 202 additions and 481 deletions

View File

@@ -25,9 +25,9 @@
size="large">
open sheet
</v-btn>
<v-btn v-if="actionIsCreate" color="primary" size="large" :disabled="!requiredData"
<v-btn v-if="actionIsCreate" color="teal" size="large" :disabled="!requiredData"
@click="createSheet">Create</v-btn>
<v-btn v-if="!actionIsCreate" color="primary" size="large" :disabled="!requiredDataExisting"
<v-btn v-if="!actionIsCreate" color="teal" size="large" :disabled="!requiredDataExisting"
@click="addExistingSheet">Add Existing Sheet</v-btn>
</v-col>
@@ -58,9 +58,6 @@ export default {
snackbarColor: "red",
loading: false,
tab: '',
items: ['Create new Archiver Sheet', 'Add existing Sheets'],
sheetName: ``.trim(),
sheetUrlId: ``,
@@ -109,8 +106,7 @@ export default {
this.loading = true;
this.newSheetId = "";
this.$store.dispatch("add", this.sheetName).then((res) => {
console.log(res);
this.$store.dispatch("createSheet", this.sheetName).then((res) => {
if (!res.success) throw new Error(res.result);
this.newSheetId = res.result;
this.addSheetToAPI(this.newSheetId);

View File

@@ -1,12 +1,8 @@
<template>
<v-container class="pane">
<v-card class="pa-3">
<v-card class="pa-0">
<v-card-title class="text-center">
Archive Google Spreadsheets
</v-card-title>
<v-tabs v-model="tab" bg-color="green-lighten-4" grow class="elevation-1 rounded">
<v-tabs v-model="tab" bg-color="teal" grow class="elevation-1">
<v-tab v-for="item in items" :key="item" :text="item" :value="item"></v-tab>
</v-tabs>
@@ -97,45 +93,8 @@
</v-tabs-window-item>
</v-tabs-window>
</v-card>
</v-container>
<v-container class="pane-l">
<v-card>
<v-card-title class="text-center">
<h4>Your Sheets</h4>
</v-card-title>
<v-table>
<thead>
<tr>
<th class="text-left">Sheet Name</th>
<th class="text-left">Action</th>
</tr>
</thead>
<tbody>
<tr>
<td>Sheet 1</td>
<td>
<v-btn color="primary" @click="archiveSheet('Sheet 1')">Archive</v-btn>
</td>
</tr>
<tr>
<td>Sheet 2</td>
<td>
<v-btn color="primary" @click="archiveSheet('Sheet 2')">Archive</v-btn>
</td>
</tr>
<tr>
<td>Sheet 3</td>
<td>
<v-btn color="primary" @click="archiveSheet('Sheet 3')">Archive</v-btn>
</td>
</tr>
</tbody>
</v-table>
</v-card>
</v-container>
</template>
<script>
@@ -149,7 +108,7 @@ export default {
data() {
return {
tab: '',
items: ['Create new Archiver Sheet', 'Add existing Sheets'],
items: ['Create new Archiver Sheet', 'Add existing Sheet'],
};
},
computed: {

View File

@@ -1,5 +1,5 @@
<template>
<v-container class="pane">
<v-container class="pane" v-if="user?.active" >
<v-card :loading="loadingArchive">
<v-card-title class="text-center">
Archive a single URL
@@ -20,7 +20,7 @@
density="compact"></v-select>
</v-col>
<v-col cols="12" md="4" class="text-right">
<v-btn @click="archiveUrl" color="primary"
<v-btn @click="archiveUrl" color="teal"
:disabled="!validUrl || loadingArchive || (!public && group == -1)">
Archive
</v-btn>
@@ -29,7 +29,7 @@
<v-row>
<v-col cols="12">
<p v-if="loadingArchive">
<v-progress-circular color="primary" indeterminate></v-progress-circular>
<v-progress-circular color="teal" indeterminate></v-progress-circular>
Archive in progress task id = <code>{{ taskId }}</code>
</p>
<v-alert color="success" icon="mdi-information" v-if="archiveResult">
@@ -41,7 +41,7 @@
</v-alert>
<p v-if="validUrl">
You can <strong v-if="archiveFailure">still</strong> <router-link
:to="`/urls?url=${encodeURIComponent(url)}`" target="_blank"><v-icon>mdi-open-in-new</v-icon> search for
:to="`/archives?url=${encodeURIComponent(url)}`" target="_blank"><v-icon>mdi-open-in-new</v-icon> search for
archives</router-link> of
this URL.
</p>
@@ -81,6 +81,9 @@ export default {
};
},
computed: {
user() {
return this.$store.state.user;
},
urlValidator() {
return urlValidator;
},
@@ -92,9 +95,6 @@ export default {
},
},
watch: {
// public(val) {
// if (!val) this.loadGroups();
// },
url(val) {
this.archiveResult = null;
this.archiveFailure = null;

View File

@@ -1,81 +0,0 @@
<template>
<v-card class="doc">
<v-card-title>{{ doc.name }}</v-card-title>
<v-card-text>
<div class="doc-timestamp">
Created: {{ new Date(doc.timestamp).toLocaleString() }}
</div>
<div class="doc-archived">
Last archived:
{{
doc.lastArchived
? new Date(doc.lastArchived).toLocaleString()
: "never"
}}
</div>
</v-card-text>
<v-card-actions>
<v-row>
<v-col>
<v-btn :href="doc.url" target="_blank"
>Open sheet
<v-icon size="small" style="margin-left: 1em"
>mdi-open-in-new</v-icon
>
</v-btn>
</v-col>
<v-col>
<v-btn @click="$store.dispatch('archive', doc)">Archive now</v-btn>
</v-col>
<v-dialog width="500" v-model="dialog" persistent :retain-focus="false">
<template v-slot:activator="{ props }">
<v-col class="text-right">
<v-btn color="#f2d97c" location="right" v-bind="props"
>Stop archiving</v-btn
>
</v-col>
</template>
<v-card>
<v-card-title>Stop archiving "{{ doc.name }}"? </v-card-title>
<v-card-text>
This will stop archiving the sheet, but will not delete the sheet
or any of its data from your Google Drive.
</v-card-text>
<v-divider></v-divider>
<v-card-actions>
<v-btn @click="dialog = false" color="primary">Cancel</v-btn>
<v-spacer></v-spacer>
<v-btn color="red" variant="text" @click="remove">
Stop archiving
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</v-row>
</v-card-actions>
</v-card>
</template>
<script>
export default {
name: "DocCard",
props: {
doc: Object,
},
data() {
return {
dialog: false,
};
},
methods: {
remove() {
this.dialog = false;
this.$store.dispatch("removeDoc", this.doc.id);
},
},
};
</script>

View File

@@ -1,30 +0,0 @@
<template>
<div style="margin-bottom: 1em">
<div class="text-h5 mt-5 mb-3" v-if="docs.length > 0">
Your auto-archiver sheets
</div>
<v-row v-for="doc in docs" :key="doc.sheetId">
<v-col>
<DocCard :doc="doc" />
</v-col>
</v-row>
</div>
</template>
<script>
import DocCard from "@/components/DocCard.vue";
export default {
name: "DocList",
components: {
DocCard,
},
computed: {
docs() {
return this.$store.state.docs;
},
},
};
</script>
<style></style>

View File

@@ -0,0 +1,129 @@
<template>
<v-container class="pane-l mb-10">
<v-card class="pa-3">
<v-card-title class="text-center">
Your <span v-if="items">{{ items.length }}</span> Sheets
</v-card-title>
<v-data-table :headers="headers" item-key="name" no-data-text="No Active Sheets available" :items="items"
:loading="loading" items-per-page="25" hover>
<template v-slot:item.actions="{ item: data }">
<v-btn color="green" size="small" icon class="mx-2" rounded
:href="`https://docs.google.com/spreadsheets/d/${data.id}`" :disabled="loading"
target="_blank"><v-icon>mdi-open-in-new</v-icon>
<v-tooltip activator="parent" location="left">Open in new tab</v-tooltip>
</v-btn>
<v-btn color="" size="small" icon class="mx-2" :disabled="loading" rounded
@click="archiveSheetNow(data.id)"><v-icon>mdi-archive-outline</v-icon>
<v-tooltip activator="parent" location="left">Archive Now!</v-tooltip>
</v-btn>
<v-btn color="red-lighten-4" size="small" icon class="mx-2" :disabled="loading" rounded
@click="removeSheet(data.id)"><v-icon>mdi-delete-outline</v-icon>
<v-tooltip activator="parent" location="left">Stop archiving, does not delete the spreadsheet
itself.</v-tooltip>
</v-btn>
</template>
<template v-slot:item.name="{ item: data }">
<span :title="data.id">{{ data.name }}</span>
</template>
</v-data-table>
</v-card>
</v-container>
<SnackBar :message="snackbarMessage" :show="snackbar" :color="snackbarColor" @update:show="snackbar = $event" />
</template>
<script>
import SnackBar from "@/components/SnackBar.vue";
export default {
name: "ManageSheets",
components: {
SnackBar,
},
props: {},
data() {
return {
snackbar: false,
snackbarMessage: "",
snackbarColor: "red",
loading: false,
headers: [
{ title: "Sheet Name", value: "name", sortable: true },
{ title: "Group", value: "group_id", sortable: true },
{ title: "Frequency", value: "frequency", sortable: true },
{ title: "Created", value: "created_at", sortable: true },
{ title: "Last Archived", value: "last_archived_at", sortable: true },
{ title: 'Actions', value: "actions", align: 'center' },
],
};
},
computed: {
user() {
return this.$store.state.user;
},
items() {
return this.$store.state.sheets;
},
},
methods: {
showSnackbar(message, color = "red") {
this.snackbarMessage = message;
this.snackbarColor = color;
this.snackbar = true;
},
archiveSheetNow(sheetId) {
this.loading = true;
fetch(`${this.$store.state.API_ENDPOINT}/sheet/${sheetId}/archive`, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${this.$store.state.access_token}`,
}
}).then(async response => {
const res = await response.json();
if (response.status === 201) {
this.showSnackbar(`Sheet ${sheetId} is being archived with task id ${res?.id}!`, "green");
this.$store.dispatch("getSheets");
} else {
throw new Error(JSON.stringify(res));
}
}).catch(error => {
console.error("/sheet/mine ", error);
this.showSnackbar(`Unable to trigger sheet archive: ${error.message}`);
}).finally(() => {
this.loading = false;
});
},
removeSheet(sheetId) {
this.loading = true;
fetch(`${this.$store.state.API_ENDPOINT}/sheet/${sheetId}`, {
method: "DELETE",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${this.$store.state.access_token}`,
}
}).then(async response => {
const res = await response.json();
if (response.status === 200 && res.deleted) {
this.showSnackbar(`Sheet ${sheetId} has been removed!`, "green");
this.$store.dispatch("getSheets");
} else {
throw new Error(JSON.stringify(res));
}
}).catch(error => {
console.error("/sheet/mine ", error);
this.showSnackbar(`Unable to remove sheet: ${error.message}`);
}).finally(() => {
this.loading = false;
});
},
},
};
</script>

View File

@@ -1,8 +1,8 @@
<template>
<v-app-bar style="flex-grow: 0" class="text-no-wrap">
<v-toolbar-title title="Bellingcat Auto Archiver demo">
<v-toolbar-title title="Bellingcat Auto Archiver prototype">
<router-link to="/" class="nodecoration">
Bellingcat Auto Archiver demo
Bellingcat Auto Archiver prototype
</router-link>
</v-toolbar-title>
@@ -13,9 +13,9 @@
</v-chip>
<v-spacer v-if="!smAndDown"></v-spacer>
<div v-if="user && !smAndDown">
<div v-if="user?.active && !smAndDown">
<template v-for="btn in btns">
<v-btn :to="btn.to" :prepend-icon="btn.icon" variant="text" class="nodecoration" size="large">
<v-btn :to="btn.to" :prepend-icon="btn.icon" variant="text" class="nodecoration ml-2" size="large" active-color="teal">
{{ btn.text }}
<v-tooltip activator="parent" location="bottom">{{ btn.tooltip }}</v-tooltip>
</v-btn>
@@ -42,7 +42,7 @@
<v-btn v-if="!user" @click="$store.dispatch('signin')">Sign In</v-btn>
<v-menu v-if="user && smAndDown">
<v-menu v-if="user?.active && smAndDown">
<template v-slot:activator="{ props }">
<v-app-bar-nav-icon v-bind="props"></v-app-bar-nav-icon>
</template>
@@ -73,9 +73,9 @@ export default {
return {
drawer: false,
btns: [
{ to: "/", icon: "mdi-cloud-download-outline", text: "URL", tooltip: "Archive a single URL." },
{ to: "/urls", icon: "mdi-magnify", text: "Archives", tooltip: "Search for archived URLs." },
{ to: "/sheets", icon: "mdi-table-large", text: "Sheets", tooltip: "Create, manage, and archive Google Sheets." }
{ to: "/", icon: "mdi-table-large", text: "Sheets", tooltip: "Create, manage, and archive Google Sheets." },
{ to: "/url", icon: "mdi-cloud-download-outline", text: "URL", tooltip: "Archive a single URL." },
{ to: "/archives", icon: "mdi-magnify", text: "Archives", tooltip: "Search for archived URLs." },
]
};
},

View File

@@ -1,7 +1,8 @@
import { createRouter, createWebHistory } from 'vue-router';
import HomeView from '../views/HomeView.vue';
import SheetView from '../views/SheetView.vue';
import UrlView from '../views/UrlView.vue';
import ArchivesView from '../views/ArchivesView.vue';
import ArchiveUrl from "../components/ArchiveUrl.vue";
const routes = [
{
@@ -10,14 +11,14 @@ const routes = [
component: HomeView,
},
{
path: '/sheets',
name: 'Google Sheets Archiving',
component: SheetView,
path: '/url',
name: 'URL Archiving',
component: ArchiveUrl,
},
{
path: '/urls',
name: 'URL Archiving',
component: UrlView,
path: '/archives',
name: 'Archives search',
component: ArchivesView,
},
{
path: '/privacy',

View File

@@ -5,17 +5,7 @@ import {
GoogleAuthProvider,
signInWithCredential,
} from "firebase/auth";
import {
collection,
addDoc,
query,
where,
limit,
getDocs,
doc,
deleteDoc,
updateDoc,
} from "firebase/firestore";
import { collection, } from "firebase/firestore";
import { firebaseAuth, firebaseFirestore } from "@/firebase.js";
function saveToLocalStorage(state) {
@@ -33,6 +23,7 @@ function clearLocalStorage() {
localStorage.removeItem("user");
localStorage.removeItem("access_token");
}
async function waitForGapiAuth2() {
return new Promise((resolve, reject) => {
const checkGapiAuth2 = () => {
@@ -51,7 +42,7 @@ export default createStore({
user: null,
active: false,
access_token: null,
docs: [],
sheets: [],
loading: false,
errorMessage: "",
// API_ENDPOINT: "https://auto-archiver-api.bellingcat.com"
@@ -69,8 +60,8 @@ export default createStore({
state.user.groups = groups;
saveToLocalStorage(state);
},
setDocs(state, docs) {
state.docs = docs;
setSheets(state, sheets) {
state.sheets = sheets;
},
setLoading(state, loading) {
state.loading = loading;
@@ -95,7 +86,7 @@ export default createStore({
commit("setUser", response.user);
dispatch("checkActiveUser");
dispatch("checkUserGroups");
dispatch("getDocs");
dispatch("getSheets");
}
commit("setUser", null);
@@ -126,7 +117,7 @@ export default createStore({
// clean user from store and local storage
commit("setUser", null);
commit("setDocs", []);
commit("setSheets", []);
clearLocalStorage();
} catch (error) {
console.error("signOutUser (firebase/auth.js): ", error);
@@ -175,71 +166,35 @@ export default createStore({
}
},
async getDocs({ state, commit }) {
if (!state.user || !state.user.active) {
return;
}
async getSheets({ state, commit }) {
try {
// get documents where uid matches user
commit("setLoading", true);
commit("setErrorMessage", "");
if(state.user?.active === false) return;
const q = query(
collection(firebaseFirestore, "sheets"),
where("uid", "==", state.user.uid)
);
const response = await getDocs(q);
const docs = response.docs.map((d) => ({ id: d.id, ...d.data() }));
commit("setDocs", docs);
commit("setLoading", false);
} catch (error) {
console.error("getDocs (firebase.js): ", error);
}
},
async removeDoc({ dispatch }, id) {
try {
await deleteDoc(doc(firebaseFirestore, "sheets", id));
dispatch("getDocs");
} catch (error) {
console.error("removeDocs (firebase.js): ", error);
}
},
async archive({ state, dispatch }, sheet) {
try {
// send a post request to the API with the sheet ID in the body
// and a bearer auth token in the header
await fetch(
`${state.API_ENDPOINT}/sheet`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${state.access_token}`,
},
body: JSON.stringify({
sheet_id: sheet.sheetId,
}),
fetch(`${state.API_ENDPOINT}/sheet/mine`, {
method: "GET",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${state.access_token}`,
}
);
// update firestore with the archive status
const docRef = doc(firebaseFirestore, "sheets", sheet.id);
await updateDoc(docRef, {
lastArchived: Date.now(),
}).then(async response => {
const res = await response.json();
if (response.status === 200) {
commit("setSheets", res);
} else {
throw new Error(JSON.stringify(res));
}
}).finally(() => {
commit("setLoading", false);
});
// update the store
dispatch("getDocs");
} catch (error) {
console.error("archive (firebase.js): ", error);
console.error("getSheets (firebase.js): ", error);
}
},
async add({ state, dispatch, commit }, name) {
},
async createSheet({ state, dispatch, commit }, name) {
commit("setLoading", true);
return new Promise(async (resolve, reject) => {
@@ -391,49 +346,6 @@ export default createStore({
commit("setLoading", false);
});
},
async enable({ state, dispatch, commit }, { spreadsheetId }) {
commit("setLoading", true);
commit("setErrorMessage", "");
try {
// fetch existing sheet
console.log(spreadsheetId);
const sheetToEnable = await gapi.client.sheets.spreadsheets.get({
spreadsheetId: spreadsheetId,
});
console.log(sheetToEnable);
const q = query(
collection(firebaseFirestore, "sheets"),
where("uid", "==", state.user.uid),
where("sheetId", "==", spreadsheetId),
limit(1)
);
const response = await getDocs(q);
if (response.docs.length > 0) {
throw "Sheet already enabled";
}
const col = await collection(firebaseFirestore, "sheets");
await addDoc(col, {
sheetId: spreadsheetId,
url: sheetToEnable.result.spreadsheetUrl,
timestamp: Date.now(),
uid: state.user.uid,
email: state.user.email,
lastArchived: null,
name: sheetToEnable.result.properties.title,
});
dispatch("getDocs");
} catch (error) {
commit("setErrorMessage", `Unable to add sheet: ${JSON.stringify(error)}`);
commit("setLoading", false);
console.error("add (firebase.js): ", error);
}
},
},
getters: {
isTokenExpired: async (state) => {
@@ -469,7 +381,7 @@ export default createStore({
//TODO: merge these into single endpoint in the future
store.dispatch("checkActiveUser");
store.dispatch("checkUserGroups");
store.dispatch("getDocs");
store.dispatch("getSheets");
}
}).catch((error) => {
console.error("Error checking token expiration:", error);

View File

@@ -1,5 +1,5 @@
<template>
<v-container class="pane-l">
<v-container class="pane-l" v-if="user?.active">
<v-row>
<v-col>
<v-card elevation="12">
@@ -23,7 +23,7 @@
variant="outlined" :rules="[urlValidator]" required @keyup.enter="searchForArchives"></v-text-field>
<v-row>
<v-col cols="12" class="text-right">
<v-btn @click="searchForArchives" color="primary" class="mt-4" size="large" :disabled="!validUrl">
<v-btn @click="searchForArchives" color="teal" class="mt-4" size="large" :disabled="!validUrl">
Search
</v-btn>
</v-col>
@@ -103,7 +103,7 @@
<script>
import { urlValidator, getUrlFromResult } from "@/utils/misc.js";
export default {
name: "UrlView",
name: "ArchivesView",
data() {
return {
today: new Date().toISOString().substring(0, 10),

View File

@@ -1,5 +1,5 @@
<template>
<v-container class="pane" fluid>
<v-container class="pane" fluid v-if="!user || !user.active" >
<v-row>
<v-col>
<v-alert color="orange" icon="mdi-information" v-if="user && !user.active">
@@ -17,7 +17,7 @@
data.
</v-alert>
<p>
This tool can be used to archive digital content via single URL or Google Sheets, you can also <router-link to="/urls">search for archive content</router-link>.
This tool can be used to archive digital content via single URL or Google Sheets, you can also search for archived content.
</p>
<p v-if="!user || !user.active">
To use this tool you need a Google account and <strong>permission from the Bellingcat team</strong>.
@@ -27,16 +27,18 @@
</v-col>
</v-row>
</v-container>
<ArchiveUrl v-if="user?.active" />
<ArchiveSheet v-if="user?.active" />
<ManageSheets v-if="user?.active" />
</template>
<script>
import ArchiveUrl from "@/components/ArchiveUrl.vue";
import ArchiveSheet from "@/components/ArchiveSheet.vue";
import ManageSheets from "@/components/ManageSheets.vue";
export default {
name: "HomeView",
components: {
ArchiveUrl
ArchiveSheet, ManageSheets
},
computed: {
user() {

View File

@@ -1,193 +1,26 @@
<template>
<ArchiveSheet v-if="user?.active" />
<v-container class="pane">
<v-row>
<v-col>
<v-card style="margin-bottom: 1em">
<v-card-text>
<v-alert color="#f2d97c" icon="mdi-alert">
This is still a pre-release prototype demo service provided on a
best-effort basis. Do not use for mission critical or sensitive
data.
</v-alert>
<p>
This tool will configure a Google Sheet on your Google account for
use with
<a href="https://github.com/bellingcat/auto-archiver"
>Bellingcat's Auto Archiver</a
>. For more information about the Auto Archiver and how to use it,
see
<a href="https://github.com/bellingcat/auto-archiver"
>our Github repository</a
>
and the
<a
href="https://www.bellingcat.com/resources/2022/09/22/preserve-vital-online-content-with-bellingcats-auto-archiver-tool/"
>associated article</a
>.
</p>
<h4>How archiving a Google Spreadsheet works</h4>
<ul>
<li>Add links to the <code>Link</code> column</li>
<li>
Links are archived
<b>every 60 minutes</b>, or you can trigger a manual archive
below
</li>
<li>
You can modify and share the Google Sheet subsequently, but do
not edit the auto archiver column names in the header row or
remove the service account from the shared users
</li>
</ul>
</v-card-text>
</v-card>
<DocList v-if="user" />
<div class="text-h5 mt-5 mb-3">Manage new auto-archiver sheets</div>
<v-card style="margin-bottom: 1em">
<v-card-title>Create a new auto-archiver sheet</v-card-title>
<v-card-text>
<ol style="margin-bottom: 1em">
<li>Press "create" to create a new archiving Google Sheet</li>
<li>
This sheet will be shared with the service account necessary for
Bellingcat's archiving server
</li>
<li>The sheet will appear in your list</li>
</ol>
<v-text-field
label="Document name"
v-model="docName"
v-if="user"
></v-text-field>
<v-btn
@click="$store.dispatch('add', { name: docName })"
:loading="$store.state.loading"
v-if="user"
>Create</v-btn
>
<v-alert v-if="!user" color="#f2d97c" icon="mdi-alert"
><a href="#!" @click="$store.dispatch('signin')"
>Sign in with a Google account</a
>
to continue</v-alert
>
</v-card-text>
</v-card>
<v-card>
<v-card-title
>Enable the auto-archiver in an existing sheet</v-card-title
>
<v-card-text>
<ol style="margin-bottom: 1em">
<li>
Invite
<code
>bellingcat-auto-archiver-api@bellingcat-auto-archiver-b85db.iam.gserviceaccount.com</code
>
into your spreadsheet
</li>
<!-- Link Archive status Destination folder Archive location Archive date Thumbnail Upload timestamp Upload title Textual content Screenshot Hash -->
<li>
Make sure you have the following <b>mandatory</b> column names:
<ul>
<li><code>Link</code> where you will put the URLs.</li>
<li>
<code>Archive Status</code> to monitor progress and success
of archiver
</li>
<li>
<code>Archive location</code> where the link to the archived
content is added
</li>
</ul>
</li>
<li>
Add any of the following <b>optional</b> column names:
<ul>
<li>
<code>Archive date</code> info on when archiving occurred
</li>
<li>
<code>Thumbnail</code> an image preview from archived media
</li>
<li>
<code>Upload timestamp</code> online content creation date
</li>
<li><code>Upload title</code> title</li>
<li><code>Textual content</code> text content</li>
<li><code>Screenshot</code> link to page screenshot</li>
<li>
<code>Hash</code> content hash (for integrity purposes)
</li>
</ul>
</li>
<li>Paste the Google Sheet URL</li>
<li>Press "enable" to add the Google Sheet to your list</li>
<li>
Manually check archiving is working and re-check the steps above
if it is not
</li>
</ol>
<v-text-field
label="Google Sheet URL"
v-model="spreadsheetUrl"
:hint="spreadsheetId ? 'Detected id: ' + spreadsheetId : ''"
persistent-hint
v-if="user"
></v-text-field>
<v-btn
@click="$store.dispatch('enable', { spreadsheetId })"
:loading="$store.state.loading"
v-if="user"
>Enable</v-btn
>
<v-alert v-if="!user" color="#f2d97c" light icon="mdi-alert"
><a href="#!" @click="$store.dispatch('signin')"
>Sign in with a Google account</a
>
to continue</v-alert
>
</v-card-text>
</v-card>
</v-col>
</v-row>
</v-container>
<ManageSheets v-if="user?.active" />
</template>
<script>
import DocList from "@/components/DocList.vue";
import ArchiveSheet from "@/components/ArchiveSheet.vue";
import ManageSheets from "@/components/ManageSheets.vue";
export default {
name: "SheetView",
components: {
DocList, ArchiveSheet
ArchiveSheet, ManageSheets
},
data() {
return {
docName: "Auto archiver sheet",
spreadsheetUrl: "",
};
},
computed: {
user() {
return this.$store.state.user;
},
spreadsheetId() {
if (
this.spreadsheetUrl.startsWith("http") &&
this.spreadsheetUrl.split("/").length >= 6
) {
return this.spreadsheetUrl.split("/")[5];
}
return this.spreadsheetUrl;
},
},
methods: {},
};