Browse Source

save a profile blurb

master
Trent Larson 6 days ago
parent
commit
7c90cf908a
  1. 161
      src/views/AccountViewView.vue

161
src/views/AccountViewView.vue

@ -263,6 +263,47 @@
</router-link> </router-link>
</div> </div>
<!-- User Profile -->
<div
class="bg-slate-100 rounded-md overflow-hidden px-4 py-4 mt-8 mb-8"
>
<div v-if="loadingProfile" class="text-center mb-2">
<fa icon="spinner" class="fa-spin text-slate-400"></fa> Loading
profile...
</div>
<div v-else class="flex items-center mb-2">
<span class="font-bold">Public Profile</span>
<fa
icon="circle-info"
class="text-slate-400 fa-fw ml-2 cursor-pointer"
@click="showProfileInfo"
/>
</div>
<textarea
v-model="userProfile"
class="w-full h-32 p-2 border border-slate-300 rounded-md"
placeholder="Write something about yourself for the public..."
:readonly="loadingProfile || savingProfile"
:class="{ 'bg-slate-100': loadingProfile || savingProfile }"
></textarea>
<button
@click="saveProfile"
class="mt-2 px-4 py-2 bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white rounded-md"
:disabled="loadingProfile || savingProfile"
:class="{
'opacity-50 cursor-not-allowed': loadingProfile || savingProfile,
}"
>
{{
loadingProfile
? "Loading..."
: savingProfile
? "Saving..."
: "Save Profile"
}}
</button>
</div>
<div <div
v-if="activeDid" v-if="activeDid"
id="sectionUsageLimits" id="sectionUsageLimits"
@ -819,6 +860,7 @@ import {
} from "@/constants/app"; } from "@/constants/app";
import { import {
db, db,
logConsoleAndDb,
retrieveSettingsForActiveAccount, retrieveSettingsForActiveAccount,
updateAccountSettings, updateAccountSettings,
} from "@/db/index"; } from "@/db/index";
@ -830,8 +872,9 @@ import {
} from "@/db/tables/settings"; } from "@/db/tables/settings";
import { import {
clearPasskeyToken, clearPasskeyToken,
ErrorResponse,
EndorserRateLimits, EndorserRateLimits,
ErrorResponse,
errorStringForLog,
fetchEndorserRateLimits, fetchEndorserRateLimits,
fetchImageRateLimits, fetchImageRateLimits,
getHeaders, getHeaders,
@ -877,6 +920,7 @@ export default class AccountViewView extends Vue {
isRegistered = false; isRegistered = false;
limitsMessage = ""; limitsMessage = "";
loadingLimits = false; loadingLimits = false;
loadingProfile = true;
notifyingNewActivity = false; notifyingNewActivity = false;
notifyingNewActivityTime = ""; notifyingNewActivityTime = "";
notifyingReminder = false; notifyingReminder = false;
@ -890,6 +934,7 @@ export default class AccountViewView extends Vue {
profileImageUrl?: string; profileImageUrl?: string;
publicHex = ""; publicHex = "";
publicBase64 = ""; publicBase64 = "";
savingProfile = false;
showAdvanced = false; showAdvanced = false;
showB64Copy = false; showB64Copy = false;
showContactGives = false; showContactGives = false;
@ -905,6 +950,7 @@ export default class AccountViewView extends Vue {
warnIfTestServer = false; warnIfTestServer = false;
webPushServer = ""; webPushServer = "";
webPushServerInput = ""; webPushServerInput = "";
userProfile = "";
/** /**
* Async function executed when the component is mounted. * Async function executed when the component is mounted.
@ -918,6 +964,38 @@ export default class AccountViewView extends Vue {
// Initialize component state with values from the database or defaults // Initialize component state with values from the database or defaults
await this.initializeState(); await this.initializeState();
await this.processIdentity(); await this.processIdentity();
// Load the user profile
try {
const headers = await getHeaders(this.activeDid);
const response = await this.axios.get(
this.apiServer + "/api/partner/user-profile/" + this.activeDid,
{ headers },
);
if (response.status === 200) {
this.userProfile = response.data.description || "";
} else {
// won't get here because axios throws an error instead
throw Error("Unable to load profile.");
}
} catch (error) {
if (error.status === 404) {
// this is ok: the profile is not yet created
} else {
logConsoleAndDb("Error loading profile: " + errorStringForLog(error));
this.$notify(
{
group: "alert",
type: "danger",
title: "Error Loading Profile",
text: "Your server profile is not available.",
},
5000,
);
}
} finally {
this.loadingProfile = false;
}
} catch (error) { } catch (error) {
// this can happen when running automated tests in dev mode because notifications don't work // this can happen when running automated tests in dev mode because notifications don't work
console.error( console.error(
@ -1498,13 +1576,22 @@ export default class AccountViewView extends Vue {
*/ */
private handleRateLimitsError(error: unknown) { private handleRateLimitsError(error: unknown) {
if (error instanceof AxiosError) { if (error instanceof AxiosError) {
const data = error.response?.data as ErrorResponse; if (error.status == 400 || error.status == 404) {
this.limitsMessage = // no worries: they probably just aren't registered and don't have any limits
(data?.error?.message as string) || "Bad server response."; console.log(
console.error( "Got 400 or 404 response retrieving limits which probably means they're not registered:",
"Got bad response retrieving limits, which usually means user isn't registered.", error,
error, );
); this.limitsMessage = "No limits found, so no actions are allowed.";
} else {
const data = error.response?.data as ErrorResponse;
this.limitsMessage =
(data?.error?.message as string) || "Bad server response.";
console.log(
"Got bad response retrieving limits:",
error,
);
}
} else { } else {
this.limitsMessage = "Got an error retrieving limits."; this.limitsMessage = "Got an error retrieving limits.";
console.error("Got some error retrieving limits:", error); console.error("Got some error retrieving limits:", error);
@ -1635,5 +1722,63 @@ export default class AccountViewView extends Vue {
} }
} }
} }
showProfileInfo() {
this.$notify(
{
group: "alert",
type: "info",
title: "Public Profile Information",
text: "This data will be published for all to see, so be careful what your write. Your ID will only be shared with people who you allow to see your activity.",
},
7000,
);
}
async saveProfile() {
this.savingProfile = true;
try {
const headers = await getHeaders(this.activeDid);
const response = await this.axios.post(
this.apiServer + "/api/partner/user-profile",
{
description: this.userProfile,
},
{ headers },
);
if (response.status === 201) {
this.$notify(
{
group: "alert",
type: "success",
title: "Profile Saved",
text: "Your profile has been updated successfully.",
},
3000,
);
} else {
// won't get here because axios throws an error on non-success
throw Error("Profile not saved");
}
} catch (error) {
logConsoleAndDb("Error saving profile: " + errorStringForLog(error));
const errorMessage: string =
error.response?.data?.error?.message ||
error.response?.data?.error ||
error.message ||
"There was an error saving your profile.";
this.$notify(
{
group: "alert",
type: "danger",
title: "Error Saving Profile",
text: errorMessage,
},
3000,
);
} finally {
this.savingProfile = false;
}
}
} }
</script> </script>

Loading…
Cancel
Save