import Button from "@app/components/button/Button"; import CardContent from "@app/components/card-content/CardContent"; import CardFooter from "@app/components/card-footer/CardFooter"; import CardHeader from "@app/components/card-header/CardHeader"; import CardSection from "@app/components/card-section/CardSection"; import Card from "@app/components/card/Card"; import InputField from "@app/components/input-field/InputField"; import NumberInput from "@app/components/number-input/NumberInput"; import Select from "@app/components/select/Select"; import * as PopoverPrimitive from "@radix-ui/react-popover"; import { Analytics, UpdateFilterPayload, VerifyAPIKeyPayload, } from "@app/models/api"; import { CardElementStyles, CardHeaderProps, CardStyles, Tag, } from "@app/models/components"; import { TopPostsSettings } from "@app/models/global"; import { VerifyAPIKey, getFilters, updateFilter, updateTopPostsSettings, } from "@app/services/api"; import { useSettings } from "@settings/contexts/SettingsContext"; import { useViewMode } from "@settings/contexts/ViewModeContext"; import React, { useEffect, useRef, useState } from "react"; import { Controller, ControllerRenderProps, useForm } from "react-hook-form"; import "./configuration-styles.scss"; import { cloneDeep, get, isEmpty, isEqual } from "lodash"; import Modal from "@app/components/modal/Modal"; import Radio from "@app/components/radio/Radio"; import ResultCard from "@app/components/result-card/ResultCard"; import CTACard from "@app/components/CTACard/CTACard"; import { BrushIcon, LockIcon, PointerIcon, ViewGrid2, ViewList, CheckCircleIcon, CancelIcon, ErrorIcon, } from "@app/assets/images/icons"; import Tooltip from "@app/components/Tooltip/Tooltip"; import { cardDate, normalizeRangeForHeaders, getDataTypeOptions, getTaxonomiesOptions, } from "@app/services/utilities"; import CustomizableCard from "@app/components/customizableCard/CustomizableCard"; import ColorPicker from "@app/components/color-picker/ColorPicker"; import { FontSizeOptions, TextStyleOptions, defaultElementStyling, } from "@app/constants"; import InputGroup from "@app/components/input-group/InputGroup"; import EmptyState from "@app/components/EmptyState/EmptyState"; import UpgradePopover from "@app/components/UpgradePopover/UpgradePopover"; import { ActivePopover, useUpgradePopover, } from "@settings/contexts/UpgradePopoverContext"; import Placeholder from "@app/assets/images/placeholder.jpg"; import Checkbox from "@app/components/checkbox/Checkbox"; const Configuration = () => { const { microSiteURL, isPremium } = process.env.CONFIG; const localization = topPostsI18n.data; const { initialSettings, setInitialSettings, showNotification, cronjobOptions, } = useSettings(); const { activePopover, setActivePopover } = useUpgradePopover(); const initialValues: TopPostsSettings = { api_key: "", api_key_verified: false, property_id: 0, scheduled_trigger: 86400, filters: {}, site_id: topPostsData.site_id, results_style: "search_results_card", columns_number: 1, custom_styles: {}, show_data_type: false, display_options: { post: { category: "category", tag: "post_tag", data_type: "post", post_name: topPostsData.languages.length > 0 ? {} : "", }, }, }; const [settings, setSettings] = useState({ ...initialValues, ...initialSettings, }); // we combine the initial values with the initial settings to get site_id const [isDeleting, setIsDeleting] = useState(false); const [isOpenDeleteConfigModal, setIsOpenDeleteConfigModal] = useState(false); const [isCustomStylesModalOpen, setIsCustomStylesModalOpen] = useState(false); const [selectedPostType, setSelectedPostType] = useState("post"); const [analyticsData, setAnalyticsData] = useState>([]); const [configHasChanges, setConfigHasChanges] = useState(false); const [displayOptionsHasChanges, setDisplayOptionsHasChanges] = useState(false); const [isOpenOptionsModal, setIsOpenOptionsModal] = useState(false); const [openPopover, setOpenPopover] = useState(-1); const [displayOptions, setDisplayOptions] = useState( !isEmpty(settings.display_options) ? settings.display_options : {} ); const [showPostTypeInput, setShowPostTypeInput] = useState(false); const [showDataType, setShowDataType] = useState( settings?.show_data_type ?? false ); const [postName, setPostName] = useState(() => { const initialPostName = settings?.display_options?.[selectedPostType]?.post_name; return initialPostName !== undefined ? initialPostName : topPostsData?.languages.length > 0 ? {} : selectedPostType; }); const { isRTL } = useViewMode(); const toastPosition = isRTL ? "top-left" : "top-right"; const [isStoring, setIsStoring] = useState(false); const [showConfigSections, setShowConfigSections] = useState( initialSettings.api_key_verified ); const [isVerifyingAPIKey, setIsVerifyingAPIKey] = useState(false); const [showCheck, setShowCheck] = useState(false); const [currentElement, setCurrentElement] = useState(""); const [ApiKey, setApiKey] = useState(settings.api_key ?? ""); const [verifyResult, setVerifyResult] = useState(false); const [changeVerifyState, setChangeVerifyState] = useState( initialSettings.api_key == "" ? true : false ); const [concealedKey, setConcealedKey] = useState(concealKey(ApiKey)); function concealKey(key: string) { if (!key) { return ""; } let starCount = key.length; let starsString = key.slice(0, 5) + "*".repeat(starCount - 5); return starsString; } const handleVerifyAPI = async () => { setIsVerifyingAPIKey(true); const verifyAPIKeyPayload: VerifyAPIKeyPayload = { site_id: topPostsData.site_id, }; const verifyAPIKeyResp = await VerifyAPIKey(ApiKey, verifyAPIKeyPayload); if (verifyAPIKeyResp?.error) { setIsVerifyingAPIKey(false); setVerifyResult(true); //show the check mark after receiving the response. setShowCheck(false); setShowConfigSections(false); setInitialSettings(initialValues); setSettings(initialValues); return; } let getFiltersResp = await getFilters(ApiKey, topPostsData.site_id); if (getFiltersResp?.error) { setIsStoring(false); const errorMessage = localization.saving_settings_error; showNotification( "error", `${errorMessage} (${localization.error} ${getFiltersResp?.status})`, toastPosition ); return; } const filters = getFiltersResp.filters; const filterKeys = Object.keys(filters || {}); if (filterKeys.length == 0) { const filterData = { display_name: localization.myFilter, description: localization.this_is_a_description_of_this_filter_please_edit_me, limit: !isPremium ? 5 : 500, scheduled_trigger: 86400, language: topPostsData.defaultLanguage, date_range: 604800, page: {}, pinned: [], excluded: [], }; const payload: UpdateFilterPayload = { site_id: topPostsData.site_id, filter_data: filterData, }; const updateFilterResp = await updateFilter(ApiKey, payload); if (updateFilterResp?.error) { setIsStoring(false); const errorMessage = localization.saving_settings_error; showNotification( "error", `${errorMessage} (${localization.error} ${updateFilterResp?.status})`, toastPosition ); return; } getFiltersResp = await getFilters(ApiKey, topPostsData.site_id); //second call if (isEmpty(getFiltersResp.filters)) { getFiltersResp = await getFilters(ApiKey, topPostsData.site_id); if (getFiltersResp?.error) { setIsStoring(false); const errorMessage = localization.saving_settings_error; showNotification( "error", `${errorMessage} (${localization.error} ${getFiltersResp?.status})`, toastPosition ); return; } } } const updatedSettings = { ...settings, property_id: Number(verifyAPIKeyResp.data.property_id), filters: getFiltersResp.filters, api_key_verified: true, api_key: ApiKey, }; const isSettingsChanged = isEqual(initialSettings, updatedSettings); if (!isSettingsChanged) { const updateSettingsResp = await updateTopPostsSettings(updatedSettings); if (updateSettingsResp?.error) { let errorMessage = updateSettingsResp?.status === 400 ? updateSettingsResp?.message : `${localization.saving_settings_error} (${localization.error} ${updateSettingsResp?.status})`; //step #1 showNotification("error", errorMessage, toastPosition); setIsVerifyingAPIKey(false); return; } setSettings((prevVal) => ({ ...prevVal, custom_styles: updateSettingsResp.updatedSettings.custom_styles, // Sometimes the custom_styles object is empty and an array is returned by PHP filters: updateSettingsResp.updatedSettings.filters, })); setInitialSettings(updateSettingsResp.updatedSettings); } setShowConfigSections(true); setShowCheck(true); setIsVerifyingAPIKey(false); setVerifyResult(true); setSettings((prev) => ({ ...prev, property_id: Number(verifyAPIKeyResp.data.property_id), api_key_verified: true, api_key: ApiKey, })); setChangeVerifyState(false); }; const previewCardTags = [ { label: localization.tag_1, href: "#", }, { label: localization.tag_2, href: "#", }, ]; const { control, handleSubmit, formState: { errors }, reset, } = useForm({ defaultValues: { ...initialValues, ...initialSettings, }, mode: "all", }); const headerProps: CardHeaderProps = { title: localization.plugin_settings, subtitle: <>{localization.plugin_subtitle}, }; const [currentStyles, setCurrentStyles] = useState( isEmpty(settings?.custom_styles) ? defaultElementStyling : settings?.custom_styles ); const onClearTaxonomies = (taxonomies: [string]) => { taxonomies.forEach((name) => { updateTaxonomyConfig(name, ""); }); }; const paddingProperties = [ { label: localization.top, name: localization.padding_top, placeholder: localization.padding_top_placeholder, }, { label: localization.right, name: localization.padding_right, placeholder: localization.padding_right_placeholder, }, { label: localization.bottom, name: localization.padding_bottom, placeholder: localization.padding_bottom_placeholder, }, { label: localization.left, name: localization.padding_left, placeholder: localization.padding_left_placeholder, }, ]; const popoverContent = ( <>

{localization.top_posts_for_google_analytics}