From 0093804caa7302e94fe4e8e4d499b543facfd91d Mon Sep 17 00:00:00 2001
From: Victor Mutai <victor.mutai@dillieduck.com>
Date: Tue, 19 Dec 2023 00:08:16 +0300
Subject: [PATCH] chore: refactor CounterInfoTool

---
 .../CounterInfoService/CounterInfoTool.js     |   5 +-
 .../CounterInfoService/CounterTool.js         | 232 ++++++++++++++++++
 2 files changed, 235 insertions(+), 2 deletions(-)
 create mode 100644 wax-prosemirror-services/src/BottomInfoService/CounterInfoService/CounterTool.js

diff --git a/wax-prosemirror-services/src/BottomInfoService/CounterInfoService/CounterInfoTool.js b/wax-prosemirror-services/src/BottomInfoService/CounterInfoService/CounterInfoTool.js
index d990da40f..7cf10f498 100644
--- a/wax-prosemirror-services/src/BottomInfoService/CounterInfoService/CounterInfoTool.js
+++ b/wax-prosemirror-services/src/BottomInfoService/CounterInfoService/CounterInfoTool.js
@@ -2,7 +2,8 @@ import React from 'react';
 import { isEmpty } from 'lodash';
 import { injectable } from 'inversify';
 import { Tools } from 'wax-prosemirror-core';
