From 87a99d9e8dbf32fbf5330c28f5beeda16c27a2e0 Mon Sep 17 00:00:00 2001 From: Ilya Y <75578537+ilya-bkv@users.noreply.github.com> Date: Thu, 26 Jan 2023 09:59:43 +0300 Subject: [PATCH] Prosemirror integrate (#86) Comment Editor --- src/components/Article/Comment.module.scss | 19 ++++ src/components/Article/Comment.tsx | 38 +++++--- src/components/Article/CommentsTree.tsx | 44 +++++---- src/components/Article/FullArticle.tsx | 6 +- src/components/Inbox/CreateModalContent.tsx | 2 +- src/components/Inbox/DialogCard.tsx | 9 +- src/components/Views/Inbox.tsx | 5 +- .../_shared/CommentEditor/CommentEditor.tsx | 91 +++++++++++++++++++ src/components/_shared/CommentEditor/index.ts | 1 + .../_shared/CommentEditor/menu/index.ts | 72 +++++++++++++++ .../CommentEditor/plugins/placeholder.ts | 21 +++++ .../_shared/CommentEditor/schema.ts | 43 +++++++++ .../styles/CommentEditor.module.scss | 32 +++++++ .../styles/ProseMirrorOverrides.scss | 14 +++ .../_shared/GrowingTextarea/index.ts | 1 - src/context/inbox.tsx | 2 +- src/graphql/mutation/create-chat.ts | 4 + src/graphql/query/chat-recipients.ts | 1 + src/graphql/types.gen.ts | 74 ++++++++++----- src/locales/ru.json | 4 +- src/stores/zine/reactions.ts | 2 +- src/utils/apiClient.ts | 4 +- 22 files changed, 421 insertions(+), 68 deletions(-) create mode 100644 src/components/_shared/CommentEditor/CommentEditor.tsx create mode 100644 src/components/_shared/CommentEditor/index.ts create mode 100644 src/components/_shared/CommentEditor/menu/index.ts create mode 100644 src/components/_shared/CommentEditor/plugins/placeholder.ts create mode 100644 src/components/_shared/CommentEditor/schema.ts create mode 100644 src/components/_shared/CommentEditor/styles/CommentEditor.module.scss create mode 100644 src/components/_shared/CommentEditor/styles/ProseMirrorOverrides.scss delete mode 100644 src/components/_shared/GrowingTextarea/index.ts diff --git a/src/components/Article/Comment.module.scss b/src/components/Article/Comment.module.scss index ffb4d852..e5c93741 100644 --- a/src/components/Article/Comment.module.scss +++ b/src/components/Article/Comment.module.scss @@ -122,12 +122,31 @@ @include font-size(1.5rem); line-height: 1.47; + + blockquote { + margin-left: 0; + padding-left: 10px; + font-style: italic; + font-weight: 400; + color: #9fa1a7; + border-left: 2px solid #696969; + + p, + .paragraph { + margin-bottom: 0; + } + } } .commentAuthor, .commentDate, .commentRating { @include font-size(1.2rem); } +.articleAuthor { + color: #2638d9; + font-size: 12px; + margin-right: 12px; +} .commentDate { color: rgb(0 0 0 / 30%); flex: 1; diff --git a/src/components/Article/Comment.tsx b/src/components/Article/Comment.tsx index b3eef418..37f2073c 100644 --- a/src/components/Article/Comment.tsx +++ b/src/components/Article/Comment.tsx @@ -13,18 +13,20 @@ import stylesHeader from '../Nav/Header.module.scss' import Userpic from '../Author/Userpic' import { useSession } from '../../context/session' import { ReactionKind } from '../../graphql/types.gen' -import GrowingTextarea from '../_shared/GrowingTextarea' +import CommentEditor from '../_shared/CommentEditor' +import { ShowOnlyOnClient } from '../_shared/ShowOnlyOnClient' type Props = { comment: Reaction compact?: boolean reactions?: Reaction[] + isArticleAuthor?: boolean } const Comment = (props: Props) => { const [isReplyVisible, setIsReplyVisible] = createSignal(false) - const [loading, setLoading] = createSignal(false) - const [errorMessage, setErrorMessage] = createSignal(null) + const [loading, setLoading] = createSignal(false) + const [submitted, setSubmitted] = createSignal(false) const { session } = useSession() const canEdit = createMemo(() => props.comment.createdBy?.slug === session()?.user?.slug) @@ -58,12 +60,13 @@ const Comment = (props: Props) => { } ) setIsReplyVisible(false) + setSubmitted(true) setLoading(false) } catch (error) { console.error('[handleCreate reaction]:', error) - setErrorMessage(t('Something went wrong, please try again')) } } + const formattedDate = createMemo(() => formatDate(new Date(comment()?.createdAt), { hour: 'numeric', minute: 'numeric' }) ) @@ -94,6 +97,10 @@ const Comment = (props: Props) => { /> + +
{t('Author')}
+
+
{formattedDate()}
{
- handleCreate(value)} - loading={loading()} - errorMessage={errorMessage()} - /> + + handleCreate(value)} + /> + @@ -179,7 +185,13 @@ const Comment = (props: Props) => {
    r.replyTo === props.comment.id)}> - {(reaction) => } + {(reaction) => ( + + )}
