File size: 5,297 Bytes
a417977
1982de5
 
a417977
1982de5
 
 
a417977
 
 
 
 
 
 
 
 
 
 
 
 
1982de5
 
 
a417977
 
1982de5
a417977
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1982de5
 
 
a417977
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1982de5
 
 
 
 
 
 
a417977
 
1982de5
 
 
 
 
 
 
a417977
1982de5
a417977
1982de5
a417977
1982de5
 
 
a417977
 
 
 
 
 
 
 
 
 
1982de5
 
 
 
 
a417977
 
 
 
1982de5
 
 
 
 
 
 
a417977
 
 
 
 
 
 
 
1982de5
 
a417977
1982de5
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
import {Post as PostType, Topic as TopicType, topicsCtx} from "@/contexts/topics";
import style from "./style.module.scss";
import {Preview} from "../preview";
import {iso8601ToFrench} from "@/utils/dates";
import {FormGroup} from "../form";
import {Slider} from "../slider";
import {Button} from "../button";
import {settingsCtx} from "@/contexts/settings";
import {useContext, useState, useMemo} from "preact/hooks";
import {Wysiwyg} from "@/components/wysiwyg";
import {
    ChevronRight,
    X,
} from "preact-feather";
import cn from "classnames";
import {Pagination} from "@/components/pagination";
import {Spinner} from "@/components/spinner";
import {logCtx} from "@/contexts/log";

const postsPerPage = 10;

export function Topic(props: {
    topic: TopicType,
    page: number,
    setPage: (newPage: number) => void,
}) {
    /**
     * TODO
     * prendre la générationDate du premier post et remplacer toutes la dates (IA) avec celle-ci en calculant le delta en en l'appliquant à chaque post
     * Pour il faut remplacer la date des citations en prenant en compte le delta
     *
     */
    const [topicsContext, , topicsActions] = useContext(topicsCtx);
    const [settings, setSettings] = useContext(settingsCtx);
    const [, , logActions] = useContext(logCtx);
    const [wysiwygText, setWysiwygText] = useState("");

    const addQuote = (post: PostType) => {
        setWysiwygText((wysiwygText.length > 1 ? `${wysiwygText}\n\n` : "") + post.content.split("\n").map(l => `> ${l}`).join("\n"))
    }

    const postsSlice = useMemo(
        () => props.topic.posts.slice(props.page * postsPerPage, (props.page + 1) * postsPerPage),
        [props.page, props.topic.posts]
    );

    const pendingGeneration = topicsContext.generation === "pending";

    const pagination = (
        <Pagination
            pageCount={Math.ceil(props.topic.posts.length / postsPerPage)}
            page={props.page}
            setPage={props.setPage}
        />
    );

    return (
        <div>
            <div className={style.wrapper}>
                {pagination}
                <div className={style.postsContainer}>
                    {postsSlice.map((post, index) => {
                        const realIndex = postsPerPage * props.page + index;
                        return (
                            <Post
                                post={post}
                                quote={() => addQuote(post)}
                                remove={() => topicsActions.deletePost(props.topic.id, realIndex)}
                                loading={pendingGeneration && realIndex >= props.topic.posts.length - 1}
                            />
                        )
                    })}
                </div>
                {pagination}
            </div>
            <div>
                <h2>Ajout de posts</h2>
                <div className={style.generationSettings}>
                    <FormGroup>
                        <label htmlFor="postCount">Nombre de posts</label>
                        <Slider
                            name="postCount"
                            value={settings.postCount}
                            onChange={(v) => setSettings({...settings, postCount: v})}
                            min={1}
                            max={10}
                            step={1}
                        />
                    </FormGroup>
                </div>
                <Button
                    onClick={() => topicsActions.generatePosts(settings, logActions.log, props.topic)}
                    secondary={true}
                    loading={pendingGeneration}
                >
                    {pendingGeneration ? "Génération en cours…" : "Générer"}
                </Button>
            </div>
            <hr/>
            <div>
                <Wysiwyg
                    showTitle={false}
                    onSubmit={(user, title, text) => {
                        topicsActions.addPost(props.topic.id, user, text)
                    }}
                    text={wysiwygText}
                    setText={setWysiwygText}
                />
            </div>
        </div>
    )
}

function Post(props: {
    post: PostType,
    quote: () => void,
    remove: () => void,
    loading: boolean,
}) {
    return (
        <div className={style.post}>
            <div className={style.postHeader}>
                <img src="https://image.jeuxvideo.com/avatar-sm/default.jpg" className={style.avatar} alt="ahi"/>
                <div className={style.user}>{props.post.user}</div>
                <div className={style.date}>{iso8601ToFrench(props.post.date)}</div>
                <div className={style.actions}>
                    <div className={cn(style.action, style.actionDanger)} title="Supprimer" onClick={props.remove}>
                        <X size={16} style={{right: 0.6, top: 1.2}}/>
                    </div>
                    <div className={style.action} title="Citer" onClick={props.quote}>
                        <ChevronRight size={16} style={{left: 1.2}}/>
                    </div>
                </div>
            </div>
            <Preview raw={props.post.content}/>
            {props.loading ? <Spinner className={style.spinner}/> : null}
        </div>
    )
}