diff --git a/CHANGELOG.md b/CHANGELOG.md index e517139f4..5ffd5e38d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,29 @@ All notable changes to this project will be documented in this file. This projects adheres to [Semantic Versioning](https://semver.org/) and [Keep a CHANGELOG](https://keepachangelog.com/). +## [3.1.0] + +### Added +- `range` field for the forms. +- `singleSubmit` attribute on all fields to allow only one submit per form to be used as calculation form. +- "Result output" custom post type. +- Blocks for the result output. +- Calculator form type and necessary filters. +- Forms can now use `single submit` option to send data without submit button. +- Setting for single form to hide global msg on submit success. + +### Changed +- `Input` fields now output correct types for e-mail and URL fields, so the experience on mobile devices should be much better. +- Admin listing URLs can now support additional types. +- All icons are now used from utils lib. + +### Fixed +- JS errors when missing data. +- Broken URLs for admin listing when using custom post types. + +### Removed +- Unnecessary options in the `rating` field. + ## [3.0.5] ### Fixed @@ -256,6 +279,7 @@ This projects adheres to [Semantic Versioning](https://semver.org/) and [Keep a - Initial production release. +[3.1.0]: https://github.com/infinum/eightshift-forms/compare/3.0.5...3.1.0 [3.0.5]: https://github.com/infinum/eightshift-forms/compare/3.0.4...3.0.5 [3.0.4]: https://github.com/infinum/eightshift-forms/compare/3.0.3...3.0.4 [3.0.3]: https://github.com/infinum/eightshift-forms/compare/3.0.2...3.0.3 diff --git a/composer.json b/composer.json index 0d3837d74..424ffacf5 100644 --- a/composer.json +++ b/composer.json @@ -40,11 +40,7 @@ "require": { "php": "^7.4 || >=8.0", "erusev/parsedown": "^1.7.4", - "infinum/eightshift-forms-utils": "^1.2.4" - }, - "suggest": { - "ext-pcov": "* || This extension is used for code coverage generation. Use either pcov, or xdebug, but not both.", - "ext-xdebug": "^3.0.0 || This extension is used for code coverage generation. Use either pcov, or xdebug, but not both." + "infinum/eightshift-forms-utils": "^1.3.0" }, "autoload": { "psr-4": { diff --git a/composer.lock b/composer.lock index f7d91e595..e428cd90a 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "4af23d84c4cb0933ffd292f56030fa05", + "content-hash": "172272e1b58c5ab88e42b618bd896799", "packages": [ { "name": "erusev/parsedown", @@ -58,16 +58,16 @@ }, { "name": "infinum/eightshift-forms-utils", - "version": "1.2.4", + "version": "dev-feature/calculator", "source": { "type": "git", "url": "https://github.com/infinum/eightshift-forms-utils.git", - "reference": "d17843ca1611c8880eac59ea783c96d6d278fddc" + "reference": "50ff7303e80c6f9f7a21b404eaf1e4d9d0c564eb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/infinum/eightshift-forms-utils/zipball/d17843ca1611c8880eac59ea783c96d6d278fddc", - "reference": "d17843ca1611c8880eac59ea783c96d6d278fddc", + "url": "https://api.github.com/repos/infinum/eightshift-forms-utils/zipball/50ff7303e80c6f9f7a21b404eaf1e4d9d0c564eb", + "reference": "50ff7303e80c6f9f7a21b404eaf1e4d9d0c564eb", "shasum": "" }, "require": { @@ -119,7 +119,7 @@ "issues": "https://github.com/infinum/eightshift-forms/issues", "source": "https://github.com/infinum/eightshift-forms" }, - "time": "2024-02-27T16:57:22+00:00" + "time": "2024-03-08T11:35:03+00:00" }, { "name": "infinum/eightshift-libs", @@ -5036,6 +5036,7 @@ "aliases": [], "minimum-stability": "dev", "stability-flags": { + "infinum/eightshift-forms-utils": 20, "brain/faker": 20 }, "prefer-stable": true, diff --git a/src/AdminMenus/FormAdminMenu.php b/src/AdminMenus/FormAdminMenu.php index d736c3a28..c9ca9f4e6 100644 --- a/src/AdminMenus/FormAdminMenu.php +++ b/src/AdminMenus/FormAdminMenu.php @@ -10,6 +10,8 @@ namespace EightshiftForms\AdminMenus; +use EightshiftForms\CustomPostType\Result; +use EightshiftForms\CustomPostType\Forms; use EightshiftForms\Entries\EntriesHelper; use EightshiftFormsVendor\EightshiftLibs\Helpers\Components; use EightshiftForms\Misc\SettingsWpml; @@ -188,10 +190,11 @@ protected function processAttributes($attr): array { $type = isset($_GET['type']) ? \sanitize_text_field(\wp_unslash($_GET['type'])) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended $formId = isset($_GET['formId']) ? \sanitize_text_field(\wp_unslash($_GET['formId'])) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended + $parent = isset($_GET['parent']) ? \sanitize_text_field(\wp_unslash($_GET['parent'])) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended $output = []; switch ($type) { - case 'locations': + case UtilsConfig::SLUG_ADMIN_LISTING_LOCATIONS: $items = UtilsGeneralHelper::getBlockLocations($formId); $count = \count($items); $formTitle = \get_the_title((int) $formId); @@ -203,7 +206,7 @@ protected function processAttributes($attr): array 'adminListingPageSubTitle' => $count === 1 ? \__('Showing 1 form location.', 'eightshift-forms') : \sprintf(\__('Showing %s form locations.', 'eightshift-forms'), $count), ]; break; - case 'entries': + case UtilsConfig::SLUG_ADMIN_LISTING_ENTRIES: $items = EntriesHelper::getEntries($formId); $count = \count($items); $formTitle = \get_the_title((int) $formId); @@ -215,19 +218,63 @@ protected function processAttributes($attr): array 'adminListingPageSubTitle' => $count === 1 ? \__('Showing 1 form entry.', 'eightshift-forms') : \sprintf(\__('Showing %s form entries.', 'eightshift-forms'), $count), ]; break; - case 'trash': - $items = $this->formsListing->getFormsList($type); + case UtilsConfig::SLUG_ADMIN_LISTING_TRASH: + $items = $this->formsListing->getFormsList($type, $parent); + $count = \count($items); + + if ($parent === UtilsConfig::SLUG_ADMIN_LISTING_RESULTS) { + $output = [ + // Translators: %s is the form title. + 'adminListingPageTitle' => $this->getMultilangTitle(\__('Deleted result outputs', 'eightshift-forms')), + // Translators: %s is the number of trashed forms. + 'adminListingPageSubTitle' => \sprintf( + _n( + 'Showing %d trashed result output.', + 'Showing %d trashed result outputs.', + $count, + 'eightshift-forms' + ), + $count + ), + ]; + } else { + $output = [ + // Translators: %s is the form title. + 'adminListingPageTitle' => $this->getMultilangTitle(\__('Deleted forms', 'eightshift-forms')), + // Translators: %s is the number of trashed forms. + 'adminListingPageSubTitle' => \sprintf( + _n( + 'Showing %d trashed form.', + 'Showing %d trashed forms.', + $count, + 'eightshift-forms' + ), + $count + ), + ]; + } + break; + case UtilsConfig::SLUG_ADMIN_LISTING_RESULTS: + $items = $this->formsListing->getFormsList($type, $parent); $count = \count($items); $output = [ // Translators: %s is the form title. - 'adminListingPageTitle' => $this->getMultilangTitle(\__('Deleted forms', 'eightshift-forms')), + 'adminListingPageTitle' => $this->getMultilangTitle(\__('Result outputs', 'eightshift-forms')), // Translators: %s is the number of trashed forms. - 'adminListingPageSubTitle' => $count === 1 ? \__('Showing 1 trashed form.', 'eightshift-forms') : \sprintf(\__('Showing %s trashed forms.', 'eightshift-forms'), $count), + 'adminListingPageSubTitle' => \sprintf( + _n( + 'Showing %d result output.', + 'Showing %d result outputs.', + $count, + 'eightshift-forms' + ), + $count + ), ]; break; default: - $items = $this->formsListing->getFormsList($type); + $items = $this->formsListing->getFormsList($type, $parent); $count = \count($items); $output = [ @@ -242,9 +289,9 @@ protected function processAttributes($attr): array $output, [ 'adminListingShowNoItems' => $count === 0, - 'adminListingItems' => $this->getListingItems($items, $type), - 'adminListingTopItems' => $this->getTopBarItems($type, $formId), - 'adminListingNoItems' => $this->getNoItemsMessage($type), + 'adminListingItems' => $this->getListingItems($items, $type, $parent), + 'adminListingTopItems' => $this->getTopBarItems($type, $formId, $parent), + 'adminListingNoItems' => $this->getNoItemsMessage($type, $parent), ] ); } @@ -273,16 +320,16 @@ private function getMultilangTitle(string $title): string * Get no items message output. * * @param string $type Type of the listing. + * @param string $parent Post type of the listing. * * @return array */ - private function getNoItemsMessage(string $type): array + private function getNoItemsMessage(string $type, string $parent): array { - $newUrl = UtilsGeneralHelper::getNewFormPageUrl(); $listingUrl = UtilsGeneralHelper::getListingPageUrl(); switch ($type) { - case 'locations': + case UtilsConfig::SLUG_ADMIN_LISTING_LOCATIONS: $output = [ Components::render('highlighted-content', [ 'highlightedContentTitle' => \__('Location list is empty', 'eightshift-forms'), @@ -294,19 +341,44 @@ private function getNoItemsMessage(string $type): array ]), ]; break; - case 'trash': + case UtilsConfig::SLUG_ADMIN_LISTING_TRASH: + if ($parent === UtilsConfig::SLUG_ADMIN_LISTING_RESULTS) { + $output = [ + Components::render('highlighted-content', [ + 'highlightedContentTitle' => \__('Trash list is empty', 'eightshift-forms'), + // Translators: %s is the link to the forms listing page. + 'highlightedContentSubtitle' => \sprintf(\__(' + Your don\'t have any result outputs in trash.
+
Go to result outputs', 'eightshift-forms'), UtilsGeneralHelper::getListingPageUrl(UtilsConfig::SLUG_ADMIN_LISTING_RESULTS, '', esc_url($parent))), + 'highlightedContentIcon' => 'emptyStateTrash', + ]), + ]; + } else { + $output = [ + Components::render('highlighted-content', [ + 'highlightedContentTitle' => \__('Trash list is empty', 'eightshift-forms'), + // Translators: %s is the link to the forms listing page. + 'highlightedContentSubtitle' => \sprintf(\__(' + Your don\'t have any form in trash.
+
Go to your forms', 'eightshift-forms'), esc_url($listingUrl)), + 'highlightedContentIcon' => 'emptyStateTrash', + ]), + ]; + } + break; + case UtilsConfig::SLUG_ADMIN_LISTING_RESULTS: $output = [ Components::render('highlighted-content', [ - 'highlightedContentTitle' => \__('Trash list is empty', 'eightshift-forms'), + 'highlightedContentTitle' => \__('Result output list is empty', 'eightshift-forms'), // Translators: %s is the link to the forms listing page. 'highlightedContentSubtitle' => \sprintf(\__(' - Your don\'t have any form in trash.
-
Go to your forms', 'eightshift-forms'), $listingUrl), - 'highlightedContentIcon' => 'emptyStateTrash', + Your don\'t have any result outputs.
+
Go to your forms', 'eightshift-forms'), esc_url(UtilsGeneralHelper::getListingPageUrl())), + 'highlightedContentIcon' => 'emptyStateResults', ]), ]; break; - case 'entries': + case UtilsConfig::SLUG_ADMIN_LISTING_ENTRIES: $output = [ Components::render('highlighted-content', [ 'highlightedContentTitle' => \__('Entrie list is empty', 'eightshift-forms'), @@ -325,7 +397,7 @@ private function getNoItemsMessage(string $type): array // Translators: %s is the link to the forms listing page. 'highlightedContentSubtitle' => \sprintf(\__(' You don\'t have any forms to show.
-
Add your first form', 'eightshift-forms'), $newUrl), +
Add your first form', 'eightshift-forms'), esc_url(UtilsGeneralHelper::getNewFormPageUrl(Forms::POST_TYPE_SLUG))), 'highlightedContentIcon' => 'emptyStateFormList', ]), ]; @@ -340,10 +412,11 @@ private function getNoItemsMessage(string $type): array * * @param string $type Type of the listing. * @param string $formId Form ID. + * @param string $parent Parent type of the listing. * * @return array */ - private function getTopBarItems(string $type, string $formId): array + private function getTopBarItems(string $type, string $formId, string $parent): array { $bulkSelector = UtilsHelper::getStateSelectorAdmin('listingBulk'); $filterSelector = UtilsHelper::getStateSelectorAdmin('listingFilter'); @@ -354,7 +427,7 @@ private function getTopBarItems(string $type, string $formId): array $right = []; switch ($type) { - case 'locations': + case UtilsConfig::SLUG_ADMIN_LISTING_LOCATIONS: $left = [ Components::render('submit', [ 'submitVariant' => 'ghost', @@ -365,7 +438,7 @@ private function getTopBarItems(string $type, string $formId): array ]), ]; break; - case 'entries': + case UtilsConfig::SLUG_ADMIN_LISTING_RESULTS: $left = [ Components::render('checkbox', [ 'checkboxValue' => 'all', @@ -385,7 +458,7 @@ private function getTopBarItems(string $type, string $formId): array 'submitIsDisabled' => true, 'additionalClass' => $bulkSelector, 'submitAttrs' => [ - UtilsHelper::getStateAttribute('bulkType') => 'delete-entry', + UtilsHelper::getStateAttribute('bulkType') => 'delete', ], ]), Components::render('submit', [ @@ -394,25 +467,27 @@ private function getTopBarItems(string $type, string $formId): array 'submitIsDisabled' => true, 'additionalClass' => $bulkSelector, 'submitAttrs' => [ - UtilsHelper::getStateAttribute('bulkType') => 'duplicate-entry', + UtilsHelper::getStateAttribute('bulkType') => 'duplicate', ], ]), ]; $right = [ Components::render('submit', [ - 'submitVariant' => 'ghost', - 'submitValue' => \__('Export to CSV', 'eightshift-forms'), - 'submitIsDisabled' => true, - 'additionalClass' => "{$exportSelector} {$bulkSelector}", - 'submitAttrs' => [ - UtilsHelper::getStateAttribute('bulkType') => 'fake', - UtilsHelper::getStateAttribute('formId') => $formId, - ], + 'submitVariant' => 'outline', + 'submitButtonAsLink' => true, + 'submitButtonAsLinkUrl' => UtilsGeneralHelper::getListingPageUrl(UtilsConfig::SLUG_ADMIN_LISTING_TRASH, '', UtilsConfig::SLUG_ADMIN_LISTING_RESULTS), + 'submitValue' => \__('Trashed', 'eightshift-forms'), + ]), + Components::render('submit', [ + 'submitButtonAsLink' => true, + 'submitButtonAsLinkUrl' => UtilsGeneralHelper::getNewFormPageUrl(Result::POST_TYPE_SLUG), + 'submitValue' => \__('Create', 'eightshift-forms'), + 'submitIcon' => UtilsHelper::getUtilsIcons('addHighContrast') ]), ]; break; - case 'trash': + case UtilsConfig::SLUG_ADMIN_LISTING_ENTRIES: $left = [ Components::render('checkbox', [ 'checkboxValue' => 'all', @@ -426,18 +501,91 @@ private function getTopBarItems(string $type, string $formId): array 'submitValue' => \__('Back', 'eightshift-forms'), 'submitIcon' => UtilsHelper::getUtilsIcons('arrowLeft') ]), + Components::render('submit', [ + 'submitVariant' => 'ghost', + 'submitValue' => \__('Delete', 'eightshift-forms'), + 'submitIsDisabled' => true, + 'additionalClass' => $bulkSelector, + 'submitAttrs' => [ + UtilsHelper::getStateAttribute('bulkType') => 'delete-entry', + ], + ]), + Components::render('submit', [ + 'submitVariant' => 'ghost', + 'submitValue' => \__('Duplicate', 'eightshift-forms'), + 'submitIsDisabled' => true, + 'additionalClass' => $bulkSelector, + 'submitAttrs' => [ + UtilsHelper::getStateAttribute('bulkType') => 'duplicate-entry', + ], + ]), ]; $right = [ Components::render('submit', [ 'submitVariant' => 'ghost', - 'submitValue' => \__('Restore', 'eightshift-forms'), + 'submitValue' => \__('Export to CSV', 'eightshift-forms'), 'submitIsDisabled' => true, - 'additionalClass' => $bulkSelector, + 'additionalClass' => "{$exportSelector} {$bulkSelector}", 'submitAttrs' => [ - UtilsHelper::getStateAttribute('bulkType') => 'restore', + UtilsHelper::getStateAttribute('bulkType') => 'fake', + UtilsHelper::getStateAttribute('formId') => $formId, ], ]), + ]; + break; + case UtilsConfig::SLUG_ADMIN_LISTING_TRASH: + if ($parent === UtilsConfig::SLUG_ADMIN_LISTING_RESULTS) { + $left = [ + Components::render('checkbox', [ + 'checkboxValue' => 'all', + 'checkboxName' => 'all', + 'additionalClass' => $selectAllSelector, + ]), + Components::render('submit', [ + 'submitVariant' => 'ghost', + 'submitButtonAsLink' => true, + 'submitButtonAsLinkUrl' => UtilsGeneralHelper::getListingPageUrl(UtilsConfig::SLUG_ADMIN_LISTING_RESULTS), + 'submitValue' => \__('Back', 'eightshift-forms'), + 'submitIcon' => UtilsHelper::getUtilsIcons('arrowLeft') + ]), + Components::render('submit', [ + 'submitVariant' => 'ghost', + 'submitValue' => \__('Restore', 'eightshift-forms'), + 'submitIsDisabled' => true, + 'additionalClass' => $bulkSelector, + 'submitAttrs' => [ + UtilsHelper::getStateAttribute('bulkType') => 'restore', + ], + ]), + ]; + } else { + $left = [ + Components::render('checkbox', [ + 'checkboxValue' => 'all', + 'checkboxName' => 'all', + 'additionalClass' => $selectAllSelector, + ]), + Components::render('submit', [ + 'submitVariant' => 'ghost', + 'submitButtonAsLink' => true, + 'submitButtonAsLinkUrl' => UtilsGeneralHelper::getListingPageUrl(), + 'submitValue' => \__('Back', 'eightshift-forms'), + 'submitIcon' => UtilsHelper::getUtilsIcons('arrowLeft') + ]), + Components::render('submit', [ + 'submitVariant' => 'ghost', + 'submitValue' => \__('Restore', 'eightshift-forms'), + 'submitIsDisabled' => true, + 'additionalClass' => $bulkSelector, + 'submitAttrs' => [ + UtilsHelper::getStateAttribute('bulkType') => 'restore', + ], + ]), + ]; + } + + $right = [ Components::render('submit', [ 'submitVariant' => 'ghost', 'submitValue' => \__('Delete permanently', 'eightshift-forms'), @@ -496,12 +644,12 @@ private function getTopBarItems(string $type, string $formId): array Components::render('submit', [ 'submitVariant' => 'outline', 'submitButtonAsLink' => true, - 'submitButtonAsLinkUrl' => UtilsGeneralHelper::getFormsTrashPageUrl(), + 'submitButtonAsLinkUrl' => UtilsGeneralHelper::getListingPageUrl(UtilsConfig::SLUG_ADMIN_LISTING_TRASH), 'submitValue' => \__('Trashed', 'eightshift-forms'), ]), Components::render('submit', [ 'submitButtonAsLink' => true, - 'submitButtonAsLinkUrl' => UtilsGeneralHelper::getNewFormPageUrl(), + 'submitButtonAsLinkUrl' => UtilsGeneralHelper::getNewFormPageUrl(Forms::POST_TYPE_SLUG), 'submitValue' => \__('Create', 'eightshift-forms'), 'submitIcon' => UtilsHelper::getUtilsIcons('addHighContrast') ]), @@ -520,16 +668,17 @@ private function getTopBarItems(string $type, string $formId): array * * @param array $items Items to be rendered. * @param string $type Type of the listing. + * @param string $parent Parent type of the listing. * * @return array */ - private function getListingItems(array $items, string $type): array + private function getListingItems(array $items, string $type, string $parent): array { $output = []; $isDevMode = UtilsDeveloperHelper::isDeveloperModeActive(); switch ($type) { - case 'locations': + case UtilsConfig::SLUG_ADMIN_LISTING_LOCATIONS: foreach ($items as $item) { $id = $item['id'] ?? ''; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited $postType = $item['postType'] ?? ''; @@ -545,11 +694,36 @@ private function getListingItems(array $items, string $type): array 'cardInlineUseHover' => true, 'cardInlineIcon' => UtilsHelper::getUtilsIcons('post'), 'cardInlineLeftContent' => Components::ensureString($this->getLeftContent($item)), - 'cardInlineRightContent' => Components::ensureString($this->getRightContent($item, $type)), + 'cardInlineRightContent' => Components::ensureString($this->getRightContent($item, $type, $parent)), ]); } break; - case 'entries': + case UtilsConfig::SLUG_ADMIN_LISTING_RESULTS: + foreach ($items as $item) { + $id = $item['id'] ?? ''; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited + $postType = $item['postType'] ?? ''; + $editLink = $item['editLink'] ?? ''; + + $title = \get_the_title($id); + + $output[] = Components::render('card-inline', [ + 'cardInlineTitle' => $title . ($isDevMode ? " ({$id})" : ''), + 'cardInlineTitleLink' => $editLink, + 'cardInlineSubTitle' => \implode(', ', $this->getSubtitle($item, ['status'])), + 'cardInlineUseHover' => true, + 'cardInlineIcon' => UtilsHelper::getUtilsIcons('resultOutput'), + 'cardInlineLeftContent' => Components::ensureString($this->getLeftContent($item)), + 'cardInlineRightContent' => Components::ensureString($this->getRightContent($item, $type, $parent)), + 'additionalAttributes' => [ + UtilsHelper::getStateAttribute('bulkId') => $id, + ], + 'additionalClass' => Components::classnames([ + UtilsHelper::getStateSelectorAdmin('listingItem'), + ]), + ]); + } + break; + case UtilsConfig::SLUG_ADMIN_LISTING_ENTRIES: $i = 0; $count = \count($items); foreach (\array_reverse($items) as $item) { @@ -597,6 +771,34 @@ function ($value, $key) { $i++; } + break; + case UtilsConfig::SLUG_ADMIN_LISTING_TRASH: + foreach ($items as $item) { + $id = $item['id'] ?? ''; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited + $title = $item['title'] ?? ''; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited + + if (!$title) { + // Translators: %s is the form ID. + $title = \sprintf(\__('Form %s', 'eightshift-forms'), $id); + } + + $output[] = Components::render('card-inline', [ + 'cardInlineTitle' => $title . ($isDevMode ? " ({$id})" : ''), + 'cardInlineTitleLink' => $item['editLink'] ?? '#', + 'cardInlineSubTitle' => \implode(', ', $this->getSubtitle($item, ['all'])), + 'cardInlineIcon' => UtilsHelper::getUtilsIcons('listingGeneric'), + 'cardInlineLeftContent' => Components::ensureString($this->getLeftContent($item)), + 'cardInlineRightContent' => Components::ensureString($this->getRightContent($item, $type, $parent)), + 'cardInlineUseHover' => true, + 'additionalAttributes' => [ + UtilsHelper::getStateAttribute('bulkId') => $id, + ], + 'additionalClass' => Components::classnames([ + UtilsHelper::getStateSelectorAdmin('listingItem'), + ]), + ]); + } + break; default: foreach ($items as $item) { @@ -620,7 +822,7 @@ function ($value, $key) { 'cardInlineSubTitle' => \implode(', ', $this->getSubtitle($item)), 'cardInlineIcon' => $cardIcon, 'cardInlineLeftContent' => Components::ensureString($this->getLeftContent($item)), - 'cardInlineRightContent' => Components::ensureString($this->getRightContent($item, $type)), + 'cardInlineRightContent' => Components::ensureString($this->getRightContent($item, $type, $parent)), 'cardInlineInvalid' => !$isValid, 'cardInlineUseHover' => true, 'additionalAttributes' => [ @@ -658,20 +860,27 @@ private function isIntegrationValid(array $item): bool * Get subtitle. * * @param array $item Item to be checked. + * @param array $showOnly Show only these items. * * @return array */ - private function getSubtitle(array $item): array + private function getSubtitle(array $item, array $showOnly = []): array { $output = []; + $showOnly = \array_flip($showOnly); + $showOnlyStatus = isset($showOnly['status']) || empty($showOnly); + $showOnlyIntegrationIsActive = isset($showOnly['integrationIsActive']) || empty($showOnly); + $showOnlyIntegrationIsValid = isset($showOnly['integrationIsValid']) || empty($showOnly); + $showOnlyIntegrationIsApiValid = isset($showOnly['integrationIsApiValid']) || empty($showOnly); + $status = $item['status'] ?? ''; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited $postType = $item['postType'] ?? ''; $isActive = $item['activeIntegration']['isActive'] ?? false; $isValid = $item['activeIntegration']['isValid'] ?? false; $isApiValid = $item['activeIntegration']['isApiValid'] ?? false; - if ($status !== 'publish') { + if ($status !== 'publish' && $showOnlyStatus) { $output[] = \ucfirst($status); if ($postType) { @@ -679,15 +888,15 @@ private function getSubtitle(array $item): array } } - if (!$isActive) { + if (!$isActive && $showOnlyIntegrationIsActive) { $output[] = '' . \esc_html__('Integration not enabled', 'eightshift-forms') . ''; } - if (!$isValid) { + if (!$isValid && $showOnlyIntegrationIsValid) { $output[] = '' . \esc_html__('Form configuration not valid', 'eightshift-forms') . ''; } - if (!$isApiValid) { + if (!$isApiValid && $showOnlyIntegrationIsApiValid) { $output[] = '' . \esc_html__('Missing form fields', 'eightshift-forms') . ''; } @@ -718,15 +927,18 @@ private function getLeftContent(array $item): array * * @param array $item Item to be checked. * @param string $type Type of the listing. + * @param string $parent Parent type of the listing. * * @return array */ - private function getRightContent(array $item, string $type): array + private function getRightContent(array $item, string $type, string $parent): array { $formId = $item['id'] ?? ''; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited + $output = []; + switch ($type) { - case 'locations': + case UtilsConfig::SLUG_ADMIN_LISTING_LOCATIONS: $output = [ Components::render('submit', [ 'submitVariant' => 'ghost', @@ -736,9 +948,49 @@ private function getRightContent(array $item, string $type): array ]), ]; break; - case 'entries': + case UtilsConfig::SLUG_ADMIN_LISTING_RESULTS: + $output = [ + Components::render('submit', [ + 'submitVariant' => 'ghost', + 'submitButtonAsLink' => true, + 'submitButtonAsLinkUrl' => $item['editLink'] ?? '', + 'submitValue' => \__('Edit', 'eightshift-forms'), + ]), + ]; + break; + case UtilsConfig::SLUG_ADMIN_LISTING_ENTRIES: $output = []; break; + case UtilsConfig::SLUG_ADMIN_LISTING_TRASH: + $entriesCount = EntriesHelper::getEntriesCount((string) $formId); + + if ($parent === '') { + $output = [ + Components::render('submit', [ + 'submitVariant' => 'ghost', + 'submitValue' => \__('Locations', 'eightshift-forms'), + 'submitAttrs' => [ + UtilsHelper::getStateAttribute('locationsId') => $formId + ], + 'additionalClass' => UtilsHelper::getStateSelectorAdmin('listingLocations'), + ]), + ($entriesCount > 0) ? + Components::render('submit', [ + 'submitVariant' => 'ghost', + 'submitButtonAsLink' => true, + 'submitButtonAsLinkUrl' => $item['entriesLink'] ?? '', + // Translators: %s is the number of entries. + 'submitValue' => \sprintf(\__('Entries (%s)', 'eightshift-forms'), $entriesCount), + ]) : null, + Components::render('submit', [ + 'submitVariant' => 'ghost', + 'submitButtonAsLink' => true, + 'submitButtonAsLinkUrl' => $item['settingsLink'] ?? '', + 'submitValue' => \__('Settings', 'eightshift-forms'), + ]), + ]; + } + break; default: $entriesCount = EntriesHelper::getEntriesCount((string) $formId); diff --git a/src/AdminMenus/FormAdminTopBarMenu.php b/src/AdminMenus/FormAdminTopBarMenu.php index eb1ed7d91..42f24e77a 100644 --- a/src/AdminMenus/FormAdminTopBarMenu.php +++ b/src/AdminMenus/FormAdminTopBarMenu.php @@ -16,6 +16,7 @@ use EightshiftFormsVendor\EightshiftFormsUtils\Helpers\UtilsGeneralHelper; use EightshiftForms\Listing\FormListingInterface; use EightshiftForms\Troubleshooting\SettingsDebug; +use EightshiftFormsVendor\EightshiftFormsUtils\Config\UtilsConfig; use EightshiftFormsVendor\EightshiftFormsUtils\Helpers\UtilsDeveloperHelper; use EightshiftFormsVendor\EightshiftFormsUtils\Helpers\UtilsHelper; use EightshiftFormsVendor\EightshiftFormsUtils\Helpers\UtilsHooksHelper; @@ -110,7 +111,7 @@ public function getTopBarMenu(WP_Admin_Bar $adminBar): void ], ); - $items = $this->formsListing->getFormsList(''); + $items = $this->formsListing->getFormsList(); if ($items) { foreach ($items as $item) { @@ -159,7 +160,7 @@ public function getTopBarMenu(WP_Admin_Bar $adminBar): void 'id' => "{$listingPrefix}-{$id}-locations", 'parent' => $link, 'title' => \esc_html__('Locations', 'eightshift-forms'), - 'href' => UtilsGeneralHelper::getFormsLocationsPageUrl((string) $id), + 'href' => UtilsGeneralHelper::getListingPageUrl(UtilsConfig::SLUG_ADMIN_LISTING_LOCATIONS, (string) $id), ], ); } @@ -170,7 +171,7 @@ public function getTopBarMenu(WP_Admin_Bar $adminBar): void 'id' => "{$prefix}-new-form", 'parent' => $prefix, 'title' => \esc_html__('Add new form', 'eightshift-forms'), - 'href' => UtilsGeneralHelper::getNewFormPageUrl(), + 'href' => UtilsGeneralHelper::getNewFormPageUrl(Forms::POST_TYPE_SLUG), ], ); diff --git a/src/AdminMenus/FormListingAdminSubMenu.php b/src/AdminMenus/FormListingAdminSubMenu.php index 30330b23e..5f333d845 100644 --- a/src/AdminMenus/FormListingAdminSubMenu.php +++ b/src/AdminMenus/FormListingAdminSubMenu.php @@ -10,7 +10,10 @@ namespace EightshiftForms\AdminMenus; +use EightshiftForms\CustomPostType\Forms; use EightshiftForms\Listing\FormListingInterface; +use EightshiftFormsVendor\EightshiftFormsUtils\Config\UtilsConfig; +use EightshiftFormsVendor\EightshiftFormsUtils\Helpers\UtilsGeneralHelper; use EightshiftFormsVendor\EightshiftLibs\AdminMenus\AbstractAdminSubMenu; /** @@ -56,6 +59,8 @@ function () { }, 20 ); + + \add_action('admin_menu', [$this, 'addCustomLinkIntoAppearanceMenu'], 32); } /** @@ -170,4 +175,28 @@ protected function processAttributes($attr): array { return []; } + + /** + * Add additional links to sidebar menu. + * + * @return void + */ + public function addCustomLinkIntoAppearanceMenu(): void + { + global $submenu; + + // phpcs:disable WordPress.WP.GlobalVariablesOverride.Prohibited + $submenu[FormAdminMenu::ADMIN_MENU_SLUG][] = [ + \esc_html__('Add new form', 'eightshift-forms'), + FormAdminMenu::ADMIN_MENU_CAPABILITY, + UtilsGeneralHelper::getNewFormPageUrl(Forms::URL_SLUG) + ]; + + $submenu[FormAdminMenu::ADMIN_MENU_SLUG][] = [ + \esc_html__('Result outputs', 'eightshift-forms'), + UtilsConfig::CAP_RESULTS, + UtilsGeneralHelper::getListingPageUrl(UtilsConfig::SLUG_ADMIN_LISTING_RESULTS) + ]; + // phpcs:enable + } } diff --git a/src/AdminMenus/FormSettingsAdminSubMenu.php b/src/AdminMenus/FormSettingsAdminSubMenu.php index de8c9e8d8..d82281d31 100644 --- a/src/AdminMenus/FormSettingsAdminSubMenu.php +++ b/src/AdminMenus/FormSettingsAdminSubMenu.php @@ -65,7 +65,6 @@ function () { \add_filter('parent_file', [$this, 'changeHighlightParent'], 31); \add_filter('admin_title', [$this, 'fixPageTitle'], 10, 2); - \add_action('admin_menu', [$this, 'addCustomLinkIntoAppearnaceMenu'], 32); } /** @@ -141,7 +140,7 @@ protected function getMenuSlug(): string */ protected function getParentMenu(): string { - return ''; + return 'null'; } /** @@ -206,7 +205,7 @@ protected function processAttributes($attr): array 'adminSettingsPageTitle' => \sprintf(\esc_html__('Form settings: %s', 'eightshift-forms'), $formTitle), 'adminSettingsBackLink' => UtilsGeneralHelper::getListingPageUrl(), 'adminSettingsFormEditLink' => $formEditLink, - 'adminSettingsFormLocationsLink' => UtilsGeneralHelper::getFormsLocationsPageUrl($formId), + 'adminSettingsFormLocationsLink' => UtilsGeneralHelper::getListingPageUrl(UtilsConfig::SLUG_ADMIN_LISTING_LOCATIONS, $formId), 'adminSettingsSidebar' => $this->settings->getSettingsSidebar($formId, $integrationTypeUsed), 'adminSettingsForm' => $this->settings->getSettingsForm($type, $formId), 'adminSettingsType' => $type, @@ -227,9 +226,8 @@ public function changeHighlightParent($parentFile) global $plugin_page; // phpcs:ignore Squiz.NamingConventions.ValidVariableName.NotCamelCaps if ($plugin_page === UtilsConfig::SLUG_ADMIN_SETTINGS) { // phpcs:ignore Squiz.NamingConventions.ValidVariableName.NotCamelCaps - $plugin_page = UtilsConfig::SLUG_ADMIN; // phpcs:ignore + $plugin_page = Forms::POST_TYPE_SLUG; // phpcs:ignore } - return $parentFile ?? ''; } @@ -249,22 +247,4 @@ public function fixPageTitle(string $adminTitle, string $title): string return $adminTitle; } - - /** - * Add additional links to sidebar menu. - * - * @return void - */ - public function addCustomLinkIntoAppearnaceMenu(): void - { - global $submenu; - - // phpcs:disable WordPress.WP.GlobalVariablesOverride.Prohibited - $submenu[FormAdminMenu::ADMIN_MENU_SLUG][] = [ - \esc_html__('Add new form', 'eightshift-forms'), - FormAdminMenu::ADMIN_MENU_CAPABILITY, - \get_admin_url(null, 'post-new.php?post_type=' . Forms::URL_SLUG) - ]; - // phpcs:enable - } } diff --git a/src/Blocks/assets/scripts/blocks-editor.js b/src/Blocks/assets/scripts/blocks-editor.js index 09671838e..35dc75c5f 100644 --- a/src/Blocks/assets/scripts/blocks-editor.js +++ b/src/Blocks/assets/scripts/blocks-editor.js @@ -37,8 +37,18 @@ registerBlocks( outputCssVariablesGlobal(); // Remove form-selector block from anywhere else other than form CPT. -if (esFormsLocalization?.postType !== 'eightshift-forms') { - const namespace = select(STORE_NAME).getSettingsNamespace(); +const namespace = select(STORE_NAME).getSettingsNamespace(); - unregisterBlockType(`${namespace}/form-selector`); +switch (esFormsLocalization?.currentPostType) { + case esFormsLocalization?.postTypes?.forms: + unregisterBlockType(`${namespace}/result-output-item`); + break; + case esFormsLocalization?.postTypes?.results: + unregisterBlockType(`${namespace}/form-selector`); + unregisterBlockType(`${namespace}/result-output`); + break; + default: + unregisterBlockType(`${namespace}/form-selector`); + unregisterBlockType(`${namespace}/result-output-item`); + break; } diff --git a/src/Blocks/components/admin-settings/admin-settings-admin.scss b/src/Blocks/components/admin-settings/admin-settings-admin.scss index 68b850864..102a3bc98 100644 --- a/src/Blocks/components/admin-settings/admin-settings-admin.scss +++ b/src/Blocks/components/admin-settings/admin-settings-admin.scss @@ -12,7 +12,9 @@ .es-form[data-form-type='settingsGlobal'][data-settings-type='geolocation'], .es-form[data-form-type='settingsGlobal'][data-settings-type='cloudflare'], .es-form[data-form-type='settingsGlobal'][data-settings-type='wp'], - .es-form[data-form-type='settingsGlobal'][data-settings-type='settings'] { + .es-form[data-form-type='settingsGlobal'][data-settings-type='settings'], + .es-form[data-form-type='settingsGlobal'][data-settings-type='wpml'], + .es-form[data-form-type='settingsGlobal'][data-settings-type='calculator'] { .es-submit--global { display: none; } diff --git a/src/Blocks/components/country/country.php b/src/Blocks/components/country/country.php index f3060f021..8f30c2209 100644 --- a/src/Blocks/components/country/country.php +++ b/src/Blocks/components/country/country.php @@ -35,6 +35,7 @@ $countryFieldAttrs = Components::checkAttr('countryFieldAttrs', $attributes, $manifest); $countryPlaceholder = Components::checkAttr('countryPlaceholder', $attributes, $manifest); $countryUseLabelAsPlaceholder = Components::checkAttr('countryUseLabelAsPlaceholder', $attributes, $manifest); +$countrySingleSubmit = Components::checkAttr('countrySingleSubmit', $attributes, $manifest); // Fix for getting attribute that is part of the child component. $countryHideLabel = false; @@ -44,6 +45,7 @@ Components::selector($manifestSelect['componentClass'], $manifestSelect['componentClass'], 'select'), Components::selector($componentClass, $componentClass, 'select'), Components::selector($additionalClass, $additionalClass), + Components::selector($countrySingleSubmit, UtilsHelper::getStateSelectorAdmin('singleSubmit')), ]); if ($countryUseSearch) { diff --git a/src/Blocks/components/country/manifest.json b/src/Blocks/components/country/manifest.json index cbe5790b6..a0dc020b7 100644 --- a/src/Blocks/components/country/manifest.json +++ b/src/Blocks/components/country/manifest.json @@ -57,6 +57,10 @@ }, "countryTypeCustom": { "type": "string" + }, + "countrySingleSubmit": { + "type": "boolean", + "default": false } } } diff --git a/src/Blocks/components/form/assets/form.js b/src/Blocks/components/form/assets/form.js index 4bdbd2169..5a627fac0 100644 --- a/src/Blocks/components/form/assets/form.js +++ b/src/Blocks/components/form/assets/form.js @@ -430,6 +430,9 @@ export class Form { if (isFinalStep) { this.steps.resetSteps(formId); } + + // Set output results. + this.utils.setResultsOutput(formId, data); } } } @@ -1000,7 +1003,16 @@ export class Form { input.addEventListener('keydown', this.onFocusEvent); input.addEventListener('focus', this.onFocusEvent); input.addEventListener('blur', this.onBlurEvent); - input.addEventListener('input', this.onInputEvent); + + if ( + (this.state.getStateConfigIsAdmin() && this.state.getStateElementIsSingleSubmit(name, formId)) || + (this.state.getStateFormConfigUseSingleSubmit(formId) && (this.state.getStateElementTypeCustom(name, formId) === 'range')) + ) { + input.addEventListener('input', debounce(this.onInputEvent, 500)); + } else { + input.addEventListener('input', this.onInputEvent); + + } } /** @@ -1638,7 +1650,10 @@ export class Form { this.utils.unsetFilledState(formId, name); } - if (this.state.getStateConfigIsAdmin() && this.state.getStateElementIsSingleSubmit(name, formId)) { + if ( + (this.state.getStateConfigIsAdmin() && this.state.getStateElementIsSingleSubmit(name, formId)) || + this.state.getStateFormConfigUseSingleSubmit(formId) + ) { debounce( this.formSubmit( formId, { @@ -1662,7 +1677,14 @@ export class Form { this.utils.setOnUserChangeInput(event.target); - if (this.state.getStateConfigIsAdmin() && this.state.getStateElementIsSingleSubmit(name, formId)) { + if ( + (this.state.getStateConfigIsAdmin() && this.state.getStateElementIsSingleSubmit(name, formId)) || + (this.state.getStateFormConfigUseSingleSubmit(formId) && ( + this.state.getStateElementTypeCustom(name, formId) === 'range') || + this.state.getStateElementTypeCustom(name, formId) === 'checkbox' || + this.state.getStateElementTypeCustom(name, formId) === 'radio' + ) + ) { debounce( this.formSubmit( formId, { @@ -1690,7 +1712,10 @@ export class Form { this.utils.setOnUserChangeInput(input); - if (this.state.getStateConfigIsAdmin() && this.state.getStateElementIsSingleSubmit(name, formId)) { + if ( + (this.state.getStateConfigIsAdmin() && this.state.getStateElementIsSingleSubmit(name, formId)) || + this.state.getStateFormConfigUseSingleSubmit(formId) + ) { debounce( this.formSubmit( formId, { diff --git a/src/Blocks/components/form/assets/state-init.js b/src/Blocks/components/form/assets/state-init.js index fa4361224..2e1f7aaea 100644 --- a/src/Blocks/components/form/assets/state-init.js +++ b/src/Blocks/components/form/assets/state-init.js @@ -49,6 +49,7 @@ export const StateEnum = { ELEMENT: 'element', HEADING_SUCCESS: 'headingSuccess', HEADING_ERROR: 'headingError', + HIDE_ON_SUCCESS: 'hideOnSuccess', IS_SINGLE_SUBMIT: 'isSingleSubmit', SAVE_AS_JSON: 'saveAsJson', IS_ADMIN: 'isAdmin', @@ -79,6 +80,7 @@ export const StateEnum = { CONFIG_SUCCESS_REDIRECT: 'successRedirect', CONFIG_SUCCESS_REDIRECT_VARIATION: 'successRedirectVariation', CONFIG_SUCCESS_REDIRECT_DOWNLOADS: 'successRedirectDownloads', + CONFIG_USE_SINGLE_SUBMIT: 'useSingleSubmit', SETTINGS: 'settings', SETTINGS_DISABLE_SCROLL_TO_GLOBAL_MSG_ON_SUCCESS: 'disableScrollToGlobalMsgOnSuccess', @@ -330,8 +332,10 @@ export function setStateFormInitial(formId) { setState([StateEnum.FORM, StateEnum.CONFIG, StateEnum.CONFIG_SUCCESS_REDIRECT], formElement?.getAttribute(getStateAttribute('successRedirect')), formId); setState([StateEnum.FORM, StateEnum.CONFIG, StateEnum.CONFIG_SUCCESS_REDIRECT_VARIATION], formElement?.getAttribute(getStateAttribute('successRedirectVariation')), formId); setState([StateEnum.FORM, StateEnum.CONFIG, StateEnum.CONFIG_SUCCESS_REDIRECT_DOWNLOADS], JSON.parse(formElement?.getAttribute(getStateAttribute('successRedirectDownloads')) ?? '{}'), formId); + setState([StateEnum.FORM, StateEnum.CONFIG, StateEnum.CONFIG_USE_SINGLE_SUBMIT], Boolean(formElement?.getAttribute(getStateAttribute('singleSubmit'))), formId); const globalMsg = formElement?.querySelector(getStateSelector('globalMsg', true)); + setState([StateEnum.FORM, StateEnum.GLOBAL_MSG, StateEnum.HIDE_ON_SUCCESS], Boolean(formElement?.getAttribute(getStateAttribute('globalMsgHideOnSuccess'))), formId); setState([StateEnum.FORM, StateEnum.GLOBAL_MSG, StateEnum.ELEMENT], globalMsg, formId); setState([StateEnum.FORM, StateEnum.GLOBAL_MSG, StateEnum.HEADING_SUCCESS], globalMsg?.getAttribute(getStateAttribute('globalMsgHeadingSuccess')), formId); setState([StateEnum.FORM, StateEnum.GLOBAL_MSG, StateEnum.HEADING_ERROR], globalMsg?.getAttribute(getStateAttribute('globalMsgHeadingError')), formId); diff --git a/src/Blocks/components/form/assets/state.js b/src/Blocks/components/form/assets/state.js index d2a57d92c..87de8789e 100644 --- a/src/Blocks/components/form/assets/state.js +++ b/src/Blocks/components/form/assets/state.js @@ -134,6 +134,9 @@ export class State { getStateFormGlobalMsgHeadingError = (formId) => { return getState([StateEnum.FORM, StateEnum.GLOBAL_MSG, StateEnum.HEADING_ERROR], formId); }; + getStateFormGlobalMsgHideOnSuccess = (formId) => { + return getState([StateEnum.FORM, StateEnum.GLOBAL_MSG, StateEnum.HIDE_ON_SUCCESS], formId); + }; //////////////////////////////////////////////////////////////// // Config getters. @@ -154,6 +157,9 @@ export class State { getStateFormConfigSuccessRedirectDownloads = (formId) => { return getState([StateEnum.FORM, StateEnum.CONFIG, StateEnum.CONFIG_SUCCESS_REDIRECT_DOWNLOADS], formId); }; + getStateFormConfigUseSingleSubmit = (formId) => { + return getState([StateEnum.FORM, StateEnum.CONFIG, StateEnum.CONFIG_USE_SINGLE_SUBMIT], formId); + }; //////////////////////////////////////////////////////////////// // Steps getters. diff --git a/src/Blocks/components/form/assets/utils.js b/src/Blocks/components/form/assets/utils.js index 49b6fe6d0..9523794a5 100644 --- a/src/Blocks/components/form/assets/utils.js +++ b/src/Blocks/components/form/assets/utils.js @@ -275,8 +275,12 @@ export class Utils { messageContainer?.classList?.add(this.state.getStateSelector('isActive')); messageContainer.dataset.status = status; - // Scroll to msg if the condition is right. + // Scroll to msg if the condition is matched. if (status === 'success') { + if (this.state.getStateFormGlobalMsgHideOnSuccess(formId)) { + return; + } + if (!this.state.getStateSettingsDisableScrollToGlobalMsgOnSuccess(formId)) { this.scrollToGlobalMsg(formId); } @@ -1247,6 +1251,89 @@ export class Utils { this.conditionalTags.setField(formId, name); } + /** + * Set output results. + * + * @param {string} formId Form Id. + * @param {object} response Api response. + * + * @returns {void} + */ + setResultsOutput(formId, data) { + // Check if we have output element - block. + const outputElement = document.querySelector(`${this.state.getStateSelector('resultOutput', true)}[${this.state.getStateAttribute('formId')}="${formId}"]`); + + // If no output element, bailout. + if (!outputElement) { + return; + } + + this.resetResultsOutput(formId); + + // Check if we have output items. + const outputItems = data?.[this.state.getStateResponseOutputKey('resultOutputItems')] ?? {}; + + if (Object.keys(outputItems).length) { + for(const [key, value] of Object.entries(outputItems)) { + const itemElement = outputElement.querySelectorAll(`${this.state.getStateSelector('resultOutputItem', true)}[${this.state.getStateAttribute('resultOutputItemKey')}="${key}"][${this.state.getStateAttribute('resultOutputItemValue')}="${value}"]`); + + itemElement.forEach((item) => { + item.classList.remove(this.state.getStateSelector('isHidden')); + }); + } + } + + // Check if we have output parts. + const outputParts = data?.[this.state.getStateResponseOutputKey('resultOutputParts')] ?? {}; + + if (Object.keys(outputParts).length) { + for(const [key, value] of Object.entries(outputParts)) { + const partElement = outputElement.querySelectorAll(`${this.state.getStateSelector('resultOutputPart', true)}[${this.state.getStateAttribute('resultOutputPart')}="${key}"]`); + + if (partElement.length && value) { + partElement.forEach((item) => { + item.classList.remove(this.state.getStateSelector('isHidden')); + item.innerHTML = value; + }); + } + } + } + + // Check if output block is hidden. + const outputElementIsHidden = outputElement.classList.contains(this.state.getStateSelector('isHidden')); + + // If hidden, show it. + if (outputElementIsHidden) { + outputElement.classList.remove(this.state.getStateSelector('isHidden')); + } + } + + resetResultsOutput(formId) { + // Check if we have output element - block. + const outputElement = document.querySelector(`${this.state.getStateSelector('resultOutput', true)}[${this.state.getStateAttribute('formId')}="${formId}"]`); + if (!outputElement) { + return; + } + + // Reset items. + const itemElements = outputElement.querySelectorAll(this.state.getStateSelector('resultOutputItem', true)); + if (itemElements.length) { + itemElements.forEach((item) => { + item.classList.add(this.state.getStateSelector('isHidden')); + }); + } + + // Reset parts. + const partElements = outputElement.querySelectorAll(this.state.getStateSelector('resultOutputPart', true)); + if (partElements.length) { + partElements.forEach((item) => { + if (item.hasAttribute(this.state.getStateAttribute('resultOutputPartDefault'))) { + item.innerHTML = item.getAttribute(this.state.getStateAttribute('resultOutputPartDefault')); + } + }); + } + } + //////////////////////////////////////////////////////////////// // Private methods - not shared to the public window object. //////////////////////////////////////////////////////////////// diff --git a/src/Blocks/components/form/form.php b/src/Blocks/components/form/form.php index 9c023be95..7af510098 100644 --- a/src/Blocks/components/form/form.php +++ b/src/Blocks/components/form/form.php @@ -52,6 +52,8 @@ $formDisabledDefaultStyles = Components::checkAttr('formDisabledDefaultStyles', $attributes, $manifest); $formHasSteps = Components::checkAttr('formHasSteps', $attributes, $manifest); $formCustomName = Components::checkAttr('formCustomName', $attributes, $manifest); +$formHideGlobalMsgOnSuccess = Components::checkAttr('formHideGlobalMsgOnSuccess', $attributes, $manifest); +$formUseSingleSubmit = Components::checkAttr('formUseSingleSubmit', $attributes, $manifest); $formDataTypeSelectorFilterName = UtilsHooksHelper::getFilterName(['block', 'form', 'dataTypeSelector']); $formDataTypeSelector = apply_filters( @@ -110,6 +112,14 @@ $formAttrs[UtilsHelper::getStateAttribute('formType')] = esc_html($formType); } +if ($formHideGlobalMsgOnSuccess) { + $formAttrs[UtilsHelper::getStateAttribute('globalMsgHideOnSuccess')] = 'true'; +} + +if ($formUseSingleSubmit) { + $formAttrs[UtilsHelper::getStateAttribute('singleSubmit')] = 'true'; +} + if ($formConditionalTags) { // Extract just the field name from the given data, if needed. $rawConditionalTagData = $formConditionalTags; diff --git a/src/Blocks/components/form/manifest.json b/src/Blocks/components/form/manifest.json index d87f2dc8b..076f83cee 100644 --- a/src/Blocks/components/form/manifest.json +++ b/src/Blocks/components/form/manifest.json @@ -50,6 +50,10 @@ "formPostId": { "type": "string" }, + "formHideGlobalMsgOnSuccess": { + "type": "boolean", + "default": false + }, "formSuccessRedirect": { "type": "string" }, @@ -99,6 +103,10 @@ "type": "boolean", "default": false }, + "formUseSingleSubmit": { + "type": "boolean", + "default": false + }, "formDownloads": { "type": "array", "items": { diff --git a/src/Blocks/components/input/components/input-editor.js b/src/Blocks/components/input/components/input-editor.js index 924e4f6bc..2ae3984c6 100644 --- a/src/Blocks/components/input/components/input-editor.js +++ b/src/Blocks/components/input/components/input-editor.js @@ -23,20 +23,29 @@ export const InputEditor = (attributes) => { const inputName = checkAttr('inputName', attributes, manifest); const inputValue = checkAttr('inputValue', attributes, manifest); const inputPlaceholder = checkAttr('inputPlaceholder', attributes, manifest); - let inputType = checkAttr('inputType', attributes, manifest); + const inputType = checkAttr('inputType', attributes, manifest); + const inputMin = checkAttr('inputMin', attributes, manifest); + const inputMax = checkAttr('inputMax', attributes, manifest); + const inputStep = checkAttr('inputStep', attributes, manifest); preventSaveOnMissingProps(blockClientId, getAttrKey('inputName', attributes, manifest), inputName); - // For some reason React won't allow input type email. - if (inputType === 'email' || inputType === 'url') { - inputType = 'text'; - } - const inputClass = classnames([ selector(componentClass, componentClass), selector(additionalClass, additionalClass), ]); + let additionalProps = {}; + + if (inputType === 'range') { + additionalProps = { + min: inputMin, + max: inputMax, + step: inputStep, + value: inputValue ?? inputMin, + }; + } + const input = ( <> { placeholder={inputPlaceholder} type={inputType} readOnly + {...additionalProps} /> diff --git a/src/Blocks/components/input/components/input-options.js b/src/Blocks/components/input/components/input-options.js index da9e506db..bc6dfe499 100644 --- a/src/Blocks/components/input/components/input-options.js +++ b/src/Blocks/components/input/components/input-options.js @@ -81,6 +81,9 @@ export const InputOptions = (attributes) => { inputValidationPatternOptions = esFormsLocalization.validationPatternsOptions; } + // Output number to 2 decimal places if it's a float, otherwise output to fixed number. + const formatNumber = (number) => (Number.isInteger(number) ? number.toString() : number.toFixed(2)); + return (
@@ -113,7 +116,7 @@ export const InputOptions = (attributes) => { setAttributes({ [getAttrKey('inputIsEmail', attributes, manifest)]: true }); } - if (value === 'number') { + if (value === 'number' || value === 'range') { setAttributes({ [getAttrKey('inputIsNumber', attributes, manifest)]: true }); } @@ -213,7 +216,7 @@ export const InputOptions = (attributes) => { /> } - {(showInputMinLength || showInputMaxLength) && + {(!['number', 'range'].includes(inputType) && (showInputMinLength || showInputMaxLength)) && { } - {inputType === 'number' && (showInputMin || showInputMax) && + {((inputType === 'number' || inputType === 'range') && (showInputMin || showInputMax)) && { setAttributes({ [getAttrKey('inputMin', attributes, manifest)]: value })} + onChange={(value) => setAttributes({ [getAttrKey('inputMin', attributes, manifest)]: formatNumber(value) })} min={options.inputMin.min} step={options.inputMin.step} disabled={isOptionDisabled(getAttrKey('inputMin', attributes, manifest), inputDisabledOptions)} @@ -314,7 +317,7 @@ export const InputOptions = (attributes) => { setAttributes({ [getAttrKey('inputMax', attributes, manifest)]: value })} + onChange={(value) => setAttributes({ [getAttrKey('inputMax', attributes, manifest)]: formatNumber(value) })} min={options.inputMax.min} step={options.inputMax.step} disabled={isOptionDisabled(getAttrKey('inputMax', attributes, manifest), inputDisabledOptions)} @@ -338,18 +341,17 @@ export const InputOptions = (attributes) => { } - {inputType === 'number' && showInputStep && + {(inputType === 'number' || inputType === 'range') && showInputStep &&
setAttributes({ [getAttrKey('inputStep', attributes, manifest)]: value })} + onChange={(value) => setAttributes({ [getAttrKey('inputStep', attributes, manifest)]: formatNumber(value) })} min={options.inputStep.min} step={options.inputStep.step} disabled={isOptionDisabled(getAttrKey('inputStep', attributes, manifest), inputDisabledOptions)} fixedWidth={4} noBottomSpacing - placeholder='1' /> {inputStep > 0 && !isOptionDisabled(getAttrKey('inputStep', attributes, manifest), inputDisabledOptions) && diff --git a/src/Blocks/components/input/input-admin.scss b/src/Blocks/components/input/input-admin.scss index 1359a5fda..ac2a8e192 100644 --- a/src/Blocks/components/input/input-admin.scss +++ b/src/Blocks/components/input/input-admin.scss @@ -49,7 +49,6 @@ input.es-input { } } - .es-field__content:has(.es-field__before-content):has(.es-field__after-content):has(.es-input:focus-visible) { .es-field__after-content, .es-field__before-content { diff --git a/src/Blocks/components/input/input-editor.scss b/src/Blocks/components/input/input-editor.scss index c38c0c9c9..430326d81 100644 --- a/src/Blocks/components/input/input-editor.scss +++ b/src/Blocks/components/input/input-editor.scss @@ -2,6 +2,10 @@ input.es-input { @include input-styles-editor; + + &[type='range'] { + padding: 0 !important; // stylelint-disable-line declaration-no-important + } } // Collision with WPML. diff --git a/src/Blocks/components/input/input-style.scss b/src/Blocks/components/input/input-style.scss index 75f94e36c..605b7fc14 100644 --- a/src/Blocks/components/input/input-style.scss +++ b/src/Blocks/components/input/input-style.scss @@ -1,3 +1,20 @@ input.es-input { @include input-styles; + + &[type='range'] { + padding: 0; + appearance: none; + background: transparent; + block-size: 0.9375rem; + + &::-webkit-slider-thumb, + &::-moz-range-thumb { + appearance: none; + block-size: 1.45rem; + inline-size: 1.45rem; + cursor: pointer; + background-color: var(--global-colors-esf-admin-accent); + border-radius: 50%; + } + } } diff --git a/src/Blocks/components/input/input.php b/src/Blocks/components/input/input.php index ca6a4dae5..7cf46620b 100644 --- a/src/Blocks/components/input/input.php +++ b/src/Blocks/components/input/input.php @@ -8,6 +8,7 @@ use EightshiftForms\Helpers\FormsHelper; use EightshiftFormsVendor\EightshiftFormsUtils\Helpers\UtilsGeneralHelper; +use EightshiftFormsVendor\EightshiftFormsUtils\Helpers\UtilsHelper; use EightshiftFormsVendor\EightshiftLibs\Helpers\Components; $manifest = Components::getManifest(__DIR__); @@ -34,6 +35,7 @@ $inputAttrs = Components::checkAttr('inputAttrs', $attributes, $manifest); $inputFieldAttrs = Components::checkAttr('inputFieldAttrs', $attributes, $manifest); $inputUseLabelAsPlaceholder = Components::checkAttr('inputUseLabelAsPlaceholder', $attributes, $manifest); +$inputSingleSubmit = Components::checkAttr('inputSingleSubmit', $attributes, $manifest); // Fix for getting attribute that is part of the child component. $inputHideLabel = false; @@ -42,13 +44,9 @@ $inputClass = Components::classnames([ Components::selector($componentClass, $componentClass), Components::selector($additionalClass, $additionalClass), + Components::selector($inputSingleSubmit && $inputType === 'range', UtilsHelper::getStateSelectorAdmin('singleSubmit')), ]); -// Override types. -if ($inputType === 'email' || $inputType === 'url') { - $inputType = 'text'; -} - if ($inputValue) { $inputAttrs['value'] = esc_attr($inputValue); } @@ -62,6 +60,16 @@ $inputHideLabel = true; } +if ($inputType === 'range') { + $inputAttrs['min'] = esc_attr($inputMin); + $inputAttrs['max'] = esc_attr($inputMax); + $inputAttrs['step'] = esc_attr($inputStep); + + if (!$inputValue) { + $inputAttrs['value'] = esc_attr($inputMin); + } +} + $inputAttrsOutput = ''; if ($inputAttrs) { foreach ($inputAttrs as $key => $value) { diff --git a/src/Blocks/components/input/manifest.json b/src/Blocks/components/input/manifest.json index b7a67039e..3aa2692bf 100644 --- a/src/Blocks/components/input/manifest.json +++ b/src/Blocks/components/input/manifest.json @@ -95,6 +95,10 @@ }, "inputDisabledOptions": { "type": "array" + }, + "inputSingleSubmit": { + "type": "boolean", + "default": false } }, "options": { @@ -114,6 +118,10 @@ { "label": "Number", "value": "number" + }, + { + "label": "Range", + "value": "range" } ], "inputMinLength": { @@ -125,16 +133,16 @@ "step": 1 }, "inputMin": { - "min": 0, - "step": 1 + "min": 0.01, + "step": 0.01 }, "inputMax": { - "min": 1, - "step": 1 + "min": 0.01, + "step": 0.01 }, "inputStep": { - "min": 1, - "step": 1 + "min": 0.01, + "step": 0.01 } } } diff --git a/src/Blocks/components/phone/components/phone-options.js b/src/Blocks/components/phone/components/phone-options.js index 6fcf0da3d..33f00c663 100644 --- a/src/Blocks/components/phone/components/phone-options.js +++ b/src/Blocks/components/phone/components/phone-options.js @@ -24,7 +24,7 @@ export const PhoneOptions = (attributes) => { const phoneName = checkAttr('phoneName', attributes, manifest); const phoneValue = checkAttr('phoneValue', attributes, manifest); const phonePlaceholder = checkAttr('phonePlaceholder', attributes, manifest); - const phoneIsNumber = checkAttr('phoneIsNumber', attributes, manifest); + const phoneIsNumber = checkAttr('phoneIsNumber', attributes, manifest); // Used in validation class to validate if the input is a number. const phoneIsDisabled = checkAttr('phoneIsDisabled', attributes, manifest); const phoneIsReadOnly = checkAttr('phoneIsReadOnly', attributes, manifest); const phoneIsRequired = checkAttr('phoneIsRequired', attributes, manifest); diff --git a/src/Blocks/components/rating/manifest.json b/src/Blocks/components/rating/manifest.json index adc0a314b..8423f3c94 100644 --- a/src/Blocks/components/rating/manifest.json +++ b/src/Blocks/components/rating/manifest.json @@ -60,46 +60,10 @@ }, "ratingDisabledOptions": { "type": "array" - } - }, - "options": { - "ratingType": [ - { - "label": "Plain text", - "value": "text" - }, - { - "label": "E-mail", - "value": "email" - }, - { - "label": "URL", - "value": "url" - }, - { - "label": "Number", - "value": "number" - } - ], - "ratingMinLength": { - "min": 0, - "step": 1 - }, - "ratingMaxLength": { - "min": 1, - "step": 1 - }, - "ratingMin": { - "min": 0, - "step": 1 }, - "ratingMax": { - "min": 1, - "step": 1 - }, - "ratingStep": { - "min": 1, - "step": 1 + "ratingSingleSubmit": { + "type": "boolean", + "default": false } } } diff --git a/src/Blocks/components/rating/rating.php b/src/Blocks/components/rating/rating.php index aa684d411..fa6850aed 100644 --- a/src/Blocks/components/rating/rating.php +++ b/src/Blocks/components/rating/rating.php @@ -30,11 +30,13 @@ $ratingAttrs = Components::checkAttr('ratingAttrs', $attributes, $manifest); $ratingFieldAttrs = Components::checkAttr('ratingFieldAttrs', $attributes, $manifest); $ratingAmount = Components::checkAttr('ratingAmount', $attributes, $manifest); +$ratingSingleSubmit = Components::checkAttr('ratingSingleSubmit', $attributes, $manifest); $ratingHideLabel = false; $ratingClass = Components::classnames([ Components::selector($componentClass, $componentClass), Components::selector($additionalClass, $additionalClass), + Components::selector($ratingSingleSubmit, UtilsHelper::getStateSelectorAdmin('singleSubmit')), UtilsHelper::getStateSelector('rating'), ]); diff --git a/src/Blocks/custom/active-campaign/active-campaign-overrides.js b/src/Blocks/custom/active-campaign/active-campaign-overrides.js new file mode 100644 index 000000000..1146e3cab --- /dev/null +++ b/src/Blocks/custom/active-campaign/active-campaign-overrides.js @@ -0,0 +1,12 @@ +// eslint-disable-next-line no-unused-vars +/* global esFormsLocalization */ + +import manifest from './manifest.json'; +import { getUtilsIcons } from '../../components/form/assets/state-init'; + +export const overrides = { + ...manifest, + icon:{ + src: getUtilsIcons('activeCampaign') ?? manifest.icon.src, + } +}; diff --git a/src/Blocks/custom/airtable/airtable-overrides.js b/src/Blocks/custom/airtable/airtable-overrides.js new file mode 100644 index 000000000..f0a6ef31a --- /dev/null +++ b/src/Blocks/custom/airtable/airtable-overrides.js @@ -0,0 +1,12 @@ +// eslint-disable-next-line no-unused-vars +/* global esFormsLocalization */ + +import manifest from './manifest.json'; +import { getUtilsIcons } from '../../components/form/assets/state-init'; + +export const overrides = { + ...manifest, + icon:{ + src: getUtilsIcons('airtable') ?? manifest.icon.src, + } +}; diff --git a/src/Blocks/custom/calculator/calculator-block.js b/src/Blocks/custom/calculator/calculator-block.js new file mode 100644 index 000000000..4d8b1a9fe --- /dev/null +++ b/src/Blocks/custom/calculator/calculator-block.js @@ -0,0 +1,15 @@ +import React from 'react'; +import { InspectorControls } from '@wordpress/block-editor'; +import { CalculatorEditor } from './components/calculator-editor'; +import { CalculatorOptions } from './components/calculator-options'; + +export const Calculator = (props) => { + return ( + <> + + + + + + ); +}; diff --git a/src/Blocks/custom/calculator/calculator-hooks.js b/src/Blocks/custom/calculator/calculator-hooks.js new file mode 100644 index 000000000..958711658 --- /dev/null +++ b/src/Blocks/custom/calculator/calculator-hooks.js @@ -0,0 +1,34 @@ +/* global esFormsLocalization */ + +import { addFilter } from '@wordpress/hooks'; +import { select } from '@wordpress/data'; +import { STORE_NAME } from '@eightshift/frontend-libs/scripts/editor'; +import { isArray } from 'lodash'; + +// Provide additional blocks to the forms. +export const hooks = () => { + const { blockName } = select(STORE_NAME).getBlock('calculator'); + const namespace = select(STORE_NAME).getSettingsNamespace(); + + // Adding all additional blocks to the custom form builder. + addFilter('blocks.registerBlockType', `${namespace}/${blockName}`, (settings, name) => { + if (name === `${namespace}/${blockName}`) { + if (typeof esFormsLocalization !== 'undefined' && isArray(esFormsLocalization?.additionalBlocks)) { + esFormsLocalization.additionalBlocks.forEach((element) => { + if (!settings.attributes.calculatorAllowedBlocks.default.includes(element)) { + settings.attributes.calculatorAllowedBlocks.default.push(element); + } + }); + } + + select(STORE_NAME).getSettings().allowedBlocksBuilderIntegrationAdditionalBlocksList.forEach((element) => { + if (!settings.attributes.calculatorAllowedBlocks.default.includes(element)) { + settings.attributes.calculatorAllowedBlocks.default.push(element); + } + }); + } + + return settings; + }); +}; + diff --git a/src/Blocks/custom/calculator/calculator-overrides.js b/src/Blocks/custom/calculator/calculator-overrides.js new file mode 100644 index 000000000..323f20e4d --- /dev/null +++ b/src/Blocks/custom/calculator/calculator-overrides.js @@ -0,0 +1,19 @@ +// eslint-disable-next-line no-unused-vars + +import globalManifest from '../../manifest.json'; +import manifest from './manifest.json'; +import { getUtilsIcons } from '../../components/form/assets/state-init'; + +export const overrides = { + ...manifest, + icon:{ + src: getUtilsIcons('calculate') ?? manifest.icon.src, + }, + attributes: { + ...manifest.attributes, + calculatorAllowedBlocks: { + ...manifest.attributes.calculatorAllowedBlocks, + default: globalManifest.allowedBlocksBuilderBlocksList + }, + }, +}; diff --git a/src/Blocks/custom/calculator/calculator.php b/src/Blocks/custom/calculator/calculator.php new file mode 100644 index 000000000..8ed7a6007 --- /dev/null +++ b/src/Blocks/custom/calculator/calculator.php @@ -0,0 +1,16 @@ + $innerBlockContent, + ]) +); diff --git a/src/Blocks/custom/calculator/components/calculator-editor.js b/src/Blocks/custom/calculator/components/calculator-editor.js new file mode 100644 index 000000000..ee8d65cab --- /dev/null +++ b/src/Blocks/custom/calculator/components/calculator-editor.js @@ -0,0 +1,31 @@ +import React from 'react'; +import { select } from '@wordpress/data'; +import { InnerBlocks } from '@wordpress/block-editor'; +import { props, checkAttr, BlockInserter, STORE_NAME } from '@eightshift/frontend-libs/scripts'; +import { FormEditor } from '../../../components/form/components/form-editor'; + +export const CalculatorEditor = ({ attributes, setAttributes, clientId }) => { + const manifest = select(STORE_NAME).getBlock('calculator'); + + const { + blockClass, + } = attributes; + + const calculatorAllowedBlocks = checkAttr('calculatorAllowedBlocks', attributes, manifest); + + return ( +
+ } + /> + })} + /> +
+ ); +}; diff --git a/src/Blocks/custom/calculator/components/calculator-options.js b/src/Blocks/custom/calculator/components/calculator-options.js new file mode 100644 index 000000000..c007b2af8 --- /dev/null +++ b/src/Blocks/custom/calculator/components/calculator-options.js @@ -0,0 +1,25 @@ +import React from 'react'; +import { select } from '@wordpress/data'; +import { IntegrationsInternalOptions } from '../../../components/integrations/components/integrations-internal-options'; +import { STORE_NAME } from '@eightshift/frontend-libs/scripts'; + +export const CalculatorOptions = ({ + attributes, + setAttributes, + clientId, +}) => { + const manifest = select(STORE_NAME).getBlock('calculator'); + + const { + title, + } = manifest; + + return ( + + ); +}; diff --git a/src/Blocks/custom/calculator/manifest.json b/src/Blocks/custom/calculator/manifest.json new file mode 100644 index 000000000..d4592eb8c --- /dev/null +++ b/src/Blocks/custom/calculator/manifest.json @@ -0,0 +1,36 @@ +{ + "$schema": "https://raw.githubusercontent.com/infinum/eightshift-frontend-libs/develop/schemas/block.json", + "blockName": "calculator", + "title": "Calculator form", + "description" : "A form with calculator", + "category": "eightshift-forms", + "icon": { + "src": "esf-form" + }, + "keywords": [ + "calculator" + ], + "hasInnerBlocks": true, + "components": { + "form": "form", + "step": "step" + }, + "parent": [ + "eightshift-forms/form-selector" + ], + "attributes": { + "calculatorAllowedBlocks": { + "type": "array", + "default": [] + }, + "calculatorFormPostId": { + "type": "string" + }, + "calculatorDataTypeSelector": { + "type": "string" + }, + "calculatorFormAction": { + "type": "string" + } + } +} diff --git a/src/Blocks/custom/checkbox/checkbox-overrides.js b/src/Blocks/custom/checkbox/checkbox-overrides.js new file mode 100644 index 000000000..9b4055ea3 --- /dev/null +++ b/src/Blocks/custom/checkbox/checkbox-overrides.js @@ -0,0 +1,12 @@ +// eslint-disable-next-line no-unused-vars +/* global esFormsLocalization */ + +import manifest from './manifest.json'; +import { getUtilsIcons } from '../../components/form/assets/state-init'; + +export const overrides = { + ...manifest, + icon:{ + src: getUtilsIcons('checkbox') ?? manifest.icon.src, + } +}; diff --git a/src/Blocks/custom/checkboxes/checkboxes-overrides.js b/src/Blocks/custom/checkboxes/checkboxes-overrides.js new file mode 100644 index 000000000..7d03d0a2d --- /dev/null +++ b/src/Blocks/custom/checkboxes/checkboxes-overrides.js @@ -0,0 +1,12 @@ +// eslint-disable-next-line no-unused-vars +/* global esFormsLocalization */ + +import manifest from './manifest.json'; +import { getUtilsIcons } from '../../components/form/assets/state-init'; + +export const overrides = { + ...manifest, + icon:{ + src: getUtilsIcons('checkboxes') ?? manifest.icon.src, + } +}; diff --git a/src/Blocks/custom/country/country-overrides.js b/src/Blocks/custom/country/country-overrides.js new file mode 100644 index 000000000..26a9bf3f5 --- /dev/null +++ b/src/Blocks/custom/country/country-overrides.js @@ -0,0 +1,12 @@ +// eslint-disable-next-line no-unused-vars +/* global esFormsLocalization */ + +import manifest from './manifest.json'; +import { getUtilsIcons } from '../../components/form/assets/state-init'; + +export const overrides = { + ...manifest, + icon:{ + src: getUtilsIcons('country') ?? manifest.icon.src, + } +}; diff --git a/src/Blocks/custom/date/date-overrides.js b/src/Blocks/custom/date/date-overrides.js new file mode 100644 index 000000000..5aa52ac10 --- /dev/null +++ b/src/Blocks/custom/date/date-overrides.js @@ -0,0 +1,12 @@ +// eslint-disable-next-line no-unused-vars +/* global esFormsLocalization */ + +import manifest from './manifest.json'; +import { getUtilsIcons } from '../../components/form/assets/state-init'; + +export const overrides = { + ...manifest, + icon:{ + src: getUtilsIcons('date') ?? manifest.icon.src, + } +}; diff --git a/src/Blocks/custom/date/manifest.json b/src/Blocks/custom/date/manifest.json index b9fbf3f63..0b793b8fd 100644 --- a/src/Blocks/custom/date/manifest.json +++ b/src/Blocks/custom/date/manifest.json @@ -2,7 +2,7 @@ "$schema": "https://raw.githubusercontent.com/infinum/eightshift-frontend-libs/develop/schemas/block.json", "blockName": "date", "title": "Date", - "description" : "Date picker field", + "description" : "Date/time picker field", "category": "eightshift-forms", "icon": { "src": "esf-date" diff --git a/src/Blocks/custom/dynamic/dynamic-overrides.js b/src/Blocks/custom/dynamic/dynamic-overrides.js new file mode 100644 index 000000000..41cb036f1 --- /dev/null +++ b/src/Blocks/custom/dynamic/dynamic-overrides.js @@ -0,0 +1,12 @@ +// eslint-disable-next-line no-unused-vars +/* global esFormsLocalization */ + +import manifest from './manifest.json'; +import { getUtilsIcons } from '../../components/form/assets/state-init'; + +export const overrides = { + ...manifest, + icon:{ + src: getUtilsIcons('dynamic') ?? manifest.icon.src, + } +}; diff --git a/src/Blocks/custom/field/field-hooks.js b/src/Blocks/custom/field/field-hooks.js index cc074e055..6f18ede19 100644 --- a/src/Blocks/custom/field/field-hooks.js +++ b/src/Blocks/custom/field/field-hooks.js @@ -16,7 +16,7 @@ const setNoneEightshiftFormsBlocksField = createHigherOrderComponent((BlockEdit) } = innerProps; // Change only none forms blocks in forms post type. - if (postType === 'eightshift-forms' && !name.includes('eightshift-forms')) { + if (postType === esFormsLocalization?.postTypes?.forms && !name.includes(esFormsLocalization?.postTypes?.forms)) { return ( @@ -34,7 +34,7 @@ const setNoneEightshiftFormsBlocksField = createHigherOrderComponent((BlockEdit) function setNoneEightshiftBlocksFieldAttributes( settings, name ) { // Change only none forms blocks in forms post type. - if (esFormsLocalization?.postType === 'eightshift-forms' && !name.includes('eightshift-forms')) { + if (esFormsLocalization?.currentPostType === esFormsLocalization?.postTypes?.forms && !name.includes(esFormsLocalization?.postTypes?.forms)) { return { ...settings, attributes: { diff --git a/src/Blocks/custom/field/field-overrides.js b/src/Blocks/custom/field/field-overrides.js new file mode 100644 index 000000000..7592930d2 --- /dev/null +++ b/src/Blocks/custom/field/field-overrides.js @@ -0,0 +1,12 @@ +// eslint-disable-next-line no-unused-vars +/* global esFormsLocalization */ + +import manifest from './manifest.json'; +import { getUtilsIcons } from '../../components/form/assets/state-init'; + +export const overrides = { + ...manifest, + icon:{ + src: getUtilsIcons('field') ?? manifest.icon.src, + } +}; diff --git a/src/Blocks/custom/file/file-overrides.js b/src/Blocks/custom/file/file-overrides.js new file mode 100644 index 000000000..ed41b899d --- /dev/null +++ b/src/Blocks/custom/file/file-overrides.js @@ -0,0 +1,12 @@ +// eslint-disable-next-line no-unused-vars +/* global esFormsLocalization */ + +import manifest from './manifest.json'; +import { getUtilsIcons } from '../../components/form/assets/state-init'; + +export const overrides = { + ...manifest, + icon:{ + src: getUtilsIcons('file') ?? manifest.icon.src, + } +}; diff --git a/src/Blocks/custom/form-selector/components/form-selector-editor.js b/src/Blocks/custom/form-selector/components/form-selector-editor.js index 00f71bbed..4b398d39e 100644 --- a/src/Blocks/custom/form-selector/components/form-selector-editor.js +++ b/src/Blocks/custom/form-selector/components/form-selector-editor.js @@ -26,10 +26,10 @@ export const FormSelectorEditor = ({ {!hasInnerBlocks && {__('Eightshift Forms', 'productive')}} + label={{__('Eightshift Forms', 'eightshift-forms')}} className='es-max-w-108 es-rounded-3! es-mx-auto! es-font-weight-400 es-color-cool-gray-500! es-nested-color-current!' > -

{__('What type is your new form?', 'productive')}

+

{__('What type is your new form?', 'eightshift-forms')}

{forms.length > 0 &&
{forms.map((form, index) => { diff --git a/src/Blocks/custom/form-selector/form-selector-editor.scss b/src/Blocks/custom/form-selector/form-selector-editor.scss index 1d6716b15..daa46b52b 100644 --- a/src/Blocks/custom/form-selector/form-selector-editor.scss +++ b/src/Blocks/custom/form-selector/form-selector-editor.scss @@ -35,16 +35,21 @@ } } -.post-type-eightshift-forms { +.post-type-eightshift-forms, +.post-type-eightshift-forms-res { h1 { span[data-rich-text-placeholder]::after { content: 'Form name'; } } + .edit-post-header { + background-color: var(--global-colors-esf-sky-50); + } + .edit-post-header-toolbar::after { content: ''; - background-image: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnIHZpZXdCb3g9JzAgMCAyMDggMzYnIHdpZHRoPScyMDgnIGhlaWdodD0nMzYnIGZpbGw9J25vbmUnPjxwYXRoIGQ9J00xNC42NjcgMTUuMzMzaDEuMzN2LTIuNjY3aC01LjMzM3YyLjY2N0gxMnYzLjk5OWgtMS4zMzZ2Mi42NjdoNS4zMzN2LTIuNjY3aC0xLjMzdi00WicgZmlsbD0nI0Q5MjMyNycvPjxwYXRoIGNsaXAtcnVsZT0nZXZlbm9kZCcgZmlsbFJ1bGU9J2V2ZW5vZGQnIGQ9J001LjMyOCA4LjY2NmgyNS4zMzN2MTcuMzMzSDUuMzI4VjguNjY2Wm0yLjY2NyAyLjY2N3YxMmgyMHYtMTJoLTIwWicgZmlsbD0nI0Q5MjMyNycvPjxwYXRoIGNsaXAtcnVsZT0nZXZlbm9kZCcgZmlsbFJ1bGU9J2V2ZW5vZGQnIGQ9J001LjUgMEE1LjUwMiA1LjUwMiAwIDAgMCAwIDUuNXYyNUMwIDMzLjUzNiAyLjQ2NCAzNiA1LjUgMzZoMjVjMy4wMzYgMCA1LjUtMi40NjQgNS41LTUuNXYtMjVDMzYgMi40NjQgMzMuNTM2IDAgMzAuNSAwaC0yNVpNMi42NjcgNS41QTIuODM1IDIuODM1IDAgMCAxIDUuNSAyLjY2N2gyNUEyLjgzNSAyLjgzNSAwIDAgMSAzMy4zMzMgNS41djI1YTIuODM1IDIuODM1IDAgMCAxLTIuODMzIDIuODMzaC0yNUEyLjgzNSAyLjgzNSAwIDAgMSAyLjY2NyAzMC41di0yNVonIGZpbGw9JyNEOTIzMjcnLz48cGF0aCBkPSdNNDUuMDc4IDI1VjkuMjdoMTEuOTI0djMuMjEyaC04LjAzdjIuODE2aDYuODg2djMuMDM2aC02Ljg4NlYyMS43aDguMTYyVjI1SDQ1LjA3OFptMTMuNTk0IDBWMTMuNzM2aDMuNTg3VjI1aC0zLjU4N1ptMC0xMi44MjZWOS4yN2gzLjU4N3YyLjkwNGgtMy41ODdabTEwLjU0MyAxNi43MmMtMy4xMDIgMC01LjE0OC0xLjI3Ni01LjUtMy42M2gzLjQ3NmMuMTk4LjU5NC43OTIgMS4xIDEuOTggMS4xIDEuNTE4IDAgMi4xNTYtLjc5MiAyLjE1Ni0yLjE1NnYtMS4xMjJoLS4wODhjLS42Ni43NDgtMS41MTggMS4yOTgtMi44ODIgMS4yOTgtMi41MyAwLTQuODg0LTEuODkyLTQuODg0LTUuMzQ2IDAtMy4zIDEuOTM2LTUuNjMyIDQuNzMtNS42MzIgMS40OTYgMCAyLjUwOC41OTQgMy4xNjggMS41NGguMDQ0di0xLjIxaDMuNDMyVjIzLjljMCAxLjY5NC0uNTk0IDIuOTI2LTEuNDk2IDMuNzQtLjk5Ljg4LTIuNDY0IDEuMjU0LTQuMTM2IDEuMjU0Wm0tLjAyMi03LjE3MmMxLjU2MiAwIDIuMjg4LTEuMjMyIDIuMjg4LTIuODE2IDAtMS41MTgtLjc5Mi0yLjc5NC0yLjI4OC0yLjc5NC0xLjM0MiAwLTIuMjIyIDEuMS0yLjIyMiAyLjgxNiAwIDEuNjk0Ljg4IDIuNzk0IDIuMjIyIDIuNzk0Wk03Ni41NyAyNVY5LjI3aDMuNTg2djUuODUyaC4wNjZjLjgxNC0xLjA3OCAxLjc4Mi0xLjcxNiAzLjM0NC0xLjcxNiAyLjQ2NCAwIDMuOTE2IDEuNzYgMy45MTYgNC4yNjhWMjVoLTMuNTg2di02LjZjMC0xLjE4OC0uNTk0LTIuMDAyLTEuNzYtMi4wMDItMS4xODggMC0xLjk4Ljk5LTEuOTggMi4zNzZWMjVINzYuNTdabTE2Ljc5OC4xMzJjLTIuMDkgMC0zLjU4Ni0uNjgyLTMuNTg2LTMuMTAydi02LjA1aC0xLjQ5NnYtMi4yNDRoMS40OTZ2LTMuNTY0aDMuNDk4djMuNTY0aDIuMDQ2djIuMjQ0SDkzLjI4djUuMjhjMCAuODguNDg0IDEuMSAxLjI1NCAxLjEuMzA4IDAgLjY2LS4wMjIuNzkyLS4wMjJ2Mi42MThjLS4zMDguMDg4LS45OS4xNzYtMS45NTguMTc2Wm04LjI1OC4yMmMtMy4zIDAtNS4zNjgtMS41MTgtNS40NzgtNC4wMDRoMy4zODhjLjEzMiAxLjEyMi44OCAxLjY3MiAyLjA2OCAxLjY3MiAxLjA3OCAwIDEuNzYtLjM5NiAxLjc2LTEuMTIyIDAtMS4wMTItMS4zNjQtMS4xMjItMi44Ni0xLjM4Ni0xLjk1OC0uMzMtNC4wNDgtLjg1OC00LjA0OC0zLjQ5OCAwLTIuMzc2IDIuMi0zLjYwOCA0Ljg2Mi0zLjYwOCAzLjE5IDAgNC45MDYgMS4zODYgNS4wODIgMy42MDhoLTMuM2MtLjEzMi0xLjAxMi0uODE0LTEuMzItMS44MDQtMS4zMi0uODggMC0xLjU2Mi4zMy0xLjU2MiAxLjAzNCAwIC43OTIgMS4yNzYuOTAyIDIuNzA2IDEuMTY2IDEuOTguMzMgNC4zMTIuODM2IDQuMzEyIDMuNzE4IDAgMi40NjQtMi4xNzggMy43NC01LjEyNiAzLjc0Wm02LjI5LS4zNTJWOS4yN2gzLjU4NnY1Ljg1MmguMDY2Yy44MTQtMS4wNzggMS43ODItMS43MTYgMy4zNDQtMS43MTYgMi40NjQgMCAzLjkxNiAxLjc2IDMuOTE2IDQuMjY4VjI1aC0zLjU4NnYtNi42YzAtMS4xODgtLjU5NC0yLjAwMi0xLjc2LTIuMDAyLTEuMTg4IDAtMS45OC45OS0xLjk4IDIuMzc2VjI1aC0zLjU4NlptMTIuNTQ3IDBWMTMuNzM2aDMuNTg2VjI1aC0zLjU4NlptMC0xMi44MjZWOS4yN2gzLjU4NnYyLjkwNGgtMy41ODZaTTEyNi42MDQgMjV2LTguOTc2aC0xLjQ1MnYtMi4yODhoMS40NTJ2LS44MTRjMC0xLjE2Ni4zMy0yLjAyNC45MjQtMi42MTguOTY4LS45NDYgMi44MzgtMS4xNjYgNC43NzQtLjk2OHYyLjUzYy0xLjM2NC0uMDQ0LTIuMTEyLjA2Ni0yLjExMiAxLjMydi41NWgyLjExMnYyLjI4OGgtMi4xMTJWMjVoLTMuNTg2Wm0xMS4zLjEzMmMtMi4wOSAwLTMuNTg2LS42ODItMy41ODYtMy4xMDJ2LTYuMDVoLTEuNDk2di0yLjI0NGgxLjQ5NnYtMy41NjRoMy40OTh2My41NjRoMi4wNDZ2Mi4yNDRoLTIuMDQ2djUuMjhjMCAuODguNDg0IDEuMSAxLjI1NCAxLjEuMzA4IDAgLjY2LS4wMjIuNzkyLS4wMjJ2Mi42MThjLS4zMDguMDg4LS45OS4xNzYtMS45NTguMTc2Wm02Ljg4My0uMTMyVjkuMjdoMTEuNzA0djMuMjc4aC03LjgxdjMuMTloNi41MzR2My4xNDZoLTYuNTM0VjI1aC0zLjg5NFptMTcuNTI2LTIuMmMxLjU2MiAwIDIuMzk4LTEuMzY0IDIuMzk4LTMuNDEgMC0yLjA0Ni0uODM2LTMuNDMyLTIuMzk4LTMuNDMyLTEuNTYyIDAtMi4zNzYgMS4zODYtMi4zNzYgMy40MzIgMCAyLjA0Ni44MTQgMy40MSAyLjM3NiAzLjQxWm0uMDIyIDIuNTUyYy0zLjYwOCAwLTYuMDI4LTIuNTc0LTYuMDI4LTUuOTYyczIuNDItNS45NjIgNi4wMjgtNS45NjJjMy42MyAwIDYuMDA2IDIuNTc0IDYuMDA2IDUuOTYycy0yLjM3NiA1Ljk2Mi02LjAwNiA1Ljk2MlptNy4yMTgtLjM1MlYxMy43MzZoMy40MzJ2MS43NmguMDY2Yy43OTItMS4zNDIgMS43MTYtMS45MzYgMy4wOC0xLjkzNi4zMyAwIC41NS4wMjIuNzA0LjA4OHYzLjA4aC0uMDg4Yy0yLjItLjMwOC0zLjYwOC43Ny0zLjYwOCAzLjIxMlYyNWgtMy41ODZabTguNDIyIDBWMTMuNzM2aDMuNDMydjEuNjA2aC4wNjZjLjcwNC0xLjE2NiAxLjc4Mi0xLjkzNiAzLjQxLTEuOTM2IDEuNDc0IDAgMi41OTYuNzcgMy4xNjggMS45OGguMDQ0Yy44OC0xLjM2NCAyLjA5LTEuOTggMy41NDItMS45OCAyLjU1MiAwIDMuODI4IDEuNzM4IDMuODI4IDQuMjY4VjI1aC0zLjU4NnYtNi42ODhjMC0xLjIxLS41MDYtMS45MTQtMS41ODQtMS45MTQtMS4xNDQgMC0xLjc4Mi45NDYtMS43ODIgMi4yODhWMjVoLTMuNTg2di02LjY4OGMwLTEuMjEtLjUwNi0xLjkxNC0xLjU4NC0xLjkxNC0xLjEyMiAwLTEuNzgyLjk0Ni0xLjc4MiAyLjI4OFYyNWgtMy41ODZabTIzLjkxNy4zNTJjLTMuMyAwLTUuMzY4LTEuNTE4LTUuNDc4LTQuMDA0aDMuMzg4Yy4xMzIgMS4xMjIuODggMS42NzIgMi4wNjggMS42NzIgMS4wNzggMCAxLjc2LS4zOTYgMS43Ni0xLjEyMiAwLTEuMDEyLTEuMzY0LTEuMTIyLTIuODYtMS4zODYtMS45NTgtLjMzLTQuMDQ4LS44NTgtNC4wNDgtMy40OTggMC0yLjM3NiAyLjItMy42MDggNC44NjItMy42MDggMy4xOSAwIDQuOTA2IDEuMzg2IDUuMDgyIDMuNjA4aC0zLjNjLS4xMzItMS4wMTItLjgxNC0xLjMyLTEuODA0LTEuMzItLjg4IDAtMS41NjIuMzMtMS41NjIgMS4wMzQgMCAuNzkyIDEuMjc2LjkwMiAyLjcwNiAxLjE2NiAxLjk4LjMzIDQuMzEyLjgzNiA0LjMxMiAzLjcxOCAwIDIuNDY0LTIuMTc4IDMuNzQtNS4xMjYgMy43NFonIGZpbGw9JyMwMDAnLz48L3N2Zz4='); + background-image: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjA4IiBoZWlnaHQ9IjM2IiB2aWV3Qm94PSIwIDAgMjA4IDM2IiBmaWxsPSJub25lIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgo8cGF0aCBkPSJNMTQuNjY3MSAxNS4zMzNIMTUuOTk3MVYxMi42NjZIMTAuNjY0MVYxNS4zMzNIMTIuMDAwMVYxOS4zMzJIMTAuNjY0MVYyMS45OTlIMTUuOTk3MVYxOS4zMzJIMTQuNjY3MVYxNS4zMzJWMTUuMzMzWiIgZmlsbD0iI0Q5MjMyNyIvPgo8cGF0aCBkPSJNNS4zMjgxMiA4LjY2NjAySDMwLjY2MTFWMjUuOTk5SDUuMzI4MTJWOC42NjYwMlpNNy45OTUxMiAxMS4zMzNWMjMuMzMzSDI3Ljk5NTFWMTEuMzMzSDcuOTk1MTJaIiBmaWxsPSIjRDkyMzI3Ii8+CjxwYXRoIGQ9Ik01LjUgMEM0LjA0MTQ3IDAuMDAwNTMwMDg1IDIuNjQyODMgMC41ODAxNjMgMS42MTE1IDEuNjExNUMwLjU4MDE2MyAyLjY0MjgzIDAuMDAwNTMwMDg1IDQuMDQxNDcgMCA1LjVMMCAzMC41QzAgMzMuNTM2IDIuNDY0IDM2IDUuNSAzNkgzMC41QzMzLjUzNiAzNiAzNiAzMy41MzYgMzYgMzAuNVY1LjVDMzYgMi40NjQgMzMuNTM2IDAgMzAuNSAwSDUuNVpNMi42NjcgNS41QzIuNjY3NTMgNC43NDg4IDIuOTY2MTggNC4wMjg1MyAzLjQ5NzM1IDMuNDk3MzVDNC4wMjg1MyAyLjk2NjE4IDQuNzQ4OCAyLjY2NzUzIDUuNSAyLjY2N0gzMC41QzMxLjI1MTIgMi42Njc1MyAzMS45NzE1IDIuOTY2MTggMzIuNTAyNiAzLjQ5NzM1QzMzLjAzMzggNC4wMjg1MyAzMy4zMzI1IDQuNzQ4OCAzMy4zMzMgNS41VjMwLjVDMzMuMzMyNSAzMS4yNTEyIDMzLjAzMzggMzEuOTcxNSAzMi41MDI2IDMyLjUwMjZDMzEuOTcxNSAzMy4wMzM4IDMxLjI1MTIgMzMuMzMyNSAzMC41IDMzLjMzM0g1LjVDNC43NDg4IDMzLjMzMjUgNC4wMjg1MyAzMy4wMzM4IDMuNDk3MzUgMzIuNTAyNkMyLjk2NjE4IDMxLjk3MTUgMi42Njc1MyAzMS4yNTEyIDIuNjY3IDMwLjVWNS41WiIgZmlsbD0iI0Q5MjMyNyIvPgo8cGF0aCBkPSJNNDUgMjAuMjMwN1Y0LjUwMDczSDU2LjcwNFY3Ljc3ODczSDQ4Ljg5NFYxMC45Njg3SDU1LjQyOFYxNC4xMTQ3SDQ4Ljg5NFYyMC4yMzA3SDQ1Wk02Mi41MjYgMTguMDMwN0M2NC4wODggMTguMDMwNyA2NC45MjQgMTYuNjY2NyA2NC45MjQgMTQuNjIwN0M2NC45MjQgMTIuNTc0NyA2NC4wODggMTEuMTg4NyA2Mi41MjYgMTEuMTg4N0M2MC45NjQgMTEuMTg4NyA2MC4xNSAxMi41NzQ3IDYwLjE1IDE0LjYyMDdDNjAuMTUgMTYuNjY2NyA2MC45NjQgMTguMDMwNyA2Mi41MjYgMTguMDMwN1pNNjIuNTQ4IDIwLjU4MjdDNTguOTQgMjAuNTgyNyA1Ni41MiAxOC4wMDg3IDU2LjUyIDE0LjYyMDdDNTYuNTIgMTEuMjMyNyA1OC45NCA4LjY1ODczIDYyLjU0OCA4LjY1ODczQzY2LjE3OCA4LjY1ODczIDY4LjU1NCAxMS4yMzI3IDY4LjU1NCAxNC42MjA3QzY4LjU1NCAxOC4wMDg3IDY2LjE3OCAyMC41ODI3IDYyLjU0OCAyMC41ODI3Wk02OS43NjYgMjAuMjMwN1Y4Ljk2NjczSDczLjE5OFYxMC43MjY3SDczLjI2NEM3NC4wNTYgOS4zODQ3MyA3NC45OCA4Ljc5MDczIDc2LjM0NCA4Ljc5MDczQzc2LjY3NCA4Ljc5MDczIDc2Ljg5NCA4LjgxMjczIDc3LjA0OCA4Ljg3ODczVjExLjk1ODdINzYuOTZDNzQuNzYgMTEuNjUwNyA3My4zNTIgMTIuNzI4NyA3My4zNTIgMTUuMTcwN1YyMC4yMzA3SDY5Ljc2NlpNNzguMTg4IDIwLjIzMDdWOC45NjY3M0g4MS42MlYxMC41NzI3SDgxLjY4NkM4Mi4zOSA5LjQwNjczIDgzLjQ2OCA4LjYzNjczIDg1LjA5NiA4LjYzNjczQzg2LjU3IDguNjM2NzMgODcuNjkyIDkuNDA2NzMgODguMjY0IDEwLjYxNjdIODguMzA4Qzg5LjE4OCA5LjI1MjczIDkwLjM5OCA4LjYzNjczIDkxLjg1IDguNjM2NzNDOTQuNDAyIDguNjM2NzMgOTUuNjc4IDEwLjM3NDcgOTUuNjc4IDEyLjkwNDdWMjAuMjMwN0g5Mi4wOTJWMTMuNTQyN0M5Mi4wOTIgMTIuMzMyNyA5MS41ODYgMTEuNjI4NyA5MC41MDggMTEuNjI4N0M4OS4zNjQgMTEuNjI4NyA4OC43MjYgMTIuNTc0NyA4OC43MjYgMTMuOTE2N1YyMC4yMzA3SDg1LjE0VjEzLjU0MjdDODUuMTQgMTIuMzMyNyA4NC42MzQgMTEuNjI4NyA4My41NTYgMTEuNjI4N0M4Mi40MzQgMTEuNjI4NyA4MS43NzQgMTIuNTc0NyA4MS43NzQgMTMuOTE2N1YyMC4yMzA3SDc4LjE4OFpNMTAyLjEwNSAyMC41ODI3Qzk4LjgwNSAyMC41ODI3IDk2LjczNyAxOS4wNjQ3IDk2LjYyNyAxNi41Nzg3SDEwMC4wMTVDMTAwLjE0NyAxNy43MDA3IDEwMC44OTUgMTguMjUwNyAxMDIuMDgzIDE4LjI1MDdDMTAzLjE2MSAxOC4yNTA3IDEwMy44NDMgMTcuODU0NyAxMDMuODQzIDE3LjEyODdDMTAzLjg0MyAxNi4xMTY3IDEwMi40NzkgMTYuMDA2NyAxMDAuOTgzIDE1Ljc0MjdDOTkuMDI1IDE1LjQxMjcgOTYuOTM1IDE0Ljg4NDcgOTYuOTM1IDEyLjI0NDdDOTYuOTM1IDkuODY4NzMgOTkuMTM1IDguNjM2NzMgMTAxLjc5NyA4LjYzNjczQzEwNC45ODcgOC42MzY3MyAxMDYuNzAzIDEwLjAyMjcgMTA2Ljg3OSAxMi4yNDQ3SDEwMy41NzlDMTAzLjQ0NyAxMS4yMzI3IDEwMi43NjUgMTAuOTI0NyAxMDEuNzc1IDEwLjkyNDdDMTAwLjg5NSAxMC45MjQ3IDEwMC4yMTMgMTEuMjU0NyAxMDAuMjEzIDExLjk1ODdDMTAwLjIxMyAxMi43NTA3IDEwMS40ODkgMTIuODYwNyAxMDIuOTE5IDEzLjEyNDdDMTA0Ljg5OSAxMy40NTQ3IDEwNy4yMzEgMTMuOTYwNyAxMDcuMjMxIDE2Ljg0MjdDMTA3LjIzMSAxOS4zMDY3IDEwNS4wNTMgMjAuNTgyNyAxMDIuMTA1IDIwLjU4MjdaIiBmaWxsPSJibGFjayIvPgo8cGF0aCBkPSJNNDQuOTMyNSAzMy43NVYyNC4yOTU1SDUwLjk4OTNWMjUuNzMxMkg0Ni42NDUyVjI4LjI5NzlINTAuNTczOVYyOS43MzM3SDQ2LjY0NTJWMzMuNzVINDQuOTMyNVpNNjAuODY3OSAyOS4wMjI3QzYwLjg2NzkgMzAuMDQxNCA2MC42NzcxIDMwLjkxMzkgNjAuMjk1NCAzMS42NDAzQzU5LjkxNjkgMzIuMzYzNSA1OS4zOTk4IDMyLjkxNzUgNTguNzQ0MyAzMy4zMDIyQzU4LjA5MTggMzMuNjg2OSA1Ny4zNTE3IDMzLjg3OTMgNTYuNTIzOCAzMy44NzkzQzU1LjY5NTkgMzMuODc5MyA1NC45NTQyIDMzLjY4NjkgNTQuMjk4NiAzMy4zMDIyQzUzLjY0NjIgMzIuOTE0NCA1My4xMjkxIDMyLjM1ODkgNTIuNzQ3NSAzMS42MzU3QzUyLjM2ODkgMzAuOTA5MyA1Mi4xNzk3IDMwLjAzODQgNTIuMTc5NyAyOS4wMjI3QzUyLjE3OTcgMjguMDA0IDUyLjM2ODkgMjcuMTMzIDUyLjc0NzUgMjYuNDA5OEM1My4xMjkxIDI1LjY4MzUgNTMuNjQ2MiAyNS4xMjggNTQuMjk4NiAyNC43NDMzQzU0Ljk1NDIgMjQuMzU4NSA1NS42OTU5IDI0LjE2NjIgNTYuNTIzOCAyNC4xNjYyQzU3LjM1MTcgMjQuMTY2MiA1OC4wOTE4IDI0LjM1ODUgNTguNzQ0MyAyNC43NDMzQzU5LjM5OTggMjUuMTI4IDU5LjkxNjkgMjUuNjgzNSA2MC4yOTU0IDI2LjQwOThDNjAuNjc3MSAyNy4xMzMgNjAuODY3OSAyOC4wMDQgNjAuODY3OSAyOS4wMjI3Wk01OS4xNDU5IDI5LjAyMjdDNTkuMTQ1OSAyOC4zMDU2IDU5LjAzMzYgMjcuNzAwOSA1OC44MDg5IDI3LjIwODVDNTguNTg3MyAyNi43MTI5IDU4LjI3OTYgMjYuMzM5IDU3Ljg4NTYgMjYuMDg2NkM1Ny40OTE3IDI1LjgzMTIgNTcuMDM3NyAyNS43MDM1IDU2LjUyMzggMjUuNzAzNUM1Ni4wMDk4IDI1LjcwMzUgNTUuNTU1OCAyNS44MzEyIDU1LjE2MTkgMjYuMDg2NkM1NC43NjggMjYuMzM5IDU0LjQ1ODcgMjYuNzEyOSA1NC4yMzQgMjcuMjA4NUM1NC4wMTI0IDI3LjcwMDkgNTMuOTAxNiAyOC4zMDU2IDUzLjkwMTYgMjkuMDIyN0M1My45MDE2IDI5LjczOTggNTQuMDEyNCAzMC4zNDYxIDU0LjIzNCAzMC44NDE2QzU0LjQ1ODcgMzEuMzM0IDU0Ljc2OCAzMS43MDggNTUuMTYxOSAzMS45NjM0QzU1LjU1NTggMzIuMjE1OCA1Ni4wMDk4IDMyLjM0MiA1Ni41MjM4IDMyLjM0MkM1Ny4wMzc3IDMyLjM0MiA1Ny40OTE3IDMyLjIxNTggNTcuODg1NiAzMS45NjM0QzU4LjI3OTYgMzEuNzA4IDU4LjU4NzMgMzEuMzM0IDU4LjgwODkgMzAuODQxNkM1OS4wMzM2IDMwLjM0NjEgNTkuMTQ1OSAyOS43Mzk4IDU5LjE0NTkgMjkuMDIyN1pNNjIuMzU3MSAzMy43NVYyNC4yOTU1SDY1LjkwMjZDNjYuNjI4OSAyNC4yOTU1IDY3LjIzODMgMjQuNDIxNiA2Ny43MzA3IDI0LjY3NEM2OC4yMjYyIDI0LjkyNjQgNjguNjAwMSAyNS4yODAzIDY4Ljg1MjUgMjUuNzM1OEM2OS4xMDc5IDI2LjE4ODIgNjkuMjM1NyAyNi43MTYgNjkuMjM1NyAyNy4zMTkyQzY5LjIzNTcgMjcuOTI1NSA2OS4xMDY0IDI4LjQ1MTggNjguODQ3OSAyOC44OTgxQzY4LjU5MjQgMjkuMzQxMyA2OC4yMTU0IDI5LjY4NDQgNjcuNzE2OCAyOS45Mjc2QzY3LjIxODIgMzAuMTY3NiA2Ni42MDU4IDMwLjI4NzYgNjUuODc5NSAzMC4yODc2SDYzLjM1NDNWMjguODY1OEg2NS42NDg2QzY2LjA3MzQgMjguODY1OCA2Ni40MjExIDI4LjgwNzMgNjYuNjkyIDI4LjY5MDNDNjYuOTYyOCAyOC41NzAzIDY3LjE2MjkgMjguMzk2NCA2Ny4yOTIxIDI4LjE2ODdDNjcuNDI0NSAyNy45Mzc5IDY3LjQ5MDYgMjcuNjU0NyA2Ny40OTA2IDI3LjMxOTJDNjcuNDkwNiAyNi45ODM4IDY3LjQyNDUgMjYuNjk3NiA2Ny4yOTIxIDI2LjQ2MDZDNjcuMTU5OCAyNi4yMjA1IDY2Ljk1ODIgMjYuMDM4OSA2Ni42ODc0IDI1LjkxNThDNjYuNDE2NSAyNS43ODk3IDY2LjA2NzIgMjUuNzI2NiA2NS42Mzk0IDI1LjcyNjZINjQuMDY5OFYzMy43NUg2Mi4zNTcxWk02Ny4yNDEzIDI5LjQ2NTlMNjkuNTgxOSAzMy43NUg2Ny42NzA3TDY1LjM3MTcgMjkuNDY1OUg2Ny4yNDEzWk03MC42ODIyIDI0LjI5NTVINzIuNzc4MUw3NS41ODQ5IDMxLjE0NjNINzUuNjk1N0w3OC41MDI1IDI0LjI5NTVIODAuNTk4NFYzMy43NUg3OC45NTQ5VjI3LjI1NDZINzguODY3Mkw3Ni4yNTQzIDMzLjcyMjNINzUuMDI2M0w3Mi40MTM0IDI3LjI0MDhINzIuMzI1NlYzMy43NUg3MC42ODIyVjI0LjI5NTVaTTg1LjQyOCAzMy43NVYyNC4yOTU1SDg5LjA0NzRDODkuNzMwNiAyNC4yOTU1IDkwLjI5ODQgMjQuNDAzMiA5MC43NTA4IDI0LjYxODZDOTEuMjA2MyAyNC44MzEgOTEuNTQ2NCAyNS4xMjE4IDkxLjc3MTEgMjUuNDkxMUM5MS45OTg4IDI1Ljg2MDQgOTIuMTEyNyAyNi4yNzkgOTIuMTEyNyAyNi43NDY4QzkyLjExMjcgMjcuMTMxNSA5Mi4wMzg4IDI3LjQ2MDggOTEuODkxMSAyNy43MzQ3QzkxLjc0MzQgMjguMDA1NiA5MS41NDQ5IDI4LjIyNTYgOTEuMjk1NiAyOC4zOTQ5QzkxLjA0NjMgMjguNTY0MiA5MC43Njc4IDI4LjY4NTcgOTAuNDYgMjguNzU5NlYyOC44NTE5QzkwLjc5NTUgMjguODcwNCA5MS4xMTcxIDI4Ljk3MzUgOTEuNDI0OCAyOS4xNjEyQzkxLjczNTcgMjkuMzQ1OSA5MS45ODk2IDI5LjYwNzUgOTIuMTg2NiAyOS45NDZDOTIuMzgzNSAzMC4yODQ2IDkyLjQ4MiAzMC42OTM5IDkyLjQ4MiAzMS4xNzRDOTIuNDgyIDMxLjY2MzQgOTIuMzYzNSAzMi4xMDM1IDkyLjEyNjUgMzIuNDk0M0M5MS44ODk2IDMyLjg4MjEgOTEuNTMyNiAzMy4xODgzIDkxLjA1NTUgMzMuNDEzQzkwLjU3ODUgMzMuNjM3NyA4OS45NzgzIDMzLjc1IDg5LjI1NTEgMzMuNzVIODUuNDI4Wk04Ny4xNDA3IDMyLjMxODlIODguOTgyN0M4OS42MDQ0IDMyLjMxODkgOTAuMDUyMiAzMi4yMDA0IDkwLjMyNjEgMzEuOTYzNEM5MC42MDMxIDMxLjcyMzQgOTAuNzQxNiAzMS40MTU2IDkwLjc0MTYgMzEuMDQwMUM5MC43NDE2IDMwLjc2MDEgOTAuNjcyNCAzMC41MDc3IDkwLjUzMzkgMzAuMjgzQzkwLjM5NTQgMzAuMDU1MyA5MC4xOTg0IDI5Ljg3NjggODkuOTQyOSAyOS43NDc1Qzg5LjY4NzUgMjkuNjE1MiA4OS4zODI4IDI5LjU0OSA4OS4wMjg5IDI5LjU0OUg4Ny4xNDA3VjMyLjMxODlaTTg3LjE0MDcgMjguMzE2NEg4OC44MzVDODkuMTMwNCAyOC4zMTY0IDg5LjM5NjcgMjguMjYyNSA4OS42MzM2IDI4LjE1NDhDODkuODcwNiAyOC4wNDQgOTAuMDU2OCAyNy44ODg2IDkwLjE5MjIgMjcuNjg4NkM5MC4zMzA3IDI3LjQ4NTQgOTAuNCAyNy4yNDU0IDkwLjQgMjYuOTY4NEM5MC40IDI2LjYwMjIgOTAuMjcwNyAyNi4zMDA1IDkwLjAxMjIgMjYuMDYzNkM4OS43NTY4IDI1LjgyNjYgODkuMzc2NyAyNS43MDgxIDg4Ljg3MTkgMjUuNzA4MUg4Ny4xNDA3VjI4LjMxNjRaTTk5LjgwMTkgMjQuMjk1NUgxMDEuNTE1VjMwLjQ3MjNDMTAxLjUxNSAzMS4xNDk0IDEwMS4zNTUgMzEuNzQ0OSAxMDEuMDM0IDMyLjI1ODlDMTAwLjcxNyAzMi43NzI4IDEwMC4yNzEgMzMuMTc0NSA5OS42OTU3IDMzLjQ2MzhDOTkuMTIwMiAzMy43NSA5OC40NDc3IDMzLjg5MzEgOTcuNjc4MyAzMy44OTMxQzk2LjkwNTggMzMuODkzMSA5Ni4yMzE4IDMzLjc1IDk1LjY1NjMgMzMuNDYzOEM5NS4wODA3IDMzLjE3NDUgOTQuNjM0NSAzMi43NzI4IDk0LjMxNzUgMzIuMjU4OUM5NC4wMDA1IDMxLjc0NDkgOTMuODQyIDMxLjE0OTQgOTMuODQyIDMwLjQ3MjNWMjQuMjk1NUg5NS41NTQ3VjMwLjMyOTJDOTUuNTU0NyAzMC43MjMxIDk1LjY0MDkgMzEuMDc0IDk1LjgxMzIgMzEuMzgxN0M5NS45ODg2IDMxLjY4OTUgOTYuMjM0OSAzMS45MzExIDk2LjU1MTkgMzIuMTA2NUM5Ni44Njg5IDMyLjI3ODkgOTcuMjQ0MyAzMi4zNjUxIDk3LjY3ODMgMzIuMzY1MUM5OC4xMTIyIDMyLjM2NTEgOTguNDg3NyAzMi4yNzg5IDk4LjgwNDcgMzIuMTA2NUM5OS4xMjQ4IDMxLjkzMTEgOTkuMzcxIDMxLjY4OTUgOTkuNTQzMyAzMS4zODE3Qzk5LjcxNTcgMzEuMDc0IDk5LjgwMTkgMzAuNzIzMSA5OS44MDE5IDMwLjMyOTJWMjQuMjk1NVpNMTA0Ljk1OSAyNC4yOTU1VjMzLjc1SDEwMy4yNDZWMjQuMjk1NUgxMDQuOTU5Wk0xMDYuNjg0IDMzLjc1VjI0LjI5NTVIMTA4LjM5NlYzMi4zMTQzSDExMi41NlYzMy43NUgxMDYuNjg0Wk0xMTcuMTIxIDMzLjc1SDExMy45MTdWMjQuMjk1NUgxMTcuMTg1QzExOC4xMjQgMjQuMjk1NSAxMTguOTMgMjQuNDg0NyAxMTkuNjA0IDI0Ljg2MzNDMTIwLjI4MSAyNS4yMzg4IDEyMC44MDIgMjUuNzc4OSAxMjEuMTY1IDI2LjQ4MzdDMTIxLjUyOCAyNy4xODg0IDEyMS43MDkgMjguMDMxNyAxMjEuNzA5IDI5LjAxMzVDMTIxLjcwOSAyOS45OTgzIDEyMS41MjYgMzAuODQ0NyAxMjEuMTYgMzEuNTUyNkMxMjAuNzk3IDMyLjI2MDQgMTIwLjI3MiAzMi44MDM2IDExOS41ODYgMzMuMTgyMkMxMTguOTAzIDMzLjU2MDcgMTE4LjA4MSAzMy43NSAxMTcuMTIxIDMzLjc1Wk0xMTUuNjMgMzIuMjY4MUgxMTcuMDM4QzExNy42OTYgMzIuMjY4MSAxMTguMjQ2IDMyLjE0ODEgMTE4LjY4NiAzMS45MDhDMTE5LjEyNiAzMS42NjQ5IDExOS40NTcgMzEuMzAzMyAxMTkuNjc4IDMwLjgyMzJDMTE5LjkgMzAuMzQgMTIwLjAxMSAyOS43MzY3IDEyMC4wMTEgMjkuMDEzNUMxMjAuMDExIDI4LjI5MDIgMTE5LjkgMjcuNjkwMSAxMTkuNjc4IDI3LjIxMzFDMTE5LjQ1NyAyNi43MzMgMTE5LjEyOSAyNi4zNzQ0IDExOC42OTUgMjYuMTM3NEMxMTguMjY0IDI1Ljg5NzQgMTE3LjcyOCAyNS43NzczIDExNy4wODggMjUuNzc3M0gxMTUuNjNWMzIuMjY4MVpNMTIzLjIwNyAzMy43NVYyNC4yOTU1SDEyOS4zNTZWMjUuNzMxMkgxMjQuOTE5VjI4LjI5NzlIMTI5LjAzN1YyOS43MzM3SDEyNC45MTlWMzIuMzE0M0gxMjkuMzkzVjMzLjc1SDEyMy4yMDdaTTEzMC45NzMgMzMuNzVWMjQuMjk1NUgxMzQuNTE5QzEzNS4yNDUgMjQuMjk1NSAxMzUuODU0IDI0LjQyMTYgMTM2LjM0NyAyNC42NzRDMTM2Ljg0MiAyNC45MjY0IDEzNy4yMTYgMjUuMjgwMyAxMzcuNDY5IDI1LjczNThDMTM3LjcyNCAyNi4xODgyIDEzNy44NTIgMjYuNzE2IDEzNy44NTIgMjcuMzE5MkMxMzcuODUyIDI3LjkyNTUgMTM3LjcyMyAyOC40NTE4IDEzNy40NjQgMjguODk4MUMxMzcuMjA5IDI5LjM0MTMgMTM2LjgzMiAyOS42ODQ0IDEzNi4zMzMgMjkuOTI3NkMxMzUuODM0IDMwLjE2NzYgMTM1LjIyMiAzMC4yODc2IDEzNC40OTYgMzAuMjg3NkgxMzEuOTdWMjguODY1OEgxMzQuMjY1QzEzNC42ODkgMjguODY1OCAxMzUuMDM3IDI4LjgwNzMgMTM1LjMwOCAyOC42OTAzQzEzNS41NzkgMjguNTcwMyAxMzUuNzc5IDI4LjM5NjQgMTM1LjkwOCAyOC4xNjg3QzEzNi4wNDEgMjcuOTM3OSAxMzYuMTA3IDI3LjY1NDcgMTM2LjEwNyAyNy4zMTkyQzEzNi4xMDcgMjYuOTgzOCAxMzYuMDQxIDI2LjY5NzYgMTM1LjkwOCAyNi40NjA2QzEzNS43NzYgMjYuMjIwNSAxMzUuNTc0IDI2LjAzODkgMTM1LjMwMyAyNS45MTU4QzEzNS4wMzMgMjUuNzg5NyAxMzQuNjgzIDI1LjcyNjYgMTM0LjI1NiAyNS43MjY2SDEzMi42ODZWMzMuNzVIMTMwLjk3M1pNMTM1Ljg1NyAyOS40NjU5TDEzOC4xOTggMzMuNzVIMTM2LjI4N0wxMzMuOTg4IDI5LjQ2NTlIMTM1Ljg1N1oiIGZpbGw9IiM4NDg3OTQiLz4KPC9zdmc+Cg=='); background-repeat: no-repeat; display: block; inline-size: 208px; @@ -54,3 +59,15 @@ background-position: center left; } } + +.post-type-eightshift-forms-res { + h1 { + span[data-rich-text-placeholder]::after { + content: 'Result output name'; + } + } + + .edit-post-header-toolbar::after { + background-image: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjA4IiBoZWlnaHQ9IjM2IiB2aWV3Qm94PSIwIDAgMjA4IDM2IiBmaWxsPSJub25lIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgo8cGF0aCBkPSJNMTQuNjY3MSAxNS4zMzNIMTUuOTk3MVYxMi42NjZIMTAuNjY0MVYxNS4zMzNIMTIuMDAwMVYxOS4zMzJIMTAuNjY0MVYyMS45OTlIMTUuOTk3MVYxOS4zMzJIMTQuNjY3MVYxNS4zMzJWMTUuMzMzWiIgZmlsbD0iI0Q5MjMyNyIvPgo8cGF0aCBkPSJNNS4zMjgxMiA4LjY2NjAySDMwLjY2MTFWMjUuOTk5SDUuMzI4MTJWOC42NjYwMlpNNy45OTUxMiAxMS4zMzNWMjMuMzMzSDI3Ljk5NTFWMTEuMzMzSDcuOTk1MTJaIiBmaWxsPSIjRDkyMzI3Ii8+CjxwYXRoIGQ9Ik01LjUgMEM0LjA0MTQ3IDAuMDAwNTMwMDg1IDIuNjQyODMgMC41ODAxNjMgMS42MTE1IDEuNjExNUMwLjU4MDE2MyAyLjY0MjgzIDAuMDAwNTMwMDg1IDQuMDQxNDcgMCA1LjVMMCAzMC41QzAgMzMuNTM2IDIuNDY0IDM2IDUuNSAzNkgzMC41QzMzLjUzNiAzNiAzNiAzMy41MzYgMzYgMzAuNVY1LjVDMzYgMi40NjQgMzMuNTM2IDAgMzAuNSAwSDUuNVpNMi42NjcgNS41QzIuNjY3NTMgNC43NDg4IDIuOTY2MTggNC4wMjg1MyAzLjQ5NzM1IDMuNDk3MzVDNC4wMjg1MyAyLjk2NjE4IDQuNzQ4OCAyLjY2NzUzIDUuNSAyLjY2N0gzMC41QzMxLjI1MTIgMi42Njc1MyAzMS45NzE1IDIuOTY2MTggMzIuNTAyNiAzLjQ5NzM1QzMzLjAzMzggNC4wMjg1MyAzMy4zMzI1IDQuNzQ4OCAzMy4zMzMgNS41VjMwLjVDMzMuMzMyNSAzMS4yNTEyIDMzLjAzMzggMzEuOTcxNSAzMi41MDI2IDMyLjUwMjZDMzEuOTcxNSAzMy4wMzM4IDMxLjI1MTIgMzMuMzMyNSAzMC41IDMzLjMzM0g1LjVDNC43NDg4IDMzLjMzMjUgNC4wMjg1MyAzMy4wMzM4IDMuNDk3MzUgMzIuNTAyNkMyLjk2NjE4IDMxLjk3MTUgMi42Njc1MyAzMS4yNTEyIDIuNjY3IDMwLjVWNS41WiIgZmlsbD0iI0Q5MjMyNyIvPgo8cGF0aCBkPSJNNDUgMjAuMjMwN1Y0LjUwMDczSDU2LjcwNFY3Ljc3ODczSDQ4Ljg5NFYxMC45Njg3SDU1LjQyOFYxNC4xMTQ3SDQ4Ljg5NFYyMC4yMzA3SDQ1Wk02Mi41MjYgMTguMDMwN0M2NC4wODggMTguMDMwNyA2NC45MjQgMTYuNjY2NyA2NC45MjQgMTQuNjIwN0M2NC45MjQgMTIuNTc0NyA2NC4wODggMTEuMTg4NyA2Mi41MjYgMTEuMTg4N0M2MC45NjQgMTEuMTg4NyA2MC4xNSAxMi41NzQ3IDYwLjE1IDE0LjYyMDdDNjAuMTUgMTYuNjY2NyA2MC45NjQgMTguMDMwNyA2Mi41MjYgMTguMDMwN1pNNjIuNTQ4IDIwLjU4MjdDNTguOTQgMjAuNTgyNyA1Ni41MiAxOC4wMDg3IDU2LjUyIDE0LjYyMDdDNTYuNTIgMTEuMjMyNyA1OC45NCA4LjY1ODczIDYyLjU0OCA4LjY1ODczQzY2LjE3OCA4LjY1ODczIDY4LjU1NCAxMS4yMzI3IDY4LjU1NCAxNC42MjA3QzY4LjU1NCAxOC4wMDg3IDY2LjE3OCAyMC41ODI3IDYyLjU0OCAyMC41ODI3Wk02OS43NjYgMjAuMjMwN1Y4Ljk2NjczSDczLjE5OFYxMC43MjY3SDczLjI2NEM3NC4wNTYgOS4zODQ3MyA3NC45OCA4Ljc5MDczIDc2LjM0NCA4Ljc5MDczQzc2LjY3NCA4Ljc5MDczIDc2Ljg5NCA4LjgxMjczIDc3LjA0OCA4Ljg3ODczVjExLjk1ODdINzYuOTZDNzQuNzYgMTEuNjUwNyA3My4zNTIgMTIuNzI4NyA3My4zNTIgMTUuMTcwN1YyMC4yMzA3SDY5Ljc2NlpNNzguMTg4IDIwLjIzMDdWOC45NjY3M0g4MS42MlYxMC41NzI3SDgxLjY4NkM4Mi4zOSA5LjQwNjczIDgzLjQ2OCA4LjYzNjczIDg1LjA5NiA4LjYzNjczQzg2LjU3IDguNjM2NzMgODcuNjkyIDkuNDA2NzMgODguMjY0IDEwLjYxNjdIODguMzA4Qzg5LjE4OCA5LjI1MjczIDkwLjM5OCA4LjYzNjczIDkxLjg1IDguNjM2NzNDOTQuNDAyIDguNjM2NzMgOTUuNjc4IDEwLjM3NDcgOTUuNjc4IDEyLjkwNDdWMjAuMjMwN0g5Mi4wOTJWMTMuNTQyN0M5Mi4wOTIgMTIuMzMyNyA5MS41ODYgMTEuNjI4NyA5MC41MDggMTEuNjI4N0M4OS4zNjQgMTEuNjI4NyA4OC43MjYgMTIuNTc0NyA4OC43MjYgMTMuOTE2N1YyMC4yMzA3SDg1LjE0VjEzLjU0MjdDODUuMTQgMTIuMzMyNyA4NC42MzQgMTEuNjI4NyA4My41NTYgMTEuNjI4N0M4Mi40MzQgMTEuNjI4NyA4MS43NzQgMTIuNTc0NyA4MS43NzQgMTMuOTE2N1YyMC4yMzA3SDc4LjE4OFpNMTAyLjEwNSAyMC41ODI3Qzk4LjgwNSAyMC41ODI3IDk2LjczNyAxOS4wNjQ3IDk2LjYyNyAxNi41Nzg3SDEwMC4wMTVDMTAwLjE0NyAxNy43MDA3IDEwMC44OTUgMTguMjUwNyAxMDIuMDgzIDE4LjI1MDdDMTAzLjE2MSAxOC4yNTA3IDEwMy44NDMgMTcuODU0NyAxMDMuODQzIDE3LjEyODdDMTAzLjg0MyAxNi4xMTY3IDEwMi40NzkgMTYuMDA2NyAxMDAuOTgzIDE1Ljc0MjdDOTkuMDI1IDE1LjQxMjcgOTYuOTM1IDE0Ljg4NDcgOTYuOTM1IDEyLjI0NDdDOTYuOTM1IDkuODY4NzMgOTkuMTM1IDguNjM2NzMgMTAxLjc5NyA4LjYzNjczQzEwNC45ODcgOC42MzY3MyAxMDYuNzAzIDEwLjAyMjcgMTA2Ljg3OSAxMi4yNDQ3SDEwMy41NzlDMTAzLjQ0NyAxMS4yMzI3IDEwMi43NjUgMTAuOTI0NyAxMDEuNzc1IDEwLjkyNDdDMTAwLjg5NSAxMC45MjQ3IDEwMC4yMTMgMTEuMjU0NyAxMDAuMjEzIDExLjk1ODdDMTAwLjIxMyAxMi43NTA3IDEwMS40ODkgMTIuODYwNyAxMDIuOTE5IDEzLjEyNDdDMTA0Ljg5OSAxMy40NTQ3IDEwNy4yMzEgMTMuOTYwNyAxMDcuMjMxIDE2Ljg0MjdDMTA3LjIzMSAxOS4zMDY3IDEwNS4wNTMgMjAuNTgyNyAxMDIuMTA1IDIwLjU4MjdaIiBmaWxsPSJibGFjayIvPgo8cGF0aCBkPSJNNDQuOTMyNSAzMy43NVYyNC4yOTU1SDQ4LjQ3OEM0OS4yMDQzIDI0LjI5NTUgNDkuODEzNyAyNC40MjE2IDUwLjMwNjEgMjQuNjc0QzUwLjgwMTYgMjQuOTI2NCA1MS4xNzU1IDI1LjI4MDMgNTEuNDI3OSAyNS43MzU4QzUxLjY4MzQgMjYuMTg4MiA1MS44MTExIDI2LjcxNiA1MS44MTExIDI3LjMxOTJDNTEuODExMSAyNy45MjU1IDUxLjY4MTggMjguNDUxOCA1MS40MjMzIDI4Ljg5ODFDNTEuMTY3OSAyOS4zNDEzIDUwLjc5MDggMjkuNjg0NCA1MC4yOTIzIDI5LjkyNzZDNDkuNzkzNyAzMC4xNjc2IDQ5LjE4MTIgMzAuMjg3NiA0OC40NTQ5IDMwLjI4NzZINDUuOTI5N1YyOC44NjU4SDQ4LjIyNDFDNDguNjQ4OCAyOC44NjU4IDQ4Ljk5NjYgMjguODA3MyA0OS4yNjc0IDI4LjY5MDNDNDkuNTM4MiAyOC41NzAzIDQ5LjczODMgMjguMzk2NCA0OS44Njc1IDI4LjE2ODdDNDkuOTk5OSAyNy45Mzc5IDUwLjA2NjEgMjcuNjU0NyA1MC4wNjYxIDI3LjMxOTJDNTAuMDY2MSAyNi45ODM4IDQ5Ljk5OTkgMjYuNjk3NiA0OS44Njc1IDI2LjQ2MDZDNDkuNzM1MiAyNi4yMjA1IDQ5LjUzMzYgMjYuMDM4OSA0OS4yNjI4IDI1LjkxNThDNDguOTkyIDI1Ljc4OTcgNDguNjQyNiAyNS43MjY2IDQ4LjIxNDggMjUuNzI2Nkg0Ni42NDUyVjMzLjc1SDQ0LjkzMjVaTTQ5LjgxNjggMjkuNDY1OUw1Mi4xNTczIDMzLjc1SDUwLjI0NjFMNDcuOTQ3MSAyOS40NjU5SDQ5LjgxNjhaTTUzLjI1NzYgMzMuNzVWMjQuMjk1NUg1OS40MDY4VjI1LjczMTJINTQuOTcwM1YyOC4yOTc5SDU5LjA4ODJWMjkuNzMzN0g1NC45NzAzVjMyLjMxNDNINTkuNDQzN1YzMy43NUg1My4yNTc2Wk02Ni4xNjIyIDI2Ljg5NDVDNjYuMTE5MSAyNi40OTE0IDY1LjkzNzYgMjYuMTc3NCA2NS42MTc1IDI1Ljk1MjhDNjUuMzAwNSAyNS43MjgxIDY0Ljg4ODEgMjUuNjE1OCA2NC4zODAzIDI1LjYxNThDNjQuMDIzMyAyNS42MTU4IDYzLjcxNyAyNS42Njk2IDYzLjQ2MTYgMjUuNzc3M0M2My4yMDYxIDI1Ljg4NTEgNjMuMDEwNyAyNi4wMzEyIDYyLjg3NTMgMjYuMjE1OUM2Mi43Mzk5IDI2LjQwMDYgNjIuNjcwNiAyNi42MTE0IDYyLjY2NzYgMjYuODQ4NEM2Mi42Njc2IDI3LjA0NTMgNjIuNzEyMiAyNy4yMTYxIDYyLjgwMTQgMjcuMzYwOEM2Mi44OTM4IDI3LjUwNTQgNjMuMDE4NCAyNy42Mjg2IDYzLjE3NTQgMjcuNzMwMUM2My4zMzIzIDI3LjgyODYgNjMuNTA2MiAyNy45MTE3IDYzLjY5NyAyNy45Nzk0QzYzLjg4NzggMjguMDQ3MSA2NC4wODAyIDI4LjEwNCA2NC4yNzQxIDI4LjE1MDJMNjUuMTYwNSAyOC4zNzE4QzY1LjUxNzUgMjguNDU0OSA2NS44NjA2IDI4LjU2NzIgNjYuMTg5OSAyOC43MDg4QzY2LjUyMjMgMjguODUwNCA2Ni44MTkzIDI5LjAyODkgNjcuMDgwOSAyOS4yNDQzQzY3LjM0NTYgMjkuNDU5OCA2Ny41NTQ5IDI5LjcxOTggNjcuNzA4NyAzMC4wMjQ1QzY3Ljg2MjYgMzAuMzI5MiA2Ny45Mzk2IDMwLjY4NjIgNjcuOTM5NiAzMS4wOTU1QzY3LjkzOTYgMzEuNjQ5NSA2Ny43OTggMzIuMTM3MyA2Ny41MTQ5IDMyLjU1ODlDNjcuMjMxNyAzMi45Nzc1IDY2LjgyMjQgMzMuMzA1MyA2Ni4yODY5IDMzLjU0MjNDNjUuNzU0NCAzMy43NzYyIDY1LjEwOTcgMzMuODkzMSA2NC4zNTI2IDMzLjg5MzFDNjMuNjE3IDMzLjg5MzEgNjIuOTc4NCAzMy43NzkyIDYyLjQzNjcgMzMuNTUxNUM2MS44OTgxIDMzLjMyMzcgNjEuNDc2NSAzMi45OTE0IDYxLjE3MTggMzIuNTU0M0M2MC44NzAyIDMyLjExNzMgNjAuNzA3MSAzMS41ODQ5IDYwLjY4MjUgMzAuOTU3SDYyLjM2NzVDNjIuMzkyMSAzMS4yODYzIDYyLjQ5MzcgMzEuNTYwMyA2Mi42NzIyIDMxLjc3ODhDNjIuODUwNyAzMS45OTczIDYzLjA4MyAzMi4xNjA0IDYzLjM2OTMgMzIuMjY4MUM2My42NTg2IDMyLjM3NTggNjMuOTgxNyAzMi40Mjk3IDY0LjMzODcgMzIuNDI5N0M2NC43MTExIDMyLjQyOTcgNjUuMDM3MyAzMi4zNzQzIDY1LjMxNzQgMzIuMjYzNUM2NS42MDA2IDMyLjE0OTYgNjUuODIyMSAzMS45OTI3IDY1Ljk4MjIgMzEuNzkyNkM2Ni4xNDIyIDMxLjU4OTUgNjYuMjIzOCAzMS4zNTI1IDY2LjIyNjkgMzEuMDgxN0M2Ni4yMjM4IDMwLjgzNTUgNjYuMTUxNSAzMC42MzIzIDY2LjAwOTkgMzAuNDcyM0M2NS44NjgzIDMwLjMwOTIgNjUuNjY5OCAzMC4xNzM4IDY1LjQxNDQgMzAuMDY2MUM2NS4xNjIgMjkuOTU1MyA2NC44NjY1IDI5Ljg1NjggNjQuNTI4IDI5Ljc3MDZMNjMuNDUyNCAyOS40OTM2QzYyLjY3MzcgMjkuMjkzNiA2Mi4wNTgyIDI4Ljk5MDQgNjEuNjA1OCAyOC41ODQyQzYxLjE1NjQgMjguMTc0OCA2MC45MzE4IDI3LjYzMTYgNjAuOTMxOCAyNi45NTQ1QzYwLjkzMTggMjYuMzk3NSA2MS4wODI2IDI1LjkwOTcgNjEuMzg0MiAyNS40OTExQzYxLjY4ODkgMjUuMDcyNiA2Mi4xMDI4IDI0Ljc0NzkgNjIuNjI2IDI0LjUxN0M2My4xNDkyIDI0LjI4MzEgNjMuNzQxNyAyNC4xNjYyIDY0LjQwMzQgMjQuMTY2MkM2NS4wNzQzIDI0LjE2NjIgNjUuNjYyMSAyNC4yODMxIDY2LjE2NjggMjQuNTE3QzY2LjY3NDcgMjQuNzQ3OSA2Ny4wNzMyIDI1LjA2OTUgNjcuMzYyNSAyNS40ODE5QzY3LjY1MTggMjUuODkxMiA2Ny44MDExIDI2LjM2MjEgNjcuODEwMyAyNi44OTQ1SDY2LjE2MjJaTTc1LjI5NjMgMjQuMjk1NUg3Ny4wMDkxVjMwLjQ3MjNDNzcuMDA5MSAzMS4xNDk0IDc2Ljg0OSAzMS43NDQ5IDc2LjUyODkgMzIuMjU4OUM3Ni4yMTE5IDMyLjc3MjggNzUuNzY1NyAzMy4xNzQ1IDc1LjE5MDIgMzMuNDYzOEM3NC42MTQ2IDMzLjc1IDczLjk0MjIgMzMuODkzMSA3My4xNzI4IDMzLjg5MzFDNzIuNDAwMyAzMy44OTMxIDcxLjcyNjMgMzMuNzUgNzEuMTUwOCAzMy40NjM4QzcwLjU3NTIgMzMuMTc0NSA3MC4xMjkgMzIuNzcyOCA2OS44MTIgMzIuMjU4OUM2OS40OTUgMzEuNzQ0OSA2OS4zMzY1IDMxLjE0OTQgNjkuMzM2NSAzMC40NzIzVjI0LjI5NTVINzEuMDQ5MlYzMC4zMjkyQzcxLjA0OTIgMzAuNzIzMSA3MS4xMzU0IDMxLjA3NCA3MS4zMDc3IDMxLjM4MTdDNzEuNDgzMSAzMS42ODk1IDcxLjcyOTMgMzEuOTMxMSA3Mi4wNDYzIDMyLjEwNjVDNzIuMzYzMyAzMi4yNzg5IDcyLjczODggMzIuMzY1MSA3My4xNzI4IDMyLjM2NTFDNzMuNjA2NyAzMi4zNjUxIDczLjk4MjIgMzIuMjc4OSA3NC4yOTkyIDMyLjEwNjVDNzQuNjE5MyAzMS45MzExIDc0Ljg2NTUgMzEuNjg5NSA3NS4wMzc4IDMxLjM4MTdDNzUuMjEwMiAzMS4wNzQgNzUuMjk2MyAzMC43MjMxIDc1LjI5NjMgMzAuMzI5MlYyNC4yOTU1Wk03OC43NDA3IDMzLjc1VjI0LjI5NTVIODAuNDUzNFYzMi4zMTQzSDg0LjYxNzRWMzMuNzVINzguNzQwN1pNODQuMzUyNCAyNS43MzEyVjI0LjI5NTVIOTEuODk1N1YyNS43MzEySDg4Ljk3MzVWMzMuNzVIODcuMjc0NlYyNS43MzEySDg0LjM1MjRaTTEwNC43NjMgMjkuMDIyN0MxMDQuNzYzIDMwLjA0MTQgMTA0LjU3MiAzMC45MTM5IDEwNC4xOSAzMS42NDAzQzEwMy44MTIgMzIuMzYzNSAxMDMuMjk1IDMyLjkxNzUgMTAyLjYzOSAzMy4zMDIyQzEwMS45ODcgMzMuNjg2OSAxMDEuMjQ2IDMzLjg3OTMgMTAwLjQxOSAzMy44NzkzQzk5LjU5MDcgMzMuODc5MyA5OC44NDkgMzMuNjg2OSA5OC4xOTM0IDMzLjMwMjJDOTcuNTQxIDMyLjkxNDQgOTcuMDIzOSAzMi4zNTg5IDk2LjY0MjMgMzEuNjM1N0M5Ni4yNjM3IDMwLjkwOTMgOTYuMDc0NSAzMC4wMzg0IDk2LjA3NDUgMjkuMDIyN0M5Ni4wNzQ1IDI4LjAwNCA5Ni4yNjM3IDI3LjEzMyA5Ni42NDIzIDI2LjQwOThDOTcuMDIzOSAyNS42ODM1IDk3LjU0MSAyNS4xMjggOTguMTkzNCAyNC43NDMzQzk4Ljg0OSAyNC4zNTg1IDk5LjU5MDcgMjQuMTY2MiAxMDAuNDE5IDI0LjE2NjJDMTAxLjI0NiAyNC4xNjYyIDEwMS45ODcgMjQuMzU4NSAxMDIuNjM5IDI0Ljc0MzNDMTAzLjI5NSAyNS4xMjggMTAzLjgxMiAyNS42ODM1IDEwNC4xOSAyNi40MDk4QzEwNC41NzIgMjcuMTMzIDEwNC43NjMgMjguMDA0IDEwNC43NjMgMjkuMDIyN1pNMTAzLjA0MSAyOS4wMjI3QzEwMy4wNDEgMjguMzA1NiAxMDIuOTI4IDI3LjcwMDkgMTAyLjcwNCAyNy4yMDg1QzEwMi40ODIgMjYuNzEyOSAxMDIuMTc0IDI2LjMzOSAxMDEuNzggMjYuMDg2NkMxMDEuMzg2IDI1LjgzMTIgMTAwLjkzMyAyNS43MDM1IDEwMC40MTkgMjUuNzAzNUM5OS45MDQ2IDI1LjcwMzUgOTkuNDUwNiAyNS44MzEyIDk5LjA1NjcgMjYuMDg2NkM5OC42NjI4IDI2LjMzOSA5OC4zNTM1IDI2LjcxMjkgOTguMTI4OCAyNy4yMDg1Qzk3LjkwNzIgMjcuNzAwOSA5Ny43OTY0IDI4LjMwNTYgOTcuNzk2NCAyOS4wMjI3Qzk3Ljc5NjQgMjkuNzM5OCA5Ny45MDcyIDMwLjM0NjEgOTguMTI4OCAzMC44NDE2Qzk4LjM1MzUgMzEuMzM0IDk4LjY2MjggMzEuNzA4IDk5LjA1NjcgMzEuOTYzNEM5OS40NTA2IDMyLjIxNTggOTkuOTA0NiAzMi4zNDIgMTAwLjQxOSAzMi4zNDJDMTAwLjkzMyAzMi4zNDIgMTAxLjM4NiAzMi4yMTU4IDEwMS43OCAzMS45NjM0QzEwMi4xNzQgMzEuNzA4IDEwMi40ODIgMzEuMzM0IDEwMi43MDQgMzAuODQxNkMxMDIuOTI4IDMwLjM0NjEgMTAzLjA0MSAyOS43Mzk4IDEwMy4wNDEgMjkuMDIyN1pNMTEyLjIxMiAyNC4yOTU1SDExMy45MjRWMzAuNDcyM0MxMTMuOTI0IDMxLjE0OTQgMTEzLjc2NCAzMS43NDQ5IDExMy40NDQgMzIuMjU4OUMxMTMuMTI3IDMyLjc3MjggMTEyLjY4MSAzMy4xNzQ1IDExMi4xMDYgMzMuNDYzOEMxMTEuNTMgMzMuNzUgMTEwLjg1OCAzMy44OTMxIDExMC4wODggMzMuODkzMUMxMDkuMzE2IDMzLjg5MzEgMTA4LjY0MiAzMy43NSAxMDguMDY2IDMzLjQ2MzhDMTA3LjQ5MSAzMy4xNzQ1IDEwNy4wNDQgMzIuNzcyOCAxMDYuNzI3IDMyLjI1ODlDMTA2LjQxIDMxLjc0NDkgMTA2LjI1MiAzMS4xNDk0IDEwNi4yNTIgMzAuNDcyM1YyNC4yOTU1SDEwNy45NjVWMzAuMzI5MkMxMDcuOTY1IDMwLjcyMzEgMTA4LjA1MSAzMS4wNzQgMTA4LjIyMyAzMS4zODE3QzEwOC4zOTkgMzEuNjg5NSAxMDguNjQ1IDMxLjkzMTEgMTA4Ljk2MiAzMi4xMDY1QzEwOS4yNzkgMzIuMjc4OSAxMDkuNjU0IDMyLjM2NTEgMTEwLjA4OCAzMi4zNjUxQzExMC41MjIgMzIuMzY1MSAxMTAuODk4IDMyLjI3ODkgMTExLjIxNSAzMi4xMDY1QzExMS41MzUgMzEuOTMxMSAxMTEuNzgxIDMxLjY4OTUgMTExLjk1MyAzMS4zODE3QzExMi4xMjYgMzEuMDc0IDExMi4yMTIgMzAuNzIzMSAxMTIuMjEyIDMwLjMyOTJWMjQuMjk1NVpNMTE1LjI0MSAyNS43MzEyVjI0LjI5NTVIMTIyLjc4NFYyNS43MzEySDExOS44NjJWMzMuNzVIMTE4LjE2M1YyNS43MzEySDExNS4yNDFaTTEyNC4xMDggMzMuNzVWMjQuMjk1NUgxMjcuNjU0QzEyOC4zOCAyNC4yOTU1IDEyOC45ODkgMjQuNDMwOSAxMjkuNDgyIDI0LjcwMTdDMTI5Ljk3NyAyNC45NzI1IDEzMC4zNTEgMjUuMzQ0OSAxMzAuNjAzIDI1LjgxODlDMTMwLjg1OSAyNi4yODk4IDEzMC45ODcgMjYuODI1MyAxMzAuOTg3IDI3LjQyNTRDMTMwLjk4NyAyOC4wMzE3IDEzMC44NTkgMjguNTcwMyAxMzAuNjAzIDI5LjA0MTJDMTMwLjM0OCAyOS41MTIxIDEyOS45NzEgMjkuODgyOSAxMjkuNDcyIDMwLjE1MzhDMTI4Ljk3NCAzMC40MjE1IDEyOC4zNiAzMC41NTU0IDEyNy42MyAzMC41NTU0SDEyNS4yODFWMjkuMTQ3NEgxMjcuNEMxMjcuODI0IDI5LjE0NzQgMTI4LjE3MiAyOS4wNzM1IDEyOC40NDMgMjguOTI1OEMxMjguNzE0IDI4Ljc3ODEgMTI4LjkxNCAyOC41NzQ5IDEyOS4wNDMgMjguMzE2NEMxMjkuMTc1IDI4LjA1NzkgMTI5LjI0MiAyNy43NjA5IDEyOS4yNDIgMjcuNDI1NEMxMjkuMjQyIDI3LjA5IDEyOS4xNzUgMjYuNzk0NSAxMjkuMDQzIDI2LjUzOTFDMTI4LjkxNCAyNi4yODM2IDEyOC43MTIgMjYuMDg1MSAxMjguNDM4IDI1Ljk0MzVDMTI4LjE2OCAyNS43OTg5IDEyNy44MTggMjUuNzI2NiAxMjcuMzkgMjUuNzI2NkgxMjUuODIxVjMzLjc1SDEyNC4xMDhaTTEzOC4zMDQgMjQuMjk1NUgxNDAuMDE3VjMwLjQ3MjNDMTQwLjAxNyAzMS4xNDk0IDEzOS44NTcgMzEuNzQ0OSAxMzkuNTM3IDMyLjI1ODlDMTM5LjIyIDMyLjc3MjggMTM4Ljc3NCAzMy4xNzQ1IDEzOC4xOTggMzMuNDYzOEMxMzcuNjIyIDMzLjc1IDEzNi45NSAzMy44OTMxIDEzNi4xODEgMzMuODkzMUMxMzUuNDA4IDMzLjg5MzEgMTM0LjczNCAzMy43NSAxMzQuMTU5IDMzLjQ2MzhDMTMzLjU4MyAzMy4xNzQ1IDEzMy4xMzcgMzIuNzcyOCAxMzIuODIgMzIuMjU4OUMxMzIuNTAzIDMxLjc0NDkgMTMyLjM0NCAzMS4xNDk0IDEzMi4zNDQgMzAuNDcyM1YyNC4yOTU1SDEzNC4wNTdWMzAuMzI5MkMxMzQuMDU3IDMwLjcyMzEgMTM0LjE0MyAzMS4wNzQgMTM0LjMxNiAzMS4zODE3QzEzNC40OTEgMzEuNjg5NSAxMzQuNzM3IDMxLjkzMTEgMTM1LjA1NCAzMi4xMDY1QzEzNS4zNzEgMzIuMjc4OSAxMzUuNzQ3IDMyLjM2NTEgMTM2LjE4MSAzMi4zNjUxQzEzNi42MTUgMzIuMzY1MSAxMzYuOTkgMzIuMjc4OSAxMzcuMzA3IDMyLjEwNjVDMTM3LjYyNyAzMS45MzExIDEzNy44NzMgMzEuNjg5NSAxMzguMDQ2IDMxLjM4MTdDMTM4LjIxOCAzMS4wNzQgMTM4LjMwNCAzMC43MjMxIDEzOC4zMDQgMzAuMzI5MlYyNC4yOTU1Wk0xNDEuMzMzIDI1LjczMTJWMjQuMjk1NUgxNDguODc2VjI1LjczMTJIMTQ1Ljk1NFYzMy43NUgxNDQuMjU1VjI1LjczMTJIMTQxLjMzM1oiIGZpbGw9IiM4NDg3OTQiLz4KPC9zdmc+Cg=='); + } +} diff --git a/src/Blocks/custom/form-selector/form-selector-overrides.js b/src/Blocks/custom/form-selector/form-selector-overrides.js index 08ab2ab04..305e1547d 100644 --- a/src/Blocks/custom/form-selector/form-selector-overrides.js +++ b/src/Blocks/custom/form-selector/form-selector-overrides.js @@ -3,6 +3,7 @@ import globalManifest from '../../manifest.json'; import manifest from './manifest.json'; +import { getUtilsIcons } from '../../components/form/assets/state-init'; const forms = [ ...manifest.forms, @@ -24,4 +25,7 @@ forms.forEach((form) => { export const overrides = { ...manifest, forms: outputForms, + icon:{ + src: getUtilsIcons('formPicker') ?? manifest.icon.src, + } }; diff --git a/src/Blocks/custom/form-selector/manifest.json b/src/Blocks/custom/form-selector/manifest.json index 9cdb40f7e..362a746bb 100644 --- a/src/Blocks/custom/form-selector/manifest.json +++ b/src/Blocks/custom/form-selector/manifest.json @@ -26,7 +26,8 @@ "eightshift-forms/moments", "eightshift-forms/workable", "eightshift-forms/jira", - "eightshift-forms/pipedrive" + "eightshift-forms/pipedrive", + "eightshift-forms/calculator" ] } }, @@ -216,6 +217,25 @@ "eightshift-forms/submit" ] ] + }, + { + "label": "Calculator form", + "slug": "calculator", + "blockName": "eightshift-forms/calculator", + "innerBlocks": [ + [ + "eightshift-forms/input", + { + "inputInputFieldLabel": "Range", + "inputInputType": "range", + "inputInputName": "range", + "inputInputIsNumber": true + } + ], + [ + "eightshift-forms/submit" + ] + ] } ] } diff --git a/src/Blocks/custom/forms/components/forms-editor.js b/src/Blocks/custom/forms/components/forms-editor.js index 1af604862..2a8efed07 100644 --- a/src/Blocks/custom/forms/components/forms-editor.js +++ b/src/Blocks/custom/forms/components/forms-editor.js @@ -17,7 +17,7 @@ export const FormsEditor = ({ attributes, setAttributes, preview, - formSelectOptions + formSelectOptions, }) => { const manifest = select(STORE_NAME).getBlock('forms'); @@ -41,7 +41,7 @@ export const FormsEditor = ({ return ( {__('Eightshift Forms', 'productive')}} + label={{__('Eightshift Forms', 'eightshift-forms')}} className='es-max-w-80 es-rounded-3! es-mx-auto! es-font-weight-400 es-color-cool-gray-500! es-nested-color-current!' > { - const manifest = select(STORE_NAME).getBlock('forms'); - const { - postType, - } = manifest; - const [isGeoPreview, setIsGeoPreview] = useState(false); const formSelectOptions = getFetchWpApi( - postType, + esFormsLocalization?.postTypes?.forms, { noCache: true, processLabel: ({ title: { rendered: label }, integration_type: metadata, id }) => { diff --git a/src/Blocks/custom/forms/forms-overrides.js b/src/Blocks/custom/forms/forms-overrides.js new file mode 100644 index 000000000..e6dedd39b --- /dev/null +++ b/src/Blocks/custom/forms/forms-overrides.js @@ -0,0 +1,12 @@ +// eslint-disable-next-line no-unused-vars +/* global esFormsLocalization */ + +import manifest from './manifest.json'; +import { getUtilsIcons } from '../../components/form/assets/state-init'; + +export const overrides = { + ...manifest, + icon:{ + src: getUtilsIcons('form') ?? manifest.icon.src, + } +}; diff --git a/src/Blocks/custom/forms/manifest.json b/src/Blocks/custom/forms/manifest.json index 804338b3a..8a51fdffe 100644 --- a/src/Blocks/custom/forms/manifest.json +++ b/src/Blocks/custom/forms/manifest.json @@ -74,7 +74,6 @@ "conditionalTags": "conditionalTags", "progressBar": "progressBar" }, - "postType": "eightshift-forms", "attributesSsr": [ "formsFormPostId", "formsStyle" diff --git a/src/Blocks/custom/goodbits/goodbits-overrides.js b/src/Blocks/custom/goodbits/goodbits-overrides.js new file mode 100644 index 000000000..95b27e2cd --- /dev/null +++ b/src/Blocks/custom/goodbits/goodbits-overrides.js @@ -0,0 +1,12 @@ +// eslint-disable-next-line no-unused-vars +/* global esFormsLocalization */ + +import manifest from './manifest.json'; +import { getUtilsIcons } from '../../components/form/assets/state-init'; + +export const overrides = { + ...manifest, + icon:{ + src: getUtilsIcons('goodbits') ?? manifest.icon.src, + } +}; diff --git a/src/Blocks/custom/greenhouse/greenhouse-overrides.js b/src/Blocks/custom/greenhouse/greenhouse-overrides.js new file mode 100644 index 000000000..4d8599a9f --- /dev/null +++ b/src/Blocks/custom/greenhouse/greenhouse-overrides.js @@ -0,0 +1,12 @@ +// eslint-disable-next-line no-unused-vars +/* global esFormsLocalization */ + +import manifest from './manifest.json'; +import { getUtilsIcons } from '../../components/form/assets/state-init'; + +export const overrides = { + ...manifest, + icon:{ + src: getUtilsIcons('greenhouse') ?? manifest.icon.src, + } +}; diff --git a/src/Blocks/custom/hubspot/hubspot-overrides.js b/src/Blocks/custom/hubspot/hubspot-overrides.js new file mode 100644 index 000000000..5b4118dab --- /dev/null +++ b/src/Blocks/custom/hubspot/hubspot-overrides.js @@ -0,0 +1,12 @@ +// eslint-disable-next-line no-unused-vars +/* global esFormsLocalization */ + +import manifest from './manifest.json'; +import { getUtilsIcons } from '../../components/form/assets/state-init'; + +export const overrides = { + ...manifest, + icon:{ + src: getUtilsIcons('hubspot') ?? manifest.icon.src, + } +}; diff --git a/src/Blocks/custom/input/input-overrides.js b/src/Blocks/custom/input/input-overrides.js new file mode 100644 index 000000000..b751036ea --- /dev/null +++ b/src/Blocks/custom/input/input-overrides.js @@ -0,0 +1,12 @@ +// eslint-disable-next-line no-unused-vars +/* global esFormsLocalization */ + +import manifest from './manifest.json'; +import { getUtilsIcons } from '../../components/form/assets/state-init'; + +export const overrides = { + ...manifest, + icon:{ + src: getUtilsIcons('input') ?? manifest.icon.src, + } +}; diff --git a/src/Blocks/custom/jira/jira-overrides.js b/src/Blocks/custom/jira/jira-overrides.js index 64222d1d9..6d62cd80b 100644 --- a/src/Blocks/custom/jira/jira-overrides.js +++ b/src/Blocks/custom/jira/jira-overrides.js @@ -2,9 +2,13 @@ import globalManifest from '../../manifest.json'; import manifest from './manifest.json'; +import { getUtilsIcons } from '../../components/form/assets/state-init'; export const overrides = { ...manifest, + icon:{ + src: getUtilsIcons('jira') ?? manifest.icon.src, + }, attributes: { ...manifest.attributes, jiraAllowedBlocks: { diff --git a/src/Blocks/custom/mailchimp/mailchimp-overrides.js b/src/Blocks/custom/mailchimp/mailchimp-overrides.js new file mode 100644 index 000000000..daa3c541f --- /dev/null +++ b/src/Blocks/custom/mailchimp/mailchimp-overrides.js @@ -0,0 +1,12 @@ +// eslint-disable-next-line no-unused-vars +/* global esFormsLocalization */ + +import manifest from './manifest.json'; +import { getUtilsIcons } from '../../components/form/assets/state-init'; + +export const overrides = { + ...manifest, + icon:{ + src: getUtilsIcons('mailchimp') ?? manifest.icon.src, + } +}; diff --git a/src/Blocks/custom/mailer/mailer-overrides.js b/src/Blocks/custom/mailer/mailer-overrides.js index 071618d1e..0f91871ef 100644 --- a/src/Blocks/custom/mailer/mailer-overrides.js +++ b/src/Blocks/custom/mailer/mailer-overrides.js @@ -2,9 +2,13 @@ import globalManifest from './../../manifest.json'; import manifest from './manifest.json'; +import { getUtilsIcons } from '../../components/form/assets/state-init'; export const overrides = { ...manifest, + icon:{ + src: getUtilsIcons('form') ?? manifest.icon.src, + }, attributes: { ...manifest.attributes, mailerAllowedBlocks: { diff --git a/src/Blocks/custom/mailerlite/mailerlite-overrides.js b/src/Blocks/custom/mailerlite/mailerlite-overrides.js new file mode 100644 index 000000000..ce3edca2a --- /dev/null +++ b/src/Blocks/custom/mailerlite/mailerlite-overrides.js @@ -0,0 +1,12 @@ +// eslint-disable-next-line no-unused-vars +/* global esFormsLocalization */ + +import manifest from './manifest.json'; +import { getUtilsIcons } from '../../components/form/assets/state-init'; + +export const overrides = { + ...manifest, + icon:{ + src: getUtilsIcons('mailerlite') ?? manifest.icon.src, + } +}; diff --git a/src/Blocks/custom/moments/moments-overrides.js b/src/Blocks/custom/moments/moments-overrides.js new file mode 100644 index 000000000..109e51cb9 --- /dev/null +++ b/src/Blocks/custom/moments/moments-overrides.js @@ -0,0 +1,12 @@ +// eslint-disable-next-line no-unused-vars +/* global esFormsLocalization */ + +import manifest from './manifest.json'; +import { getUtilsIcons } from '../../components/form/assets/state-init'; + +export const overrides = { + ...manifest, + icon:{ + src: getUtilsIcons('moments') ?? manifest.icon.src, + } +}; diff --git a/src/Blocks/custom/phone/phone-overrides.js b/src/Blocks/custom/phone/phone-overrides.js new file mode 100644 index 000000000..52d74abc7 --- /dev/null +++ b/src/Blocks/custom/phone/phone-overrides.js @@ -0,0 +1,12 @@ +// eslint-disable-next-line no-unused-vars +/* global esFormsLocalization */ + +import manifest from './manifest.json'; +import { getUtilsIcons } from '../../components/form/assets/state-init'; + +export const overrides = { + ...manifest, + icon:{ + src: getUtilsIcons('phone') ?? manifest.icon.src, + } +}; diff --git a/src/Blocks/custom/pipedrive/pipedrive-overrides.js b/src/Blocks/custom/pipedrive/pipedrive-overrides.js index a50432494..b57bfb830 100644 --- a/src/Blocks/custom/pipedrive/pipedrive-overrides.js +++ b/src/Blocks/custom/pipedrive/pipedrive-overrides.js @@ -2,9 +2,13 @@ import globalManifest from '../../manifest.json'; import manifest from './manifest.json'; +import { getUtilsIcons } from '../../components/form/assets/state-init'; export const overrides = { ...manifest, + icon:{ + src: getUtilsIcons('pipedrive') ?? manifest.icon.src, + }, attributes: { ...manifest.attributes, pipedriveAllowedBlocks: { diff --git a/src/Blocks/custom/radio/radio-overrides.js b/src/Blocks/custom/radio/radio-overrides.js new file mode 100644 index 000000000..f0ce805a5 --- /dev/null +++ b/src/Blocks/custom/radio/radio-overrides.js @@ -0,0 +1,12 @@ +// eslint-disable-next-line no-unused-vars +/* global esFormsLocalization */ + +import manifest from './manifest.json'; +import { getUtilsIcons } from '../../components/form/assets/state-init'; + +export const overrides = { + ...manifest, + icon:{ + src: getUtilsIcons('radio') ?? manifest.icon.src, + } +}; diff --git a/src/Blocks/custom/radios/radios-overrides.js b/src/Blocks/custom/radios/radios-overrides.js new file mode 100644 index 000000000..ba31b1f2f --- /dev/null +++ b/src/Blocks/custom/radios/radios-overrides.js @@ -0,0 +1,12 @@ +// eslint-disable-next-line no-unused-vars +/* global esFormsLocalization */ + +import manifest from './manifest.json'; +import { getUtilsIcons } from '../../components/form/assets/state-init'; + +export const overrides = { + ...manifest, + icon:{ + src: getUtilsIcons('radios') ?? manifest.icon.src, + } +}; diff --git a/src/Blocks/custom/rating/rating-overrides.js b/src/Blocks/custom/rating/rating-overrides.js new file mode 100644 index 000000000..6e23e9b69 --- /dev/null +++ b/src/Blocks/custom/rating/rating-overrides.js @@ -0,0 +1,12 @@ +// eslint-disable-next-line no-unused-vars +/* global esFormsLocalization */ + +import manifest from './manifest.json'; +import { getUtilsIcons } from '../../components/form/assets/state-init'; + +export const overrides = { + ...manifest, + icon:{ + src: getUtilsIcons('starRating') ?? manifest.icon.src, + } +}; diff --git a/src/Blocks/custom/result-output-item/components/result-output-item-editor.js b/src/Blocks/custom/result-output-item/components/result-output-item-editor.js new file mode 100644 index 000000000..77e772749 --- /dev/null +++ b/src/Blocks/custom/result-output-item/components/result-output-item-editor.js @@ -0,0 +1,31 @@ +import React from 'react'; +import { __ } from '@wordpress/i18n'; +import { InnerBlocks } from '@wordpress/block-editor'; +import { checkAttr, BlockInserter, selector } from '@eightshift/frontend-libs/scripts'; +import manifest from '../manifest.json'; + +export const ResultOutputItemEditor = ({ attributes, clientId }) => { + const { + blockClass, + } = attributes; + + const resultOutputItemName = checkAttr('resultOutputItemName', attributes, manifest); + const resultOutputItemValue = checkAttr('resultOutputItemValue', attributes, manifest); + + return ( +
+
+
+ {__('Show if the following condition matches:', 'eightshift-forms')} +
+
+ {resultOutputItemName} = {resultOutputItemValue} +
+
+ + } + /> +
+ ); +}; diff --git a/src/Blocks/custom/result-output-item/components/result-output-item-options.js b/src/Blocks/custom/result-output-item/components/result-output-item-options.js new file mode 100644 index 000000000..76314327d --- /dev/null +++ b/src/Blocks/custom/result-output-item/components/result-output-item-options.js @@ -0,0 +1,35 @@ +import React from 'react'; +import { __ } from '@wordpress/i18n'; +import { PanelBody, TextControl } from '@wordpress/components'; +import { checkAttr, getAttrKey, icons, IconLabel, Notification } from '@eightshift/frontend-libs/scripts'; +import manifest from '../manifest.json'; + +export const ResultOutputItemOptions = ({ + attributes, + setAttributes, +}) => { + + const resultOutputItemName = checkAttr('resultOutputItemName', attributes, manifest); + const resultOutputItemValue = checkAttr('resultOutputItemValue', attributes, manifest); + + return ( + + } + value={resultOutputItemName} + onChange={(value) => setAttributes({ [getAttrKey('resultOutputItemName', attributes, manifest)]: value })} + /> + } + value={resultOutputItemValue} + onChange={(value) => setAttributes({ [getAttrKey('resultOutputItemValue', attributes, manifest)]: value })} + /> + + + + + ); +}; diff --git a/src/Blocks/custom/result-output-item/manifest.json b/src/Blocks/custom/result-output-item/manifest.json new file mode 100644 index 000000000..36cfbd048 --- /dev/null +++ b/src/Blocks/custom/result-output-item/manifest.json @@ -0,0 +1,24 @@ +{ + "$schema": "https://raw.githubusercontent.com/infinum/eightshift-frontend-libs/develop/schemas/block.json", + "blockName": "result-output-item", + "title": "Result output item", + "description" : "Display the result output variable blocks based on the users form submission", + "category": "eightshift-forms", + "icon": { + "src": "esf-checkbox" + }, + "keywords": [ + "result", + "output", + "item" + ], + "hasInnerBlocks": true, + "attributes": { + "resultOutputItemName": { + "type": "string" + }, + "resultOutputItemValue": { + "type": "string" + } + } +} diff --git a/src/Blocks/custom/result-output-item/result-output-item-block.js b/src/Blocks/custom/result-output-item/result-output-item-block.js new file mode 100644 index 000000000..0957974ae --- /dev/null +++ b/src/Blocks/custom/result-output-item/result-output-item-block.js @@ -0,0 +1,15 @@ +import React from 'react'; +import { InspectorControls } from '@wordpress/block-editor'; +import { ResultOutputItemEditor } from './components/result-output-item-editor'; +import { ResultOutputItemOptions } from './components/result-output-item-options'; + +export const ResultOutputItem = (props) => { + return ( + <> + + + + + + ); +}; diff --git a/src/Blocks/custom/result-output-item/result-output-item-editor.scss b/src/Blocks/custom/result-output-item/result-output-item-editor.scss new file mode 100644 index 000000000..77dac6948 --- /dev/null +++ b/src/Blocks/custom/result-output-item/result-output-item-editor.scss @@ -0,0 +1,24 @@ +.es-block-result-output-item { + &__intro { + text-align: center; + transform: translateY(50%); + + &::before { + content: ''; + inline-size: 100%; + block-size: 1px; + display: block; + background-color: var(--global-colors-esf-gray-300); + } + + &-inner { + border: 1px solid var(--global-colors-esf-gray-300); + padding: 0.3125rem 1.25rem; + display: inline-block; + border-radius: var(--es-input-radius); + font-weight: 500; + transform: translateY(-50%); + background-color: var(--global-colors-esf-white); + } + } +} diff --git a/src/Blocks/custom/result-output-item/result-output-item-overrides.js b/src/Blocks/custom/result-output-item/result-output-item-overrides.js new file mode 100644 index 000000000..cf8b09c9b --- /dev/null +++ b/src/Blocks/custom/result-output-item/result-output-item-overrides.js @@ -0,0 +1,12 @@ +// eslint-disable-next-line no-unused-vars +/* global esFormsLocalization */ + +import manifest from './manifest.json'; +import { getUtilsIcons } from '../../components/form/assets/state-init'; + +export const overrides = { + ...manifest, + icon:{ + src: getUtilsIcons('resultOutputItem') ?? manifest.icon.src, + } +}; diff --git a/src/Blocks/custom/result-output-item/result-output-item.php b/src/Blocks/custom/result-output-item/result-output-item.php new file mode 100644 index 000000000..a4c2f8c0d --- /dev/null +++ b/src/Blocks/custom/result-output-item/result-output-item.php @@ -0,0 +1,43 @@ + esc_attr($resultOutputItemName), + UtilsHelper::getStateAttribute('resultOutputItemValue') => esc_attr($resultOutputItemValue), +]; + +$resultAttrsOutput = ''; +foreach ($resultAttrs as $key => $value) { + $resultAttrsOutput .= wp_kses_post(" {$key}='" . $value . "'"); +} + +$resultClass = Components::classnames([ + Components::selector($blockClass, $blockClass), + UtilsHelper::getStateSelector('isHidden'), + UtilsHelper::getStateSelector('resultOutputItem'), +]); + +?> + +
> + +
diff --git a/src/Blocks/custom/result-output/components/result-output-editor.js b/src/Blocks/custom/result-output/components/result-output-editor.js new file mode 100644 index 000000000..5cfc89468 --- /dev/null +++ b/src/Blocks/custom/result-output/components/result-output-editor.js @@ -0,0 +1,97 @@ +import React from 'react'; +import { select } from '@wordpress/data'; +import { ServerSideRender, + checkAttr, + icons, + AsyncSelect, + getAttrKey, + STORE_NAME, +} from '@eightshift/frontend-libs/scripts'; +import { __ } from '@wordpress/i18n'; +import { Placeholder } from '@wordpress/components'; +import { getFilteredAttributes, outputFormSelectItemWithIcon } from '../../../components/utils'; + +export const ResultOutputEditor = ({ + attributes, + setAttributes, + formSelectOptions, + resultSelectOptions, +}) => { + const manifest = select(STORE_NAME).getBlock('result-output'); + + const { + blockFullName + } = attributes; + + const { + attributesSsr, + } = manifest; + + const resultOutputFormPostId = checkAttr('resultOutputFormPostId', attributes, manifest); + const resultOutputFormPostIdRaw = checkAttr('resultOutputFormPostIdRaw', attributes, manifest); + const resultOutputPostIdRaw = checkAttr('resultOutputPostIdRaw', attributes, manifest); + const resultOutputPostId = checkAttr('resultOutputPostId', attributes, manifest); + + if (resultOutputPostId?.length < 1 || resultOutputFormPostId?.length < 1) { + return ( + {__('Eightshift Forms - Result output', 'eightshift-forms')}} + className='es-max-w-80 es-rounded-3! es-mx-auto! es-font-weight-400 es-color-cool-gray-500! es-nested-color-current!' + > + { + setAttributes({ + [getAttrKey('resultOutputPostIdRaw', attributes, manifest)]: { + id: value?.id, + label: value?.metadata?.label, + value: value?.metadata?.value, + metadata: value?.metadata?.metadata, + }, + [getAttrKey('resultOutputPostId', attributes, manifest)]: `${value?.value}`, + }); + }} + noBottomSpacing + /> + + { + setAttributes({ + [getAttrKey('resultOutputFormPostIdRaw', attributes, manifest)]: { + id: value?.id, + label: value?.metadata?.label, + value: value?.metadata?.value, + metadata: value?.metadata?.metadata, + }, + [getAttrKey('resultOutputFormPostId', attributes, manifest)]: `${value?.value}`, + }); + }} + noBottomSpacing + /> + + ); + } + + return ( + + ); +}; diff --git a/src/Blocks/custom/result-output/components/result-output-options.js b/src/Blocks/custom/result-output/components/result-output-options.js new file mode 100644 index 000000000..390c50314 --- /dev/null +++ b/src/Blocks/custom/result-output/components/result-output-options.js @@ -0,0 +1,76 @@ +import React from 'react'; +import { select } from '@wordpress/data'; +import { __ } from '@wordpress/i18n'; +import { PanelBody } from '@wordpress/components'; +import { checkAttr, + getAttrKey, + AsyncSelect, + STORE_NAME, + IconToggle, + icons, +} from '@eightshift/frontend-libs/scripts'; +import { outputFormSelectItemWithIcon } from '../../../components/utils'; + +export const ResultOutputOptions = ({ + attributes, + setAttributes, + formSelectOptions, + resultSelectOptions, +}) => { + const manifest = select(STORE_NAME).getBlock('result-output'); + + const resultOutputFormPostId = checkAttr('resultOutputFormPostId', attributes, manifest); + const resultOutputFormPostIdRaw = checkAttr('resultOutputFormPostIdRaw', attributes, manifest); + const resultOutputPostId = checkAttr('resultOutputPostId', attributes, manifest); + const resultOutputPostIdRaw = checkAttr('resultOutputPostIdRaw', attributes, manifest); + const resultOutputHide = checkAttr('resultOutputHide', attributes, manifest); + + return ( + + { + setAttributes({ + [getAttrKey('resultOutputPostIdRaw', attributes, manifest)]: { + id: value?.id, + label: value?.metadata?.label, + value: value?.metadata?.value, + metadata: value?.metadata?.metadata, + }, + [getAttrKey('resultOutputPostId', attributes, manifest)]: `${value?.value.toString()}`, + }); + }} + /> + + { + setAttributes({ + [getAttrKey('resultOutputFormPostIdRaw', attributes, manifest)]: { + id: value?.id, + label: value?.metadata?.label, + value: value?.metadata?.value, + metadata: value?.metadata?.metadata, + }, + [getAttrKey('resultOutputFormPostId', attributes, manifest)]: `${value?.value.toString()}`, + }); + }} + /> + + setAttributes({ [getAttrKey('resultOutputHide', attributes, manifest)]: value })} + noBottomSpacing + /> + + ); +}; diff --git a/src/Blocks/custom/result-output/manifest.json b/src/Blocks/custom/result-output/manifest.json new file mode 100644 index 000000000..b91da7f13 --- /dev/null +++ b/src/Blocks/custom/result-output/manifest.json @@ -0,0 +1,48 @@ +{ + "$schema": "https://raw.githubusercontent.com/infinum/eightshift-frontend-libs/develop/schemas/block.json", + "blockName": "result-output", + "title": "Result output", + "description" : "Display the result output of the form after success", + "category": "eightshift-forms", + "icon": { + "src": "esf-checkbox" + }, + "keywords": [ + "result", + "output", + "results" + ], + "hasInnerBlocks": true, + "attributes": { + "resultOutputName": { + "type": "string" + }, + "resultOutputValue": { + "type": "string" + }, + "resultOutputPostId": { + "type": "string" + }, + "resultOutputPostIdRaw": { + "type": "object" + }, + "resultOutputFormPostId": { + "type": "string" + }, + "resultOutputFormPostIdRaw": { + "type": "object" + }, + "resultOutputServerSideRender": { + "type": "boolean", + "default": false + }, + "resultOutputHide": { + "type": "boolean", + "default": false + } + }, + "attributesSsr": [ + "resultOutputPostId", + "resultOutputFormPostId" + ] +} diff --git a/src/Blocks/custom/result-output/result-output-block.js b/src/Blocks/custom/result-output/result-output-block.js new file mode 100644 index 000000000..facd5d5a2 --- /dev/null +++ b/src/Blocks/custom/result-output/result-output-block.js @@ -0,0 +1,50 @@ +/* global esFormsLocalization */ + +import React from 'react'; +import { InspectorControls } from '@wordpress/block-editor'; +import { ResultOutputEditor } from './components/result-output-editor'; +import { ResultOutputOptions } from './components/result-output-options'; +import { getFetchWpApi } from '@eightshift/frontend-libs/scripts'; +import { outputFormSelectItemWithIcon } from '../../components/utils'; + +const dynamicItemSelectOptions = function(postType) { + return getFetchWpApi( + postType, + { + noCache: true, + processLabel: ({ title: { rendered: label }, integration_type: metadata, id }) => { + return outputFormSelectItemWithIcon({ + label, + id, + metadata, + })?.label; + }, + fields: 'id,title,integration_type', + processMetadata: ({ title: { rendered: label }, integration_type: metadata, id }) => ({ + id, + value: id, + label, + metadata, + }), + } + ); +}; + +export const ResultOutput = (props) => { + return ( + <> + + + + + + ); +}; diff --git a/src/Blocks/custom/result-output/result-output-editor.scss b/src/Blocks/custom/result-output/result-output-editor.scss new file mode 100644 index 000000000..a755b73ee --- /dev/null +++ b/src/Blocks/custom/result-output/result-output-editor.scss @@ -0,0 +1,24 @@ +.es-block-result-output { + &__intro { + text-align: center; + transform: translateY(50%); + + &::before { + content: ''; + inline-size: 100%; + block-size: 1px; + display: block; + background-color: var(--global-colors-esf-gray-300); + } + + &-inner { + border: 1px solid var(--global-colors-esf-gray-300); + padding: 0.3125rem 1.25rem; + display: inline-block; + border-radius: var(--es-input-radius); + font-weight: 500; + transform: translateY(-50%); + background-color: var(--global-colors-esf-white); + } + } +} diff --git a/src/Blocks/custom/result-output/result-output-overrides.js b/src/Blocks/custom/result-output/result-output-overrides.js new file mode 100644 index 000000000..b0c0eedf1 --- /dev/null +++ b/src/Blocks/custom/result-output/result-output-overrides.js @@ -0,0 +1,12 @@ +// eslint-disable-next-line no-unused-vars +/* global esFormsLocalization */ + +import manifest from './manifest.json'; +import { getUtilsIcons } from '../../components/form/assets/state-init'; + +export const overrides = { + ...manifest, + icon:{ + src: getUtilsIcons('resultOutput') ?? manifest.icon.src, + } +}; diff --git a/src/Blocks/custom/result-output/result-output.php b/src/Blocks/custom/result-output/result-output.php new file mode 100644 index 000000000..af3b36bc2 --- /dev/null +++ b/src/Blocks/custom/result-output/result-output.php @@ -0,0 +1,41 @@ + esc_attr($resultOutputFormPostId), +]; + +$resultAttrsOutput = ''; +foreach ($resultAttrs as $key => $value) { + $resultAttrsOutput .= wp_kses_post(" {$key}='" . $value . "'"); +} + +$resultClass = Components::classnames([ + Components::selector($blockClass, $blockClass), + Components::selector($resultOutputHide, UtilsHelper::getStateSelector('isHidden')), + UtilsHelper::getStateSelector('resultOutput'), +]); + +?> + +
> + +
diff --git a/src/Blocks/custom/select-option/select-option-overrides.js b/src/Blocks/custom/select-option/select-option-overrides.js new file mode 100644 index 000000000..be0b43698 --- /dev/null +++ b/src/Blocks/custom/select-option/select-option-overrides.js @@ -0,0 +1,12 @@ +// eslint-disable-next-line no-unused-vars +/* global esFormsLocalization */ + +import manifest from './manifest.json'; +import { getUtilsIcons } from '../../components/form/assets/state-init'; + +export const overrides = { + ...manifest, + icon:{ + src: getUtilsIcons('selectOption') ?? manifest.icon.src, + } +}; diff --git a/src/Blocks/custom/select/select-overrides.js b/src/Blocks/custom/select/select-overrides.js new file mode 100644 index 000000000..7009aab07 --- /dev/null +++ b/src/Blocks/custom/select/select-overrides.js @@ -0,0 +1,12 @@ +// eslint-disable-next-line no-unused-vars +/* global esFormsLocalization */ + +import manifest from './manifest.json'; +import { getUtilsIcons } from '../../components/form/assets/state-init'; + +export const overrides = { + ...manifest, + icon:{ + src: getUtilsIcons('select') ?? manifest.icon.src, + } +}; diff --git a/src/Blocks/custom/step/step-overrides.js b/src/Blocks/custom/step/step-overrides.js new file mode 100644 index 000000000..04ebe7e6e --- /dev/null +++ b/src/Blocks/custom/step/step-overrides.js @@ -0,0 +1,12 @@ +// eslint-disable-next-line no-unused-vars +/* global esFormsLocalization */ + +import manifest from './manifest.json'; +import { getUtilsIcons } from '../../components/form/assets/state-init'; + +export const overrides = { + ...manifest, + icon:{ + src: getUtilsIcons('steps') ?? manifest.icon.src, + } +}; diff --git a/src/Blocks/custom/submit/submit-overrides.js b/src/Blocks/custom/submit/submit-overrides.js new file mode 100644 index 000000000..83b558d07 --- /dev/null +++ b/src/Blocks/custom/submit/submit-overrides.js @@ -0,0 +1,12 @@ +// eslint-disable-next-line no-unused-vars +/* global esFormsLocalization */ + +import manifest from './manifest.json'; +import { getUtilsIcons } from '../../components/form/assets/state-init'; + +export const overrides = { + ...manifest, + icon:{ + src: getUtilsIcons('submit') ?? manifest.icon.src, + } +}; diff --git a/src/Blocks/custom/textarea/textarea-overrides.js b/src/Blocks/custom/textarea/textarea-overrides.js new file mode 100644 index 000000000..e7a8b9821 --- /dev/null +++ b/src/Blocks/custom/textarea/textarea-overrides.js @@ -0,0 +1,12 @@ +// eslint-disable-next-line no-unused-vars +/* global esFormsLocalization */ + +import manifest from './manifest.json'; +import { getUtilsIcons } from '../../components/form/assets/state-init'; + +export const overrides = { + ...manifest, + icon:{ + src: getUtilsIcons('textarea') ?? manifest.icon.src, + } +}; diff --git a/src/Blocks/custom/workable/workable-overrides.js b/src/Blocks/custom/workable/workable-overrides.js new file mode 100644 index 000000000..04503af51 --- /dev/null +++ b/src/Blocks/custom/workable/workable-overrides.js @@ -0,0 +1,12 @@ +// eslint-disable-next-line no-unused-vars +/* global esFormsLocalization */ + +import manifest from './manifest.json'; +import { getUtilsIcons } from '../../components/form/assets/state-init'; + +export const overrides = { + ...manifest, + icon:{ + src: getUtilsIcons('workable') ?? manifest.icon.src, + } +}; diff --git a/src/Blocks/manifest.json b/src/Blocks/manifest.json index 1561de978..95bb27a11 100644 --- a/src/Blocks/manifest.json +++ b/src/Blocks/manifest.json @@ -17,7 +17,10 @@ "useWrapper": false }, "allowedBlocksNoneBuilderBlocksList": [ - "eightshift-forms/forms" + "eightshift-forms/form-selector", + "eightshift-forms/forms", + "eightshift-forms/result-output", + "eightshift-forms/result-output-item" ], "allowedBlocksBuilderIntegrationAdditionalBlocksList": [ "eightshift-forms/step" diff --git a/src/CustomPostType/Result.php b/src/CustomPostType/Result.php new file mode 100644 index 000000000..fc73f932a --- /dev/null +++ b/src/CustomPostType/Result.php @@ -0,0 +1,103 @@ + Array of arguments. + */ + protected function getPostTypeArguments(): array + { + return [ + 'label' => \esc_html__('Result outputs', 'eightshift-forms'), + 'public' => true, + 'menu_position' => static::MENU_POSITION, + 'menu_icon' => static::MENU_ICON, + 'supports' => ['title', 'editor', 'revisions'], + 'has_archive' => false, + 'show_in_rest' => true, + 'publicly_queryable' => false, + 'show_in_menu' => false, + 'show_in_nav_menus' => false, + 'can_export' => true, + 'capability_type' => self::POST_CAPABILITY_TYPE, + 'rest_base' => static::REST_API_ENDPOINT_SLUG, + ]; + } +} diff --git a/src/Editor/Editor.php b/src/Editor/Editor.php index 0cb4bedce..caa16b97d 100644 --- a/src/Editor/Editor.php +++ b/src/Editor/Editor.php @@ -10,8 +10,9 @@ namespace EightshiftForms\Editor; -use EightshiftForms\AdminMenus\FormAdminMenu; +use EightshiftForms\CustomPostType\Result; use EightshiftForms\CustomPostType\Forms; +use EightshiftFormsVendor\EightshiftFormsUtils\Config\UtilsConfig; use EightshiftFormsVendor\EightshiftFormsUtils\Helpers\UtilsGeneralHelper; use EightshiftFormsVendor\EightshiftLibs\Services\ServiceInterface; @@ -37,21 +38,40 @@ public function register(): void */ public function getEditorBackLink(): void { - $actialUrl = UtilsGeneralHelper::getCurrentUrl(); - $postType = Forms::POST_TYPE_SLUG; - $page = FormAdminMenu::ADMIN_MENU_SLUG; - - $links = [ - \get_admin_url(null, "edit.php?post_type={$postType}"), - \get_admin_url(null, "edit.php?post_status=publish&post_type={$postType}"), - \get_admin_url(null, "edit.php?post_status=draft&post_type={$postType}"), - \get_admin_url(null, "edit.php?post_status=trash&post_type={$postType}"), - \get_admin_url(null, "edit.php?post_status=publish&post_type={$postType}"), - \get_admin_url(null, "edit.php?post_status=future&post_type={$postType}"), + $actualUrl = UtilsGeneralHelper::getCurrentUrl(); + + $types = [ + Forms::POST_TYPE_SLUG, + Result::POST_TYPE_SLUG, ]; - if (\in_array($actialUrl, $links, true)) { - echo ''; // phpcs:ignore Eightshift.Security.ComponentsEscape.OutputNotEscaped + foreach ($types as $type) { + $links = $this->getListOfLinks($type); + + $typeKey = ($type === Forms::POST_TYPE_SLUG) ? '' : UtilsConfig::SLUG_ADMIN_LISTING_RESULTS; + + if (isset($links[$actualUrl])) { + echo ''; // phpcs:ignore Eightshift.Security.ComponentsEscape.OutputNotEscaped + } } } + + /** + * Get list of links. + * + * @param string $type Type of post. + * + * @return array List of links. + */ + private function getListOfLinks(string $type): array + { + return [ + \get_admin_url(null, "edit.php?post_type={$type}") => '', + \get_admin_url(null, "edit.php?post_status=publish&post_type={$type}") => '', + \get_admin_url(null, "edit.php?post_status=draft&post_type={$type}") => '', + \get_admin_url(null, "edit.php?post_status=trash&post_type={$type}") => '', + \get_admin_url(null, "edit.php?post_status=publish&post_type={$type}") => '', + \get_admin_url(null, "edit.php?post_status=future&post_type={$type}") => '', + ]; + } } diff --git a/src/Enqueue/Blocks/EnqueueBlocks.php b/src/Enqueue/Blocks/EnqueueBlocks.php index 527ceed60..b73faae57 100644 --- a/src/Enqueue/Blocks/EnqueueBlocks.php +++ b/src/Enqueue/Blocks/EnqueueBlocks.php @@ -16,6 +16,8 @@ use EightshiftForms\Enrichment\SettingsEnrichment; use EightshiftForms\Settings\Settings\SettingsSettings; use EightshiftForms\Captcha\SettingsCaptcha; +use EightshiftForms\CustomPostType\Result; +use EightshiftForms\CustomPostType\Forms; use EightshiftForms\Enqueue\SharedEnqueue; use EightshiftForms\Enqueue\Theme\EnqueueTheme; use EightshiftForms\Geolocation\SettingsGeolocation; @@ -165,7 +167,11 @@ public function enqueueBlockEditorScript(string $hook): void $output['validationPatternsOptions'] = $this->validationPatterns->getValidationPatternsEditor(); $output['mediaBreakpoints'] = \apply_filters($breakpointsFilterName, []); $output['formsSelectorTemplates'] = \apply_filters($formSelectorTemplatesFilterName, []); - $output['postType'] = \get_post_type() ? \get_post_type() : ''; + $output['currentPostType'] = \get_post_type() ? \get_post_type() : ''; + $output['postTypes'] = [ + 'results' => Result::POST_TYPE_SLUG, + 'forms' => Forms::POST_TYPE_SLUG, + ]; $output['settings'] = [ 'successRedirectVariations' => FiltersOuputMock::getSuccessRedirectVariationOptionsFilterValue()['data'], diff --git a/src/Entries/SettingsEntries.php b/src/Entries/SettingsEntries.php index 133493e02..fc9d6c4c0 100644 --- a/src/Entries/SettingsEntries.php +++ b/src/Entries/SettingsEntries.php @@ -10,6 +10,7 @@ namespace EightshiftForms\Entries; +use EightshiftFormsVendor\EightshiftFormsUtils\Config\UtilsConfig; use EightshiftFormsVendor\EightshiftFormsUtils\Helpers\UtilsGeneralHelper; use EightshiftFormsVendor\EightshiftFormsUtils\Helpers\UtilsSettingsOutputHelper; use EightshiftFormsVendor\EightshiftFormsUtils\Settings\UtilsSettingInterface; @@ -161,7 +162,7 @@ public function getSettingsData(string $formId): array 'component' => 'checkbox', 'checkboxLabel' => \__('Store entries in database', 'eightshift-forms'), // translators: %s is replaced with the form entries page URL. - 'checkboxHelp' => $isUsed ? \sprintf(\__("You can find all form entries here.", 'eightshift-forms'), UtilsGeneralHelper::getFormsEntriesPageUrl($formId)) : '', + 'checkboxHelp' => $isUsed ? \sprintf(\__("You can find all form entries here.", 'eightshift-forms'), UtilsGeneralHelper::getListingPageUrl(UtilsConfig::SLUG_ADMIN_LISTING_ENTRIES, $formId)) : '', 'checkboxIsChecked' => $isUsed, 'checkboxValue' => self::SETTINGS_ENTRIES_SETTINGS_USE_KEY, 'checkboxSingleSubmit' => true, diff --git a/src/Form/Form.php b/src/Form/Form.php index f5b624323..858729ad2 100644 --- a/src/Form/Form.php +++ b/src/Form/Form.php @@ -102,6 +102,12 @@ public function updateFormComponentAttributesOutput(array $attributes): array $attributes["{$prefix}CustomName"] = $customFormName; } + // Custom form name. + $attributes["{$prefix}HideGlobalMsgOnSuccess"] = !!UtilsSettingsHelper::isSettingCheckboxChecked(SettingsGeneral::SETTINGS_HIDE_GLOBAL_MSG_ON_SUCCESS_KEY, SettingsGeneral::SETTINGS_HIDE_GLOBAL_MSG_ON_SUCCESS_KEY, $formId); + + // Use single submit. + $attributes["{$prefix}UseSingleSubmit"] = UtilsSettingsHelper::isSettingCheckboxChecked(SettingsGeneral::SETTINGS_USE_SINGLE_SUBMIT_KEY, SettingsGeneral::SETTINGS_USE_SINGLE_SUBMIT_KEY, $formId); + // Phone sync with country block. $attributes["{$prefix}PhoneSync"] = ''; $filterName = UtilsHooksHelper::getFilterName(['block', 'form', 'phoneSync']); diff --git a/src/General/SettingsGeneral.php b/src/General/SettingsGeneral.php index d26a52b63..78e18a484 100644 --- a/src/General/SettingsGeneral.php +++ b/src/General/SettingsGeneral.php @@ -69,6 +69,16 @@ class SettingsGeneral implements UtilsSettingGlobalInterface, UtilsSettingInterf */ public const SETTINGS_GENERAL_FORM_CUSTOM_NAME_KEY = 'form-custom-name'; + /** + * Hide global message on success key. + */ + public const SETTINGS_HIDE_GLOBAL_MSG_ON_SUCCESS_KEY = 'hide-global-msg-on-success'; + + /** + * Use single submit key. + */ + public const SETTINGS_USE_SINGLE_SUBMIT_KEY = 'use-single-submit'; + /** * Register all the hooks * @@ -167,6 +177,25 @@ function ($selectOption) use ($successRedirectVariation) { ) ), ], + [ + 'component' => 'divider', + 'dividerExtraVSpacing' => true, + ], + [ + 'component' => 'checkboxes', + 'checkboxesFieldLabel' => '', + 'checkboxesName' => UtilsSettingsHelper::getSettingName(self::SETTINGS_HIDE_GLOBAL_MSG_ON_SUCCESS_KEY), + 'checkboxesContent' => [ + [ + 'component' => 'checkbox', + 'checkboxLabel' => \__('Hide global message on success', 'eightshift-forms'), + 'checkboxIsChecked' => UtilsSettingsHelper::isSettingCheckboxChecked(self::SETTINGS_HIDE_GLOBAL_MSG_ON_SUCCESS_KEY, self::SETTINGS_HIDE_GLOBAL_MSG_ON_SUCCESS_KEY, $formId), + 'checkboxValue' => self::SETTINGS_HIDE_GLOBAL_MSG_ON_SUCCESS_KEY, + 'checkboxSingleSubmit' => true, + 'checkboxAsToggle' => true, + ] + ] + ], ], ], [ @@ -261,6 +290,55 @@ function ($selectOption) use ($successRedirectVariation) { ] ], ], + [ + 'component' => 'tab', + 'tabLabel' => \__('Single submit', 'eightshift-forms'), + 'tabContent' => [ + [ + 'component' => 'checkboxes', + 'checkboxesFieldLabel' => '', + 'checkboxesName' => UtilsSettingsHelper::getSettingName(self::SETTINGS_USE_SINGLE_SUBMIT_KEY), + 'checkboxesContent' => [ + [ + 'component' => 'checkbox', + 'checkboxLabel' => \__('Use single submit', 'eightshift-forms'), + 'checkboxIsChecked' => UtilsSettingsHelper::isSettingCheckboxChecked(self::SETTINGS_USE_SINGLE_SUBMIT_KEY, self::SETTINGS_USE_SINGLE_SUBMIT_KEY, $formId), + 'checkboxValue' => self::SETTINGS_USE_SINGLE_SUBMIT_KEY, + 'checkboxSingleSubmit' => true, + 'checkboxAsToggle' => true, + ] + ] + ], + [ + 'component' => 'divider', + 'dividerExtraVSpacing' => true, + ], + [ + 'component' => 'intro', + 'introSubtitle' => \__('This option may create a large number of request to your server.
Use with caution!', 'eightshift-forms'), + 'introIsHighlighted' => true, + 'introIsHighlightedImportant' => true, + ], + [ + 'component' => 'intro', + 'introSubtitle' => \__(' + By selecting single submit form your form will not wait for the click on the submit button. + The form will submit data to the server as soon as the user changes are made. +

