Skip to content
Snippets Groups Projects
Commit 98b022a2 authored by Deleephan K S's avatar Deleephan K S Committed by chris
Browse files

fix(custom-tag-block): fixed custom-tag-block

parent dcf5d0ea
No related branches found
No related tags found
1 merge request!232feat(custom-tag-block): added custom-tag-block
......@@ -130,6 +130,13 @@ export default {
invisibles([hardBreak()]),
WaxSelectionPlugin,
],
CustomTagService: {
tags: [
{ label: 'custom-tag-label-1', tagType: 'inline' },
{ label: 'custom-tag-label-2', tagType: 'inline' },
{ label: 'custom-tag-label-3', tagType: 'block' }
]
},
// Always load first CommentsService and LinkService,
//as it matters on how PM treats nodes and marks
......
......@@ -89,6 +89,13 @@ export default {
invisibles([hardBreak()]),
WaxSelectionPlugin,
],
CustomTagService: {
tags: [
{ label: 'custom-tag-label-1', tagType: 'inline' },
{ label: 'custom-tag-label-2', tagType: 'inline' },
{ label: 'custom-tag-label-3', tagType: 'block' }
]
},
// Always load first CommentsService and LinkService,
//as it matters on how PM treats nodes and marks
......
import React, { useContext, useMemo, useRef, useState } from 'react';
import React, { useContext, useMemo, useRef, useState, useEffect } from 'react';
import styled from 'styled-components';
import { WaxContext } from 'wax-prosemirror-core';
import { Commands } from 'wax-prosemirror-utilities';
import useDeepCompareEffect from 'use-deep-compare-effect';
import { v4 as uuidv4 } from 'uuid';
const Wrapper = styled.div``;
......@@ -49,15 +51,18 @@ const StyledButton = styled.div``;
const CustomTagBlockComponent = (isIconClicked) => {
const CustomTagBlockComponent = (isIconClicked, item) => {
const ref = useRef();
const [inputValue, setInputValue] = useState('');
const [tagName, setTagName] = useState('');
const localTagList = JSON.parse(localStorage.getItem('tagBlockList'));
const { view: { main }, activeView } = useContext(WaxContext);
const { app, view: { main }, activeView } = useContext(WaxContext);
const { state, dispatch } = main;
const { selection: { $from, $to } } = state;
const serviceConfig = app.config.get('config.CustomTagService');
const [serviceList, setServiceList] = useState([]);
const onChangeTagName = (e) => {
setTagName(e.target.value)
......@@ -68,24 +73,45 @@ const CustomTagBlockComponent = (isIconClicked) => {
if (tagName === '') return;
let tagNameList = [];
if (localStorage.getItem('tagBlockList') === null) {
tagNameList.push(tagName);
tagNameList.push({ label: tagName, type: 'block' });
localStorage.setItem('tagBlockList', JSON.stringify(tagNameList));
} else {
tagNameList = JSON.parse(localStorage.getItem('tagBlockList'));
tagNameList.push(tagName);
tagNameList.push({ label: tagName, type: 'block' });
localStorage.clear('tagBlockList');
localStorage.setItem('tagBlockList', JSON.stringify(tagNameList));
}
setInputValue(' ')
}
const onSelectTag = (e, item) => {
item = item.replace(/ /g, "-");
const onSelectTag = (e, val) => {
val = val.replace(/ /g, "-");
Commands.setBlockType(state.config.schema.nodes.customTagBlock, {
class: 'custom-tag-block ' + item
class: 'custom-tag-block ' + val
})(state, dispatch);
}
useDeepCompareEffect(() => {
let labels = [];
if (serviceConfig !== undefined) {
serviceConfig.tags.forEach(item => {
if (item.tagType === 'block') {
labels.push(item.label);
}
});
}
if (localTagList !== null) {
localTagList.forEach(item => {
labels.push(item.label)
})
}
setServiceList(labels);
}, [localTagList, serviceConfig]);
return useMemo(
() => (
<Wrapper>
......@@ -98,7 +124,7 @@ const CustomTagBlockComponent = (isIconClicked) => {
<Add onClick={onClickAdd}>Add</Add>
</FlexDiv>}
{localTagList !== null && localTagList.map((item, pos) => <ListStyle key={pos}>
{serviceList !== null && serviceList.map((item, pos) => <ListStyle key={uuidv4()}>
<FlexDiv onClick={e => onSelectTag(e, item)} >
<Box />
<StyledButton>{item}</StyledButton>
......
/* eslint react/prop-types: 0 */
import React, { useRef, useEffect, useState, useContext } from 'react';
import React, { useRef, useEffect, useState, useContext, Fragment } from 'react';
import styled from 'styled-components';
import { grid, th } from '@pubsweet/ui-toolkit';
import { WaxContext } from 'wax-prosemirror-core';
import { DocumentHelpers } from 'wax-prosemirror-utilities';
import { v4 as uuidv4 } from 'uuid';
const IconSVG = props => {
const { className } = props;
......@@ -64,12 +66,22 @@ const ListStyle = styled.div`
cursor: pointer;
`;
const Flex = styled.div`
display: flex;
justify-content: space-between;
`;
const DivWidth = styled.div`
width: 100%;
`;
const CustomTagInlineOverlayComponent = ({ mark, setPosition, position }) => {
const ref = useRef(null);
const [tagName, setTagName] = useState();
const [inputValue, setInputValue] = useState('');
const [selectedTagName, setSelectedTagName] = useState('');
const [selectedTagName, setSelectedTagName] = useState([]);
const localTagList = JSON.parse(localStorage.getItem('tagList'));
const [isCustomTagInline, setCustomTag] = useState(JSON.parse(localStorage.getItem('isInline')));
const { view: { main } } = useContext(WaxContext);
......@@ -82,63 +94,124 @@ const CustomTagInlineOverlayComponent = ({ mark, setPosition, position }) => {
}
const onClickAdd = () => {
const localItem = localStorage.getItem('isInline');
let tagNameList = [];
if (localStorage.getItem('tagList') === null) {
tagNameList.push(tagName);
tagNameList.push({ label: tagName, type: 'inline' });
localStorage.setItem('tagList', JSON.stringify(tagNameList));
} else {
tagNameList = JSON.parse(localStorage.getItem('tagList'));
tagNameList.push(tagName);
tagNameList.push({ label: tagName, type: 'inline' });
localStorage.clear('tagList');
localStorage.setItem('tagList', JSON.stringify(tagNameList));
localStorage.setItem('isInline', localItem);
}
setInputValue(' ')
setInputValue('');
}
const onListClicked = (e, item) => {
const onListClicked = (item) => {
let tagNames = [];
let finalTag = [];
let isExist = false;
let classNames = 'custom-tag-inline ';
const mark = DocumentHelpers.findMark(state, state.schema.marks.customTagInline, true);
tagNames.push(item);
if (mark.length > 0) {
mark.forEach(itemArtt => {
const classArray = itemArtt.attrs.class.split(' ');
classArray.forEach(classData => {
item.replace(/ /g, "-");
if (classData === item.replace(/ /g, "-")) {
isExist = true;
}
})
const parseArray = JSON.parse(itemArtt.attrs.tagNames)
classNames = itemArtt.attrs.class + ' '
finalTag = tagNames.concat(parseArray);
});
} else {
finalTag.push(item);
}
if (isExist) return;
setSelectedTagName(oldArray => [...oldArray, item]);
item = classNames + item.replace(/ /g, "-");
setSelectedTagName(item);
dispatch(
state.tr.addMark(
$from.pos,
$to.pos,
state.schema.marks.customTagInline.create({
tagName: item,
class: 'custom-tag-inline',
tagNames: JSON.stringify(finalTag),
class: item
}),
),
);
}
const onClickCancel = () => {
dispatch(state.tr.removeMark($from.pos, $to.pos, state.schema.marks.customTagInline));
setSelectedTagName('');
const onClickCancel = (tagName) => {
let classNames = '';
let classArray = [];
let tagArray = [];
let finalTag = [];
const mark = DocumentHelpers.findMark(state, state.schema.marks.customTagInline, true);
setSelectedTagName(finalTag)
tagName = tagName.replace(/ /g, "-");
if (mark.length > 0) {
mark.forEach(itemArtt => {
classNames = ''
classArray = itemArtt.attrs.class.split(' ');
tagArray = JSON.parse(itemArtt.attrs.tagNames);
classArray.forEach(classData => {
if (classData !== tagName) {
classNames = classNames + ' ' + classData
}
})
tagArray.forEach(tag => {
if (tag.replace(/ /g, "-") !== tagName) {
finalTag.push(tag);
}
});
});
setSelectedTagName(finalTag.filter((item, index) => finalTag.indexOf(item) === index));
if (finalTag.length === 0) {
dispatch(state.tr.removeMark($from.pos, $to.pos, state.schema.marks.customTagInline));
} else {
dispatch(
state.tr.addMark(
$from.pos,
$to.pos,
state.schema.marks.customTagInline.create({
tagNames: JSON.stringify(finalTag),
class: classNames
}),
),
);
}
}
}
useEffect(() => {
state.doc.nodesBetween(
$from.pos, $to.pos,
(node, from) => {
node.marks.forEach(item => {
setSelectedTagName(item.attrs.tagName !== undefined ? item.attrs.tagName : '' );
});
},
);
setCustomTag(JSON.parse(localStorage.getItem('isInline')));
});
return isCustomTagInline === true ? (
<Wrapper>
{localTagList !== null && localTagList.map((item, pos) => <ListStyle key={pos}>
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
<div onClick={e => onListClicked(e, item)}> {item} </div>
{selectedTagName === item &&
<div onClick={onClickCancel}>
<Icon />
</div>
}
{localTagList !== null && localTagList.map((item) => <ListStyle key={uuidv4()}>
<Flex>
<DivWidth onClick={e => onListClicked(item.label)}> {item.label} </DivWidth>
</div>
{selectedTagName.map(value => <Fragment key={uuidv4()}>
{value === item.label ? <span onClick={e => onClickCancel(item.label)}>
<Icon />
</span> : ''}
</Fragment>)}
</Flex>
</ListStyle>)}
<CustomWrapper ref={ref}>
<Input type="text" onChange={e => onChangeTagName(e)} value={inputValue} />
......
const customtagInline = {
excludes: 'cutomInline',
excludes: '',
attrs: {
class: { default: null },
tagName: ''
tagNames: '',
},
inclusive: false,
parseDOM: [
......@@ -12,7 +12,7 @@ const customtagInline = {
getAttrs(hook, next) {
Object.assign(hook, {
class: hook.dom.getAttribute('class'),
tagname: hook.dom.getAttribute('tagName')
tagNames: hook.dom.getAttribute('tagNames'),
});
next();
},
......
import React from 'react';
// eslint-disable-next-line import/no-named-as-default,import/no-named-as-default-member
import Tools from '../../lib/Tools';
import { v4 as uuidv4 } from 'uuid';
import { CustomTagBlockComponent } from 'wax-prosemirror-components';
class CustomTagBlockTool extends Tools {
title = 'Custom Tag Block';
name = 'CustomTagBlock';
renderTool(view) {
return (
<CustomTagBlockComponent item={this.toJSON()} key={uuidv4()} view={view} />
);
get active() {
return state => {
return Commands.blockActive(state.config.schema.nodes.customTagBlock)(
state,
);
};
}
}
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment