Merge pull request #70 from Maix0/frontend/profileDesc

feat(frontend): added description handling the /profile
This commit is contained in:
Nigel 2025-12-22 20:09:25 +01:00 committed by GitHub
commit 90a40aa626
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 57 additions and 9 deletions

View file

@ -45,6 +45,12 @@ export interface GetUser200ResponsePayload {
* @memberof GetUser200ResponsePayload * @memberof GetUser200ResponsePayload
*/ */
guest: boolean; guest: boolean;
/**
*
* @type {string}
* @memberof GetUser200ResponsePayload
*/
desc: string;
/** /**
* *
* @type {GetUser200ResponsePayloadSelfInfo} * @type {GetUser200ResponsePayloadSelfInfo}
@ -60,6 +66,7 @@ export function instanceOfGetUser200ResponsePayload(value: object): value is Get
if (!('name' in value) || value['name'] === undefined) return false; if (!('name' in value) || value['name'] === undefined) return false;
if (!('id' in value) || value['id'] === undefined) return false; if (!('id' in value) || value['id'] === undefined) return false;
if (!('guest' in value) || value['guest'] === undefined) return false; if (!('guest' in value) || value['guest'] === undefined) return false;
if (!('desc' in value) || value['desc'] === undefined) return false;
return true; return true;
} }
@ -76,6 +83,7 @@ export function GetUser200ResponsePayloadFromJSONTyped(json: any, ignoreDiscrimi
'name': json['name'], 'name': json['name'],
'id': json['id'], 'id': json['id'],
'guest': json['guest'], 'guest': json['guest'],
'desc': json['desc'],
'selfInfo': json['selfInfo'] == null ? undefined : GetUser200ResponsePayloadSelfInfoFromJSON(json['selfInfo']), 'selfInfo': json['selfInfo'] == null ? undefined : GetUser200ResponsePayloadSelfInfoFromJSON(json['selfInfo']),
}; };
} }
@ -94,6 +102,7 @@ export function GetUser200ResponsePayloadToJSONTyped(value?: GetUser200ResponseP
'name': value['name'], 'name': value['name'],
'id': value['id'], 'id': value['id'],
'guest': value['guest'], 'guest': value['guest'],
'desc': value['desc'],
'selfInfo': GetUser200ResponsePayloadSelfInfoToJSON(value['selfInfo']), 'selfInfo': GetUser200ResponsePayloadSelfInfoToJSON(value['selfInfo']),
}; };
} }

View file

@ -15,6 +15,7 @@ export type User = {
id: string; id: string;
guest: boolean; guest: boolean;
name: string; name: string;
desc: string;
selfInfo?: { selfInfo?: {
loginName?: string; loginName?: string;
providerId?: string; providerId?: string;

View file

@ -47,6 +47,14 @@
<button id="passwordButton" <button id="passwordButton"
class="w-full bg-blue-600 text-white py-2 rounded hover:bg-blue-700">Update</button> class="w-full bg-blue-600 text-white py-2 rounded hover:bg-blue-700">Update</button>
</div> </div>
<!-- Description -->
<div id="descWrapper" class="py-2">
<label class="block font-medium mb-1 text-gray-700">Description</label>
<input id="descBox" type="text" placeholder="Description..." name="Description"
class="w-full px-4 py-2 border border-gray-300 text-gray-700 rounded-xl focus:outline-none focus:ring-2 focus:ring-blue-500" />
<button id="descButton"
class="w-full bg-blue-600 text-white py-2 rounded hover:bg-blue-700">Update</button>
</div>
<!-- TOTP --> <!-- TOTP -->
<div class="border rounded p-4" id="totpWrapper" hidden> <div class="border rounded p-4" id="totpWrapper" hidden>
<h2 class="font-semibold text-lg mb-2">Two-Factor Authentication (TOTP)</h2> <h2 class="font-semibold text-lg mb-2">Two-Factor Authentication (TOTP)</h2>

View file

@ -97,6 +97,13 @@ async function route(url: string, _args: { [k: string]: string }) {
let providerUserBox = let providerUserBox =
app.querySelector<HTMLDivElement>("#providerUserBox")!; app.querySelector<HTMLDivElement>("#providerUserBox")!;
let descWrapper =
app.querySelector<HTMLDivElement>("#descWrapper")!;
let descBox =
app.querySelector<HTMLInputElement>("#descBox")!;
let descButton =
app.querySelector<HTMLButtonElement>("#descButton")!;
let accountTypeBox = let accountTypeBox =
app.querySelector<HTMLDivElement>("#accountType")!; app.querySelector<HTMLDivElement>("#accountType")!;
displayNameBox.value = user.name; displayNameBox.value = user.name;
@ -119,12 +126,8 @@ async function route(url: string, _args: { [k: string]: string }) {
let totpWrapper = let totpWrapper =
app.querySelector<HTMLDivElement>("#totpWrapper")!; app.querySelector<HTMLDivElement>("#totpWrapper")!;
if (user.guest) { descBox.value = user.desc;
for (let c of passwordButton.classList.values()) {
if (c.startsWith("bg-") || c.startsWith("hover:bg-"))
passwordButton.classList.remove(c);
}
}
if (user.guest) { if (user.guest) {
removeBgColor( removeBgColor(
passwordButton, passwordButton,
@ -132,8 +135,16 @@ async function route(url: string, _args: { [k: string]: string }) {
enableBtn, enableBtn,
disableBtn, disableBtn,
showSecretBtn, showSecretBtn,
descButton,
); );
descButton.classList.add(
"bg-gray-700",
"hover:bg-gray-700",
);
descButton.disabled = true;
descBox.disabled = true;
passwordButton.classList.add( passwordButton.classList.add(
"bg-gray-700", "bg-gray-700",
"hover:bg-gray-700", "hover:bg-gray-700",
@ -257,6 +268,16 @@ async function route(url: string, _args: { [k: string]: string }) {
showError(`Failed to update: ${req.msg}`); showError(`Failed to update: ${req.msg}`);
} }
}; };
descButton.onclick = async () => {
let req = await client.changeDesc({ changeDescRequest: { desc: descBox.value } });
if (req.kind === "success") {
showSuccess("Successfully changed description");
handleRoute();
}
else {
showError(`Failed to update: ${req.msg}`);
}
};
// Initialize UI state // Initialize UI state
refreshTotpUI(); refreshTotpUI();

View file

@ -1767,7 +1767,8 @@
"required": [ "required": [
"name", "name",
"id", "id",
"guest" "guest",
"desc"
], ],
"properties": { "properties": {
"name": { "name": {
@ -1779,6 +1780,9 @@
"guest": { "guest": {
"type": "boolean" "type": "boolean"
}, },
"desc": {
"type": "string"
},
"selfInfo": { "selfInfo": {
"type": "object", "type": "object",
"properties": { "properties": {

View file

@ -529,7 +529,8 @@
"required": [ "required": [
"name", "name",
"id", "id",
"guest" "guest",
"desc"
], ],
"properties": { "properties": {
"name": { "name": {
@ -541,6 +542,9 @@
"guest": { "guest": {
"type": "boolean" "type": "boolean"
}, },
"desc": {
"type": "string"
},
"selfInfo": { "selfInfo": {
"type": "object", "type": "object",
"properties": { "properties": {

View file

@ -6,7 +6,7 @@ import { isNullish, MakeStaticResponse, typeResponse } from '@shared/utils';
export const UserInfoRes = { export const UserInfoRes = {
'200': typeResponse('success', 'userinfo.success', { '200': typeResponse('success', 'userinfo.success', {
name: Type.String(), id: Type.String(), guest: Type.Boolean(), name: Type.String(), id: Type.String(), guest: Type.Boolean(), desc: Type.String(),
selfInfo: Type.Optional(Type.Object({ selfInfo: Type.Optional(Type.Object({
login_name: Type.Optional(Type.String()), login_name: Type.Optional(Type.String()),
provider_id: Type.Optional(Type.String()), provider_id: Type.Optional(Type.String()),
@ -61,6 +61,7 @@ const route: FastifyPluginAsync = async (fastify, _opts): Promise<void> => {
// ``` // ```
// is the same as `val = !!something` // is the same as `val = !!something`
guest: !!user.guest, guest: !!user.guest,
desc: user.desc,
selfInfo: askSelf ? { selfInfo: askSelf ? {
login_name: user.login, login_name: user.login,
provider_id: user.provider_name, provider_id: user.provider_name,