HEX
Server: LiteSpeed
System: Linux server240.web-hosting.com 4.18.0-553.45.1.lve.el8.x86_64 #1 SMP Wed Mar 26 12:08:09 UTC 2025 x86_64
User: creaqbdc (8964)
PHP: 8.0.30
Disabled: NONE
Upload Files
File: //proc/self/cwd/wp-content/plugins/essential-blocks/src/admin/dashboard/components/TabAISuite.js
import { useEffect, useState } from "@wordpress/element";
import { __ } from "@wordpress/i18n";
import Switch from "rc-switch";
import AsyncSelect from "react-select/async";
import apiFetch from "@wordpress/api-fetch";
import { select, useSelect, withSelect } from "@wordpress/data";
import { Dashicon } from '@wordpress/components';

import {
    fetchEBSettingsData,
    saveEBSettingsData,
} from "@essential-blocks/controls";

export default function TabAISuite() {
    const [aiSettings, setAiSettings] = useState({
        writePageContent: true,
        writeRichtext: true,
        writeInputFields: true,
        generateImage: true,
        postTypes: ['all'],
        apiKey: "",
        maxTokens: 1500,
        contentModel: 'gpt-4.1-nano',
    });

    // Track if settings have been loaded from the server
    const [settingsLoaded, setSettingsLoaded] = useState(false);

    const [isSaving, setIsSaving] = useState(false);
    const [saveMessage, setSaveMessage] = useState({});
    const [apiKeyError, setApiKeyError] = useState('');
    const [showFeatureOptions, setShowFeatureOptions] = useState(false);
    const [postTypeOptions, setPostTypeOptions] = useState([
        { value: 'all', label: __('All Post Types', 'essential-blocks') }
    ]);

    const filterablePostTypes = useSelect((select) => {
        const postTypes = select("core").getPostTypes({ per_page: -1 });

        if (!postTypes) {
            return []; // Or default value if needed
        }

        const filteredValues = postTypes.filter((item) => (!['attachment', 'docs', 'product'].includes(item.slug)) && item.viewable)
            .map((item) => ({
                label: item.name,
                value: item.slug
            }));

        return filteredValues.length > 0 ? filteredValues : [{ label: "Post", value: "posts" }];
    }, []);

    // Function to load post types
    const loadPostTypes = (inputValue, callback) => {
        const options = [
            { value: 'all', label: __('All Post Types', 'essential-blocks') },
            ...filterablePostTypes
        ];

        setPostTypeOptions(options);
        callback(options.filter(option =>
            option.label.toLowerCase().includes(inputValue.toLowerCase())
        ));
    };

    // Effect to load settings data
    useEffect(() => {
        fetchEBSettingsData("eb_write_with_ai").then((data) => {
            if (data) {
                data = { ...aiSettings, ...data }

                // Ensure postTypes is always an array
                if (!Array.isArray(data.postTypes)) {
                    data.postTypes = ['all'];
                }

                if ('enableAi' in data) {
                    if (data.enableAi === true) {
                        data.writePageContent = true;
                        data.writeRichtext = true;
                        data.writeInputFields = true;
                    }
                    else {
                        data.writePageContent = false;
                        data.writeRichtext = false;
                        data.writeInputFields = false;
                    }

                    delete data.enableAi
                }

                setAiSettings({
                    ...data
                });
            }

            setSettingsLoaded(true);
        });
    }, []);

    // Effect to update post type options when filterablePostTypes changes
    useEffect(() => {
        if (filterablePostTypes && filterablePostTypes.length > 0) {
            const options = [
                { value: 'all', label: __('All Post Types', 'essential-blocks') },
                ...filterablePostTypes
            ];
            setPostTypeOptions(options);
        }
    }, [filterablePostTypes]);

    const allContentEnabled = aiSettings.writePageContent || aiSettings.writeRichtext || aiSettings.writeInputFields;

    const onChangeAllContentSwitch = (value) => {
        setAiSettings({
            ...aiSettings,
            writePageContent: value,
            writeRichtext: value,
            writeInputFields: value,
        });
    };

    const toggleFeatureOptions = () => {
        setShowFeatureOptions(!showFeatureOptions);
    };

    const onChangewritePageContent = (value) => {
        setAiSettings({
            ...aiSettings,
            writePageContent: value,
        });
    };

    const onChangewriteRichtext = (value) => {
        setAiSettings({
            ...aiSettings,
            writeRichtext: value,
        });
    };

    const onChangewriteInputFields = (value) => {
        setAiSettings({
            ...aiSettings,
            writeInputFields: value,
        });
    };

    const onChangeGenerateImage = (value) => {
        setAiSettings({
            ...aiSettings,
            generateImage: value,
        });
    };

    const handlePostTypesChange = (selectedOptions) => {
        setAiSettings({
            ...aiSettings,
            postTypes: selectedOptions ? selectedOptions.map(option => option.value) : ['all'],
        });
    };

    const handleApiKeyChange = (event) => {
        // Clear any previous API key error when the user starts typing
        if (apiKeyError) {
            setApiKeyError('');
        }

        setAiSettings({
            ...aiSettings,
            apiKey: event.target.value,
        });
    };

    const handleMaxTokensChange = (event) => {
        setAiSettings({
            ...aiSettings,
            maxTokens: parseInt(event.target.value) || 1200,
        });
    };

    const handleContentModelChange = (event) => {
        setAiSettings({
            ...aiSettings,
            contentModel: event.target.value,
        });
    };

    const saveOptionsData = () => {
        setIsSaving(true);
        setSaveMessage({});

        saveEBSettingsData("eb_write_with_ai", JSON.stringify(aiSettings), "write_with_ai").then((res) => {
            const response = JSON.parse(res);
            setIsSaving(false);

            if (response.success) {
                setSaveMessage({
                    type: "success",
                    message: __("Settings saved successfully.", "essential-blocks"),
                });
                setTimeout(() => setSaveMessage({}), 3000);
            } else {
                // Check if it's an API key validation error
                if (response.data && response.data.type === 'api_key_error') {
                    // const errorMessage = response.data.message || __("Incorrect API key provided. Please check and try again.", "essential-blocks");
                    const errorMessage = __("Incorrect API key provided. Please check and try again.", "essential-blocks");
                    setApiKeyError(errorMessage);
                    setSaveMessage({
                        type: "error",
                        message: errorMessage,
                    });
                } else {
                    setSaveMessage({
                        type: "error",
                        message: __("Error saving settings.", "essential-blocks"),
                    });
                }
            }
        });
    };

    return (
        <>
            <div className="eb-admin-grid">
                <div className="eb-col-12">
                    <div className="eb-admin-block eb-write-with-ai mb30">
                        <div className="eb-admin-grid">

                            {/* Write with AI */}
                            <div className="eb-admin-inner-grid eb-col-12">
                                <div className="eb-col-6">
                                    <h2>{__("Enable Write with AI", "essential-blocks")}</h2>
                                    <p>{__("Toggle to enable or disable the AI writing functionality inside the Gutenberg Editor.", "essential-blocks")}</p>
                                </div>
                                <div className="eb-col-6 eb-admin-checkbox-wrapper">
                                    <div className="eb-admin-input-wrapper eb-admin-checkbox-all eb-admin-checkbox eb-block-box">
                                        <h4 className={allContentEnabled ? "enabled" : "disabled"}>
                                            Enable or disable all content features
                                        </h4>
                                        <div style={{ display: 'flex', alignItems: 'center', gap: '10px' }}>
                                            <label className="eb-toggle-switch">
                                                <label htmlFor="switch-all-content" className="eb-admin-checkbox-label">
                                                    <Switch
                                                        checked={allContentEnabled}
                                                        onChange={onChangeAllContentSwitch}
                                                        defaultChecked={true}
                                                        disabled={false}
                                                        checkedChildren="ON"
                                                        unCheckedChildren="OFF"
                                                    />
                                                </label>
                                            </label>

                                            <button
                                                type="button"
                                                onClick={toggleFeatureOptions}
                                                style={{
                                                    background: 'none',
                                                    border: '1px solid #ccc',
                                                    borderRadius: '4px',
                                                    padding: '4px 8px',
                                                    cursor: 'pointer',
                                                    fontSize: '12px',
                                                    color: '#666'
                                                }}
                                            >
                                                <Dashicon icon={showFeatureOptions ? "arrow-up-alt2" : "arrow-down-alt2"} />
                                            </button>
                                        </div>
                                    </div>

                                    {showFeatureOptions && (
                                        <div className="eb-admin-checkbox-items-wrapper">
                                            <div className="eb-admin-input-wrapper eb-admin-checkbox eb-block-box">
                                                <h4 className={aiSettings?.writePageContent ? "enabled" : "disabled"}>
                                                    Generate Page Content
                                                </h4>
                                                <label className="eb-toggle-switch">
                                                    <label htmlFor="switch-feature-one" className="eb-admin-checkbox-label">
                                                        <Switch
                                                            checked={aiSettings?.writePageContent}
                                                            onChange={onChangewritePageContent}
                                                            defaultChecked={true}
                                                            disabled={false}
                                                            checkedChildren="ON"
                                                            unCheckedChildren="OFF"
                                                        />
                                                    </label>
                                                </label>
                                            </div>

                                            <div className="eb-admin-input-wrapper eb-admin-checkbox eb-block-box">
                                                <h4 className={aiSettings?.writeRichtext ? "enabled" : "disabled"}>
                                                    Generate RichText Content
                                                </h4>
                                                <label className="eb-toggle-switch">
                                                    <label htmlFor="switch-feature-two" className="eb-admin-checkbox-label">
                                                        <Switch
                                                            checked={aiSettings?.writeRichtext}
                                                            onChange={onChangewriteRichtext}
                                                            defaultChecked={true}
                                                            disabled={false}
                                                            checkedChildren="ON"
                                                            unCheckedChildren="OFF"
                                                        />
                                                    </label>
                                                </label>
                                            </div>

                                            <div className="eb-admin-input-wrapper eb-admin-checkbox eb-block-box">
                                                <h4 className={aiSettings?.writeInputFields ? "enabled" : "disabled"}>
                                                    Generate Block Input Content
                                                </h4>
                                                <label className="eb-toggle-switch">
                                                    <label htmlFor="switch-feature-three" className="eb-admin-checkbox-label">
                                                        <Switch
                                                            checked={aiSettings?.writeInputFields}
                                                            onChange={onChangewriteInputFields}
                                                            defaultChecked={true}
                                                            disabled={false}
                                                            checkedChildren="ON"
                                                            unCheckedChildren="OFF"
                                                        />
                                                    </label>
                                                </label>
                                            </div>


                                        </div>
                                    )}
                                </div>
                            </div>

                            {/* Generate AI Images */}
                            <div className="eb-admin-inner-grid eb-col-12">
                                <div className="eb-col-6">
                                    <h2>{__("Generate AI Images", "essential-blocks")}</h2>
                                    <p>{__("Toggle to enable or disable the AI image generation functionality inside the Gutenberg Editor.", "essential-blocks")}</p>
                                </div>
                                <div className="eb-col-6 eb-admin-checkbox-wrapper">
                                    <div className="eb-admin-input-wrapper eb-admin-checkbox eb-block-box">
                                        <h4 className={aiSettings?.generateImage ? "enabled" : "disabled"}>
                                            Generate AI Images
                                        </h4>
                                        <label className="eb-toggle-switch">
                                            <label htmlFor="switch-generate-images" className="eb-admin-checkbox-label">
                                                <Switch
                                                    checked={aiSettings?.generateImage}
                                                    onChange={onChangeGenerateImage}
                                                    defaultChecked={true}
                                                    disabled={false}
                                                    checkedChildren="ON"
                                                    unCheckedChildren="OFF"
                                                />
                                            </label>
                                        </label>
                                    </div>
                                </div>
                            </div>

                            {/* Choose Post Types */}
                            <div className="eb-admin-inner-grid eb-col-12">
                                <div className="eb-col-6">
                                    <h2>{__("Choose Post Types", "essential-blocks")}</h2>
                                    <p>{__("Select which post types you want to enable AI writing for (Posts, Pages, or any custom post types).", "essential-blocks")}</p>
                                </div>
                                <div className="eb-col-6">
                                    <div className="eb-admin-input-wrapper eb-block-box p0">
                                        <AsyncSelect
                                            isMulti
                                            cacheOptions
                                            defaultOptions={postTypeOptions}
                                            loadOptions={loadPostTypes}
                                            value={settingsLoaded && postTypeOptions.filter(option =>
                                                aiSettings.postTypes && aiSettings.postTypes.includes(option.value)
                                            )}
                                            onChange={handlePostTypesChange}
                                            placeholder={__("Select Post Types", "essential-blocks")}
                                            className="eb-post-types-select"
                                            classNamePrefix="eb-select"
                                            isLoading={!settingsLoaded || !filterablePostTypes || filterablePostTypes.length === 0}
                                        />
                                    </div>
                                </div>
                            </div>

                            {/* Content Generation Model */}
                            <div className="eb-admin-inner-grid eb-col-12">
                                <div className="eb-col-6">
                                    <h2>{__("Content Generation Model", "essential-blocks")}</h2>
                                    <p>{__("Select the OpenAI model to use for AI content generation. Different models offer varying capabilities and performance.", "essential-blocks")}</p>
                                </div>
                                <div className="eb-col-6">
                                    <div className="eb-admin-input-wrapper eb-block-box p0">
                                        <select
                                            value={aiSettings.contentModel}
                                            onChange={handleContentModelChange}
                                            className="eb-content-model-select"
                                        >
                                            <option value="gpt-4.1-nano">{__("GPT-4.1 Nano (Recommended)", "essential-blocks")}</option>
                                            <option value="gpt-4o">{__("GPT-4o", "essential-blocks")}</option>
                                            <option value="gpt-4-turbo">{__("GPT-4 Turbo", "essential-blocks")}</option>
                                            <option value="gpt-4o-mini">{__("GPT-4o Mini", "essential-blocks")}</option>
                                            <option value="gpt-3.5-turbo">{__("GPT-3.5 Turbo", "essential-blocks")}</option>
                                        </select>
                                    </div>
                                </div>
                            </div>

                            {/* API Keys */}
                            <div className="eb-admin-inner-grid eb-col-12">
                                <div className="eb-col-6">
                                    <h2>{__("API Key", "essential-blocks")}</h2>
                                    <p>{__("Connect your OpenAI account by entering your API key.", "essential-blocks")}</p>
                                    <p>
                                        {__("Check this ", "essential-blocks")}
                                        <a href="https://essential-blocks.com/docs/write-with-ai/" target="_blank" rel="noopener noreferrer">{__("documentation", "essential-blocks")}</a>
                                        {__(" to learn how to generate your OpenAI API key.", "essential-blocks")}
                                    </p>
                                </div>
                                <div className="eb-col-6">
                                    <div className="eb-admin-input-wrapper eb-openai-api-key eb-block-box p0">
                                        <input
                                            type="text"
                                            value={aiSettings.apiKey}
                                            onChange={handleApiKeyChange}
                                            placeholder={__("Enter API key", "essential-blocks")}
                                            className={apiKeyError ? "eb-input-error" : ""}
                                        />
                                        {apiKeyError && (
                                            <div className="eb-api-key-error">
                                                {apiKeyError}
                                            </div>
                                        )}
                                    </div>
                                </div>
                            </div>

                            {/* Set Max Tokens */}
                            <div className="eb-admin-inner-grid eb-col-12">
                                <div className="eb-col-6">
                                    <h2>{__("Set Max Tokens", "essential-blocks")}</h2>
                                    <p>
                                        {__("Content will be generated based on the Token Limits you have set. For more information on Token Limits, you can check out this ", "essential-blocks")}
                                        <a href="https://platform.openai.com/settings/organization/limits" target="_blank" rel="noopener noreferrer">{__("link.", "essential-blocks")}</a>
                                    </p>
                                </div>
                                <div className="eb-col-6">
                                    <div className="eb-admin-input-wrapper eb-block-box p0">
                                        <input
                                            type="number"
                                            value={aiSettings.maxTokens}
                                            onChange={handleMaxTokensChange}
                                            min="1"
                                            max="4000"
                                        />
                                    </div>
                                </div>
                            </div>

                            {/* Save Button */}
                            <div className="eb-admin-action-grid eb-col-12" style={{ textAlign: "right", marginTop: "20px" }}>
                                {saveMessage && (
                                    <span className={`eb-save-message ${saveMessage?.type}`} style={{ marginRight: "10px" }}>
                                        {saveMessage?.message}
                                    </span>
                                )}
                                <button
                                    className="eb-save-button eb-btn-md eb-btn-border"
                                    onClick={saveOptionsData}
                                    disabled={isSaving}
                                >
                                    {isSaving
                                        ? __("Saving...", "essential-blocks")
                                        : __("Save Changes", "essential-blocks")
                                    }
                                </button>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </>
    );
}