Skip to content

Commit

Permalink
feat: replace ckeditor with tiptap editor
Browse files Browse the repository at this point in the history
  • Loading branch information
AliKdhim87 committed Apr 28, 2023
1 parent b42e0fe commit 8da48eb
Show file tree
Hide file tree
Showing 67 changed files with 4,650 additions and 503 deletions.
3 changes: 2 additions & 1 deletion Dockerfile.dev
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,14 @@ COPY ./packages/strapi-plugin-ckeditor5/package.json packages/strapi-plugin-cked
COPY ./packages/strapi-plugin-gemeente-select/package.json packages/strapi-plugin-gemeente-select/package.json
COPY ./packages/strapi-plugin-scheme-select/package.json packages/strapi-plugin-scheme-select/package.json
COPY ./packages/utrecht-editor/package.json packages/utrecht-editor/package.json
COPY ./packages/strapi-tiptap-editor/package.json packages/strapi-tiptap-editor/package.json


# Build target dependencies #
#############################
FROM build AS dependencies
# Install prod dependencies
RUN yarn install
RUN yarn install

# Build target builder #
########################
Expand Down
22 changes: 22 additions & 0 deletions apps/frontend/src/components/Markdown/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,15 @@ const components = ({ strapiBackendURL, priceData, locale }: any) =>
},
p: ({ children, node }) => {
delete node.properties?.style;
if (node.properties?.dataLead) {
delete node.properties?.dataLead;
return (
<Paragraph {...node.properties} lead>
{children}
</Paragraph>
);
}

return <Paragraph {...node.properties}>{children}</Paragraph>;
},
ul: ({ children, node }) => {
Expand Down Expand Up @@ -130,6 +139,19 @@ const components = ({ strapiBackendURL, priceData, locale }: any) =>
}
return <section {...node.properties}>{children}</section>;
},
'react-widget': ({ node }: any) => {
if (node.properties?.id && priceData && priceData.length > 0) {
const product: any = priceData.find(({ id }: any) => id === node.properties?.id);
const price = new Intl.NumberFormat(locale, {
style: 'currency',
currency: product?.currency,
}).format(Number(product?.value));

return <data value={price}>{price}</data>;
} else {
return null;
}
},
} as Components);

