mirror of https://github.com/usememos/memos
parent
a0667abec8
commit
2042737004
@ -1,13 +1,12 @@
|
|||||||
package api
|
package api
|
||||||
|
|
||||||
type Signin struct {
|
type Signin struct {
|
||||||
Email string `json:"email"`
|
Username string `json:"username"`
|
||||||
Password string `json:"password"`
|
Password string `json:"password"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Signup struct {
|
type Signup struct {
|
||||||
Email string `json:"email"`
|
Username string `json:"username"`
|
||||||
Role Role `json:"role"`
|
|
||||||
Name string `json:"name"`
|
|
||||||
Password string `json:"password"`
|
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