+ Not all fields are supported with this option. +
+ Supported fields are: +
    +
  • Input range
  • +
  • Checkbox
  • +
  • Radio
  • +
  • Rating
  • +
  • Select
  • +
+ ', 'eightshift-forms'), + ], + ], + ], ] ], ]; diff --git a/src/Hooks/Filters.php b/src/Hooks/Filters.php index 1675f173c..574097197 100644 --- a/src/Hooks/Filters.php +++ b/src/Hooks/Filters.php @@ -30,6 +30,7 @@ use EightshiftForms\Troubleshooting\SettingsDebug; use EightshiftForms\Troubleshooting\SettingsFallback; use EightshiftForms\Captcha\SettingsCaptcha; +use EightshiftForms\Integrations\Calculator\SettingsCalculator; use EightshiftForms\Integrations\Pipedrive\SettingsPipedrive; use EightshiftForms\Misc\SettingsCloudflare; use EightshiftForms\Misc\SettingsWpml; @@ -82,6 +83,8 @@ private static function getPublicFilters(): array 'preResponseAddonData', 'preResponseSuccessRedirectData', 'additionalHiddenFields', + 'resultOutputItems', + 'resultOutputParts', ], 'formSelector' => [ 'formTemplates', @@ -233,6 +236,9 @@ private static function getPublicFilters(): array SettingsPipedrive::SETTINGS_TYPE_KEY => [ 'prePostParams', ], + SettingsCalculator::SETTINGS_TYPE_KEY => [ + 'prePostParams', + ], ], 'entries' => [ 'prePostParams', diff --git a/src/Hooks/FiltersSettingsBuilder.php b/src/Hooks/FiltersSettingsBuilder.php index 7ab6fefbc..2df6dd3d2 100644 --- a/src/Hooks/FiltersSettingsBuilder.php +++ b/src/Hooks/FiltersSettingsBuilder.php @@ -54,6 +54,7 @@ use EightshiftForms\Troubleshooting\SettingsFallback; use EightshiftForms\Captcha\SettingsCaptcha; use EightshiftForms\Entries\SettingsEntries; +use EightshiftForms\Integrations\Calculator\SettingsCalculator; use EightshiftForms\Integrations\Pipedrive\PipedriveClient; use EightshiftForms\Integrations\Pipedrive\SettingsPipedrive; use EightshiftForms\Misc\SettingsCloudflare; @@ -436,6 +437,16 @@ public function getSettingsFiltersData(): array 'externalLink' => 'https://www.pipedrive.com/', ], ], + SettingsCalculator::SETTINGS_TYPE_KEY => [ + 'settingsGlobal' => SettingsCalculator::FILTER_SETTINGS_GLOBAL_NAME, + 'type' => UtilsConfig::SETTINGS_INTERNAL_TYPE_INTEGRATION, + 'integrationType' => UtilsConfig::INTEGRATION_TYPE_NO_BUILDER, + 'use' => SettingsCalculator::SETTINGS_CALCULATOR_USE_KEY, + 'labels' => [ + 'title' => \__('Calculator', 'eightshift-forms'), + 'desc' => \__('Calculator form type settings.', 'eightshift-forms'), + ], + ], // ------------------------------ // MISCELLANEOUS. // ------------------------------ diff --git a/src/Integrations/Calculator/SettingsCalculator.php b/src/Integrations/Calculator/SettingsCalculator.php new file mode 100644 index 000000000..8af7e9695 --- /dev/null +++ b/src/Integrations/Calculator/SettingsCalculator.php @@ -0,0 +1,95 @@ +> + */ + public function getSettingsGlobalData(): array + { + // Bailout if feature is not active. + if (!$this->isSettingsGlobalValid()) { + return UtilsSettingsOutputHelper::getNoActiveFeature(); + } + + return [ + UtilsSettingsOutputHelper::getIntro(self::SETTINGS_TYPE_KEY), + [ + 'component' => 'tabs', + 'tabsContent' => [ + [ + 'component' => 'tab', + 'tabLabel' => \__('General', 'eightshift-forms'), + 'tabContent' => [ + [ + 'component' => 'intro', + 'introSubtitle' => \__('Calculator is used to output dynamic data to the user, it doesn\'t send any emails nor is implemented in any integration.', 'eightshift-forms'), + ], + ], + ], + ], + ], + ]; + } +} diff --git a/src/Labels/Labels.php b/src/Labels/Labels.php index 56a4e22ae..5679d36ef 100644 --- a/src/Labels/Labels.php +++ b/src/Labels/Labels.php @@ -22,6 +22,7 @@ use EightshiftForms\Integrations\Workable\SettingsWorkable; use EightshiftFormsVendor\EightshiftFormsUtils\Helpers\UtilsSettingsHelper; use EightshiftForms\Captcha\SettingsCaptcha; +use EightshiftForms\Integrations\Calculator\SettingsCalculator; use EightshiftForms\Integrations\Pipedrive\SettingsPipedrive; /** @@ -46,6 +47,7 @@ class Labels implements LabelsInterface 'workableSuccess', 'jiraSuccess', 'pipedriveSuccess', + 'calculatorSuccess', ]; /** @@ -122,6 +124,11 @@ public function getLabels(): array $output = \array_merge($output, $this->getPipedriveLabels()); } + // Calculator. + if (UtilsSettingsHelper::isOptionCheckboxChecked(SettingsCalculator::SETTINGS_CALCULATOR_USE_KEY, SettingsCalculator::SETTINGS_CALCULATOR_USE_KEY)) { + $output = \array_merge($output, $this->getCalculatorLabels()); + } + return $output; } @@ -485,4 +492,18 @@ private function getPipedriveLabels(): array 'pipedriveSuccess' => \__('Application submitted successfully. Thank you!', 'eightshift-forms'), ]; } + + /** + * Return labels - Calculator + * + * @return array + */ + private function getCalculatorLabels(): array + { + return [ + 'calculatorErrorSettingsMissing' => \__('Calculator integration is not configured correctly. Please try again.', 'eightshift-forms'), + 'calculatorBadRequestError' => \__('Something is not right with the subscription. Please check all the fields and try again.', 'eightshift-forms'), + 'calculatorSuccess' => \__('Calculator result success. Thank you!', 'eightshift-forms'), + ]; + } } diff --git a/src/Listing/FormListingInterface.php b/src/Listing/FormListingInterface.php index 6a2338fef..132ca3ec7 100644 --- a/src/Listing/FormListingInterface.php +++ b/src/Listing/FormListingInterface.php @@ -18,9 +18,10 @@ interface FormListingInterface /** * Get Forms List. * - * @param string $status Status for listing to output. + * @param string $type Type of listing to output. + * @param string $parent Parent type for listing to output. * * @return array> */ - public function getFormsList(string $status): array; + public function getFormsList(string $type = '', string $parent = ''): array; } diff --git a/src/Listing/FormsListing.php b/src/Listing/FormsListing.php index ea9e78576..9a8a465d4 100644 --- a/src/Listing/FormsListing.php +++ b/src/Listing/FormsListing.php @@ -11,7 +11,9 @@ namespace EightshiftForms\Listing; use EightshiftForms\CustomPostType\Forms; +use EightshiftForms\CustomPostType\Result; use EightshiftForms\General\SettingsGeneral; +use EightshiftFormsVendor\EightshiftFormsUtils\Config\UtilsConfig; use EightshiftFormsVendor\EightshiftFormsUtils\Helpers\UtilsGeneralHelper; use EightshiftFormsVendor\EightshiftFormsUtils\Helpers\UtilsIntegrationsHelper; use WP_Query; @@ -24,25 +26,40 @@ class FormsListing implements FormListingInterface /** * Get Forms List. * - * @param string $status Status for listing to output. + * @param string $type Type of listing to output. + * @param string $parent Parent type for listing to output. * * @return array> */ - public function getFormsList(string $status): array + public function getFormsList(string $type = '', string $parent = ''): array { + $postType = Forms::POST_TYPE_SLUG; + $showTrash = false; + + switch ($type) { + case UtilsConfig::SLUG_ADMIN_LISTING_TRASH: + $postType = ($parent === UtilsConfig::SLUG_ADMIN_LISTING_RESULTS) ? Result::POST_TYPE_SLUG : Forms::POST_TYPE_SLUG; + $showTrash = true; + break; + case UtilsConfig::SLUG_ADMIN_LISTING_RESULTS: + $postType = Result::POST_TYPE_SLUG; + break; + default: + $postType = Forms::POST_TYPE_SLUG; + break; + } + // Prepare query args. $args = [ - 'post_type' => Forms::POST_TYPE_SLUG, + 'post_type' => $postType, 'posts_per_page' => 5000, // phpcs:ignore WordPress.WP.PostsPerPage.posts_per_page_posts_per_page - 'post_status' => $status, + 'post_status' => $showTrash ? 'trash' : '', ]; $theQuery = new WP_Query($args); $output = []; - $permanent = $status === 'trash'; - if (!$theQuery->have_posts()) { \wp_reset_postdata(); return []; @@ -56,10 +73,10 @@ public function getFormsList(string $status): array 'id' => $id, 'title' => \get_the_title($id), 'status' => \get_post_status($id), - 'settingsLink' => !$permanent ? UtilsGeneralHelper::getSettingsPageUrl((string) $id, SettingsGeneral::SETTINGS_TYPE_KEY) : '', - 'editLink' => !$permanent ? UtilsGeneralHelper::getFormEditPageUrl((string) $id) : '', - 'trashLink' => UtilsGeneralHelper::getFormTrashActionUrl((string) $id, $permanent), - 'entriesLink' => UtilsGeneralHelper::getFormsEntriesPageUrl((string) $id), + 'settingsLink' => UtilsGeneralHelper::getSettingsPageUrl((string) $id, SettingsGeneral::SETTINGS_TYPE_KEY), + 'editLink' => !$showTrash ? UtilsGeneralHelper::getFormEditPageUrl((string) $id) : '', + 'trashLink' => UtilsGeneralHelper::getFormTrashActionUrl((string) $id, $showTrash), + 'entriesLink' => UtilsGeneralHelper::getListingPageUrl(UtilsConfig::SLUG_ADMIN_LISTING_ENTRIES, (string) $id), 'trashRestoreLink' => UtilsGeneralHelper::getFormTrashRestoreActionUrl((string) $id), 'activeIntegration' => UtilsIntegrationsHelper::getIntegrationDetailsById((string) $id), 'useSync' => true, diff --git a/src/Rest/Routes/AbstractFormSubmit.php b/src/Rest/Routes/AbstractFormSubmit.php index cb76c4afe..1a6c32be4 100644 --- a/src/Rest/Routes/AbstractFormSubmit.php +++ b/src/Rest/Routes/AbstractFormSubmit.php @@ -403,6 +403,18 @@ protected function getIntegrationCommonSubmitOutput(array $formDetails, string $ $this->getFormSubmitMailer()->sendEmails($formDetails); } + // Return result output items as a response key. + $filterName = UtilsHooksHelper::getFilterName(['block', 'form', 'resultOutputItems']); + if (\has_filter($filterName)) { + $additionalOutput[UtilsHelper::getStateResponseOutputKey('resultOutputItems')] = \apply_filters($filterName, [], $formDetails, $formId) ?? []; + } + + // Output result output parts as a response key. + $filterName = UtilsHooksHelper::getFilterName(['block', 'form', 'resultOutputParts']); + if (\has_filter($filterName)) { + $additionalOutput[UtilsHelper::getStateResponseOutputKey('resultOutputParts')] = \apply_filters($filterName, [], $formDetails, $formId) ?? []; + } + $additionalOutput = \array_merge( $additionalOutput, UtilsApiHelper::getApiPublicAdditionalDataOutput($formDetails) diff --git a/src/Rest/Routes/Integrations/Calculator/FormSubmitCalculatorRoute.php b/src/Rest/Routes/Integrations/Calculator/FormSubmitCalculatorRoute.php new file mode 100644 index 000000000..668ebc697 --- /dev/null +++ b/src/Rest/Routes/Integrations/Calculator/FormSubmitCalculatorRoute.php @@ -0,0 +1,115 @@ +validator = $validator; + $this->validationPatterns = $validationPatterns; + $this->labels = $labels; + $this->captcha = $captcha; + $this->security = $security; + $this->formSubmitMailer = $formSubmitMailer; + } + + /** + * Get the base url of the route + * + * @return string The base URL for route you are adding. + */ + protected function getRouteName(): string + { + return '/' . UtilsConfig::ROUTE_PREFIX_FORM_SUBMIT . '/' . self::ROUTE_SLUG; + } + + /** + * Implement submit action. + * + * @param array $formDetails Data passed from the `getFormDetailsApi` function. + * + * @return mixed + */ + protected function submitAction(array $formDetails) + { + $formId = $formDetails[UtilsConfig::FD_FORM_ID]; + + $debug = [ + 'formDetails' => $formDetails, + ]; + + // Filter params. + $filterName = UtilsHooksHelper::getFilterName(['integrations', SettingsCalculator::SETTINGS_TYPE_KEY, 'prePostParams']); + if (\has_filter($filterName)) { + $formDetails[UtilsConfig::FD_PARAMS] = \apply_filters($filterName, $formDetails[UtilsConfig::FD_PARAMS], $formId) ?? []; + } + + $additionalOutput = []; + + // Output result output items as a response key. + $filterName = UtilsHooksHelper::getFilterName(['block', 'form', 'resultOutputItems']); + if (\has_filter($filterName)) { + $additionalOutput[UtilsHelper::getStateResponseOutputKey('resultOutputItems')] = \apply_filters($filterName, [], $formDetails, $formId) ?? []; + } + + // Output result output parts as a response key. + $filterName = UtilsHooksHelper::getFilterName(['block', 'form', 'resultOutputParts']); + if (\has_filter($filterName)) { + $additionalOutput[UtilsHelper::getStateResponseOutputKey('resultOutputParts')] = \apply_filters($filterName, [], $formDetails, $formId) ?? []; + } + + return \rest_ensure_response( + UtilsApiHelper::getApiSuccessPublicOutput( + $this->labels->getLabel('calculatorSuccess', $formId), + $additionalOutput, + $debug + ) + ); + } +} diff --git a/src/Rest/Routes/Integrations/Mailer/FormSubmitCustomRoute.php b/src/Rest/Routes/Integrations/Mailer/FormSubmitCustomRoute.php index 3d8422c02..a1d918306 100644 --- a/src/Rest/Routes/Integrations/Mailer/FormSubmitCustomRoute.php +++ b/src/Rest/Routes/Integrations/Mailer/FormSubmitCustomRoute.php @@ -22,6 +22,7 @@ use EightshiftForms\Security\SecurityInterface; use EightshiftForms\Validation\ValidationPatternsInterface; use EightshiftFormsVendor\EightshiftFormsUtils\Config\UtilsConfig; +use EightshiftFormsVendor\EightshiftFormsUtils\Helpers\UtilsHelper; use EightshiftFormsVendor\EightshiftFormsUtils\Helpers\UtilsHooksHelper; /** @@ -147,11 +148,25 @@ protected function submitAction(array $formDetails) ); } + $additionalOutput = []; + + // Output result output items as a response key. + $filterName = UtilsHooksHelper::getFilterName(['block', 'form', 'resultOutputItems']); + if (\has_filter($filterName)) { + $additionalOutput[UtilsHelper::getStateResponseOutputKey('resultOutputItems')] = \apply_filters($filterName, [], $formDetails, $formId) ?? []; + } + + // Output result output parts as a response key. + $filterName = UtilsHooksHelper::getFilterName(['block', 'form', 'resultOutputParts']); + if (\has_filter($filterName)) { + $additionalOutput[UtilsHelper::getStateResponseOutputKey('resultOutputParts')] = \apply_filters($filterName, [], $formDetails, $formId) ?? []; + } + // Finish. return \rest_ensure_response( UtilsApiHelper::getApiSuccessPublicOutput( $this->labels->getLabel('customSuccess', $formId), - [], + $additionalOutput, $debug ) ); diff --git a/src/Rest/Routes/Integrations/Mailer/FormSubmitMailer.php b/src/Rest/Routes/Integrations/Mailer/FormSubmitMailer.php index 2a16a094c..e8fb224d3 100644 --- a/src/Rest/Routes/Integrations/Mailer/FormSubmitMailer.php +++ b/src/Rest/Routes/Integrations/Mailer/FormSubmitMailer.php @@ -19,6 +19,7 @@ use EightshiftFormsVendor\EightshiftFormsUtils\Config\UtilsConfig; use EightshiftFormsVendor\EightshiftFormsUtils\Helpers\UtilsApiHelper; use EightshiftFormsVendor\EightshiftFormsUtils\Helpers\UtilsEncryption; +use EightshiftFormsVendor\EightshiftFormsUtils\Helpers\UtilsHelper; use EightshiftFormsVendor\EightshiftFormsUtils\Helpers\UtilsHooksHelper; use EightshiftFormsVendor\EightshiftFormsUtils\Helpers\UtilsSettingsHelper; @@ -127,10 +128,29 @@ public function sendEmails(array $formDetails, bool $useSuccessAction = false): $this->sendConfirmationEmail($formId, $params, $files); + $additionalOutput = []; + + // Output result output items as a response key. + $filterName = UtilsHooksHelper::getFilterName(['block', 'form', 'resultOutputItems']); + if (\has_filter($filterName)) { + $additionalOutput[UtilsHelper::getStateResponseOutputKey('resultOutputItems')] = \apply_filters($filterName, [], $formDetails, $formId) ?? []; + } + + // Output result output parts as a response key. + $filterName = UtilsHooksHelper::getFilterName(['block', 'form', 'resultOutputParts']); + if (\has_filter($filterName)) { + $additionalOutput[UtilsHelper::getStateResponseOutputKey('resultOutputParts')] = \apply_filters($filterName, [], $formDetails, $formId) ?? []; + } + + $additionalOutput = \array_merge( + $additionalOutput, + UtilsApiHelper::getApiPublicAdditionalDataOutput($formDetails) + ); + // Finish. return UtilsApiHelper::getApiSuccessPublicOutput( $this->labels->getLabel('mailerSuccess', $formId), - UtilsApiHelper::getApiPublicAdditionalDataOutput($formDetails), + $additionalOutput, $debug ); } diff --git a/src/Rest/Routes/Settings/BulkRoute.php b/src/Rest/Routes/Settings/BulkRoute.php index 5ae260dc9..c44c4e8b5 100644 --- a/src/Rest/Routes/Settings/BulkRoute.php +++ b/src/Rest/Routes/Settings/BulkRoute.php @@ -224,7 +224,7 @@ private function output(array $details, string $type): array if (\count($details) > 1) { $msgOutput = [ // translators: %s replaces type. - \sprintf(\esc_html__('Not all forms were %s with success. Please check the following log.', 'eightshift-forms'), $intrernaType, $msg), + \sprintf(\esc_html__('Not all items were %s with success. Please check the following log.', 'eightshift-forms'), $intrernaType), ]; if ($error) { @@ -252,22 +252,20 @@ private function output(array $details, string $type): array return [ 'status' => 'success', // translators: %s replaces form msg type. - 'msg' => \sprintf(\esc_html__('Success, all selected %1$s were %2$s.', 'eightshift-forms'), $intrernaType, $msg), + 'msg' => \sprintf(\esc_html__('Success, all selected items were %s.', 'eightshift-forms'), $msg), ]; } if ($skip) { return [ 'status' => 'warning', - // translators: %s replaces form msg type. - 'msg' => \sprintf(\esc_html__('Warning, all selected %s were skipped.', 'eightshift-forms'), $intrernaType), + 'msg' => \esc_html__('Warning, all selected items were skipped.', 'eightshift-forms'), ]; } return [ 'status' => 'error', - // translators: %s replaces form msg type. - 'msg' => \sprintf(\esc_html__('There was and error on all selected %s.', 'eightshift-forms'), $intrernaType), + 'msg' => \esc_html__('There was an error on all selected items.', 'eightshift-forms'), ]; } @@ -320,7 +318,7 @@ private function delete(array $ids): array if (!$title) { // translators: %s replaces form id. - $title = \sprintf(\esc_html__('Form %s', 'eightshift-forms'), $id); + $title = \sprintf(\esc_html__('Item %s', 'eightshift-forms'), $id); } $action = \wp_trash_post((int) $id); @@ -351,7 +349,7 @@ private function deletePerminently(array $ids): array if (!$title) { // translators: %s replaces form id. - $title = \sprintf(\esc_html__('Form %s', 'eightshift-forms'), $id); + $title = \sprintf(\esc_html__('Item %s', 'eightshift-forms'), $id); } $action = \wp_delete_post((int) $id, true); @@ -413,7 +411,7 @@ private function restore(array $ids): array if (!$title) { // translators: %s replaces form id. - $title = \sprintf(\esc_html__('Form %s', 'eightshift-forms'), $id); + $title = \sprintf(\esc_html__('Item %s', 'eightshift-forms'), $id); } $action = \wp_update_post([ @@ -447,7 +445,7 @@ private function duplicate(array $ids): array if (!$title) { // translators: %s replaces form id. - $title = \sprintf(\esc_html__('Form %s', 'eightshift-forms'), $id); + $title = \sprintf(\esc_html__('Item %s', 'eightshift-forms'), $id); } $export = $this->transfer->getExportForm((string) $id); diff --git a/src/Shortcode/ShortcodeLink.php b/src/Shortcode/Link.php similarity index 85% rename from src/Shortcode/ShortcodeLink.php rename to src/Shortcode/Link.php index 2ed659542..216cef317 100644 --- a/src/Shortcode/ShortcodeLink.php +++ b/src/Shortcode/Link.php @@ -1,7 +1,7 @@ 'something', - 'label' => 'something else', + 'url' => '', + 'label' => '', ], $atts ); diff --git a/src/Shortcode/ResultOutputItemPart.php b/src/Shortcode/ResultOutputItemPart.php new file mode 100644 index 000000000..e9b312b58 --- /dev/null +++ b/src/Shortcode/ResultOutputItemPart.php @@ -0,0 +1,61 @@ + $atts Attributes passed to the shortcode. + * @param string $content Content inside the shortcode. + * + * @return string + */ + public function callback(array $atts, string $content): string + { + $params = \shortcode_atts( + [ + 'name' => '', + ], + $atts + ); + + $name = isset($params['name']) ? \esc_html($params['name']) : ''; + + if (!$name || !$content) { + return ''; + } + + $classSelector = UtilsHelper::getStateSelector('resultOutputPart'); + + $attrPartName = UtilsHelper::getStateAttribute('resultOutputPart'); + $attrPartDefaultName = UtilsHelper::getStateAttribute('resultOutputPartDefault'); + + return "{$content}"; + } +} diff --git a/src/Validation/Validator.php b/src/Validation/Validator.php index 1bdffb29f..96592303e 100644 --- a/src/Validation/Validator.php +++ b/src/Validation/Validator.php @@ -15,6 +15,7 @@ use EightshiftFormsVendor\EightshiftFormsUtils\Helpers\UtilsGeneralHelper; use EightshiftFormsVendor\EightshiftFormsUtils\Helpers\UtilsUploadHelper; use EightshiftForms\Integrations\Airtable\SettingsAirtable; +use EightshiftForms\Integrations\Calculator\SettingsCalculator; use EightshiftForms\Integrations\Jira\SettingsJira; use EightshiftForms\Integrations\Mailer\SettingsMailer; use EightshiftForms\Integrations\Pipedrive\SettingsPipedrive; @@ -429,6 +430,7 @@ public function validateFormManadatoryProperies(array $formDetails): bool case SettingsMailer::SETTINGS_TYPE_KEY: case SettingsJira::SETTINGS_TYPE_KEY: case SettingsPipedrive::SETTINGS_TYPE_KEY: + case SettingsCalculator::SETTINGS_TYPE_KEY: if (!$formId || !$postId) { return false; }