diff --git a/src/components/Article/CommentsTree.tsx b/src/components/Article/CommentsTree.tsx index c0af2615..67eb9f77 100644 --- a/src/components/Article/CommentsTree.tsx +++ b/src/components/Article/CommentsTree.tsx @@ -7,14 +7,21 @@ import type { Reaction } from '../../graphql/types.gen' import { clsx } from 'clsx' import { byCreated, byStat } from '../../utils/sortby' import { Loading } from '../Loading' -import GrowingTextarea from '../_shared/GrowingTextarea' -import { ReactionKind } from '../../graphql/types.gen' +import { Author, ReactionKind } from '../../graphql/types.gen' import { useSession } from '../../context/session' +import CommentEditor from '../_shared/CommentEditor' +import { ShowOnlyOnClient } from '../_shared/ShowOnlyOnClient' const ARTICLE_COMMENTS_PAGE_SIZE = 50 const MAX_COMMENT_LEVEL = 6 -export const CommentsTree = (props: { shoutSlug: string; shoutId: number }) => { +type Props = { + commentAuthors: Author[] + shoutSlug: string + shoutId: number +} + +export const CommentsTree = (props: Props) => { const [getCommentsPage, setCommentsPage] = createSignal(0) const [commentsOrder, setCommentsOrder] = createSignal<'rating' | 'createdAt'>('createdAt') const [isCommentsLoading, setIsCommentsLoading] = createSignal(false) @@ -47,11 +54,9 @@ export const CommentsTree = (props: { shoutSlug: string; shoutId: number }) => { } onMount(async () => await loadMore()) - const [loading, setLoading] = createSignal(false) - const [errorMessage, setErrorMessage] = createSignal(null) + const [submitted, setSubmitted] = createSignal(false) const handleSubmitComment = async (value) => { try { - setLoading(true) await createReaction( { kind: ReactionKind.Comment, @@ -64,12 +69,12 @@ export const CommentsTree = (props: { shoutSlug: string; shoutId: number }) => { slug: session().user.slug } ) - setLoading(false) + setSubmitted(true) } catch (error) { - setErrorMessage(t('Something went wrong, please try again')) console.error('[handleCreate reaction]:', error) } } + return (
}> @@ -109,20 +114,25 @@ export const CommentsTree = (props: { shoutSlug: string; shoutId: number }) => { .reverse() .filter((r) => !r.replyTo)} > - {(reaction) => } + {(reaction) => ( + a.slug === session()?.user.slug))} + reactions={reactions()} + comment={reaction} + /> + )} - handleSubmitComment(value)} - loading={loading()} - errorMessage={errorMessage()} - /> + + handleSubmitComment(value)} + /> +
) diff --git a/src/components/Article/FullArticle.tsx b/src/components/Article/FullArticle.tsx index 88552fb3..44ccd2aa 100644 --- a/src/components/Article/FullArticle.tsx +++ b/src/components/Article/FullArticle.tsx @@ -224,7 +224,11 @@ export const FullArticle = (props: ArticleProps) => { )} - + ) diff --git a/src/components/Inbox/CreateModalContent.tsx b/src/components/Inbox/CreateModalContent.tsx index 3e0b3054..38a19465 100644 --- a/src/components/Inbox/CreateModalContent.tsx +++ b/src/components/Inbox/CreateModalContent.tsx @@ -35,7 +35,7 @@ const CreateModalContent = (props: Props) => { }) }) if (usersId().length > 1 && theme().length === 1) { - setTheme(t('group_chat')) + setTheme(t('Group Chat')) } }) diff --git a/src/components/Inbox/DialogCard.tsx b/src/components/Inbox/DialogCard.tsx index 14c36678..cf90d5d4 100644 --- a/src/components/Inbox/DialogCard.tsx +++ b/src/components/Inbox/DialogCard.tsx @@ -5,12 +5,12 @@ import GroupDialogAvatar from './GroupDialogAvatar' import formattedTime from '../../utils/formatDateTime' import { clsx } from 'clsx' import styles from './DialogCard.module.scss' +import { t } from '../../utils/intl' type DialogProps = { online?: boolean message?: string counter?: number - title?: string ownId: number members: ChatMember[] onClick?: () => void @@ -23,6 +23,7 @@ const DialogCard = (props: DialogProps) => { const companions = createMemo( () => props.members && props.members.filter((member) => member.id !== props.ownId) ) + const names = createMemo(() => companions() ?.map((companion) => companion.name) @@ -40,14 +41,16 @@ const DialogCard = (props: DialogProps) => { onClick={props.onClick} >
- }> + }> = 3}>
-
{props.title}
+
+ {companions()?.length > 1 ? t('Group Chat') : companions()[0]?.name} +
{props.message} diff --git a/src/components/Views/Inbox.tsx b/src/components/Views/Inbox.tsx index fa8138e7..03df14d7 100644 --- a/src/components/Views/Inbox.tsx +++ b/src/components/Views/Inbox.tsx @@ -9,7 +9,7 @@ import MessagesFallback from '../Inbox/MessagesFallback' import QuotedMessage from '../Inbox/QuotedMessage' import { Icon } from '../_shared/Icon' import { useSession } from '../../context/session' -import { loadMessages, loadRecipients } from '../../stores/inbox' +import { loadRecipients } from '../../stores/inbox' import { t } from '../../utils/intl' import { Modal } from '../Nav/Modal' import { showModal } from '../../stores/ui' @@ -155,7 +155,7 @@ export const InboxView = () => { return messages().find((message) => message.id === messageId) } - const handleKeyDown = (event) => { + const handleKeyDown = async (event) => { if (event.keyCode === 13 && event.shiftKey) return if (event.keyCode === 13 && !event.shiftKey && postMessageText().trim().length > 0) { event.preventDefault() @@ -217,7 +217,6 @@ export const InboxView = () => { handleOpenChat(chat)} isOpened={chat.id === currentDialog()?.id} - title={chat.title || chat.members[0].name} members={chat.members} ownId={currentUserId()} lastUpdate={chat.updatedAt} diff --git a/src/components/_shared/CommentEditor/CommentEditor.tsx b/src/components/_shared/CommentEditor/CommentEditor.tsx new file mode 100644 index 00000000..74cb9ad9 --- /dev/null +++ b/src/components/_shared/CommentEditor/CommentEditor.tsx @@ -0,0 +1,91 @@ +import styles from './styles/CommentEditor.module.scss' +import './styles/ProseMirrorOverrides.scss' +import { clsx } from 'clsx' +import Button from '../Button' +import { createEffect, createMemo, onMount } from 'solid-js' +import { t } from '../../../utils/intl' +//ProseMirror deps +import { schema } from './schema' +import { EditorState } from 'prosemirror-state' +import { EditorView } from 'prosemirror-view' +import { DOMSerializer } from 'prosemirror-model' +import { renderGrouped } from 'prosemirror-menu' +import { buildMenuItems } from './menu' +import { keymap } from 'prosemirror-keymap' +import { baseKeymap } from 'prosemirror-commands' +import { customKeymap } from '../../EditorNew/prosemirror/plugins/customKeymap' +import { placeholder } from '../../EditorNew/prosemirror/plugins/placeholder' +import { undo, redo, history } from 'prosemirror-history' + +type Props = { + initialValue: string + onSubmit: (value: string) => void + clear?: boolean +} + +const htmlContainer = typeof document === 'undefined' ? null : document.createElement('div') +const getHtml = (state: EditorState) => { + const fragment = DOMSerializer.fromSchema(schema).serializeFragment(state.doc.content) + htmlContainer.replaceChildren(fragment) + return htmlContainer.innerHTML +} + +const CommentEditor = (props: Props) => { + const editorElRef: { current: HTMLDivElement } = { current: null } + const menuElRef: { current: HTMLDivElement } = { current: null } + const editorViewRef: { current: EditorView } = { current: null } + const initEditor = () => { + editorViewRef.current = new EditorView(editorElRef.current, { + state: EditorState.create({ + schema, + plugins: [ + history(), + customKeymap(), + placeholder(props.initialValue), + keymap({ 'Mod-z': undo, 'Mod-y': redo }), + keymap(baseKeymap) + ] + }) + }) + } + + onMount(() => { + initEditor() + const { dom } = renderGrouped(editorViewRef.current, buildMenuItems(schema)) + menuElRef.current.appendChild(dom) + }) + + const handleSubmitButtonClick = () => { + props.onSubmit(getHtml(editorViewRef.current.state)) + } + + const clearEditor = () => { + editorViewRef.current.destroy() + initEditor() + } + + createEffect(() => { + if (props.clear) clearEditor() + }) + + return ( + <> +
+
(editorElRef.current = el)} + /> +
+
(menuElRef.current = el)} /> +
+
+
+
+
{'"Cmd-Z": Undo, "Cmd-Y": Redo'}
+ + ) +} + +export default CommentEditor diff --git a/src/components/_shared/CommentEditor/index.ts b/src/components/_shared/CommentEditor/index.ts new file mode 100644 index 00000000..779d0142 --- /dev/null +++ b/src/components/_shared/CommentEditor/index.ts @@ -0,0 +1 @@ +export { default } from './CommentEditor' diff --git a/src/components/_shared/CommentEditor/menu/index.ts b/src/components/_shared/CommentEditor/menu/index.ts new file mode 100644 index 00000000..f766b400 --- /dev/null +++ b/src/components/_shared/CommentEditor/menu/index.ts @@ -0,0 +1,72 @@ +import { blockTypeItem, icons, MenuItem, wrapItem } from 'prosemirror-menu' +import { toggleMark } from 'prosemirror-commands' + +const markActive = (state, type) => { + const { from, $from, to, empty } = state.selection + + if (empty) return type.isInSet(state.storedMarks || $from.marks()) + + return state.doc.rangeHasMark(from, to, type) +} + +const cmdItem = (cmd, options) => { + const passedOptions = { + label: options.title, + run: cmd + } + + for (const prop in options) passedOptions[prop] = options[prop] + + if ((!options.enable || options.enable === true) && !options.select) { + passedOptions[options.enable ? 'enable' : 'select'] = (state) => cmd(state) + } + + return new MenuItem(passedOptions) +} + +const markItem = (markType, options) => { + const passedOptions = { + active(state) { + return markActive(state, markType) + }, + enable: true + } + + for (const prop in options) passedOptions[prop] = options[prop] + + return cmdItem(toggleMark(markType), passedOptions) +} + +//TODO: вывести тип для схемы +export const buildMenuItems = (schema) => { + const toggleStrong = markItem(schema.marks.strong, { + title: 'Toggle strong style', + icon: { + width: 14, + height: 16, + path: 'M9.82857 7.76C10.9371 6.99429 11.7143 5.73714 11.7143 4.57143C11.7143 1.98857 9.71428 0 7.14286 0H0V16H8.04571C10.4343 16 12.2857 14.0571 12.2857 11.6686C12.2857 9.93143 11.3029 8.44571 9.82857 7.76ZM3.42799 2.85708H6.85656C7.80513 2.85708 8.57085 3.6228 8.57085 4.57137C8.57085 5.51994 7.80513 6.28565 6.85656 6.28565H3.42799V2.85708ZM3.42799 13.1429H7.42799C8.37656 13.1429 9.14228 12.3772 9.14228 11.4286C9.14228 10.4801 8.37656 9.71434 7.42799 9.71434H3.42799V13.1429Z' + } + }) + + const toggleEm = markItem(schema.marks.em, { + title: 'Toggle emphasis', + icon: { + width: 14, + height: 16, + path: 'M4.39216 0V3.42857H6.81882L3.06353 12.5714H0V16H8.78431V12.5714H6.35765L10.1129 3.42857H13.1765V0H4.39216Z' + } + }) + + // const toggleLink = linkItem(schema.marks.link) + + // const insertImage = insertImageItem(schema.nodes.image) + + const wrapBlockQuote = wrapItem(schema.nodes.blockquote, { + title: 'Wrap in block quote', + icon: icons.blockquote + }) + + const inlineMenu = [toggleStrong, toggleEm, wrapBlockQuote] + + return [inlineMenu] +} diff --git a/src/components/_shared/CommentEditor/plugins/placeholder.ts b/src/components/_shared/CommentEditor/plugins/placeholder.ts new file mode 100644 index 00000000..4794245c --- /dev/null +++ b/src/components/_shared/CommentEditor/plugins/placeholder.ts @@ -0,0 +1,21 @@ +import { Plugin } from 'prosemirror-state' +import { DecorationSet, Decoration } from 'prosemirror-view' + +export const placeholder = (text: string): Plugin => + new Plugin({ + props: { + decorations(state) { + const { doc } = state + + if (doc.childCount > 1 || !doc.firstChild.isTextblock || doc.firstChild.content.size > 0) { + return + } + + const div = document.createElement('div') + div.setAttribute('contenteditable', 'false') + div.textContent = text + + return DecorationSet.create(doc, [Decoration.widget(1, div)]) + } + } + }) diff --git a/src/components/_shared/CommentEditor/schema.ts b/src/components/_shared/CommentEditor/schema.ts new file mode 100644 index 00000000..a0dd6d1a --- /dev/null +++ b/src/components/_shared/CommentEditor/schema.ts @@ -0,0 +1,43 @@ +import { Schema } from 'prosemirror-model' + +export const schema = new Schema({ + nodes: { + doc: { + content: 'block+' + }, + text: { + group: 'inline', + inline: true + }, + paragraph: { + content: 'inline*', + group: 'block', + toDOM: function toDOM(node) { + return ['p', { class: 'paragraph' }, 0] + } + }, + blockquote: { + content: 'block+', + group: 'block', + defining: true, + parseDOM: [{ tag: 'blockquote' }], + toDOM() { + return ['blockquote', 0] + } + } + }, + marks: { + strong: { + toDOM() { + return ['strong', 0] + }, + parseDOM: [{ tag: 'strong' }, { tag: 'b' }, { style: 'font-weight=bold' }] + }, + em: { + toDOM() { + return ['em', 0] + }, + parseDOM: [{ tag: 'em' }, { tag: 'i' }, { style: 'font-style=italic' }] + } + } +}) diff --git a/src/components/_shared/CommentEditor/styles/CommentEditor.module.scss b/src/components/_shared/CommentEditor/styles/CommentEditor.module.scss new file mode 100644 index 00000000..ea33f29d --- /dev/null +++ b/src/components/_shared/CommentEditor/styles/CommentEditor.module.scss @@ -0,0 +1,32 @@ +.commentEditor { + border: 2px solid #e8e8e8; + border-radius: 8px; + padding: 0 16px 16px; + + .textarea { + min-height: 1em; + overflow: hidden; + } + + .actions { + display: flex; + flex-direction: row; + justify-content: space-between; + + .menu, + .buttons { + display: flex; + flex-direction: row; + } + .buttons { + gap: 10px; + } + } +} + +.helpText { + font-size: 12px; + color: #696969; + margin: 12px 0; + font-style: italic; +} diff --git a/src/components/_shared/CommentEditor/styles/ProseMirrorOverrides.scss b/src/components/_shared/CommentEditor/styles/ProseMirrorOverrides.scss new file mode 100644 index 00000000..d5554675 --- /dev/null +++ b/src/components/_shared/CommentEditor/styles/ProseMirrorOverrides.scss @@ -0,0 +1,14 @@ +.ProseMirrorOverrides > .ProseMirror { + .paragraph { + font-size: 15px; + line-height: 1.1em; + } + + blockquote { + padding-left: 10px; + font-style: italic; + font-weight: 400; + color: #9fa1a7; + border-left: 2px solid #696969; + } +} diff --git a/src/components/_shared/GrowingTextarea/index.ts b/src/components/_shared/GrowingTextarea/index.ts deleted file mode 100644 index a0d16325..00000000 --- a/src/components/_shared/GrowingTextarea/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './GrowingTextarea' diff --git a/src/context/inbox.tsx b/src/context/inbox.tsx index a54ed68d..0a94ffc2 100644 --- a/src/context/inbox.tsx +++ b/src/context/inbox.tsx @@ -1,4 +1,4 @@ -import { createContext, createSignal, useContext } from 'solid-js' +import { createContext, createEffect, createSignal, useContext } from 'solid-js' import type { Accessor, JSX } from 'solid-js' // import { createChatClient } from '../graphql/privateGraphQLClient' import type { Chat, Message, MutationCreateMessageArgs } from '../graphql/types.gen' diff --git a/src/graphql/mutation/create-chat.ts b/src/graphql/mutation/create-chat.ts index 46993794..39c0da9c 100644 --- a/src/graphql/mutation/create-chat.ts +++ b/src/graphql/mutation/create-chat.ts @@ -6,6 +6,10 @@ export default gql` error chat { id + members { + id + slug + } } } } diff --git a/src/graphql/query/chat-recipients.ts b/src/graphql/query/chat-recipients.ts index 154c1fea..579686bb 100644 --- a/src/graphql/query/chat-recipients.ts +++ b/src/graphql/query/chat-recipients.ts @@ -9,6 +9,7 @@ export default gql` id slug userpic + online } error } diff --git a/src/graphql/types.gen.ts b/src/graphql/types.gen.ts index a67be3cb..620d5f56 100644 --- a/src/graphql/types.gen.ts +++ b/src/graphql/types.gen.ts @@ -84,14 +84,6 @@ export type ChatMember = { userpic?: Maybe } -export type Collab = { - authors: Array> - chat?: Maybe - createdAt: Scalars['Int'] - invites?: Maybe>> - shout?: Maybe -} - export type Collection = { amount?: Maybe createdAt: Scalars['DateTime'] @@ -113,6 +105,30 @@ export type Community = { slug: Scalars['String'] } +export type DraftCollab = { + authors: Array> + body?: Maybe + chat?: Maybe + cover?: Maybe + createdAt: Scalars['Int'] + layout?: Maybe + slug?: Maybe + subtitle?: Maybe + title?: Maybe + topics?: Maybe>> + updatedAt?: Maybe +} + +export type DraftInput = { + authors?: InputMaybe>> + body?: InputMaybe + cover?: InputMaybe + slug?: InputMaybe + subtitle?: InputMaybe + title?: InputMaybe + topics?: InputMaybe>> +} + export enum FollowingEntity { Author = 'AUTHOR', Community = 'COMMUNITY', @@ -167,28 +183,30 @@ export type MessagesBy = { } export type Mutation = { - acceptCoauthor: Result confirmEmail: AuthResult createChat: Result + createDraft: Result createMessage: Result createReaction: Result createShout: Result createTopic: Result deleteChat: Result + deleteDraft: Result deleteMessage: Result deleteReaction: Result deleteShout: Result destroyTopic: Result follow: Result getSession: AuthResult - inviteCoauthor: Result + inviteAccept: Result + inviteAuthor: Result markAsRead: Result rateUser: Result registerUser: AuthResult - removeCoauthor: Result sendLink: Result unfollow: Result updateChat: Result + updateDraft: Result updateMessage: Result updateOnlineStatus: Result updateProfile: Result @@ -197,10 +215,6 @@ export type Mutation = { updateTopic: Result } -export type MutationAcceptCoauthorArgs = { - shout: Scalars['Int'] -} - export type MutationConfirmEmailArgs = { token: Scalars['String'] } @@ -210,6 +224,10 @@ export type MutationCreateChatArgs = { title?: InputMaybe } +export type MutationCreateDraftArgs = { + draft: DraftInput +} + export type MutationCreateMessageArgs = { body: Scalars['String'] chat: Scalars['String'] @@ -232,6 +250,10 @@ export type MutationDeleteChatArgs = { chatId: Scalars['String'] } +export type MutationDeleteDraftArgs = { + draft: Scalars['Int'] +} + export type MutationDeleteMessageArgs = { chatId: Scalars['String'] id: Scalars['Int'] @@ -254,9 +276,13 @@ export type MutationFollowArgs = { what: FollowingEntity } -export type MutationInviteCoauthorArgs = { - author: Scalars['String'] - shout: Scalars['Int'] +export type MutationInviteAcceptArgs = { + draft: Scalars['Int'] +} + +export type MutationInviteAuthorArgs = { + author: Scalars['Int'] + draft: Scalars['Int'] } export type MutationMarkAsReadArgs = { @@ -275,11 +301,6 @@ export type MutationRegisterUserArgs = { password?: InputMaybe } -export type MutationRemoveCoauthorArgs = { - author: Scalars['String'] - shout: Scalars['Int'] -} - export type MutationSendLinkArgs = { email: Scalars['String'] lang?: InputMaybe @@ -295,6 +316,10 @@ export type MutationUpdateChatArgs = { chat: ChatInput } +export type MutationUpdateDraftArgs = { + draft: DraftInput +} + export type MutationUpdateMessageArgs = { body: Scalars['String'] chatId: Scalars['String'] @@ -345,11 +370,11 @@ export type ProfileInput = { export type Query = { authorsAll: Array> getAuthor?: Maybe - getCollabs: Array> getTopic?: Maybe isEmailUsed: Scalars['Boolean'] loadAuthorsBy: Array> loadChats: Result + loadDrafts: Array> loadMessagesBy: Result loadReactionsBy: Array> loadRecipients: Result @@ -545,6 +570,7 @@ export type Result = { chats?: Maybe>> communities?: Maybe>> community?: Maybe + drafts?: Maybe>> error?: Maybe members?: Maybe>> message?: Maybe diff --git a/src/locales/ru.json b/src/locales/ru.json index 5d346178..a4335faa 100644 --- a/src/locales/ru.json +++ b/src/locales/ru.json @@ -166,6 +166,7 @@ "actions": "действия", "all topics": "все темы", "author": "автор", + "Author": "Автор", "authors": "авторы", "collections": "коллекции", "community": "сообщество", @@ -192,7 +193,7 @@ "discourse_theme": "Тема дискурса", "cancel": "Отмена", "Send": "Отправить", - "group_chat": "Общий чат", + "Group Chat": "Общий чат", "Choose who you want to write to": "Выберите кому хотите написать", "Start conversation": "Начать беседу", "Profile settings": "Настройки профиля", @@ -218,6 +219,7 @@ "It does not look like url": "Это не похоже на ссылку", "Something went wrong, please try again": "Что-то пошло не так, попробуйте еще раз", "To write a comment, you must": "Чтобы написать комментарий, необходимо", + "Write a comment...": "Написать комментарий..." "Add comment": "Комментировать", "My subscriptions": "Подписки" } diff --git a/src/stores/zine/reactions.ts b/src/stores/zine/reactions.ts index 4cae72f3..6f50d75c 100644 --- a/src/stores/zine/reactions.ts +++ b/src/stores/zine/reactions.ts @@ -1,4 +1,4 @@ -import type { Reaction, ReactionInput, User } from '../../graphql/types.gen' +import type { Reaction, ReactionInput } from '../../graphql/types.gen' import { apiClient } from '../../utils/apiClient' import { createSignal } from 'solid-js' // TODO: import { roomConnect } from '../../utils/p2p' diff --git a/src/utils/apiClient.ts b/src/utils/apiClient.ts index 7909ddac..39c405fc 100644 --- a/src/utils/apiClient.ts +++ b/src/utils/apiClient.ts @@ -296,12 +296,12 @@ export const apiClient = { createMessage: async (options: MutationCreateMessageArgs) => { const resp = await privateGraphQLClient.mutation(createMessage, options).toPromise() - return resp.data.createMessage + return resp.data.createMessage.message }, getChatMessages: async (options: QueryLoadMessagesByArgs) => { const resp = await privateGraphQLClient.query(chatMessagesLoadBy, options).toPromise() - return resp.data.loadChat + return resp.data.loadMessagesBy.messages }, getRecipients: async (options: QueryLoadRecipientsArgs) => { const resp = await privateGraphQLClient.query(loadRecipients, options).toPromise()