interface MarkdownProps {
Expand Down
9 changes: 9 additions & 0 deletions apps/frontend/src/pages/products/[slug].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,15 @@ const Product: NextPage = ({ product, localizations, preview }: any) => {
</Markdown>
</SpotlightSection>
) : null;
case 'ComponentComponentsButtonLink':
return component.text && component.href ? (
<div>
<Paragraph>{component?.label}</Paragraph>
<ButtonLink appearance={`${component?.button_link_appearance}-action-button`} href={component.href}>
{component.text}
</ButtonLink>
</div>
) : null;
case 'ComponentComponentsMultiColumnsButton':
return (
<div className="utrecht-multi-columns-button">
Expand Down
20 changes: 20 additions & 0 deletions apps/frontend/src/styles/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -127,3 +127,23 @@ nav {
gap: 12px;
margin-block-end: 16px;
}

table * p {
--utrecht-paragraph-margin-block-start: 0;
}

th {
--utrecht-table-header-cell-font-weight: var(--utrecht-table-header-font-weight);

border-block-end-color: var(--utrecht-table-header-border-block-end-color, transparent);
border-block-end-style: solid;
border-block-end-width: var(--utrecht-table-header-border-block-end-width, 0);
padding-block-end: var(--utrecht-table-cell-padding-block-end, 0);
padding-block-start: var(--utrecht-table-cell-padding-block-start, 0);
padding-inline-end: var(--utrecht-table-cell-padding-inline-end, 0);
padding-inline-start: var(--utrecht-table-cell-padding-inline-start, 0);
}

th > p {
--utrecht-paragraph-font-weight: var(--utrecht-table-header-font-weight);
}
3 changes: 3 additions & 0 deletions apps/strapi-dashboard/config/plugins.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
export default ({ env }) => ({
ckeditor5: {
enabled: false,
},
'strapi-tiptap-editor': {
enabled: true,
},
slugify: {
Expand Down
1 change: 1 addition & 0 deletions apps/strapi-dashboard/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"@frameless/strapi-plugin-ckeditor5": "0.0.0-semantically-released",
"@frameless/strapi-plugin-gemeente-select": "0.0.0-semantically-released",
"@frameless/strapi-plugin-scheme-select": "0.0.0-semantically-released",
"@frameless/strapi-tiptap-editor": "0.0.0-semantically-released",
"@strapi/plugin-graphql": "4.9.0",
"@strapi/plugin-i18n": "4.9.0",
"@strapi/plugin-users-permissions": "4.9.0",
Expand Down
2 changes: 1 addition & 1 deletion apps/strapi-dashboard/src/admin/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"extends": "@strapi/typescript-utils/tsconfigs/admin",
"include": ["../plugins/**/admin/src/**/*", "./"],
"include": ["../../../../packages/**/**/admin/src/**/*", "./"],
"exclude": ["node_modules/", "build/", "dist/", "**/*.test.ts"]
}
5 changes: 4 additions & 1 deletion apps/strapi-dashboard/src/admin/webpack.config.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
'use strict';
module.exports = (config, _webpack) => {
module.exports = (config, webpack) => {
config.plugins.push(
new webpack.NormalModuleReplacementPlugin(/^tippy\.js$/, 'tippy.js/dist/tippy-bundle.umd.min.js'),
);
return config;
};
1 change: 1 addition & 0 deletions packages/strapi-tiptap-editor/.npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
dev/
Empty file.
1 change: 1 addition & 0 deletions packages/strapi-tiptap-editor/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Strapi TipTap Editor
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { Flex } from '@strapi/design-system/Flex';
import { BubbleMenu } from '@tiptap/react';
import React from 'react';
import { TableMenuBar } from './TableMenuBar';

// Floating bubble menu for table
export function BubbleMenuComponent({ editor }) {
if (editor) {
let menuBars = [];

if (editor.isActive('table')) {
menuBars.push(TableMenuBar(editor));
}

return (
<BubbleMenu editor={editor} tippyOptions={{ zIndex: 2, maxWidth: '550px' }}>
{menuBars.length ? (
<Flex padding={2} className="menu-bar floating" style={{ flexWrap: 'wrap' }}>
{/* Render menu bars */}
{menuBars}
</Flex>
) : null}
</BubbleMenu>
);
}

return null;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { Option, Select } from '@strapi/design-system/Select';
import React from 'react';
import { formatCurrency } from '../../utils/formateCurrency';

export function PriceList({ editor, productPrice }) {
if (productPrice && productPrice.price && productPrice.price.length === 0) {
return null;
}
const title = `${productPrice?.title} price`;

return (
<Select
required
size="S"
placeholder="Select Price"
onChange={(event) => {
const price = productPrice.price?.find(({ id }) => id === event);

if (price && editor) {
editor.chain().focus().insertReactComponent(price).run();
}
}}
>
{title && <Option value="price">{title}</Option>}
{productPrice?.price?.map((price) => (
<Option key={price.id} className="icon" value={price.id.toString()}>
{`${price.label}: ${formatCurrency(price)}`}
</Option>
))}
</Select>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
import {
Button,
Dialog,
DialogBody,
DialogFooter,
Flex,
IconButton,
IconButtonGroup,
Typography,
} from '@strapi/design-system';
import { Grid, GridItem } from '@strapi/design-system/Grid';
import { Option, Select } from '@strapi/design-system/Select';
import React, { Fragment, useState } from 'react';
import { AiOutlineDelete } from 'react-icons/ai';
import { ImWarning } from 'react-icons/im';
import { RiInsertRowBottom, RiLayoutColumnLine, RiMergeCellsHorizontal, RiToggleLine } from 'react-icons/ri';

export function TableMenuBar(editor) {
const [isVisibleDeleteTable, setIsVisibleDeleteTable] = useState({ visible: false, type: '' });

const onTableMenubarChange = (event) => {
editor.chain().focus()[`${event}`]().run();
};

return (
<Fragment key="tableMenubar">
<Grid gap={2}>
<GridItem col={3}>
<Select onChange={onTableMenubarChange} startIcon={<RiInsertRowBottom color="black" />} label="Table Row">
<Option value="addRowAfter">Insert row below</Option>
<Option value="addRowBefore">Insert row above</Option>
<Option value="deleteRow">Delete row</Option>
</Select>
</GridItem>
<GridItem col={3}>
<Select onChange={onTableMenubarChange} startIcon={<RiLayoutColumnLine color="black" />} label="Table Column">
<Option value="addColumnAfter">Insert column after</Option>
<Option value="addColumnBefore">Insert column before</Option>
<Option value="deleteColumn">Delete column</Option>
</Select>
</GridItem>
<GridItem col={3}>
<Select onChange={onTableMenubarChange} startIcon={<RiToggleLine color="black" />} label="Toggle header">
<Option value="toggleHeaderRow">Toggle header row</Option>
<Option value="toggleHeaderColumn">Toggle header column</Option>
<Option value="toggleHeaderCell">Toggle header cell</Option>
</Select>
</GridItem>
<GridItem col={3}>
<Select
onChange={onTableMenubarChange}
startIcon={<RiMergeCellsHorizontal color="black" />}
label="Table cell"
>
<Option value="mergeCells">Merge cells</Option>
<Option value="splitCell">Split cell</Option>
<Option value="mergeOrSplit">Merge or split cell</Option>
</Select>
</GridItem>
</Grid>
<Grid>
<IconButtonGroup className="button-group">
<IconButton
icon={<AiOutlineDelete />}
label={editor.can().deleteNode('capturedTable') ? 'Delete table with caption' : 'Delete table'}
onClick={() =>
setIsVisibleDeleteTable({
visible: true,
type: editor.can().deleteNode('capturedTable') ? 'capturedTable' : 'table',
})
}
/>
</IconButtonGroup>
</Grid>
<Dialog
onClose={() => setIsVisibleDeleteTable({ visible: false, type: '' })}
title="Confirmation"
isOpen={isVisibleDeleteTable.visible}
>
<DialogBody icon={<ImWarning />}>
<Flex direction="column" alignItems="center" gap={2}>
<Flex justifyContent="center">
<Typography id="confirm-description">{`Are you sure you want to delete the ${
isVisibleDeleteTable.type === 'capturedTable' ? 'table with caption' : 'table'
}?`}</Typography>
</Flex>
</Flex>
</DialogBody>
<DialogFooter
startAction={
<Button onClick={() => setIsVisibleDeleteTable({ visible: false, type: '' })} variant="tertiary">
Cancel
</Button>
}
endAction={
<Button
variant="danger-light"
startIcon={<AiOutlineDelete />}
onClick={() => {
switch (isVisibleDeleteTable.type) {
case 'table':
editor.chain().focus().deleteTable().run();
break;

case 'capturedTable':
editor.chain().focus().deleteNode('capturedTable').run();
break;

default:
break;
}
}}
>
Confirm
</Button>
}
/>
</Dialog>
</Fragment>
);
}
Loading

0 comments on commit 8da48eb

Please sign in to comment.