-import EditorInfoTool from './components/EditorInfoTool';
+// import EditorInfoTool from './components/EditorInfoTool';
+import CounterTool from './CounterTool';
 
 @injectable()
 class CounterInfoTool extends Tools {
@@ -22,7 +23,7 @@ class CounterInfoTool extends Tools {
   renderTool(view) {
     if (isEmpty(view)) return null;
     return this.isDisplayed() ? (
-      <EditorInfoTool item={this.toJSON()} key="CounterInfo" view={view} />
+      <CounterTool item={this.toJSON()} key="CounterInfo" view={view} />
     ) : null;
   }
 }
diff --git a/wax-prosemirror-services/src/BottomInfoService/CounterInfoService/CounterTool.js b/wax-prosemirror-services/src/BottomInfoService/CounterInfoService/CounterTool.js
new file mode 100644
index 000000000..396d9bd93
--- /dev/null
+++ b/wax-prosemirror-services/src/BottomInfoService/CounterInfoService/CounterTool.js
@@ -0,0 +1,232 @@
+import React, { useMemo, useState, useEffect } from 'react';
+import styled from 'styled-components';
+import { grid, override } from '@pubsweet/ui-toolkit';
+import { MenuButton } from 'wax-prosemirror-core';
+import { isEmpty } from 'lodash';
+import { useTranslation } from 'react-i18next';
+
+const Wrapper = styled.div`
+  font-size: 0;
+  position: relative;
+  z-index: 2;
+
+  button {
+    background: ${props => (props.active ? `#535E76` : '#fff')};
+    border: ${props =>
+      props.active ? `1px solid #535E76` : `1px solid #D8DAE0`};
+
+    &:hover {
+      background: ${props => (props.active ? `#535E76` : '#D8DAE0')};
+    }
+    box-shadow: 0px -2px 6px 1px rgba(204, 204, 204, 0.41);
+  }
+
+  &:before {
+    border-bottom: ${props =>
+      props.active ? `8px solid #535E76` : `8px solid #D8DAE0`};
+
+    border-left: 8px solid transparent;
+    border-right: 8px solid transparent;
+    bottom: 26px;
+    content: '';
+    height: 0;
+    left: 48%;
+    position: relative;
+    width: 0;
+  }
+
+  /* stylelint-disable-next-line order/properties-alphabetical-order */
+  ${override('Wax.CounterWrapper')}
+`;
+
+const DropWrapper = styled.div`
+  background: white;
+  margin-top: ${grid(1)};
+  position: absolute;
+  top: 32px;
+  width: max-content;
+
+  /* stylelint-disable-next-line order/properties-alphabetical-order */
+  ${override('Wax.CounterDropWrapper')}
+`;
+
+const CounterInfoComponent = styled.div`
+  background: #fff;
+  border-radius: 1.03093% / 8%;
+  bottom: 45px;
+  box-shadow: rgb(9 30 66 / 25%) 0px 4px 8px 0px,
+    rgb(9 30 66 / 31%) 0px 0px 1px 0px;
+  display: flex;
+  flex-direction: column;
+  font-size: 14px;
+  padding: calc(4px * 2);
+  position: fixed;
+  right: 31px;
+  transform-origin: 50% 50% 0px;
+
+  /* stylelint-disable-next-line order/properties-alphabetical-order */
+  ${override('Wax.CounterInfoComponent')}
+`;
+
+const Counter = styled.div`
+  color: black;
+  display: block;
+  font-size: 14px;
+  height: 25px;
+  margin: 5px;
+  min-width: 150px;
+
+  /* stylelint-disable-next-line order/properties-alphabetical-order */
+  ${override('Wax.Counters')}
+`;
+
+const CounterTool = ({ view: { state }, item }) => {
+  const { t, i18n } = useTranslation();
+
+  const [isOpen, setIsOpen] = useState(true);
+
+  const [wordCount, setWordCount] = useState(0);
+  const [characterCount, setCharacterCount] = useState(0);
+  const [charactersNoSpaceCount, setCharactersNoSpace] = useState(0);
+  const [paragraphCount, setParagraphCount] = useState(0);
+  const [imageCount, setImageCount] = useState(0);
+  const [footnoteCount, setFootnoteCount] = useState(0);
+  const [tableCount, setTableCount] = useState(0);
+  // eslint-disable-next-line no-unused-vars
+  const [blockLevelNodes, setBlockLevelNodes] = useState(0);
+
+  useEffect(() => {
+    const docText = state.doc.textBetween(
+      0,
+      state.doc.content.size,
+      undefined,
+      ' ',
+    );
+
+    const wordCounter = docText.split(' ').filter(word => word !== '').length;
+    const chars = docText.split('');
+
+    const charactersNoSpace = chars.filter(char => char !== ' ').length;
+
+    setWordCount(wordCounter);
+    setCharacterCount(charactersNoSpace);
+    setCharactersNoSpace(chars.length);
+
+    state.doc.descendants(node => {
+      if (node.type.name === 'paragraph') {
+        setParagraphCount(prevState => prevState + 1);
+      }
+      if (node.type.name === 'image') {
+        setImageCount(prevState => prevState + 1);
+      }
+      if (node.type.groups.includes('notes')) {
+        setFootnoteCount(prevState => prevState + 1);
+      }
+      if (node.type.name === 'table') {
+        setTableCount(prevState => prevState + 1);
+      }
+    });
+  }, []);
+
+  const infoDropDownOptions = [
+    {
+      name: `${wordCount} ${
+        !isEmpty(i18n) && i18n.exists(`Wax.Counters.Words`)
+          ? t(`Wax.Counters.Words`)
+          : 'Words'
+      }`,
+    },
+    {
+      name: `${characterCount} ${
+        !isEmpty(i18n) && i18n.exists(`Wax.Counters.Characters`)
+          ? t(`Wax.Counters.Characters`)
+          : 'Characters'
+      }`,
+    },
+    {
+      name: `${charactersNoSpaceCount} ${
+        !isEmpty(i18n) && i18n.exists(`Wax.Counters.Characters Without Space`)
+          ? t(`Wax.Counters.Characters Without Space`)
+          : 'Characters Without Space'
+      }`,
+    },
+    {
+      name: `${paragraphCount} ${
+        !isEmpty(i18n) && i18n.exists(`Wax.Counters.Paragraph`)
+          ? t(`Wax.Counters.Paragraph`)
+          : 'Paragraph'
+      }`,
+    },
+    {
+      name: `${imageCount} ${
+        !isEmpty(i18n) && i18n.exists(`Wax.Counters.Images`)
+          ? t(`Wax.Counters.Images`)
+          : 'Images'
+      }`,
+    },
+    {
+      name: `${tableCount} ${
+        !isEmpty(i18n) && i18n.exists(`Wax.Counters.Tables`)
+          ? t(`Wax.Counters.Tables`)
+          : 'Tables'
+      }`,
+    },
+    {
+      name: `${footnoteCount} ${
+        !isEmpty(i18n) && i18n.exists(`Wax.Counters.Footnotes`)
+          ? t(`Wax.Counters.Footnotes`)
+          : 'Footnotes'
+      }`,
+    },
+    {
+      name: `${blockLevelNodes} ${
+        !isEmpty(i18n) && i18n.exists(`Wax.Counters.Block-Level Nodes`)
+          ? t(`Wax.Counters.Block-Level Nodes`)
+          : 'Block-Level Nodes'
+      }`,
+    },
+  ];
+
+  const renderList = () => {
+    const lists = [];
+
+    Object.keys(infoDropDownOptions).forEach(key => {
+      lists.push(
+        <Counter key={key} title={infoDropDownOptions[key].name}>
+          <span>{infoDropDownOptions[key].name}</span>
+        </Counter>,
+      );
+    });
+    return <div>{lists}</div>;
+  };
+
+  const MenuButtonComponent = useMemo(
+    () => (
+      <Wrapper active={isOpen}>
+        <MenuButton
+          active={isOpen}
+          disabled={false}
+          label="Words"
+          title={item.title}
+        />
+
+        {isOpen && (
+          <DropWrapper>
+            <CounterInfoComponent
+              close={() => setIsOpen(false)}
+              item={item}
+              view={state}
+            >
+              {renderList()}
+            </CounterInfoComponent>
+          </DropWrapper>
+        )}
+      </Wrapper>
+    ),
+    [isOpen, renderList],
+  );
+
+  return MenuButtonComponent;
+};
+
+export default CounterTool;
-- 
GitLab