Merge branch 'dev' into feature/linking-accounts

This commit is contained in:
MTG2000
2022-08-09 14:29:18 +03:00
8 changed files with 212 additions and 2 deletions

View File

@@ -0,0 +1,17 @@
import { ComponentStory, ComponentMeta } from '@storybook/react';
import InsertLinkModal from './InsertLinkModal';
import { ModalsDecorator } from 'src/utils/storybook/decorators';
export default {
title: 'Shared/Inputs/Text Editor/Insert Link Modal',
component: InsertLinkModal,
decorators: [ModalsDecorator]
} as ComponentMeta<typeof InsertLinkModal>;
const Template: ComponentStory<typeof InsertLinkModal> = (args) => <InsertLinkModal {...args} />;
export const Default = Template.bind({});

View File

@@ -0,0 +1,107 @@
import React, { FormEvent, useState } from 'react'
import { ModalCard, modalCardVariants } from 'src/Components/Modals/ModalsContainer/ModalsContainer'
import { motion } from 'framer-motion'
import { IoClose } from 'react-icons/io5'
import Button from 'src/Components/Button/Button'
import { useAppDispatch } from 'src/utils/hooks'
import { PayloadAction } from '@reduxjs/toolkit'
import * as yup from "yup";
import { SubmitHandler, useForm } from "react-hook-form"
import { yupResolver } from "@hookform/resolvers/yup";
interface Props extends ModalCard {
callbackAction: PayloadAction<{ href: string, text: string }>
}
const schema = yup.object({
text: yup.string().trim().required().min(2, 'Link text should be at least 2 characters'),
href: yup.string().trim().required().url(),
}).required();
export interface IFormInputs {
text: string,
href: string,
}
export default function InsertLinkModal({ onClose, direction, callbackAction, ...props }: Props) {
const { register, formState: { errors }, handleSubmit } = useForm<IFormInputs>({
defaultValues: {
href: '',
text: '',
},
resolver: yupResolver(schema),
mode: 'onBlur',
});
const dispatch = useAppDispatch();
const onSubmit: SubmitHandler<IFormInputs> = data => {
const action = Object.assign({}, callbackAction);
action.payload = { text: data.text, href: data.href }
dispatch(action)
onClose?.();
};
return (
<motion.div
custom={direction}
variants={modalCardVariants}
initial='initial'
animate="animate"
exit='exit'
className="modal-card max-w-[660px] p-24 rounded-xl relative"
>
<IoClose className='absolute text-body2 top-24 right-24 hover:cursor-pointer' onClick={onClose} />
<h2 className='text-h5 font-bold'>Insert Link</h2>
<form onSubmit={handleSubmit(onSubmit)}>
<div className="grid md:grid-cols-2 gap-16 mt-32">
<div>
<p className="text-body5">
Link Text
</p>
<div className="input-wrapper mt-8 relative">
<input
type='text'
className="input-text"
placeholder='My Website'
{...register('text')}
/>
</div>
{errors.text && <p className="input-error">
{errors.text.message}
</p>}
</div>
<div>
<p className="text-body5">
Link URL
</p>
<div className="input-wrapper mt-8 relative">
<input
type='text'
className="input-text"
placeholder='https://www.website.com'
{...register('href')}
/>
</div>
{errors.href && <p className="input-error">
{errors.href.message}
</p>}
</div>
</div>
<div className="flex gap-16 justify-end mt-32">
<Button onClick={onClose}>
Cancel
</Button>
<Button type='submit' color='primary' >
Insert
</Button>
</div>
</form>
</motion.div>
)
}

View File

@@ -0,0 +1,4 @@
import { lazyModal } from 'src/utils/helperFunctions';
export const { LazyComponent: InsertLinkModal } = lazyModal(() => import('./InsertLinkModal'))

View File

