Add "Import Follows" page
This commit is contained in:
parent
6852c69498
commit
133cffa120
5 changed files with 115 additions and 3 deletions
|
@ -10,6 +10,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|||
|
||||
- Added "Experiments" section to Settings page (includes "Move Followers" feature).
|
||||
- Show error message if moving of followers fails.
|
||||
- Added "Import Follows" page.
|
||||
|
||||
### Changed
|
||||
|
||||
|
|
|
@ -49,6 +49,22 @@ export async function exportFollows(
|
|||
downloadBlob(blob)
|
||||
}
|
||||
|
||||
export async function importFollows(
|
||||
authToken: string,
|
||||
followsCsv: string,
|
||||
): Promise<void> {
|
||||
const url = `${BACKEND_URL}/api/v1/settings/import_follows`
|
||||
const response = await http(url, {
|
||||
method: "POST",
|
||||
authToken,
|
||||
json: { follows_csv: followsCsv },
|
||||
})
|
||||
if (response.status !== 204) {
|
||||
const data = await response.json()
|
||||
throw new Error(data.message)
|
||||
}
|
||||
}
|
||||
|
||||
export async function moveFollowers(
|
||||
authToken: string,
|
||||
fromActorId: string,
|
||||
|
|
|
@ -4,6 +4,7 @@ import AboutPage from "@/views/About.vue"
|
|||
import EthereumPage from "@/views/Ethereum.vue"
|
||||
import HomeTimeline from "@/views/HomeTimeline.vue"
|
||||
import IdentityProof from "@/views/IdentityProof.vue"
|
||||
import ImportFollows from "@/views/ImportFollows.vue"
|
||||
import LandingPage from "@/views/LandingPage.vue"
|
||||
import MoveFollowers from "@/views/MoveFollowers.vue"
|
||||
import NotificationList from "@/views/NotificationList.vue"
|
||||
|
@ -140,6 +141,12 @@ const routes: Array<RouteRecordRaw> = [
|
|||
component: IdentityProof,
|
||||
meta: { onlyAuthenticated: true },
|
||||
},
|
||||
{
|
||||
path: "/settings/import-follows",
|
||||
name: "import-follows",
|
||||
component: ImportFollows,
|
||||
meta: { onlyAuthenticated: true },
|
||||
},
|
||||
{
|
||||
path: "/subscriptions/settings",
|
||||
name: "subscriptions-settings",
|
||||
|
|
76
src/views/ImportFollows.vue
Normal file
76
src/views/ImportFollows.vue
Normal file
|
@ -0,0 +1,76 @@
|
|||
<template>
|
||||
<sidebar-layout>
|
||||
<template #content>
|
||||
<h1>Import follows</h1>
|
||||
<form class="import-follows">
|
||||
<div class="input-group">
|
||||
<textarea
|
||||
id="follows"
|
||||
placeholder="Follows (CSV)"
|
||||
v-model="followsCsv"
|
||||
>
|
||||
</textarea>
|
||||
</div>
|
||||
<button
|
||||
type="submit"
|
||||
class="btn"
|
||||
:disabled="!canImport() || isLoading"
|
||||
@click.prevent="submit()"
|
||||
>
|
||||
Import
|
||||
</button>
|
||||
<div class="error-message" v-if="errorMessage">{{ errorMessage }}</div>
|
||||
</form>
|
||||
</template>
|
||||
</sidebar-layout>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { $, $ref } from "vue/macros"
|
||||
import { useRouter } from "vue-router"
|
||||
|
||||
import { importFollows } from "@/api/settings"
|
||||
import SidebarLayout from "@/components/SidebarLayout.vue"
|
||||
import { useCurrentUser } from "@/store/user"
|
||||
|
||||
const router = useRouter()
|
||||
const { currentUser, ensureAuthToken } = $(useCurrentUser())
|
||||
|
||||
const followsCsv = $ref("")
|
||||
let isLoading = $ref(false)
|
||||
let errorMessage = $ref<string | null>(null)
|
||||
|
||||
function canImport(): boolean {
|
||||
return followsCsv.length > 0
|
||||
}
|
||||
|
||||
async function submit() {
|
||||
if (currentUser === null) {
|
||||
return
|
||||
}
|
||||
isLoading = true
|
||||
try {
|
||||
await importFollows(
|
||||
ensureAuthToken(),
|
||||
followsCsv,
|
||||
)
|
||||
} catch (error: any) {
|
||||
isLoading = false
|
||||
errorMessage = error.message
|
||||
return
|
||||
}
|
||||
isLoading = false
|
||||
errorMessage = null
|
||||
router.push({ name: "profile", params: { profileId: currentUser.id } })
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "../styles/layout";
|
||||
@import "../styles/mixins";
|
||||
@import "../styles/theme";
|
||||
|
||||
form {
|
||||
@include content-form;
|
||||
}
|
||||
</style>
|
|
@ -57,9 +57,14 @@
|
|||
<h2>Experiments</h2>
|
||||
<details class="experiments">
|
||||
<summary>This section contains experimental features. Use at your own risk.</summary>
|
||||
<router-link class="btn" :to="{ name: 'move-followers' }">
|
||||
Move followers
|
||||
</router-link>
|
||||
<div class="experiments-wrapper">
|
||||
<router-link class="btn" :to="{ name: 'import-follows' }">
|
||||
Import follows
|
||||
</router-link>
|
||||
<router-link class="btn" :to="{ name: 'move-followers' }">
|
||||
Move followers
|
||||
</router-link>
|
||||
</div>
|
||||
</details>
|
||||
</section>
|
||||
</template>
|
||||
|
@ -138,5 +143,12 @@ form {
|
|||
summary {
|
||||
margin-bottom: $block-outer-padding;
|
||||
}
|
||||
|
||||
.experiments-wrapper {
|
||||
align-items: flex-start;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: $block-outer-padding;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
Loading…
Reference in a new issue