Compare commits

...

13 Commits

31 changed files with 560 additions and 452 deletions

9
.artifactignore Normal file
View File

@ -0,0 +1,9 @@
src
node_modules
README.md
.*
package.json
yarn.lock
webpack.config.js
tsconfig.json

View File

@ -1,8 +1,13 @@
{
"root": true,
"parser": "babel-eslint",
"parser": "@typescript-eslint/parser",
"plugins": [
"@typescript-eslint",
"react",
"jsx-a11y",
"jest"
],
"extends": [
"wordpress",
"plugin:react/recommended",
"plugin:jsx-a11y/recommended",
"plugin:jest/recommended"
@ -26,7 +31,6 @@
"window": true,
"document": true
},
"plugins": ["react", "jsx-a11y", "jest"],
"settings": {
"react": {
"pragma": "wp"

32
README.md Normal file
View File

@ -0,0 +1,32 @@
# Cognito Forms WordPress Plugin
## Development
1. Install [Docker Desktop](https://www.docker.com/products/docker-desktop) and [Yarn](https://yarnpkg.com/)
2. Start WordPress and MariaDB using `docker-compose`:
docker-compose up -d
3. Install the necessary NPM packages:
yarn install
4. Build the Gutenberg Block:
yarn build
or run the development server:
yarn start
5. Visit the local WordPress instance at `localhost:8085` and go through the installation steps
6. Enable the Cognito Forms plugin (Plugins > Installed Plugins > Cognito Forms)
7. Hack away ⚙️
## Deploy
Plugin is automatically built in a DevOps pipeline.
Details under construction 🚧

64
api.php
View File

@ -1,64 +0,0 @@
<?php
/**
* Cognito Forms WordPress Plugin.
*
* The Cognito Forms WordPress Plugin is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License, version 2, as
* published by the Free Software Foundation.
*
* The Cognito Forms WordPress Plugin is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
// Cognito API access
class CognitoAPI {
public static $servicesBase = 'https://services.cognitoforms.com/';
public static $formsBase = 'https://www.cognitoforms.com/';
// Fetches all forms for an organization
// $api_key - API Key for the organization
public static function get_forms($api_key) {
$response = wp_remote_fopen(self::$servicesBase . 'forms/api/' . $api_key . '/forms');
return $response;
}
// Fetches organization information for a given member
// $session_token - Valid session token
public static function get_organization($session_token) {
$response = wp_remote_fopen(self::$servicesBase . 'member/admin/organization?token=' . urlencode($session_token));
$organization = json_decode($response);
return $organization;
}
// Builds form embed script
public static function get_form_embed_script($public_key, $formId) {
$base = self::$servicesBase;
return <<< EOF
<div class="cognito">
<script src="{$base}session/script/{$public_key}"></script>
<script>Cognito.load("forms", { id: "{$formId}" });</script>
</div>
EOF;
}
// Builds Cognito module embed script
public static function get_embed_script($key, $module) {
$base = self::$servicesBase;
return <<< EOF
<div class="cognito">
<script src="{$base}session/script/{$key}"></script>
<script>Cognito.load("{$module}");</script>
</div>
EOF;
}
}
?>

16
azure-pipelines.yaml Normal file
View File

@ -0,0 +1,16 @@
trigger:
- main
pool:
vmImage: 'ubuntu-latest'
steps:
- script: yarn install
displayName: 🛠️ Install Dependencies
- script: yarn build
displayName: 🚀 Build Plugin
- task: PublishPipelineArtifact@1
displayName: 📦 Create Artifact
inputs:
targetPath: $(System.DefaultWorkingDirectory)
artifactName: CognitoFormsPlugin

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -1,13 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
version="1.1"
viewBox="-4.6 230 110.9 111"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<path
id="path4"
class="st0"
d="M 48.599609 0 L 45.699219 16 C 41.699219 17.1 37.999609 18.4 34.599609 20.5 L 21.5 11.5 L 11.699219 20.699219 L 20.599609 34.699219 C 18.399609 38.199219 16.9 41.900391 16 45.900391 L 0 48.699219 L 0 62.699219 L 15.900391 65.599609 C 17.000391 69.699609 18.499219 73.4 20.699219 77 C 20.699219 77 21.199609 77.9 20.599609 77 L 20.5 76.900391 L 11.5 90 L 21.300781 99.800781 L 34.5 90.800781 C 38 93.000781 41.699219 94.499609 45.699219 95.599609 L 48.5 111 L 62.400391 111 L 65.199219 95.099609 C 69.199219 94.099609 73.099609 92.5 76.599609 90.5 L 89.699219 99.5 L 99.5 89.699219 L 90.5 76.599609 C 92.6 73.099609 94.200781 69.299219 95.300781 65.199219 L 110.90039 62.400391 L 110.90039 48.5 L 95.300781 45.699219 C 94.200781 41.699219 92.7 37.900781 90.5 34.300781 L 99.5 21.199219 L 89.699219 11.400391 L 76.599609 20.599609 C 72.699609 18.299609 65.400391 16 65.400391 16 L 62.5 0 L 48.599609 0 z M 55.800781 26.599609 C 63.900781 26.599609 70.7 29.300391 76 34.900391 C 78.2 37.200391 80.1 39.799609 81.5 43.099609 C 80.6 44.899609 79.9 46.699219 79.5 48.699219 L 66.599609 50.900391 C 64.599609 45.300391 60.699219 42.900391 55.199219 42.900391 C 51.599219 42.900391 48.7 44.1 46.5 46.5 C 44.2 48.9 43.099609 51.899219 43.099609 55.699219 C 43.099609 59.299219 44.200391 62.199609 46.400391 64.599609 C 48.700391 66.999609 51.500391 68.099609 54.900391 68.099609 C 58.400391 68.099609 61.099219 67.1 63.199219 65 C 64.499219 63.8 65.3 62.300391 66 60.400391 L 79.400391 62.900391 L 79.400391 62.800781 C 79.800391 64.500781 80.399609 66.199219 81.099609 67.699219 C 79.699609 71.099219 77.700781 74.2 74.800781 77 C 69.800781 81.8 63.300781 84.199219 55.300781 84.199219 C 47.200781 84.199219 40.300781 81.5 34.800781 76 C 29.300781 70.5 26.5 63.699609 26.5 55.599609 C 26.5 47.399609 29.3 40.500391 35 34.900391 C 40.6 29.400391 47.600781 26.599609 55.800781 26.599609 z "
transform="translate(-4.6,230)" />
</svg>
<svg id="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 18 18"><defs><style>.cls-1{fill:#d85427;}.cls-2{fill:#fff;}</style></defs><g id="cogicon"><path id="cogicon__cog" class="cls-1" d="M5,14.19l1.54-1.06a4.89,4.89,0,0,0,1.31.56l.33,1.81H9.81l.33-1.86a5.38,5.38,0,0,0,1.34-.54L13,14.15,14.16,13,13.1,11.47a5.46,5.46,0,0,0,.57-1.34L15.5,9.8V8.17l-1.83-.32a5.21,5.21,0,0,0-.56-1.33L14.16,5,13,3.83,11.48,4.91a8.28,8.28,0,0,0-1.32-.54L9.82,2.5H8.19L7.85,4.37a4.87,4.87,0,0,0-1.3.53L5,3.84,3.87,4.92l1,1.64a4.53,4.53,0,0,0-.54,1.31L2.5,8.2V9.84l1.86.34a5,5,0,0,0,.55,1.3L3.87,13Z"/><path id="cogicon__c" class="cls-2" d="M8,10.1a1.33,1.33,0,0,0,1,.42,1.37,1.37,0,0,0,1-.37,1.51,1.51,0,0,0,.33-.56l1.54.29.5.11s-.15.41-.15.41a3.84,3.84,0,0,1-.83,1.21A3.23,3.23,0,0,1,9,12.48,3.4,3.4,0,0,1,5.56,9.16V9a3.34,3.34,0,0,1,1-2.49,3.38,3.38,0,0,1,2.51-1,3.2,3.2,0,0,1,2.43,1,3.15,3.15,0,0,1,.67,1,2.54,2.54,0,0,1,.19.59l-2,.36A1.33,1.33,0,0,0,9,7.49a1.34,1.34,0,0,0-1,.43A1.6,1.6,0,0,0,7.57,9,1.53,1.53,0,0,0,8,10.1Z"/></g></svg>

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

BIN
gear.ico

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -33,6 +33,7 @@
"@wordpress/block-editor": "^8.0.13",
"@wordpress/blocks": "^11.1.5",
"@wordpress/i18n": "^4.2.4",
"@wordpress/icons": "^6.1.1",
"@wordpress/scripts": "^19.2.2",
"classnames": "^2.2.6",
"react": "^17.0.2",
@ -45,7 +46,10 @@
"webpack-cli": "^4.9.1"
},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^5.10.0",
"@typescript-eslint/parser": "^5.10.0",
"concurrently": "^7.0.0",
"eslint-plugin-jest": "^25.7.0",
"prettier": "^2.0.5",
"sass": "^1.48.0",
"shx": "^0.3.4",

View File

@ -49,7 +49,7 @@ if ( !class_exists('CognitoFormsPlugin') ) {
add_action($action, array($this, $action));
}
// Registers tinyMCE filters
// Registers plug-in filters
private function addFilters($filters) {
foreach($filters as $filter)
add_filter($filter, array($this, $filter));
@ -60,34 +60,19 @@ if ( !class_exists('CognitoFormsPlugin') ) {
$this->addActions(self::$actions);
}
public function init() {
// Initialize Gutenberg Block
$this->block_init();
// Add support for oEmbed
$this->oembed_init();
}
// Initialize plug-in
public function admin_init() {
if(!current_user_can('edit_posts') && !current_user_can('edit_pages')) return;
register_setting('cognito_plugin', 'cognito_api_key');
register_setting('cognito_plugin', 'cognito_admin_key');
register_setting('cognito_plugin', 'cognito_public_key');
register_setting('cognito_plugin', 'cognito_organization');
// If the flag to delete options was passed-in, delete them
if (isset($_GET['cog_clear']) && $_GET['cog_clear'] == '1') {
delete_option('cognito_api_key');
delete_option('cognito_admin_key');
delete_option('cognito_public_key');
delete_option('cognito_organization');
}
// Add tinyMCE plug-in
if(get_user_option('rich_editing') == 'true') {
$this->addfilters(array(
'mce_buttons',
'mce_external_plugins'
));
}
}
public function init() {
$this->block_init();
// Initialize TinyMCE Plugin
$this->tinymce_init();
}
// Initialize block
@ -131,26 +116,34 @@ if ( !class_exists('CognitoFormsPlugin') ) {
) );
}
// Set up tinyMCE buttons
public function mce_buttons($buttons) {
// Initialize classic editor (TinyMCE)
public function tinymce_init() {
if(get_user_option('rich_editing') == 'true') {
$this->addFilters(array(
'mce_buttons',
'mce_external_plugins'
));
}
}
// Set up TinyMCE buttons
public function mce_buttons( $buttons ) {
array_push($buttons, '|', 'cognito');
return $buttons;
}
// Initialize tinyMCE plug-in
public function mce_external_plugins($plugins) {
$plugins['cognito'] = plugin_dir_url( __FILE__ ) . 'tinymce/plugin.js';
return $plugins;
// Initialize TinyMCE plug-in
public function mce_external_plugins( $plugin_array ) {
$plugin_array['cognito_mce_plugin'] = plugins_url( '/tinymce/plugin.js', __FILE__ );
return $plugin_array;
}
// Initialize administration menu (left-bar)
public function admin_menu() {
add_menu_page('Cognito Forms', 'Cognito Forms', 'manage_options', 'Cognito', array($this, 'main_page'), plugin_dir_url( __FILE__ ).'cogicon.ico');
add_submenu_page('Cognito', 'Cognito Forms', 'View Forms', 'manage_options', 'Cognito', array($this, 'main_page'));
add_submenu_page('Cognito', 'Create Form', 'New Form', 'manage_options', 'CognitoCreateForm', array($this, 'main_page'));
add_submenu_page('Cognito', 'Templates', 'Templates', 'manage_options', 'CognitoTemplates', array($this, 'main_page'));
add_options_page('Cognito Options', 'Cognito Forms', 'manage_options', 'CognitoOptions', array($this, 'options_page'));
add_menu_page( 'Cognito Forms', 'Cognito Forms', 'manage_options', 'Cognito', array( $this, 'main_page' ), "data:image/svg+xml;base64," . base64_encode( '<?xml version="1.0" encoding="UTF-8"?><svg id="icon" version="1.1" viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg"><path fill="black" d="m8.0125 1.0813-0.41402 2.2771a5.9329 5.9329 0 0 0-1.5823 0.6472l-1.8893-1.292-1.3777 1.3158 1.2183 1.9987a5.5187 5.5187 0 0 0-0.65672 1.5942l-2.2295 0.40212v1.9987l2.2652 0.41402a6.0913 6.0913 0 0 0 0.671 1.5847l-1.2682 1.8512 1.3777 1.4491 1.875-1.2896a5.9573 5.9573 0 0 0 1.5966 0.68052l0.40212 2.2057h1.9868l0.40212-2.2652a6.5543 6.5543 0 0 0 1.6323-0.6591l1.8512 1.2801 1.4134-1.4015-1.292-1.8631a6.6517 6.6517 0 0 0 0.69479-1.6323l2.2295-0.40212v-1.9868l-2.2295-0.39023a6.3472 6.3472 0 0 0-0.68289-1.6204l1.2801-1.8512-1.4134-1.4253-1.8512 1.3158a10.087 10.087 0 0 0-1.6085-0.6591l-0.41402-2.2771zm1.0731 3.6667a3.8984 3.8984 0 0 1 2.96 1.2183 3.8375 3.8375 0 0 1 0.81614 1.2183 3.0944 3.0944 0 0 1 0.2308 0.71859l-2.4365 0.44019a1.6203 1.6203 0 0 0-1.6561-1.1826 1.6325 1.6325 0 0 0-1.2183 0.52347 1.9492 1.9492 0 0 0-0.52347 1.3158 1.8639 1.8639 0 0 0 0.52347 1.3396 1.6203 1.6203 0 0 0 1.2183 0.51158 1.669 1.669 0 0 0 1.2183-0.44971 1.8396 1.8396 0 0 0 0.40212-0.6829l1.875 0.35453 0.60913 0.13325-0.18084 0.49968a4.6781 4.6781 0 0 1-1.0113 1.4729 3.935 3.935 0 0 1-2.9124 1.0612 4.1421 4.1421 0 0 1-4.1902-4.045v-0.19511a4.069 4.069 0 0 1 1.2183-3.0338 4.1177 4.1177 0 0 1 3.0576-1.2183z" stroke-width="1.2183"/></svg>' ) );
add_submenu_page( 'Cognito', 'Cognito Forms', 'View Forms', 'manage_options', 'Cognito', array( $this, 'main_page' ) );
add_submenu_page( 'Cognito', 'Create Form', 'New Form', 'manage_options', 'CognitoCreateForm', array( $this, 'main_page' ) );
add_submenu_page( 'Cognito', 'Templates', 'Templates', 'manage_options', 'CognitoTemplates', array( $this, 'main_page' ) );
}
// Entrypoint for Cognito Forms access
@ -158,9 +151,11 @@ if ( !class_exists('CognitoFormsPlugin') ) {
include 'templates/main.php';
}
public function options_page() {
include 'templates/options.php';
// Add support for oEmbed using the generic Gutenberg Embed block
public function oembed_init() {
wp_oembed_add_provider( '#https?://(www\.)?cognitoforms\.com/.*#i', 'https://www.cognitoforms.com/f/oembed/', true );
}
}
new CognitoFormsPlugin;
}

1
src/assets/cogicon.svg Normal file
View File

@ -0,0 +1 @@
<svg version="1.1" viewBox="-4.6 230 110.9 111" xmlns="http://www.w3.org/2000/svg"><path id="path4" class="st0" d="M 48.599609 0 L 45.699219 16 C 41.699219 17.1 37.999609 18.4 34.599609 20.5 L 21.5 11.5 L 11.699219 20.699219 L 20.599609 34.699219 C 18.399609 38.199219 16.9 41.900391 16 45.900391 L 0 48.699219 L 0 62.699219 L 15.900391 65.599609 C 17.000391 69.699609 18.499219 73.4 20.699219 77 C 20.699219 77 21.199609 77.9 20.599609 77 L 20.5 76.900391 L 11.5 90 L 21.300781 99.800781 L 34.5 90.800781 C 38 93.000781 41.699219 94.499609 45.699219 95.599609 L 48.5 111 L 62.400391 111 L 65.199219 95.099609 C 69.199219 94.099609 73.099609 92.5 76.599609 90.5 L 89.699219 99.5 L 99.5 89.699219 L 90.5 76.599609 C 92.6 73.099609 94.200781 69.299219 95.300781 65.199219 L 110.90039 62.400391 L 110.90039 48.5 L 95.300781 45.699219 C 94.200781 41.699219 92.7 37.900781 90.5 34.300781 L 99.5 21.199219 L 89.699219 11.400391 L 76.599609 20.599609 C 72.699609 18.299609 65.400391 16 65.400391 16 L 62.5 0 L 48.599609 0 z M 55.800781 26.599609 C 63.900781 26.599609 70.7 29.300391 76 34.900391 C 78.2 37.200391 80.1 39.799609 81.5 43.099609 C 80.6 44.899609 79.9 46.699219 79.5 48.699219 L 66.599609 50.900391 C 64.599609 45.300391 60.699219 42.900391 55.199219 42.900391 C 51.599219 42.900391 48.7 44.1 46.5 46.5 C 44.2 48.9 43.099609 51.899219 43.099609 55.699219 C 43.099609 59.299219 44.200391 62.199609 46.400391 64.599609 C 48.700391 66.999609 51.500391 68.099609 54.900391 68.099609 C 58.400391 68.099609 61.099219 67.1 63.199219 65 C 64.499219 63.8 65.3 62.300391 66 60.400391 L 79.400391 62.900391 L 79.400391 62.800781 C 79.800391 64.500781 80.399609 66.199219 81.099609 67.699219 C 79.699609 71.099219 77.700781 74.2 74.800781 77 C 69.800781 81.8 63.300781 84.199219 55.300781 84.199219 C 47.200781 84.199219 40.300781 81.5 34.800781 76 C 29.300781 70.5 26.5 63.699609 26.5 55.599609 C 26.5 47.399609 29.3 40.500391 35 34.900391 C 40.6 29.400391 47.600781 26.599609 55.800781 26.599609 z " transform="translate(-4.6,230)" /></svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@ -1,3 +0,0 @@
import * as React from 'react';
export default <svg version="1.1" viewBox="-4.6 230 110.9 111" xmlns="http://www.w3.org/2000/svg"><path id="path4" className="st0" d="M 48.599609 0 L 45.699219 16 C 41.699219 17.1 37.999609 18.4 34.599609 20.5 L 21.5 11.5 L 11.699219 20.699219 L 20.599609 34.699219 C 18.399609 38.199219 16.9 41.900391 16 45.900391 L 0 48.699219 L 0 62.699219 L 15.900391 65.599609 C 17.000391 69.699609 18.499219 73.4 20.699219 77 C 20.699219 77 21.199609 77.9 20.599609 77 L 20.5 76.900391 L 11.5 90 L 21.300781 99.800781 L 34.5 90.800781 C 38 93.000781 41.699219 94.499609 45.699219 95.599609 L 48.5 111 L 62.400391 111 L 65.199219 95.099609 C 69.199219 94.099609 73.099609 92.5 76.599609 90.5 L 89.699219 99.5 L 99.5 89.699219 L 90.5 76.599609 C 92.6 73.099609 94.200781 69.299219 95.300781 65.199219 L 110.90039 62.400391 L 110.90039 48.5 L 95.300781 45.699219 C 94.200781 41.699219 92.7 37.900781 90.5 34.300781 L 99.5 21.199219 L 89.699219 11.400391 L 76.599609 20.599609 C 72.699609 18.299609 65.400391 16 65.400391 16 L 62.5 0 L 48.599609 0 z M 55.800781 26.599609 C 63.900781 26.599609 70.7 29.300391 76 34.900391 C 78.2 37.200391 80.1 39.799609 81.5 43.099609 C 80.6 44.899609 79.9 46.699219 79.5 48.699219 L 66.599609 50.900391 C 64.599609 45.300391 60.699219 42.900391 55.199219 42.900391 C 51.599219 42.900391 48.7 44.1 46.5 46.5 C 44.2 48.9 43.099609 51.899219 43.099609 55.699219 C 43.099609 59.299219 44.200391 62.199609 46.400391 64.599609 C 48.700391 66.999609 51.500391 68.099609 54.900391 68.099609 C 58.400391 68.099609 61.099219 67.1 63.199219 65 C 64.499219 63.8 65.3 62.300391 66 60.400391 L 79.400391 62.900391 L 79.400391 62.800781 C 79.800391 64.500781 80.399609 66.199219 81.099609 67.699219 C 79.699609 71.099219 77.700781 74.2 74.800781 77 C 69.800781 81.8 63.300781 84.199219 55.300781 84.199219 C 47.200781 84.199219 40.300781 81.5 34.800781 76 C 29.300781 70.5 26.5 63.699609 26.5 55.599609 C 26.5 47.399609 29.3 40.500391 35 34.900391 C 40.6 29.400391 47.600781 26.599609 55.800781 26.599609 z " transform="translate(-4.6,230)" /></svg>;

View File

@ -1,55 +0,0 @@
/**
* WordPress dependencies
*/
import * as React from 'react';
import { __ } from '@wordpress/i18n';
import {
ToolbarButton,
PanelBody,
ToggleControl,
ToolbarGroup,
} from '@wordpress/components';
import { BlockControls, InspectorControls } from '@wordpress/block-editor';
import { edit } from '@wordpress/icons';
const EmbedControls = ( {
blockSupportsResponsive,
showEditButton,
themeSupportsResponsive,
allowResponsive,
getResponsiveHelp,
toggleResponsive,
switchBackToURLInput,
} ) => (
<>
<BlockControls>
<ToolbarGroup>
{ showEditButton && (
<ToolbarButton
className="components-toolbar__control"
label={ __( 'Edit URL' ) }
icon={ edit }
onClick={ switchBackToURLInput }
/>
) }
</ToolbarGroup>
</BlockControls>
{ themeSupportsResponsive && blockSupportsResponsive && (
<InspectorControls>
<PanelBody
title={ __( 'Media settings' ) }
className="blocks-responsive"
>
<ToggleControl
label={ __( 'Resize for smaller devices' ) }
checked={ allowResponsive }
help={ getResponsiveHelp }
onChange={ toggleResponsive }
/>
</PanelBody>
</InspectorControls>
) }
</>
);
export default EmbedControls;

View File

@ -0,0 +1,101 @@
/**
* WordPress dependencies
*/
import * as React from 'react';
import * as _ from 'lodash';
import { Spinner } from '@wordpress/components';
import { baseUrl } from '@/globals';
import { ReactComponent as CogIcon } from '@/assets/cogicon.svg';
type PreviewProps = {
formId: string;
embedCode: string;
};
type PreviewState = {
uniqueId: string;
loading: boolean;
};
class PreviewForm extends React.Component<PreviewProps, PreviewState> {
constructor( props: any ) {
super( props );
// Generate a unique identifier, so that the embed script can be identified
// and removed from the page once it is no longer needed.
this.state = {
uniqueId: _.uniqueId(),
loading: true,
};
}
componentDidMount() {
this.loadEmbedScript( this.formReady.bind( this ) );
}
componentWillUnmount() {
this.removeEmbedScript();
}
// Force the embed script to load, which makes Iframes in the editor resize properly.
loadEmbedScript( callback?: Function ) {
const existingScript = document.getElementById( `cog-embed-script-${ this.state.uniqueId }` );
if ( ! existingScript ) {
const script = document.createElement( 'script' );
script.src = `${ baseUrl }/f/iframe.js`;
script.id = `cog-embed-script-${ this.state.uniqueId }`;
document.body.appendChild( script );
script.onload = () => {
if ( callback ) callback();
};
}
if ( existingScript && callback ) callback();
}
// Clean up before block is removed
removeEmbedScript() {
const existingScript = document.getElementById( `cog-embed-script-${ this.state.uniqueId }` );
if ( existingScript ) {
existingScript.remove();
}
}
// Check if form is loaded
formReady() {
this.setState( { loading: false } );
}
render() {
return (
<div className="form-preview">
<div className="focus-grabber"></div>
{ this.state.loading &&
<div className="loader">
<div className="icon">
<CogIcon />
</div>
<p>
Loading...
</p>
<Spinner />
</div>
}
<div
className="cog-wp-embed cog-wp-embed__preview"
dangerouslySetInnerHTML={ { __html: this.props.embedCode } } // Must be Iframe embed code as others do not work in Gutenberg
id={ `cog-form-${ this.state.uniqueId }` }
></div>
</div>
);
}
}
export default PreviewForm;

View File

@ -32,9 +32,10 @@ class SelectDialog extends React.Component<DialogProps, DialogState> {
}
handlePostMessage = ( event: MessageEvent ) => {
console.log( 'PostMessage recieved:', event.data );
if (event.origin === baseUrl && event.data.type === 'cog-form-selected') {
this.props.onSelectForm( event.data );
this.setState({ isOpen: false });
this.setState({ isOpen: false }); // Close Dialog
}
}
render() {

View File

@ -2,27 +2,49 @@ import * as React from 'react';
import { __ } from '@wordpress/i18n';
import { BlockEditProps } from '@wordpress/blocks';
import { Placeholder, ExternalLink } from '@wordpress/components';
import {
Placeholder,
ToolbarButton,
RadioControl,
PanelBody,
PanelRow,
ExternalLink,
} from '@wordpress/components';
import { edit } from '@wordpress/icons';
import CogIcon from '@/assets/cogicon';
import { BlockControls, InspectorControls } from '@wordpress/block-editor';
import { ReactComponent as CogIcon } from '@/assets/cogicon.svg';
import SelectDialog from '@/components/select-dialog';
import PreviewForm from '@/components/preview-form';
import { BlockAttributes, EmbedMode } from '@/types';
const Edit: React.FC<BlockEditProps<BlockAttributes>> = ( { attributes, setAttributes, className } ) => {
const handleForm = ( form: string ) => {
const formObj = JSON.parse( form );
const handleForm = ( form: { [key: string]: any } ) => {
setAttributes( {
formId: formObj.formId,
seamlessEmbedCode: formObj.embedCodes.Seamless,
iframeEmbedCode: formObj.embedCodes.IFrame,
ampEmbedCode: formObj.embedCodes.Amp,
formId: form.formId,
seamlessEmbedCode: form.embedCodes.Seamless,
iframeEmbedCode: form.embedCodes.IFrame,
ampEmbedCode: form.embedCodes.Amp,
embedMode: EmbedMode.Seamless,
} );
};
const resetForm = () => {
// Create a new object which sets all attributes to null
const nullAttributes = Object.keys( attributes ).reduce(
( accumulator, current ) => {
// @ts-ignore
accumulator[ current ] = null;
return accumulator;
}, {} );
setAttributes( nullAttributes );
};
if ( ! attributes.formId ) {
return (
<div>
<Placeholder
icon={ CogIcon }
label="Cognito Forms"
@ -32,26 +54,49 @@ const Edit: React.FC<BlockEditProps<BlockAttributes>> = ( { attributes, setAttri
) }
>
<SelectDialog onSelectForm={ handleForm }></SelectDialog>
<br />
<div className="components-placeholder__learn-more">
<ExternalLink
href={ __(
'https://wordpress.org/support/article/embeds/'
) }
>
{ __( 'Learn more about embeds' ) }
</ExternalLink>
</div>
</Placeholder>
</div>
);
}
return (
<div
className="cog-wp-embed cog-wp-embed__preview"
dangerouslySetInnerHTML={ { __html: attributes.iframeEmbedCode } } // Must be Iframe embed code as others do not work in Gutenberg
></div>
<div>
{
<BlockControls>
<ToolbarButton
icon={ edit }
label="Edit"
onClick={ () => resetForm() }
/>
</BlockControls>
}
<InspectorControls key="setting">
<PanelBody title="Embed Settings">
<PanelRow>
<RadioControl
label="Embed Mode"
help={
<span>
The type of embed code to use with your form. <ExternalLink href="https://www.cognitoforms.com/support/10/style-publish">Learn more</ExternalLink>
</span>
}
selected={ attributes.embedMode }
options={ [
{ label: 'Seamless', value: EmbedMode.Seamless },
{ label: 'Iframe', value: EmbedMode.IFrame },
] }
onChange={ ( value: EmbedMode ) => setAttributes( { embedMode: parseInt( value.toString() ) } ) }
/>
</PanelRow>
</PanelBody>
</InspectorControls>
<PreviewForm
embedCode={ attributes.iframeEmbedCode }
/>
</div>
);
}
};
export default Edit;

View File

@ -1 +1 @@
export const baseUrl: string = '//forms.cognito.test';
export const baseUrl: string = 'https://forms.cognito.test';

View File

@ -3,7 +3,6 @@
*/
import { registerBlockType } from '@wordpress/blocks';
import { __ } from '@wordpress/i18n';
import { BlockAttributes } from './types';
@ -13,15 +12,12 @@ import { BlockAttributes } from './types';
import Edit from './edit';
import Save from './save';
import CogIcon from './assets/cogicon';
import { ReactComponent as CogIcon } from './assets/cogicon.svg';
registerBlockType<BlockAttributes> ( 'cognito-forms/cognito-embed', {
registerBlockType<BlockAttributes>( 'cognito-forms/cognito-embed', {
title: 'Cognito Forms',
icon: CogIcon,
description: __(
'Easily build powerful forms.',
'cognito'
),
description: 'Easily build powerful forms.',
category: 'embed',
supports: {
// Removes support for an HTML mode.

View File

@ -16,8 +16,6 @@ const Save: React.FC<BlockSaveProps<BlockAttributes>> = ( { attributes: { formId
break;
}
console.log(formId);
return (
<div
className="cog-wp-embed"

View File

@ -15,6 +15,43 @@
margin: initial;
}
.cog-wp-embed__preview > iframe {
height: 500px;
// .cog-wp-embed__preview > iframe {
// height: 500px;
// }
.form-preview {
min-height: 200px;
.focus-grabber {
position: absolute;
width: 100%;
height: 100%;
z-index: 1;
}
.loader {
padding: 1em;
background: #fff;
text-align: center;
min-height: 200px;
border-radius: 2px;
box-shadow: inset 0 0 0 1px #1e1e1e;
display: flex;
gap: 0.5em;
flex-direction: column;
align-items: center;
justify-content: center;
.icon {
width: 2em;
height: 2em;
margin: 0 auto;
}
p {
font-size: 13px;
margin: 0;
}
}
}

View File

@ -16,9 +16,7 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
require_once dirname(__FILE__) . '/../api.php';
$url = CognitoAPI::$formsBase;
$url = 'https://www.cognitoforms.com/';
if ($_GET['page'] == 'CognitoCreateForm') {
$url = $url . 'forms/new';
@ -29,7 +27,7 @@ if ($_GET['page'] == 'CognitoCreateForm') {
}
?>
<iframe id="cognito-frame" src="<?php print $url; ?>" style="width:100%; overflow-x: hidden;"></iframe>
<iframe id="cognito-frame" src="<?= $url ?>"></iframe>
<style>
body {
@ -38,24 +36,18 @@ if ($_GET['page'] == 'CognitoCreateForm') {
#wpcontent {
padding-left: 0!important;
}
#wpfooter {
display: none;
}
#wpwrap, #wpcontent, #wpbody, #wpbody-content {
height: 100%;
}
#wpbody-content *:not(#cognito-frame) {
display: none!important;
}
#cognito-frame {
width: 100%;
height: 100%;
overflow-x: hidden;
}
</style>
<script language="javascript">
// Remove all content injected prior to the iframe (ex. wordpress update banners)
var element = document.getElementById('cognito-frame');
for (; element; element = element.previousSibling) {
if (element.nodeType === 1 && element.id !== 'cognito-frame') {
element.style.display = 'none';
}
}
window.addEventListener('resize', resizeListener);
// Handler to watch for window resize to correctly update iframe height
function resizeListener(event) {
var adminheight = document.getElementById('wpadminbar').clientHeight;
document.getElementById('cognito-frame').height = (document.body.clientHeight) + "px";
}
resizeListener();
</script>

View File

@ -1,29 +0,0 @@
<h2>Cognito Forms</h2>
<form method="post" action="options.php">
<?php settings_fields('cognito_plugin'); ?>
<table class="form-table">
<tr valign="top">
<th scope="row">API Key</th>
<td><input type="text" name="cognito_api_key" style="width:300px;" value="<?php echo get_option('cognito_api_key'); ?>" /></td>
</tr>
<tr valign="top">
<th scope="row">Admin API Key</th>
<td><input type="text" name="cognito_admin_key" style="width:300px;" value="<?php echo get_option('cognito_admin_key'); ?>" /></td>
</tr>
<tr valign="top">
<th scope="row">Public API Key</th>
<td><input type="text" name="cognito_public_key" style="width:300px;" value="<?php echo get_option('cognito_public_key'); ?>" /></td>
</tr>
<tr valign="top">
<th scope="row">Organization Code</th>
<td><input type="text" name="cognito_organization" style="width:300px;" value="<?php echo get_option('cognito_organization'); ?>" /></td>
</tr>
</table>
<p class="submit">
<input type="submit" class="button-primary" value="<?php _e('Save Changes') ?>" />
</p>
</form>

View File

@ -1,20 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Form Selection</title>
</head>
<body>
<textarea id="embed-code"></textarea>
<button type="submit" onclick="postEmbedCode()">Submit</button>
<script type="text/javascript">
function postEmbedCode(event) {
var embedCode = document.querySelector("#embed-code").value;
window.parent.postMessage(embedCode);
}
</script>
</body>
</html>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

BIN
tinymce/cogicon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

117
tinymce/dialog.php Executable file → Normal file
View File

@ -15,89 +15,54 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
?>
?>
<!DOCTYPE html>
<html>
<head>
<style>
body { overflow: hidden; }
button{margin-top:20px;color: #fff !important;text-shadow: 0 1px 1px rgba(0,0,0,.3);outline: none;cursor: pointer;text-align: center;text-decoration: none;font: 14px/100% 'Open Sans Condensed', sans-serif !important;font-weight: 700 !important;padding: 5px 15px 6px;border: solid 1px #95ba14;background: #aed136;}
.clearlooks2 .mceTop .mceLeft, .clearlooks2 .mceTop .mceRight{background:#00B4AC;padding:20px;font-family: 'Open Sans Condensed', Arial, Helvetica, sans-serif;font-size: 18px;font-weight: 700;color: #fff;}
body{padding: 10px 20px!important;font-family: 'Open Sans', Arial, Helvetica, sans-serif;font-size: 14px;font-weight: 400;}
h3 {margin-bottom:20px!important;color:#444!important;}
</style>
<script src="../../../../wp-includes/js/jquery/jquery.js"></script>
<script src="../../../../wp-includes/js/tinymce/tiny_mce_popup.js"></script>
<script src="../../../../wp-includes/js/tinymce/utils/mctabs.js"></script>
<script src="../../../../wp-includes/js/tinymce/utils/form_utils.js"></script>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Cognito Forms</title>
<script>
var titleElements = tinyMCEPopup.getWin().document.querySelectorAll('.mceTop .mceLeft, .mceTop .mceRight, .mce-title');
for (var i = 0; i < titleElements.length; i++) {
titleElements[i].style.background = '#00B4AC';
titleElements[i].style.color = '#fff';
<style>
html, body {
margin: 0;
padding: 0;
height: 100%;
}
#cognito-frame {
width: 100%;
height: 100%;
border: none;
}
</style>
</head>
<body>
<iframe id="cognito-frame" src="https://forms.cognito.test/integrations/cms"></iframe>
<script type="text/javascript">
window.addEventListener('message', handleMessage);
function handleMessage(event) {
var frame = document.getElementById('cognito-frame');
var baseUrl = new URL(frame.getAttribute('src')).origin;
if (event.origin === baseUrl) {
console.log('Message received!');
sendData(event.data);
}
}
var closeElement = tinyMCEPopup.getWin().document.querySelector('.mceClose, .mce-close');
if (closeElement) closeElement.style.color = '#fff';
function sendData(data) {
embedCode = data.embedCodes.Seamless;
console.log(embedCode);
function cognito_submit() {
var formSelect = document.getElementById('formSelect');
var shortcode = '[CognitoForms id="' + formSelect.value + '"]';
if (window.tinyMCE) {
if (window.tinyMCE.execInstanceCommand) {
window.tinyMCE.execInstanceCommand('content', 'mceInsertContent', false, shortcode);
tinyMCEPopup.editor.execCommand('mceRepaint');
}
else if (window.tinyMCE.focusedEditor) {
window.tinyMCE.focusedEditor.insertContent(shortcode);
if (top.tinyMCE && top.tinyMCE.activeEditor) {
top.tinyMCE.activeEditor.insertContent(embedCode);
}
tinyMCEPopup.close();
top.tinymce.activeEditor.windowManager.close();
}
return false;
}
jQuery(function() {
var data = {
action: "get_forms"
};
jQuery.post(tinyMCEPopup.params.ajax_url, data, function(response) {
if (response) {
var forms = JSON.parse(response);
var formSelect = jQuery("#formSelect");
jQuery.each(forms, function() {
formSelect.append(jQuery("<option></option>")
.attr("value", this.Id)
.text(this.Name));
});
jQuery("#form-list").show();
} else {
jQuery("#no-forms").show();
}
});
});
</script>
</head>
<body>
<div id="no-forms" style="display:none;">
<h3>You are not logged into your Cognito Forms account.</h3>
<p>Please click on the "Cognito Forms" link in the menu on the left and log in to register this plug-in with your account.</p>
</div>
<div id="form-list">
<h3>Embed a Form</h3>
<form method="post" action="">
<label for="formSelect">Choose a form</label>
<select id="formSelect">
</select><br/>
<button id="cognito-insert-form" type="button" onclick="cognito_submit();">Insert Form</button>
</form>
</div>
</body>
</body>
</html>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -1,24 +1,32 @@
(function(){
tinymce.create('tinymce.plugins.cognito', {
init : function(ed, url) {
ed.addCommand('cognito_embed_window', function() {
ed.windowManager.open({
file : url + '/dialog.php',
width : 400,
height : 160,
inline: 1
}, { plugin_url : url, ajax_url: ajaxurl });
});
( function() {
tinymce.create( 'tinymce.plugins.cognito_mce_plugin', {
getInfo: function() {
return {
longname: 'Cognito Forms',
author: 'cognitoapps',
authorurl: 'https://cognitoforms.com',
infourl: 'https://cognitoforms.com',
version: "2.0",
};
},
init: function( editor, url ) {
editor.addCommand( 'cognito_embed_window', function() {
editor.windowManager.open( {
title: 'Cognito Forms',
url: url + '/dialog.php',
width: 500,
height: 500,
} );
} );
ed.addButton('cognito', {
title : 'Cognito Forms',
cmd : 'cognito_embed_window',
image : url + '/cogicon.ico'
});
}
});
editor.addButton( 'cognito', {
title: 'Cognito Forms',
cmd: 'cognito_embed_window',
image: url + '/cogicon.png',
} );
},
} );
tinymce.PluginManager.add('cognito', tinymce.plugins.cognito);
})()
tinymce.PluginManager.add( 'cognito_mce_plugin', tinymce.plugins.cognito_mce_plugin );
} )();

View File

@ -9,7 +9,8 @@
"allowSyntheticDefaultImports": true,
"paths": {
"@/*": ["./src/*"]
}
},
"resolveJsonModule": true
},
"include": [
"src"

View File

@ -14,17 +14,13 @@ module.exports = {
},
{
test: /\.svg$/,
exclude: /node_modules/,
use: {
loader: 'svg-react-loader',
options: {
jsx: true
},
},
issuer: /\.tsx?$/,
use: [ '@svgr/webpack', 'url-loader' ],
type: 'javascript/auto',
},
{
test: /\.scss$/,
use: [ 'style-loader', 'sass-loader' ]
use: [ 'style-loader', 'sass-loader' ],
},
...defaultConfig.module.rules,
],
@ -32,7 +28,10 @@ module.exports = {
resolve: {
...defaultConfig.resolve,
extensions: [ '.tsx', '.ts', 'js', 'jsx' ],
alias: {
"@": path.resolve( __dirname, 'src' ),
},
extensions: [ '.tsx', '.ts', '.js', '.jsx' ],
},
output: {

View File

@ -2482,6 +2482,21 @@
semver "^7.3.5"
tsutils "^3.21.0"
"@typescript-eslint/eslint-plugin@^5.10.0":
version "5.10.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.10.0.tgz#e90afea96dff8620892ad216b0e4ccdf8ee32d3a"
integrity sha512-XXVKnMsq2fuu9K2KsIxPUGqb6xAImz8MEChClbXmE3VbveFtBUU5bzM6IPVWqzyADIgdkS2Ws/6Xo7W2TeZWjQ==
dependencies:
"@typescript-eslint/scope-manager" "5.10.0"
"@typescript-eslint/type-utils" "5.10.0"
"@typescript-eslint/utils" "5.10.0"
debug "^4.3.2"
functional-red-black-tree "^1.0.1"
ignore "^5.1.8"
regexpp "^3.2.0"
semver "^7.3.5"
tsutils "^3.21.0"
"@typescript-eslint/eslint-plugin@^5.5.0":
version "5.9.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.9.1.tgz#e5a86d7e1f9dc0b3df1e6d94feaf20dd838d066c"
@ -2531,6 +2546,16 @@
"@typescript-eslint/typescript-estree" "4.33.0"
debug "^4.3.1"
"@typescript-eslint/parser@^5.10.0":
version "5.10.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.10.0.tgz#8f59e036f5f1cffc178cacbd5ccdd02aeb96c91c"
integrity sha512-pJB2CCeHWtwOAeIxv8CHVGJhI5FNyJAIpx5Pt72YkK3QfEzt6qAlXZuyaBmyfOdM62qU0rbxJzNToPTVeJGrQw==
dependencies:
"@typescript-eslint/scope-manager" "5.10.0"
"@typescript-eslint/types" "5.10.0"
"@typescript-eslint/typescript-estree" "5.10.0"
debug "^4.3.2"
"@typescript-eslint/parser@^5.5.0":
version "5.9.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.9.1.tgz#b114011010a87e17b3265ca715e16c76a9834cef"
@ -2549,6 +2574,14 @@
"@typescript-eslint/types" "4.33.0"
"@typescript-eslint/visitor-keys" "4.33.0"
"@typescript-eslint/scope-manager@5.10.0":
version "5.10.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.10.0.tgz#bb5d872e8b9e36203908595507fbc4d3105329cb"
integrity sha512-tgNgUgb4MhqK6DoKn3RBhyZ9aJga7EQrw+2/OiDk5hKf3pTVZWyqBi7ukP+Z0iEEDMF5FDa64LqODzlfE4O/Dg==
dependencies:
"@typescript-eslint/types" "5.10.0"
"@typescript-eslint/visitor-keys" "5.10.0"
"@typescript-eslint/scope-manager@5.9.1":
version "5.9.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.9.1.tgz#6c27be89f1a9409f284d95dfa08ee3400166fe69"
@ -2557,6 +2590,15 @@
"@typescript-eslint/types" "5.9.1"
"@typescript-eslint/visitor-keys" "5.9.1"
"@typescript-eslint/type-utils@5.10.0":
version "5.10.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.10.0.tgz#8524b9479c19c478347a7df216827e749e4a51e5"
integrity sha512-TzlyTmufJO5V886N+hTJBGIfnjQDQ32rJYxPaeiyWKdjsv2Ld5l8cbS7pxim4DeNs62fKzRSt8Q14Evs4JnZyQ==
dependencies:
"@typescript-eslint/utils" "5.10.0"
debug "^4.3.2"
tsutils "^3.21.0"
"@typescript-eslint/type-utils@5.9.1":
version "5.9.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.9.1.tgz#c6832ffe655b9b1fec642d36db1a262d721193de"
@ -2571,6 +2613,11 @@
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.33.0.tgz#a1e59036a3b53ae8430ceebf2a919dc7f9af6d72"
integrity sha512-zKp7CjQzLQImXEpLt2BUw1tvOMPfNoTAfb8l51evhYbOEEzdWyQNmHWWGPR6hwKJDAi+1VXSBmnhL9kyVTTOuQ==
"@typescript-eslint/types@5.10.0":
version "5.10.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.10.0.tgz#beb3cb345076f5b088afe996d57bcd1dfddaa75c"
integrity sha512-wUljCgkqHsMZbw60IbOqT/puLfyqqD5PquGiBo1u1IS3PLxdi3RDGlyf032IJyh+eQoGhz9kzhtZa+VC4eWTlQ==
"@typescript-eslint/types@5.9.1":
version "5.9.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.9.1.tgz#1bef8f238a2fb32ebc6ff6d75020d9f47a1593c6"
@ -2589,6 +2636,19 @@
semver "^7.3.5"
tsutils "^3.21.0"
"@typescript-eslint/typescript-estree@5.10.0":
version "5.10.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.10.0.tgz#4be24a3dea0f930bb1397c46187d0efdd955a224"
integrity sha512-x+7e5IqfwLwsxTdliHRtlIYkgdtYXzE0CkFeV6ytAqq431ZyxCFzNMNR5sr3WOlIG/ihVZr9K/y71VHTF/DUQA==
dependencies:
"@typescript-eslint/types" "5.10.0"
"@typescript-eslint/visitor-keys" "5.10.0"
debug "^4.3.2"
globby "^11.0.4"
is-glob "^4.0.3"
semver "^7.3.5"
tsutils "^3.21.0"
"@typescript-eslint/typescript-estree@5.9.1":
version "5.9.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.9.1.tgz#d5b996f49476495070d2b8dd354861cf33c005d6"
@ -2602,6 +2662,18 @@
semver "^7.3.5"
tsutils "^3.21.0"
"@typescript-eslint/utils@5.10.0":
version "5.10.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.10.0.tgz#c3d152a85da77c400e37281355561c72fb1b5a65"
integrity sha512-IGYwlt1CVcFoE2ueW4/ioEwybR60RAdGeiJX/iDAw0t5w0wK3S7QncDwpmsM70nKgGTuVchEWB8lwZwHqPAWRg==
dependencies:
"@types/json-schema" "^7.0.9"
"@typescript-eslint/scope-manager" "5.10.0"
"@typescript-eslint/types" "5.10.0"
"@typescript-eslint/typescript-estree" "5.10.0"
eslint-scope "^5.1.1"
eslint-utils "^3.0.0"
"@typescript-eslint/visitor-keys@4.33.0":
version "4.33.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.33.0.tgz#2a22f77a41604289b7a186586e9ec48ca92ef1dd"
@ -2610,6 +2682,14 @@
"@typescript-eslint/types" "4.33.0"
eslint-visitor-keys "^2.0.0"
"@typescript-eslint/visitor-keys@5.10.0":
version "5.10.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.10.0.tgz#770215497ad67cd15a572b52089991d5dfe06281"
integrity sha512-GMxj0K1uyrFLPKASLmZzCuSddmjZVbVj3Ouy5QVuIGKZopxvOr24JsS7gruz6C3GExE01mublZ3mIBOaon9zuQ==
dependencies:
"@typescript-eslint/types" "5.10.0"
eslint-visitor-keys "^3.0.0"
"@typescript-eslint/visitor-keys@5.9.1":
version "5.9.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.9.1.tgz#f52206f38128dd4f675cf28070a41596eee985b7"
@ -5838,6 +5918,13 @@ eslint-plugin-jest@^25.3.0:
dependencies:
"@typescript-eslint/experimental-utils" "^5.0.0"
eslint-plugin-jest@^25.7.0:
version "25.7.0"
resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-25.7.0.tgz#ff4ac97520b53a96187bad9c9814e7d00de09a6a"
integrity sha512-PWLUEXeeF7C9QGKqvdSbzLOiLTx+bno7/HC9eefePfEb257QFHg7ye3dh80AZVkaa/RQsBB1Q/ORQvg2X7F0NQ==
dependencies:
"@typescript-eslint/experimental-utils" "^5.0.0"
eslint-plugin-jsdoc@^36.0.8:
version "36.1.1"
resolved "https://registry.yarnpkg.com/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-36.1.1.tgz#124cd0e53a5d07f01ebde916a96dd1a6009625d6"