@@ -0,0 +1,68 @@
import { useActive, useCommands } from '@remirror/react';
import { useAppDispatch } from 'src/utils/hooks';
import { openModal } from 'src/redux/features/modals.slice';
import { useReduxEffect } from 'src/utils/hooks/useReduxEffect';
import { useCallback } from 'react';
import { createAction } from '@reduxjs/toolkit';
import { cmdToBtn } from './helpers';
interface Props {
classes: {
button: string,
icon: string,
active: string,
enabled: string
disabled: string
}
}
const INSERT_LINK_ACTION = createAction<{ href: string, text: string }>('LINK_INSERTED_IN_EDITOR')({ href: '', text: '' })
export default function LinkToolButton({ classes }: Props) {
const commands = useCommands();
const dispatch = useAppDispatch()
const onInsertLink = useCallback(({ payload: { href, text } }: typeof INSERT_LINK_ACTION) => {
commands.insertMarkdown(`[${text}](${href})`)
}, [commands])
useReduxEffect(onInsertLink, INSERT_LINK_ACTION.type)
const { tip, Icon } = cmdToBtn['link'];
const onClick = () => {
dispatch(openModal({
Modal: "InsertLinkModal",
props: {
callbackAction: {
type: INSERT_LINK_ACTION.type,
payload: {
href: "",
text: "",
}
}
}
}))
}
return (
<button
type='button'
data-tip={tip}
className={`
${classes.button}
${classes.enabled}
`}
onClick={onClick}
>
<Icon className={classes.icon} />
</button>
)
}

View File

@@ -3,6 +3,7 @@ import HeadingsToolButton from './HeadingsToolBtn';
import DefaultToolButton from './DefaultToolBtn';
import { Command, isCommand } from './helpers';
import VideoToolButton from './VideoToolBtn';
import LinkToolButton from './LinkToolBtn';
interface Props {
cmd: Command
@@ -43,6 +44,10 @@ export default function ToolButton({ cmd,
if (cmd === 'img')
return <ImageToolButton classes={classes} />
if (cmd === 'link')
return <LinkToolButton classes={classes} />
return <DefaultToolButton classes={classes} cmd={cmd} />

View File

@@ -1,5 +1,5 @@
import { FiBold, FiItalic, FiType, FiUnderline, FiAlignCenter, FiAlignLeft, FiAlignRight, FiCode } from 'react-icons/fi'
import { FaListOl, FaListUl, FaUndo, FaRedo, FaImage, FaYoutube, FaQuoteLeft } from 'react-icons/fa'
import { FaListOl, FaListUl, FaUndo, FaRedo, FaImage, FaYoutube, FaQuoteLeft, FaLink } from 'react-icons/fa'
import { BiCodeCurly } from 'react-icons/bi';
@@ -97,6 +97,12 @@ export const cmdToBtn = {
tip: "Insert Image",
Icon: FaImage,
},
link: {
cmd: 'insertLink',
activeCmd: 'link',
tip: "Insert Link",
Icon: FaLink,
},
youtube: {
cmd: 'addYouTubeVideo',

View File

@@ -17,9 +17,10 @@ export default function Toolbar() {
{/* <TextEditorComponents.ToolButton cmd='leftAlign' />
<TextEditorComponents.ToolButton cmd='centerAlign' />
<TextEditorComponents.ToolButton cmd='rightAlign' /> */}
<TextEditorComponents.ToolButton cmd='blockquote' />
<TextEditorComponents.ToolButton cmd='link' />
<TextEditorComponents.ToolButton cmd='code' />
<TextEditorComponents.ToolButton cmd='codeBlock' />
<TextEditorComponents.ToolButton cmd='blockquote' />
<TextEditorComponents.ToolButton cmd='bulletList' />
<TextEditorComponents.ToolButton cmd='orderedList' />
<TextEditorComponents.ToolButton cmd='img' />

View File

@@ -4,6 +4,7 @@ import { ProjectDetailsCard } from "src/features/Projects/pages/ProjectPage/Proj
import VoteCard from "src/features/Projects/pages/ProjectPage/VoteCard/VoteCard";
import { InsertImageModal } from 'src/Components/Inputs/TextEditor/InsertImageModal'
import { InsertVideoModal } from 'src/Components/Inputs/TextEditor/InsertVideoModal'
import { InsertLinkModal } from 'src/Components/Inputs/TextEditor/InsertLinkModal'
import { Claim_FundWithdrawCard, Claim_CopySignatureCard, Claim_GenerateSignatureCard, Claim_SubmittedCard } from "src/features/Projects/pages/ProjectPage/ClaimProject";
import { ModalCard } from "src/Components/Modals/ModalsContainer/ModalsContainer";
import { ConfirmModal } from "src/Components/Modals/ConfirmModal";
@@ -38,6 +39,7 @@ export const ALL_MODALS = {
// Text Editor Modals
InsertImageModal,
InsertVideoModal,
InsertLinkModal,
}
type ExcludeBaseModalProps<U> = Omit<U, keyof ModalCard>