mirror of https://github.com/usememos/memos
parent
a0667abec8
commit
2042737004
@ -1,13 +1,12 @@
|
||||
package api
|
||||
|
||||
type Signin struct {
|
||||
Email string `json:"email"`
|
||||
Username string `json:"username"`
|
||||
Password string `json:"password"`
|
||||
}
|
||||
|
||||
type Signup struct {
|
||||
Email string `json:"email"`
|
||||
Role Role `json:"role"`
|
||||
Name string `json:"name"`
|
||||
Username string `json:"username"`
|
||||
Password string `json:"password"`
|
||||
Role Role `json:"role"`
|
||||
}
|
||||
|
@ -0,0 +1,41 @@
|
||||
-- add column username TEXT NOT NULL UNIQUE
|
||||
-- rename column name to nickname
|
||||
-- add role `ADMIN`
|
||||
DROP TABLE IF EXISTS _user_old;
|
||||
|
||||
ALTER TABLE user RENAME TO _user_old;
|
||||
|
||||
-- user
|
||||
CREATE TABLE user (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
created_ts BIGINT NOT NULL DEFAULT (strftime('%s', 'now')),
|
||||
updated_ts BIGINT NOT NULL DEFAULT (strftime('%s', 'now')),
|
||||
row_status TEXT NOT NULL CHECK (row_status IN ('NORMAL', 'ARCHIVED')) DEFAULT 'NORMAL',
|
||||
username TEXT NOT NULL UNIQUE,
|
||||
role TEXT NOT NULL CHECK (role IN ('HOST', 'ADMIN', 'USER')) DEFAULT 'USER',
|
||||
email TEXT NOT NULL DEFAULT '',
|
||||
nickname TEXT NOT NULL DEFAULT '',
|
||||
password_hash TEXT NOT NULL,
|
||||
open_id TEXT NOT NULL UNIQUE
|
||||
);
|
||||
|
||||
INSERT INTO user (
|
||||
id, created_ts, updated_ts, row_status,
|
||||
username, role, email, nickname, password_hash,
|
||||
open_id
|
||||
)
|
||||
SELECT
|
||||
id,
|
||||
created_ts,
|
||||
updated_ts,
|
||||
row_status,
|
||||
email,
|
||||
role,
|
||||
email,
|
||||
name,
|
||||
password_hash,
|
||||
open_id
|
||||
FROM
|
||||
_user_old;
|
||||
|
||||
DROP TABLE IF EXISTS _user_old;
|
@ -0,0 +1,118 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useAppSelector } from "../store";
|
||||
import { userService } from "../services";
|
||||
import Icon from "./Icon";
|
||||
import { generateDialog } from "./Dialog";
|
||||
import toastHelper from "./Toast";
|
||||
|
||||
type Props = DialogProps;
|
||||
|
||||
interface State {
|
||||
username: string;
|
||||
nickname: string;
|
||||
email: string;
|
||||
}
|
||||
|
||||
const UpdateAccountDialog: React.FC<Props> = ({ destroy }: Props) => {
|
||||
const { t } = useTranslation();
|
||||
const user = useAppSelector((state) => state.user.user as User);
|
||||
const [state, setState] = useState<State>({
|
||||
username: user.username,
|
||||
nickname: user.nickname,
|
||||
email: user.email,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
// do nth
|
||||
}, []);
|
||||
|
||||
const handleCloseBtnClick = () => {
|
||||
destroy();
|
||||
};
|
||||
|
||||
const handleNicknameChanged = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setState((state) => {
|
||||
return {
|
||||
...state,
|
||||
nickname: e.target.value as string,
|
||||
};
|
||||
});
|
||||
};
|
||||
const handleUsernameChanged = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setState((state) => {
|
||||
return {
|
||||
...state,
|
||||
username: e.target.value as string,
|
||||
};
|
||||
});
|
||||
};
|
||||
const handleEmailChanged = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setState((state) => {
|
||||
return {
|
||||
...state,
|
||||
email: e.target.value as string,
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
const handleSaveBtnClick = async () => {
|
||||
if (state.username === "") {
|
||||
toastHelper.error(t("message.fill-all"));
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const user = userService.getState().user as User;
|
||||
await userService.patchUser({
|
||||
id: user.id,
|
||||
username: state.username,
|
||||
nickname: state.nickname,
|
||||
email: state.email,
|
||||
});
|
||||
toastHelper.info("Update succeed");
|
||||
handleCloseBtnClick();
|
||||
} catch (error: any) {
|
||||
console.error(error);
|
||||
toastHelper.error(error.response.data.error);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="dialog-header-container !w-64">
|
||||
<p className="title-text">Update information</p>
|
||||
<button className="btn close-btn" onClick={handleCloseBtnClick}>
|
||||
<Icon.X />
|
||||
</button>
|
||||
</div>
|
||||
<div className="dialog-content-container">
|
||||
<p className="text-sm mb-1">Nickname</p>
|
||||
<input type="text" className="input-text" value={state.nickname} onChange={handleNicknameChanged} />
|
||||
<p className="text-sm mb-1 mt-2">Username</p>
|
||||
<input type="text" className="input-text" value={state.username} onChange={handleUsernameChanged} />
|
||||
<p className="text-sm mb-1 mt-2">Email</p>
|
||||
<input type="text" className="input-text" value={state.email} onChange={handleEmailChanged} />
|
||||
<div className="mt-4 w-full flex flex-row justify-end items-center space-x-2">
|
||||
<span className="btn-text" onClick={handleCloseBtnClick}>
|
||||
{t("common.cancel")}
|
||||
</span>
|
||||
<span className="btn-primary" onClick={handleSaveBtnClick}>
|
||||
{t("common.save")}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
function showUpdateAccountDialog() {
|
||||
generateDialog(
|
||||
{
|
||||
className: "update-account-dialog",
|
||||
},
|
||||
UpdateAccountDialog
|
||||
);
|
||||
}
|
||||
|
||||
export default showUpdateAccountDialog;
|
@ -1,46 +0,0 @@
|
||||
.change-password-dialog {
|
||||
> .dialog-container {
|
||||
@apply w-72;
|
||||
|
||||
> .dialog-content-container {
|
||||
@apply flex flex-col justify-start items-start;
|
||||
|
||||
> .tip-text {
|
||||
@apply bg-gray-400 text-xs p-2 rounded-lg;
|
||||
}
|
||||
|
||||
> .form-label {
|
||||
@apply flex flex-col justify-start items-start;
|
||||
@apply relative w-full leading-relaxed;
|
||||
|
||||
&.input-form-label {
|
||||
@apply py-3 pb-1;
|
||||
|
||||
> input {
|
||||
@apply w-full p-2 text-sm leading-6 rounded border border-gray-400 bg-transparent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
> .btns-container {
|
||||
@apply mt-2 w-full flex flex-row justify-end items-center;
|
||||
|
||||
> .btn {
|
||||
@apply text-sm px-4 py-2 rounded ml-2 bg-gray-400;
|
||||
|
||||
&:hover {
|
||||
@apply opacity-80;
|
||||
}
|
||||
|
||||
&.confirm-btn {
|
||||
@apply bg-green-600 text-white shadow-inner;
|
||||
}
|
||||
|
||||
&.cancel-btn {
|
||||
background-color: unset;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue