gutenberg_ai_tools-1.0.x-dev/blocks/ai-block/edit.js

blocks/ai-block/edit.js
/* eslint-disable-next-line import/no-unresolved */
import React, { useState } from 'react';

/* eslint-disable-next-line import/no-unresolved */
import { PanelBody, PanelRow, TextareaControl } from '@wordpress/components';

import {
  useBlockProps,
  BlockControls,
  InnerBlocks,
  InspectorControls,
  RichText,
  /* eslint-disable-next-line import/no-unresolved */
} from '@wordpress/block-editor';

// drupal import is set as external in webpack.config.js
/* eslint-disable-next-line import/no-unresolved */
import { t } from 'drupal';
import RenderAIResponse from './render';
import parseAIResponse from './parser';

// i18n package could be also used. It is a wrapper around Drupal.t.
//   import { __ } from "@wordpress/i18n";
//   __('Text to be translated');

const ALLOWED_BLOCKS = ['core/heading', 'core/paragraph', 'core/quote'];

const checkIfHTMLString = (string) => {
  const regexForHTML = /<([A-Za-z][A-Za-z0-9]*)\b[^>]*>(.*?)<\/\1>/;

  string = JSON.parse(string);

  const isValid = regexForHTML.test(string);

  if (isValid) {
    return true;
  }
};

const htmlEntities = (str) => {
  return String(str)
    .replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;')
    .replace(/\n/g, '<br />');
};

function Edit({ attributes, setAttributes }) {
  const { title, blockTitle, aiAnswer } = attributes;
  const [token, setToken] = useState({ token: '' });
  const [isDisabled, setIsDisabled] = useState(false);
  const [processingMessage, setProcessingMessage] = useState('');
  const [questionCopy, setQuestionCopy] = useState('');

  const handleClick = () => {
    /* title must not be empty of course */
    if (title === undefined) {
      setProcessingMessage('Please enter a valid question.');
      return false;
    }

    /* Don't allow the user to click to request AI to answer the same question
     * many times, this sends unnecessary requests and consume extra pennies
     * that aren't needed */
    if (questionCopy === title) {
      setProcessingMessage(
        'You are asking the same question, please ask another question....',
      );

      return false;
    }

    const data = {
      ai_prompt: title,
    };

    setIsDisabled(true);
    setProcessingMessage('Processing....');

    /* @TODO: these fetch chains look ugly as hell, consider using async/await instead. */
    fetch('/session/token')
      .then((response) => response.text())
      .then((csrfToken) => {
        fetch('/gutenberg-ai-tools/ai-rest?_format=json', {
          body: JSON.stringify(data),
          headers: {
            'Content-Type': 'application/json',
            'X-Csrf-Token': csrfToken,
          },
          method: 'POST',
        })
          .then((response) => response.text())
          .then((data) => {
            let parsedData = '';

            const regex = /\\u([\d\w]{4})/gi;
            const found = data.match(regex);

            if (found !== null && found.length > 0 && checkIfHTMLString(data)) {
              /* eslint-disable-next-line prefer-template */
              parsedData = `<code>${htmlEntities(
                JSON.parse(data),
              )}</code><br /><br />`;
            } else {
              parsedData = parseAIResponse(data);
            }

            setToken({ token: parsedData });
            setAttributes({ aiAnswer: parsedData });
            setIsDisabled(false);
            setProcessingMessage('');
            setQuestionCopy(title);
          })
          .catch((error) => console.error(error));
      });
  };

  const postSearch = (value) => {
    setAttributes({ aiAnswer: value });
    setIsDisabled(false);
    setProcessingMessage('');
    setQuestionCopy(title);
  };

  return (
    <div {...useBlockProps()}>
      <BlockControls></BlockControls>
      <InspectorControls>
        <PanelBody title={t('Block settings')} initialOpen>
          <PanelRow></PanelRow>
          <PanelRow>
            <TextareaControl
              label={t('Block Title')}
              help={t(
                'Use this field if you want to put a question title above the answer',
              )}
              value={blockTitle}
              onChange={(value) => setAttributes({ blockTitle: value })}
            />
          </PanelRow>
          <PanelRow>
            <TextareaControl
              label={t('AI Answer')}
              help={t(
                'AI answer generated by the engine. You can change the answer here',
              )}
              value={aiAnswer}
              onChange={(value) => postSearch(value)}
            />
          </PanelRow>
        </PanelBody>
      </InspectorControls>
      <div>
        <RichText
          tagName="h2"
          placeholder={t('Start typing your question here:')}
          value={title}
          onChange={(value) => setAttributes({ title: value })}
        />
        <button onClick={handleClick} disabled={isDisabled}>
          {t('Ask AI')}
        </button>
        <span>&nbsp;{processingMessage}</span>
        <div>
          <h3>{blockTitle}</h3>
          <RenderAIResponse
            question={title}
            block_title={blockTitle}
            answer={aiAnswer}
          />
          <InnerBlocks allowedBlocks={ALLOWED_BLOCKS} />
        </div>
      </div>
    </div>
  );
}

export default Edit;

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc