fix: improve migration page UX
- Show current alias value on the page (persists across GET/POST) - Pre-fill alias input with current value - Add fieldset legend and per-item hints to import checkboxes - Add intro paragraph explaining the migration flow - Rewrite copy to be clearer and more reassuring - Note irreversibility of step 3 explicitly
This commit is contained in:
@@ -178,7 +178,7 @@ export default class ActivityPubEndpoint {
|
|||||||
router.get("/admin/followers", followersController(mp));
|
router.get("/admin/followers", followersController(mp));
|
||||||
router.get("/admin/following", followingController(mp));
|
router.get("/admin/following", followingController(mp));
|
||||||
router.get("/admin/activities", activitiesController(mp));
|
router.get("/admin/activities", activitiesController(mp));
|
||||||
router.get("/admin/migrate", migrateGetController(mp));
|
router.get("/admin/migrate", migrateGetController(mp, this.options));
|
||||||
router.post("/admin/migrate", migratePostController(mp, this.options));
|
router.post("/admin/migrate", migratePostController(mp, this.options));
|
||||||
|
|
||||||
return router;
|
return router;
|
||||||
|
|||||||
@@ -12,12 +12,13 @@ import {
|
|||||||
bulkImportFollowers,
|
bulkImportFollowers,
|
||||||
} from "../migration.js";
|
} from "../migration.js";
|
||||||
|
|
||||||
export function migrateGetController(mountPath) {
|
export function migrateGetController(mountPath, pluginOptions) {
|
||||||
return async (request, response, next) => {
|
return async (request, response, next) => {
|
||||||
try {
|
try {
|
||||||
response.render("activitypub-migrate", {
|
response.render("activitypub-migrate", {
|
||||||
title: response.locals.__("activitypub.migrate.title"),
|
title: response.locals.__("activitypub.migrate.title"),
|
||||||
mountPath,
|
mountPath,
|
||||||
|
currentAlias: pluginOptions.alsoKnownAs || "",
|
||||||
result: null,
|
result: null,
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -94,6 +95,7 @@ export function migratePostController(mountPath, pluginOptions) {
|
|||||||
response.render("activitypub-migrate", {
|
response.render("activitypub-migrate", {
|
||||||
title: response.locals.__("activitypub.migrate.title"),
|
title: response.locals.__("activitypub.migrate.title"),
|
||||||
mountPath,
|
mountPath,
|
||||||
|
currentAlias: pluginOptions.alsoKnownAs || "",
|
||||||
result,
|
result,
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
+19
-14
@@ -21,23 +21,28 @@
|
|||||||
"directionOutbound": "Sent",
|
"directionOutbound": "Sent",
|
||||||
"migrate": {
|
"migrate": {
|
||||||
"title": "Mastodon migration",
|
"title": "Mastodon migration",
|
||||||
"step1Title": "Step 1 — Configure actor alias",
|
"intro": "This guide walks you through moving your Mastodon identity to your IndieWeb site. Complete each step in order — your existing followers will be notified and can re-follow you automatically.",
|
||||||
"step1Desc": "Link your old Mastodon account to this actor so the fediverse knows they are the same person.",
|
"step1Title": "Step 1 — Link your old account",
|
||||||
"aliasLabel": "Your old Mastodon account URL",
|
"step1Desc": "Tell the fediverse that your old Mastodon account and this site belong to the same person. This sets the <code>alsoKnownAs</code> property on your ActivityPub actor, which Mastodon checks before allowing a Move.",
|
||||||
"aliasHint": "e.g. https://mstdn.social/users/rmdes — sets alsoKnownAs on your actor",
|
"aliasLabel": "Old Mastodon account URL",
|
||||||
|
"aliasHint": "The full URL of your Mastodon profile, e.g. https://mstdn.social/users/rmdes",
|
||||||
"aliasSave": "Save alias",
|
"aliasSave": "Save alias",
|
||||||
"step2Title": "Step 2 — Import followers/following",
|
"aliasCurrent": "Current alias",
|
||||||
"step2Desc": "Upload your Mastodon data export CSV to import your social graph.",
|
"aliasNone": "No alias configured yet.",
|
||||||
"importLabel": "Import followers and following",
|
"step2Title": "Step 2 — Import your social graph",
|
||||||
"fileLabel": "Mastodon export CSV",
|
"step2Desc": "Upload the CSV files from your Mastodon data export to bring over your connections. Go to your Mastodon instance → Preferences → Import and export → Data export to download them.",
|
||||||
"fileHint": "Upload following_accounts.csv from your Mastodon data export",
|
"importLegend": "What to import",
|
||||||
|
"fileLabel": "CSV file",
|
||||||
|
"fileHint": "Select a CSV file from your Mastodon data export (e.g. following_accounts.csv or followers.csv)",
|
||||||
"importButton": "Import",
|
"importButton": "Import",
|
||||||
"importFollowing": "Import following list",
|
"importFollowing": "Following list",
|
||||||
"importFollowers": "Import followers list (pending until they re-follow after Move)",
|
"importFollowingHint": "Accounts you follow — they will appear in your Following list immediately",
|
||||||
"step3Title": "Step 3 — Trigger Move on Mastodon",
|
"importFollowers": "Followers list",
|
||||||
"step3Desc": "Go to your Mastodon instance → Preferences → Account → Move to a different account. Enter your new handle and confirm. After the Move, followers will automatically re-follow you here.",
|
"importFollowersHint": "Your current followers — they will be recorded as pending until they re-follow you after the Move in step 3",
|
||||||
|
"step3Title": "Step 3 — Move your account",
|
||||||
|
"step3Desc": "Once you have saved your alias and imported your data, go to your Mastodon instance → Preferences → Account → <strong>Move to a different account</strong>. Enter your new fediverse handle and confirm. Mastodon will notify all your followers, and those whose servers support it will automatically re-follow you here. This step is irreversible — your old account will become a redirect.",
|
||||||
"success": "Imported %d following, %d followers (%d failed).",
|
"success": "Imported %d following, %d followers (%d failed).",
|
||||||
"aliasSuccess": "Actor alias updated."
|
"aliasSuccess": "Alias saved — your actor document now includes this account as alsoKnownAs."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@rmdes/indiekit-endpoint-activitypub",
|
"name": "@rmdes/indiekit-endpoint-activitypub",
|
||||||
"version": "0.1.5",
|
"version": "0.1.6",
|
||||||
"description": "ActivityPub federation endpoint for Indiekit via Fedify. Adds full fediverse support: actor, inbox, outbox, followers, following, syndication, and Mastodon migration.",
|
"description": "ActivityPub federation endpoint for Indiekit via Fedify. Adds full fediverse support: actor, inbox, outbox, followers, following, syndication, and Mastodon migration.",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"indiekit",
|
"indiekit",
|
||||||
|
|||||||
@@ -5,9 +5,9 @@
|
|||||||
{% from "button/macro.njk" import button with context %}
|
{% from "button/macro.njk" import button with context %}
|
||||||
{% from "checkboxes/macro.njk" import checkboxes with context %}
|
{% from "checkboxes/macro.njk" import checkboxes with context %}
|
||||||
{% from "file-input/macro.njk" import fileInput with context %}
|
{% from "file-input/macro.njk" import fileInput with context %}
|
||||||
{% from "details/macro.njk" import details with context %}
|
|
||||||
{% from "notification-banner/macro.njk" import notificationBanner with context %}
|
{% from "notification-banner/macro.njk" import notificationBanner with context %}
|
||||||
{% from "prose/macro.njk" import prose with context %}
|
{% from "prose/macro.njk" import prose with context %}
|
||||||
|
{% from "badge/macro.njk" import badge with context %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
{{ heading({ text: title, level: 1, parent: { text: __("activitypub.title"), href: mountPath } }) }}
|
{{ heading({ text: title, level: 1, parent: { text: __("activitypub.title"), href: mountPath } }) }}
|
||||||
@@ -16,16 +16,28 @@
|
|||||||
{{ notificationBanner({ type: result.type, text: result.text }) }}
|
{{ notificationBanner({ type: result.type, text: result.text }) }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
{{ prose({ text: __("activitypub.migrate.intro") }) }}
|
||||||
|
|
||||||
{# Step 1 — Actor alias #}
|
{# Step 1 — Actor alias #}
|
||||||
{{ heading({ text: __("activitypub.migrate.step1Title"), level: 2 }) }}
|
{{ heading({ text: __("activitypub.migrate.step1Title"), level: 2 }) }}
|
||||||
{{ prose({ text: __("activitypub.migrate.step1Desc") }) }}
|
{{ prose({ text: __("activitypub.migrate.step1Desc") }) }}
|
||||||
|
|
||||||
|
{% if currentAlias %}
|
||||||
|
<p>
|
||||||
|
<strong>{{ __("activitypub.migrate.aliasCurrent") }}:</strong>
|
||||||
|
<a href="{{ currentAlias }}">{{ currentAlias }}</a>
|
||||||
|
</p>
|
||||||
|
{% else %}
|
||||||
|
<p><em>{{ __("activitypub.migrate.aliasNone") }}</em></p>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
<form method="post" novalidate>
|
<form method="post" novalidate>
|
||||||
<input type="hidden" name="action" value="alias">
|
<input type="hidden" name="action" value="alias">
|
||||||
{{ input({
|
{{ input({
|
||||||
name: "aliasUrl",
|
name: "aliasUrl",
|
||||||
label: __("activitypub.migrate.aliasLabel"),
|
label: __("activitypub.migrate.aliasLabel"),
|
||||||
hint: __("activitypub.migrate.aliasHint"),
|
hint: __("activitypub.migrate.aliasHint"),
|
||||||
|
value: currentAlias,
|
||||||
type: "url"
|
type: "url"
|
||||||
}) }}
|
}) }}
|
||||||
{{ button({ text: __("activitypub.migrate.aliasSave") }) }}
|
{{ button({ text: __("activitypub.migrate.aliasSave") }) }}
|
||||||
@@ -42,9 +54,20 @@
|
|||||||
|
|
||||||
{{ checkboxes({
|
{{ checkboxes({
|
||||||
name: "importTypes",
|
name: "importTypes",
|
||||||
|
fieldset: {
|
||||||
|
legend: __("activitypub.migrate.importLegend")
|
||||||
|
},
|
||||||
items: [
|
items: [
|
||||||
{ value: "following", text: __("activitypub.migrate.importFollowing") },
|
{
|
||||||
{ value: "followers", text: __("activitypub.migrate.importFollowers") }
|
label: __("activitypub.migrate.importFollowing"),
|
||||||
|
value: "following",
|
||||||
|
hint: __("activitypub.migrate.importFollowingHint")
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: __("activitypub.migrate.importFollowers"),
|
||||||
|
value: "followers",
|
||||||
|
hint: __("activitypub.migrate.importFollowersHint")
|
||||||
|
}
|
||||||
],
|
],
|
||||||
values: ["following"]
|
values: ["following"]
|
||||||
}) }}
|
}) }}
|
||||||
|
|||||||
Reference in New Issue
Block a user