aboutsummaryrefslogtreecommitdiff
path: root/Timeline/ClientApp/src/app/views/timeline-common/TimelineMember.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'Timeline/ClientApp/src/app/views/timeline-common/TimelineMember.tsx')
-rw-r--r--Timeline/ClientApp/src/app/views/timeline-common/TimelineMember.tsx211
1 files changed, 0 insertions, 211 deletions
diff --git a/Timeline/ClientApp/src/app/views/timeline-common/TimelineMember.tsx b/Timeline/ClientApp/src/app/views/timeline-common/TimelineMember.tsx
deleted file mode 100644
index 67a8543a..00000000
--- a/Timeline/ClientApp/src/app/views/timeline-common/TimelineMember.tsx
+++ /dev/null
@@ -1,211 +0,0 @@
-import React, { useState } from "react";
-import { useTranslation } from "react-i18next";
-import { Container, ListGroup, Modal, Row, Col, Button } from "react-bootstrap";
-
-import { User, useAvatar } from "@/services/user";
-
-import SearchInput from "../common/SearchInput";
-import BlobImage from "../common/BlobImage";
-
-const TimelineMemberItem: React.FC<{
- user: User;
- owner: boolean;
- onRemove?: (username: string) => void;
-}> = ({ user, owner, onRemove }) => {
- const { t } = useTranslation();
-
- const avatar = useAvatar(user.username);
-
- return (
- <ListGroup.Item className="container">
- <Row>
- <Col xs="auto">
- <BlobImage blob={avatar} className="avatar small" />
- </Col>
- <Col>
- <Row>{user.nickname}</Row>
- <Row>
- <small>{"@" + user.username}</small>
- </Row>
- </Col>
- {(() => {
- if (owner) {
- return null;
- }
- if (onRemove == null) {
- return null;
- }
- return (
- <Button
- className="align-self-center"
- variant="danger"
- onClick={() => {
- onRemove(user.username);
- }}
- >
- {t("timeline.member.remove")}
- </Button>
- );
- })()}
- </Row>
- </ListGroup.Item>
- );
-};
-
-export interface TimelineMemberCallbacks {
- onCheckUser: (username: string) => Promise<User | null>;
- onAddUser: (user: User) => Promise<void>;
- onRemoveUser: (username: string) => void;
-}
-
-export interface TimelineMemberProps {
- members: User[];
- edit: TimelineMemberCallbacks | null | undefined;
-}
-
-const TimelineMember: React.FC<TimelineMemberProps> = (props) => {
- const { t } = useTranslation();
-
- const [userSearchText, setUserSearchText] = useState<string>("");
- const [userSearchState, setUserSearchState] = useState<
- | {
- type: "user";
- data: User;
- }
- | { type: "error"; data: string }
- | { type: "loading" }
- | { type: "init" }
- >({ type: "init" });
-
- const userSearchAvatar = useAvatar(
- userSearchState.type === "user" ? userSearchState.data.username : undefined
- );
-
- const members = props.members;
-
- return (
- <Container className="px-4">
- <ListGroup className="my-3">
- {members.map((member, index) => (
- <TimelineMemberItem
- key={member.username}
- user={member}
- owner={index === 0}
- onRemove={props.edit?.onRemoveUser}
- />
- ))}
- </ListGroup>
- {(() => {
- const edit = props.edit;
- if (edit != null) {
- return (
- <>
- <SearchInput
- value={userSearchText}
- onChange={(v) => {
- setUserSearchText(v);
- }}
- loading={userSearchState.type === "loading"}
- onButtonClick={() => {
- if (userSearchText === "") {
- setUserSearchState({
- type: "error",
- data: "login.emptyUsername",
- });
- return;
- }
-
- setUserSearchState({ type: "loading" });
- edit.onCheckUser(userSearchText).then(
- (u) => {
- if (u == null) {
- setUserSearchState({
- type: "error",
- data: "timeline.userNotExist",
- });
- } else {
- setUserSearchState({ type: "user", data: u });
- }
- },
- (e) => {
- setUserSearchState({
- type: "error",
- data: `${e as string}`,
- });
- }
- );
- }}
- />
- {(() => {
- if (userSearchState.type === "user") {
- const u = userSearchState.data;
- const addable =
- members.findIndex((m) => m.username === u.username) === -1;
- return (
- <>
- {!addable ? (
- <p>{t("timeline.member.alreadyMember")}</p>
- ) : null}
- <Container className="mb-3">
- <Row>
- <Col className="col-auto">
- <BlobImage
- blob={userSearchAvatar}
- className="avatar small"
- />
- </Col>
- <Col>
- <Row>{u.nickname}</Row>
- <Row>
- <small>{"@" + u.username}</small>
- </Row>
- </Col>
- <Button
- variant="primary"
- className="align-self-center"
- disabled={!addable}
- onClick={() => {
- void edit.onAddUser(u).then((_) => {
- setUserSearchText("");
- setUserSearchState({ type: "init" });
- });
- }}
- >
- {t("timeline.member.add")}
- </Button>
- </Row>
- </Container>
- </>
- );
- } else if (userSearchState.type === "error") {
- return (
- <p className="text-danger">{t(userSearchState.data)}</p>
- );
- }
- })()}
- </>
- );
- } else {
- return null;
- }
- })()}
- </Container>
- );
-};
-
-export default TimelineMember;
-
-export interface TimelineMemberDialogProps extends TimelineMemberProps {
- open: boolean;
- onClose: () => void;
-}
-
-export const TimelineMemberDialog: React.FC<TimelineMemberDialogProps> = (
- props
-) => {
- return (
- <Modal show centered onHide={props.onClose}>
- <TimelineMember {...props} />
- </Modal>
- );
-};