From 86ee6acf912d92ca84f0510b87a907bda9336645 Mon Sep 17 00:00:00 2001 From: Rishad Alam <101513331+RishadAlam@users.noreply.github.com> Date: Thu, 23 Apr 2026 14:59:13 +0600 Subject: [PATCH 1/7] feat: monday integration init --- .../Actions/MondayCom/MondayComController.php | 237 +++++++++++ backend/Actions/MondayCom/RecordApiHelper.php | 211 ++++++++++ backend/Actions/MondayCom/Routes.php | 14 + .../components/AllIntegrations/EditInteg.jsx | 3 + .../components/AllIntegrations/IntegInfo.jsx | 3 + .../MondayCom/EditMondayCom.jsx | 102 +++++ .../AllIntegrations/MondayCom/MondayCom.jsx | 148 +++++++ .../MondayCom/MondayComAuthorization.jsx | 126 ++++++ .../MondayCom/MondayComCommonFunc.js | 197 ++++++++++ .../MondayCom/MondayComFieldMap.jsx | 110 ++++++ .../MondayCom/MondayComIntegLayout.jsx | 369 ++++++++++++++++++ .../AllIntegrations/MondayCom/staticData.js | 78 ++++ .../components/AllIntegrations/NewInteg.jsx | 10 + .../src/components/Flow/New/SelectAction.jsx | 1 + frontend/src/resource/img/integ/mondayCom.svg | 1 + 15 files changed, 1610 insertions(+) create mode 100644 backend/Actions/MondayCom/MondayComController.php create mode 100644 backend/Actions/MondayCom/RecordApiHelper.php create mode 100644 backend/Actions/MondayCom/Routes.php create mode 100644 frontend/src/components/AllIntegrations/MondayCom/EditMondayCom.jsx create mode 100644 frontend/src/components/AllIntegrations/MondayCom/MondayCom.jsx create mode 100644 frontend/src/components/AllIntegrations/MondayCom/MondayComAuthorization.jsx create mode 100644 frontend/src/components/AllIntegrations/MondayCom/MondayComCommonFunc.js create mode 100644 frontend/src/components/AllIntegrations/MondayCom/MondayComFieldMap.jsx create mode 100644 frontend/src/components/AllIntegrations/MondayCom/MondayComIntegLayout.jsx create mode 100644 frontend/src/components/AllIntegrations/MondayCom/staticData.js create mode 100644 frontend/src/resource/img/integ/mondayCom.svg diff --git a/backend/Actions/MondayCom/MondayComController.php b/backend/Actions/MondayCom/MondayComController.php new file mode 100644 index 000000000..eb8d46df4 --- /dev/null +++ b/backend/Actions/MondayCom/MondayComController.php @@ -0,0 +1,237 @@ +apiToken)) { + wp_send_json_error(__('API Token is empty', 'bit-integrations'), 400); + } + + $query = 'query { me { id name email } }'; + $response = self::request($requestParams->apiToken, $query); + + if (!self::hasErrors($response) && isset($response->data->me->id)) { + wp_send_json_success(__('Authentication successful', 'bit-integrations'), 200); + } + + wp_send_json_error(self::errorMessage($response, __('Authentication failed', 'bit-integrations')), 400); + } + + public function getBoards($requestParams) + { + self::validateToken($requestParams); + + $query = <<<'GRAPHQL' + query ($limit: Int) { + boards (limit: $limit) { + id + name + } + } + GRAPHQL; + $response = self::request($requestParams->apiToken, $query, ['limit' => 100]); + + if (self::hasErrors($response) || !isset($response->data->boards)) { + wp_send_json_error(self::errorMessage($response, __('Boards fetching failed', 'bit-integrations')), 400); + } + + $boards = array_map( + fn ($b) => (object) ['id' => $b->id, 'name' => $b->name], + $response->data->boards + ); + + wp_send_json_success($boards, 200); + } + + public function getGroups($requestParams) + { + self::validateToken($requestParams); + if (empty($requestParams->boardId)) { + wp_send_json_error(__('Board ID is empty', 'bit-integrations'), 400); + } + + $query = <<<'GRAPHQL' + query ($boardIds: [ID!]) { + boards (ids: $boardIds) { + groups { + id + title + } + } + } + GRAPHQL; + $response = self::request($requestParams->apiToken, $query, ['boardIds' => [(string) $requestParams->boardId]]); + + if (self::hasErrors($response) || !isset($response->data->boards[0]->groups)) { + wp_send_json_error(self::errorMessage($response, __('Groups fetching failed', 'bit-integrations')), 400); + } + + $groups = array_map( + fn ($g) => (object) ['id' => $g->id, 'name' => $g->title], + $response->data->boards[0]->groups + ); + + wp_send_json_success($groups, 200); + } + + public function getColumns($requestParams) + { + self::validateToken($requestParams); + if (empty($requestParams->boardId)) { + wp_send_json_error(__('Board ID is empty', 'bit-integrations'), 400); + } + + $query = <<<'GRAPHQL' + query ($boardIds: [ID!]) { + boards (ids: $boardIds) { + columns { + id + title + type + } + } + } + GRAPHQL; + $response = self::request($requestParams->apiToken, $query, ['boardIds' => [(string) $requestParams->boardId]]); + + if (self::hasErrors($response) || !isset($response->data->boards[0]->columns)) { + wp_send_json_error(self::errorMessage($response, __('Columns fetching failed', 'bit-integrations')), 400); + } + + $columns = array_map( + fn ($c) => (object) [ + 'key' => $c->id, + 'label' => $c->title, + 'type' => $c->type, + 'required' => false, + ], + $response->data->boards[0]->columns + ); + + wp_send_json_success($columns, 200); + } + + public function getItems($requestParams) + { + self::validateToken($requestParams); + if (empty($requestParams->boardId)) { + wp_send_json_error(__('Board ID is empty', 'bit-integrations'), 400); + } + + $query = <<<'GRAPHQL' + query ($boardIds: [ID!], $limit: Int) { + boards (ids: $boardIds) { + items_page (limit: $limit) { + items { + id + name + } + } + } + } + GRAPHQL; + $response = self::request( + $requestParams->apiToken, + $query, + [ + 'boardIds' => [(string) $requestParams->boardId], + 'limit' => 100, + ] + ); + + if (self::hasErrors($response) || !isset($response->data->boards[0]->items_page->items)) { + wp_send_json_error(self::errorMessage($response, __('Items fetching failed', 'bit-integrations')), 400); + } + + $items = array_map( + fn ($i) => (object) ['id' => $i->id, 'name' => $i->name], + $response->data->boards[0]->items_page->items + ); + + wp_send_json_success($items, 200); + } + + public function execute($integrationData, $fieldValues) + { + $integrationDetails = $integrationData->flow_details; + $integId = $integrationData->id; + $fieldMap = $integrationDetails->field_map ?? []; + $apiToken = $integrationDetails->apiToken ?? ''; + + if (empty($apiToken)) { + return new WP_Error('REQ_FIELD_EMPTY', __('API Token is required for Monday.com api', 'bit-integrations')); + } + + $recordApiHelper = new RecordApiHelper($integrationDetails, $integId, $apiToken); + $response = $recordApiHelper->execute($fieldValues, $fieldMap); + + if (is_wp_error($response)) { + return $response; + } + + return $response; + } + + private static function validateToken($requestParams) + { + if (empty($requestParams->apiToken)) { + wp_send_json_error(__('API Token is empty', 'bit-integrations'), 400); + } + } + + private static function setHeaders($apiToken) + { + return [ + 'Authorization' => $apiToken, + 'Content-Type' => 'application/json', + 'API-Version' => self::API_VERSION, + ]; + } + + private static function request($apiToken, $query, $variables = []) + { + $body = ['query' => $query]; + + if (!empty($variables)) { + $body['variables'] = $variables; + } + + return HttpHelper::post(self::API_URL, wp_json_encode($body), self::setHeaders($apiToken)); + } + + private static function hasErrors($response) + { + return is_wp_error($response) || !empty($response->errors) || !empty($response->error); + } + + private static function errorMessage($response, $fallback) + { + if (is_wp_error($response)) { + return $response->get_error_message(); + } + + if (!empty($response->errors[0]->message)) { + return $response->errors[0]->message; + } + + if (!empty($response->error)) { + return \is_string($response->error) ? $response->error : wp_json_encode($response->error); + } + + return $fallback; + } +} diff --git a/backend/Actions/MondayCom/RecordApiHelper.php b/backend/Actions/MondayCom/RecordApiHelper.php new file mode 100644 index 000000000..572093f28 --- /dev/null +++ b/backend/Actions/MondayCom/RecordApiHelper.php @@ -0,0 +1,211 @@ +integrationDetails = $integrationDetails; + $this->integrationId = $integId; + $this->apiToken = $apiToken; + } + + public function handleFilterResponse($response) + { + if ($response) { + return $response; + } + + // translators: %s: Placeholder value + return (object) ['error' => wp_sprintf(__('%s plugin is not installed or activate', 'bit-integrations'), 'Bit Integrations Pro')]; + } + + public function createItem($fieldData) + { + $boardId = $this->integrationDetails->selectedBoard ?? ''; + $groupId = $this->integrationDetails->selectedGroup ?? ''; + $itemName = $fieldData['item_name'] ?? ''; + + if (empty($boardId) || empty($itemName) || empty($this->apiToken)) { + return (object) ['error' => __('Required params are empty!', 'bit-integrations')]; + } + + $columnValues = $fieldData; + unset($columnValues['item_name']); + + $query = <<<'GRAPHQL' + mutation ($boardId: ID!, $groupId: String, $itemName: String!, $columnValues: JSON) { + create_item ( + board_id: $boardId, + group_id: $groupId, + item_name: $itemName, + column_values: $columnValues + ) { + id + name + } + } + GRAPHQL; + + return $this->request( + $query, + [ + 'boardId' => (string) $boardId, + 'groupId' => $groupId ? (string) $groupId : null, + 'itemName' => (string) $itemName, + 'columnValues' => wp_json_encode((object) $columnValues), + ] + ); + } + + public function generateReqDataFromFieldMap($fieldValues, $fieldMap) + { + $dataFinal = []; + foreach ($fieldMap as $item) { + $triggerValue = $item->formField ?? ''; + $actionValue = $item->mondayComField ?? ''; + + if (empty($actionValue)) { + continue; + } + + if ($triggerValue === 'custom') { + $dataFinal[$actionValue] = Common::replaceFieldWithValue($item->customValue ?? '', $fieldValues); + } elseif (!empty($triggerValue)) { + $dataFinal[$actionValue] = $fieldValues[$triggerValue] ?? ''; + } + } + + return $dataFinal; + } + + public function execute($fieldValues, $fieldMap) + { + $fieldData = $this->generateReqDataFromFieldMap($fieldValues, $fieldMap); + $mainAction = $this->integrationDetails->mainAction ?? 'create_item'; + $this->type = 'item'; + $this->typeName = $mainAction; + + $default = (object) ['error' => wp_sprintf(__('%s plugin is not installed or activate', 'bit-integrations'), 'Bit Integrations Pro')]; + + switch ($mainAction) { + case 'create_item': + $this->type = 'item'; + $apiResponse = $this->createItem($fieldData); + + break; + case 'update_item': + $this->type = 'item'; + $apiResponse = $this->handleFilterResponse(Hooks::apply(Config::withPrefix('mondayCom_update_item'), false, $fieldData, $this->integrationDetails, $this->apiToken)); + + break; + case 'create_subitem': + $this->type = 'subitem'; + $apiResponse = $this->handleFilterResponse(Hooks::apply(Config::withPrefix('mondayCom_create_subitem'), false, $fieldData, $this->integrationDetails, $this->apiToken)); + + break; + case 'move_item_to_group': + $this->type = 'item'; + $apiResponse = $this->handleFilterResponse(Hooks::apply(Config::withPrefix('mondayCom_move_item_to_group'), false, $fieldData, $this->integrationDetails, $this->apiToken)); + + break; + case 'archive_item': + $this->type = 'item'; + $apiResponse = $this->handleFilterResponse(Hooks::apply(Config::withPrefix('mondayCom_archive_item'), false, $fieldData, $this->integrationDetails, $this->apiToken)); + + break; + case 'delete_item': + $this->type = 'item'; + $apiResponse = $this->handleFilterResponse(Hooks::apply(Config::withPrefix('mondayCom_delete_item'), false, $fieldData, $this->integrationDetails, $this->apiToken)); + + break; + case 'archive_board': + $this->type = 'board'; + $apiResponse = $this->handleFilterResponse(Hooks::apply(Config::withPrefix('mondayCom_archive_board'), false, $fieldData, $this->integrationDetails, $this->apiToken)); + + break; + case 'archive_group': + $this->type = 'group'; + $apiResponse = $this->handleFilterResponse(Hooks::apply(Config::withPrefix('mondayCom_archive_group'), false, $fieldData, $this->integrationDetails, $this->apiToken)); + + break; + case 'delete_group': + $this->type = 'group'; + $apiResponse = $this->handleFilterResponse(Hooks::apply(Config::withPrefix('mondayCom_delete_group'), false, $fieldData, $this->integrationDetails, $this->apiToken)); + + break; + case 'create_group': + $this->type = 'group'; + $apiResponse = $this->handleFilterResponse(Hooks::apply(Config::withPrefix('mondayCom_create_group'), false, $fieldData, $this->integrationDetails, $this->apiToken)); + + break; + case 'duplicate_group': + $this->type = 'group'; + $apiResponse = $this->handleFilterResponse(Hooks::apply(Config::withPrefix('mondayCom_duplicate_group'), false, $fieldData, $this->integrationDetails, $this->apiToken)); + + break; + case 'create_column': + $this->type = 'column'; + $apiResponse = $this->handleFilterResponse(Hooks::apply(Config::withPrefix('mondayCom_create_column'), false, $fieldData, $this->integrationDetails, $this->apiToken)); + + break; + default: + $apiResponse = $default; + } + + $responseType = $this->hasErrors($apiResponse) || !isset($apiResponse->data) ? 'error' : 'success'; + LogHandler::save($this->integrationId, wp_json_encode(['type' => $this->type, 'type_name' => $this->typeName]), $responseType, wp_json_encode($apiResponse)); + + return $apiResponse; + } + + private function request($query, $variables = []) + { + $body = ['query' => $query]; + + if (!empty($variables)) { + $body['variables'] = $variables; + } + + return HttpHelper::post(self::API_URL, wp_json_encode($body), $this->setHeaders()); + } + + private function hasErrors($response) + { + return is_wp_error($response) || !empty($response->errors) || !empty($response->error); + } + + private function setHeaders() + { + return [ + 'Authorization' => $this->apiToken, + 'Content-Type' => 'application/json', + 'API-Version' => self::API_VERSION, + ]; + } +} diff --git a/backend/Actions/MondayCom/Routes.php b/backend/Actions/MondayCom/Routes.php new file mode 100644 index 000000000..73fe8153c --- /dev/null +++ b/backend/Actions/MondayCom/Routes.php @@ -0,0 +1,14 @@ + import('./TheEventsCalendar/EditTheEven const EditLMFWC = lazy(() => import('./LMFWC/EditLMFWC')) const EditVoxel = lazy(() => import('./Voxel/EditVoxel')) const EditSmartSuite = lazy(() => import('./SmartSuite/EditSmartSuite')) +const EditMondayCom = lazy(() => import('./MondayCom/EditMondayCom')) const EditBento = lazy(() => import('./Bento/EditBento')) const EditLine = lazy(() => import('./Line/EditLine')) const EditACPT = lazy(() => import('./ACPT/EditACPT')) @@ -579,6 +580,8 @@ const IntegType = memo(({ allIntegURL, flow }) => { return case 'SmartSuite': return + case 'MondayCom': + return case 'Bento': return case 'Line': diff --git a/frontend/src/components/AllIntegrations/IntegInfo.jsx b/frontend/src/components/AllIntegrations/IntegInfo.jsx index 092b907d9..bee87024c 100644 --- a/frontend/src/components/AllIntegrations/IntegInfo.jsx +++ b/frontend/src/components/AllIntegrations/IntegInfo.jsx @@ -166,6 +166,7 @@ const TheEventsCalendarAuthorization = lazy( const LMFWCAuthorization = lazy(() => import('./LMFWC/LMFWCAuthorization')) const VoxelAuthorization = lazy(() => import('./Voxel/VoxelAuthorization')) const SmartSuiteAuthorization = lazy(() => import('./SmartSuite/SmartSuiteAuthorization')) +const MondayComAuthorization = lazy(() => import('./MondayCom/MondayComAuthorization')) const BentoAuthorization = lazy(() => import('./Bento/BentoAuthorization')) const LineAuthorization = lazy(() => import('./Line/LineAuthorization')) const ACPTAuthorization = lazy(() => import('./ACPT/ACPTAuthorization')) @@ -616,6 +617,8 @@ export default function IntegInfo() { return case 'SmartSuite': return + case 'MondayCom': + return case 'Bento': return case 'Line': diff --git a/frontend/src/components/AllIntegrations/MondayCom/EditMondayCom.jsx b/frontend/src/components/AllIntegrations/MondayCom/EditMondayCom.jsx new file mode 100644 index 000000000..0dd9ae198 --- /dev/null +++ b/frontend/src/components/AllIntegrations/MondayCom/EditMondayCom.jsx @@ -0,0 +1,102 @@ +/* eslint-disable no-unused-vars */ +import { useState } from 'react' +import { toast } from 'react-hot-toast' +import { useNavigate } from 'react-router' +import { useRecoilState, useRecoilValue } from 'recoil' +import { $actionConf, $formFields, $newFlow } from '../../../GlobalStates' +import { __ } from '../../../Utils/i18nwrap' +import SnackMsg from '../../Utilities/SnackMsg' +import SetEditIntegComponents from '../IntegrationHelpers/SetEditIntegComponents' +import { saveActionConf } from '../IntegrationHelpers/IntegrationHelpers' +import IntegrationStepThree from '../IntegrationHelpers/IntegrationStepThree' +import { checkMappedFields, handleInput } from './MondayComCommonFunc' +import MondayComIntegLayout from './MondayComIntegLayout' +import { needsBoard, needsGroup, needsItem } from './staticData' + +function EditMondayCom({ allIntegURL }) { + const navigate = useNavigate() + const [flow, setFlow] = useRecoilState($newFlow) + const [mondayComConf, setMondayComConf] = useRecoilState($actionConf) + const [isLoading, setIsLoading] = useState(false) + const [loading, setLoading] = useState({}) + const [snack, setSnackbar] = useState({ show: false }) + const formField = useRecoilValue($formFields) + + const saveConfig = () => { + if (!checkMappedFields(mondayComConf)) { + setSnackbar({ show: true, msg: __('Please map mandatory fields', 'bit-integrations') }) + return + } + const action = mondayComConf.mainAction + if (needsBoard.includes(action) && !mondayComConf.selectedBoard) { + toast.error(__('Please select a board', 'bit-integrations')) + return + } + if (needsGroup.includes(action) && !mondayComConf.selectedGroup) { + toast.error(__('Please select a group', 'bit-integrations')) + return + } + if (needsItem.includes(action) && !mondayComConf.selectedItem) { + toast.error(__('Please select an item', 'bit-integrations')) + return + } + if (action === 'create_column' && !mondayComConf.columnType) { + toast.error(__('Please select a column type', 'bit-integrations')) + return + } + + saveActionConf({ + flow, + allIntegURL, + conf: mondayComConf, + navigate, + edit: 1, + setIsLoading, + setSnackbar + }) + } + + return ( +
+ + +
+ {__('Integration Name:', 'bit-integrations')} + handleInput(e, mondayComConf, setMondayComConf)} + name="name" + value={mondayComConf.name} + type="text" + placeholder={__('Integration Name...', 'bit-integrations')} + /> +
+
+ + + + + +
+
+ ) +} + +export default EditMondayCom diff --git a/frontend/src/components/AllIntegrations/MondayCom/MondayCom.jsx b/frontend/src/components/AllIntegrations/MondayCom/MondayCom.jsx new file mode 100644 index 000000000..514049e49 --- /dev/null +++ b/frontend/src/components/AllIntegrations/MondayCom/MondayCom.jsx @@ -0,0 +1,148 @@ +/* eslint-disable no-console */ +/* eslint-disable no-unused-expressions */ +import { useState } from 'react' +import toast from 'react-hot-toast' +import 'react-multiple-select-dropdown-lite/dist/index.css' +import { useNavigate } from 'react-router' +import { __ } from '../../../Utils/i18nwrap' +import SnackMsg from '../../Utilities/SnackMsg' +import Steps from '../../Utilities/Steps' +import { saveIntegConfig } from '../IntegrationHelpers/IntegrationHelpers' +import IntegrationStepThree from '../IntegrationHelpers/IntegrationStepThree' +import MondayComAuthorization from './MondayComAuthorization' +import { checkMappedFields, generateMappedField } from './MondayComCommonFunc' +import MondayComIntegLayout from './MondayComIntegLayout' +import { actionLists, needsBoard, needsGroup, needsItem } from './staticData' + +function MondayCom({ formFields, setFlow, flow, allIntegURL }) { + const navigate = useNavigate() + const [isLoading, setIsLoading] = useState(false) + const [loading, setLoading] = useState({}) + + const [step, setStep] = useState(1) + const [snack, setSnackbar] = useState({ show: false }) + + const mondayComFields = [] + const [mondayComConf, setMondayComConf] = useState({ + name: 'MondayCom', + type: 'MondayCom', + apiToken: '', + field_map: generateMappedField(mondayComFields), + mainAction: '', + mondayComFields, + actionLists + }) + + const saveConfig = () => { + setIsLoading(true) + const resp = saveIntegConfig( + flow, + setFlow, + allIntegURL, + mondayComConf, + navigate, + '', + '', + setIsLoading + ) + resp.then(res => { + if (res.success) { + toast.success(res.data?.msg) + navigate(allIntegURL) + } else { + toast.error(res.data || res) + } + }) + } + + const nextPage = pageNo => { + setTimeout(() => { + document.getElementById('btcd-settings-wrp').scrollTop = 0 + }, 300) + + if (!checkMappedFields(mondayComConf)) { + toast.error(__('Please map mandatory fields', 'bit-integrations')) + return + } + + const action = mondayComConf.mainAction + if (needsBoard.includes(action) && !mondayComConf.selectedBoard) { + toast.error(__('Please select a board', 'bit-integrations')) + return + } + if (needsGroup.includes(action) && !mondayComConf.selectedGroup) { + toast.error(__('Please select a group', 'bit-integrations')) + return + } + if (needsItem.includes(action) && !mondayComConf.selectedItem) { + toast.error(__('Please select an item', 'bit-integrations')) + return + } + if (action === 'create_column' && !mondayComConf.columnType) { + toast.error(__('Please select a column type', 'bit-integrations')) + return + } + setStep(pageNo) + } + + return ( +
+ +
+ +
+ + {/* STEP 1 */} + + + {/* STEP 2 */} +
+ + + {mondayComConf?.mainAction && ( + + )} +
+ + {/* STEP 3 */} + {mondayComConf?.mainAction && ( + saveConfig()} + isLoading={isLoading} + dataConf={mondayComConf} + setDataConf={setMondayComConf} + formFields={formFields} + /> + )} +
+ ) +} + +export default MondayCom diff --git a/frontend/src/components/AllIntegrations/MondayCom/MondayComAuthorization.jsx b/frontend/src/components/AllIntegrations/MondayCom/MondayComAuthorization.jsx new file mode 100644 index 000000000..cdd9d9b09 --- /dev/null +++ b/frontend/src/components/AllIntegrations/MondayCom/MondayComAuthorization.jsx @@ -0,0 +1,126 @@ +/* eslint-disable jsx-a11y/anchor-is-valid */ +import { useState } from 'react' +import { __ } from '../../../Utils/i18nwrap' +import LoaderSm from '../../Loaders/LoaderSm' +import Note from '../../Utilities/Note' +import tutorialLinks from '../../../Utils/StaticData/tutorialLinks' +import TutorialLink from '../../Utilities/TutorialLink' +import { mondayComAuthentication } from './MondayComCommonFunc' +import { create } from 'mutative' + +export default function MondayComAuthorization({ + mondayComConf, + setMondayComConf, + step, + setStep, + loading, + setLoading, + isInfo +}) { + const [isAuthorized, setIsAuthorized] = useState(false) + const [error, setError] = useState({ apiToken: '' }) + + const nextPage = () => { + setTimeout(() => { + document.getElementById('btcd-settings-wrp').scrollTop = 0 + }, 300) + setStep(2) + } + + const handleInput = e => { + const { name, value } = e.target + setError(err => + create(err, draft => { + draft[name] = '' + }) + ) + setMondayComConf(prev => + create(prev, draft => { + draft[name] = value + }) + ) + } + + const ActiveInstructions = ` +

${__('To Get Monday.com API Token', 'bit-integrations')}

+
    +
  • ${__('Log in to your Monday.com account.', 'bit-integrations')}
  • +
  • ${__('Click on your avatar in the bottom left corner.', 'bit-integrations')}
  • +
  • ${__('Select Developers → My access tokens.', 'bit-integrations')}
  • +
  • ${__('Copy your personal API token (v2).', 'bit-integrations')}
  • +
` + + return ( +
+ + +
+ {__('Integration Name:', 'bit-integrations')} +
+ + +
+ {__('API Token:', 'bit-integrations')} +
+ +
{error.apiToken}
+ + + {__('To Get API Token, Please Visit', 'bit-integrations')} +   + + {__('Monday.com Developers', 'bit-integrations')} + + +
+
+ + {!isInfo && ( +
+ +
+ +
+ )} + +
+ ) +} diff --git a/frontend/src/components/AllIntegrations/MondayCom/MondayComCommonFunc.js b/frontend/src/components/AllIntegrations/MondayCom/MondayComCommonFunc.js new file mode 100644 index 000000000..f5eb086e9 --- /dev/null +++ b/frontend/src/components/AllIntegrations/MondayCom/MondayComCommonFunc.js @@ -0,0 +1,197 @@ +/* eslint-disable no-console */ +/* eslint-disable no-else-return */ +import toast from 'react-hot-toast' +import bitsFetch from '../../../Utils/bitsFetch' +import { __ } from '../../../Utils/i18nwrap' +import { create } from 'mutative' +import { staticFieldsMap, needsColumnMap } from './staticData' + +export const handleInput = (e, mondayComConf, setMondayComConf) => { + setMondayComConf(mondayComConf => + create(mondayComConf, draftConf => { + const { name, value } = e.target + if (value !== '') { + draftConf[name] = value + } else { + delete draftConf[name] + } + }) + ) +} + +export const generateMappedField = mondayComFields => { + const requiredFlds = mondayComFields?.filter(fld => fld.required === true) || [] + + if (requiredFlds.length > 0) { + return requiredFlds.map(field => ({ formField: '', mondayComField: field.key })) + } + + if (!mondayComFields || mondayComFields.length === 0) { + return [] + } + + return [{ formField: '', mondayComField: '' }] +} + +export const checkMappedFields = mondayComConf => { + const mappedFields = mondayComConf?.field_map + ? mondayComConf.field_map.filter( + mappedField => + !mappedField.formField || + !mappedField.mondayComField || + (mappedField.formField === 'custom' && !mappedField.customValue) + ) + : [] + if (mappedFields.length > 0) { + return false + } + return true +} + +export const mondayComAuthentication = (confTmp, setError, setIsAuthorized, loading, setLoading) => { + if (!confTmp.apiToken) { + setError({ + apiToken: !confTmp.apiToken ? __("API Token can't be empty", 'bit-integrations') : '' + }) + return + } + + setError({}) + setLoading({ ...loading, auth: true }) + + const requestParams = { + apiToken: confTmp.apiToken + } + + bitsFetch(requestParams, 'mondayCom_authentication').then(result => { + if (result && result.success) { + setIsAuthorized(true) + setLoading({ ...loading, auth: false }) + toast.success(__('Authorized Successfully', 'bit-integrations')) + return + } + setLoading({ ...loading, auth: false }) + toast.error(__('Authorized failed', 'bit-integrations')) + }) +} + +export const getAllBoards = (confTmp, setConf, setLoading) => { + setLoading(prev => ({ ...prev, board: true })) + + const requestParams = { + apiToken: confTmp.apiToken + } + + bitsFetch(requestParams, 'mondayCom_fetch_boards').then(result => { + if (result && result.success) { + if (result.data) { + setConf(prevConf => + create(prevConf, draftConf => { + draftConf.boards = result.data + }) + ) + + setLoading(prev => ({ ...prev, board: false })) + toast.success(__('Boards fetched successfully', 'bit-integrations')) + return + } + setLoading(prev => ({ ...prev, board: false })) + toast.error(__('Boards Not Found!', 'bit-integrations')) + return + } + setLoading(prev => ({ ...prev, board: false })) + toast.error(__('Boards fetching failed', 'bit-integrations')) + }) +} + +export const getAllGroups = (confTmp, setConf, boardId, setLoading) => { + setLoading(prev => ({ ...prev, group: true })) + + const requestParams = { + apiToken: confTmp.apiToken, + boardId + } + + bitsFetch(requestParams, 'mondayCom_fetch_groups').then(result => { + if (result && result.success) { + if (result.data) { + setConf(prevConf => + create(prevConf, draftConf => { + draftConf.groups = result.data + }) + ) + + setLoading(prev => ({ ...prev, group: false })) + return + } + setLoading(prev => ({ ...prev, group: false })) + toast.error(__('Groups Not Found!', 'bit-integrations')) + return + } + setLoading(prev => ({ ...prev, group: false })) + toast.error(__('Groups fetching failed', 'bit-integrations')) + }) +} + +export const getAllColumns = (confTmp, setConf, boardId, setLoading) => { + setLoading(prev => ({ ...prev, column: true })) + + const requestParams = { + apiToken: confTmp.apiToken, + boardId + } + + bitsFetch(requestParams, 'mondayCom_fetch_columns').then(result => { + if (result && result.success) { + if (result.data) { + setConf(prevConf => + create(prevConf, draftConf => { + draftConf.columns = result.data + if (needsColumnMap.includes(draftConf.mainAction)) { + const base = staticFieldsMap[draftConf.mainAction] || [] + draftConf.mondayComFields = [...base, ...result.data] + draftConf.field_map = generateMappedField(draftConf.mondayComFields) + } + }) + ) + + setLoading(prev => ({ ...prev, column: false })) + return + } + setLoading(prev => ({ ...prev, column: false })) + toast.error(__('Columns Not Found!', 'bit-integrations')) + return + } + setLoading(prev => ({ ...prev, column: false })) + toast.error(__('Columns fetching failed', 'bit-integrations')) + }) +} + +export const getAllItems = (confTmp, setConf, boardId, setLoading) => { + setLoading(prev => ({ ...prev, item: true })) + + const requestParams = { + apiToken: confTmp.apiToken, + boardId + } + + bitsFetch(requestParams, 'mondayCom_fetch_items').then(result => { + if (result && result.success) { + if (result.data) { + setConf(prevConf => + create(prevConf, draftConf => { + draftConf.items = result.data + }) + ) + + setLoading(prev => ({ ...prev, item: false })) + return + } + setLoading(prev => ({ ...prev, item: false })) + toast.error(__('Items Not Found!', 'bit-integrations')) + return + } + setLoading(prev => ({ ...prev, item: false })) + toast.error(__('Items fetching failed', 'bit-integrations')) + }) +} diff --git a/frontend/src/components/AllIntegrations/MondayCom/MondayComFieldMap.jsx b/frontend/src/components/AllIntegrations/MondayCom/MondayComFieldMap.jsx new file mode 100644 index 000000000..80232e5d0 --- /dev/null +++ b/frontend/src/components/AllIntegrations/MondayCom/MondayComFieldMap.jsx @@ -0,0 +1,110 @@ +import { useRecoilValue } from 'recoil' +import { $appConfigState } from '../../../GlobalStates' +import { SmartTagField } from '../../../Utils/StaticData/SmartTagField' +import { __, sprintf } from '../../../Utils/i18nwrap' +import TagifyInput from '../../Utilities/TagifyInput' +import { addFieldMap, delFieldMap, handleFieldMapping } from '../IntegrationHelpers/FieldMapHelper' +import { handleCustomValue } from '../IntegrationHelpers/IntegrationHelpers' + +export default function MondayComFieldMap({ + i, + formFields, + field, + mondayComConf, + setMondayComConf +}) { + const { isPro } = useRecoilValue($appConfigState) + + const availableFields = mondayComConf?.mondayComFields || [] + const requiredFields = availableFields.filter(f => f.required === true) + const nonRequiredFields = availableFields.filter(f => f.required === false) + + return ( +
+
+
+ + + {field.formField === 'custom' && ( + handleCustomValue(e, i, mondayComConf, setMondayComConf)} + label={__('Custom Value', 'bit-integrations')} + className="mr-2" + type="text" + value={field.customValue} + placeholder={__('Custom Value', 'bit-integrations')} + formFields={formFields} + /> + )} + + +
+ {i >= requiredFields.length && ( + <> + + + + )} +
+
+ ) +} diff --git a/frontend/src/components/AllIntegrations/MondayCom/MondayComIntegLayout.jsx b/frontend/src/components/AllIntegrations/MondayCom/MondayComIntegLayout.jsx new file mode 100644 index 000000000..df1670434 --- /dev/null +++ b/frontend/src/components/AllIntegrations/MondayCom/MondayComIntegLayout.jsx @@ -0,0 +1,369 @@ +/* eslint-disable no-unused-vars */ +import 'react-multiple-select-dropdown-lite/dist/index.css' +import { useRecoilValue } from 'recoil' +import { $appConfigState } from '../../../GlobalStates' +import { __ } from '../../../Utils/i18nwrap' +import Loader from '../../Loaders/Loader' +import { addFieldMap } from '../IntegrationHelpers/FieldMapHelper' +import MultiSelect from 'react-multiple-select-dropdown-lite' +import { + getAllBoards, + getAllGroups, + getAllColumns, + getAllItems, + generateMappedField +} from './MondayComCommonFunc' +import MondayComFieldMap from './MondayComFieldMap' +import { + staticFieldsMap, + columnTypeList, + needsBoard, + needsGroup, + needsItem, + needsColumnMap +} from './staticData' +import { checkIsPro, getProLabel } from '../../Utilities/ProUtilHelpers' +import { create } from 'mutative' + +export default function MondayComIntegLayout({ + formFields, + mondayComConf, + setMondayComConf, + loading, + setLoading, + isLoading +}) { + const btcbi = useRecoilValue($appConfigState) + const { isPro } = btcbi + + const handleActionChange = (value, name) => { + const needBoard = needsBoard.includes(value) + setMondayComConf(prevConf => + create(prevConf, draftConf => { + if (value !== '') { + draftConf[name] = value + } else { + delete draftConf[name] + } + + delete draftConf.selectedBoard + delete draftConf.selectedGroup + delete draftConf.selectedItem + delete draftConf.columns + delete draftConf.groups + delete draftConf.items + delete draftConf.columnType + delete draftConf.addToTop + + const base = staticFieldsMap[value] || [] + draftConf.mondayComFields = base + draftConf.field_map = generateMappedField(base) + }) + ) + + if (needBoard) { + getAllBoards(mondayComConf, setMondayComConf, setLoading) + } + } + + const handleBoardChange = val => { + setMondayComConf(prevConf => + create(prevConf, draftConf => { + draftConf.selectedBoard = val + delete draftConf.selectedGroup + delete draftConf.selectedItem + delete draftConf.groups + delete draftConf.items + delete draftConf.columns + }) + ) + + if (!val) return + + const action = mondayComConf.mainAction + + if (needsColumnMap.includes(action)) { + getAllColumns(mondayComConf, setMondayComConf, val, setLoading) + } + if (needsGroup.includes(action) || action === 'create_item') { + getAllGroups(mondayComConf, setMondayComConf, val, setLoading) + } + if (needsItem.includes(action)) { + getAllItems(mondayComConf, setMondayComConf, val, setLoading) + } + } + + const handleSelectChange = (val, name) => { + setMondayComConf(prevConf => + create(prevConf, draftConf => { + if (val === '' || val === null || val === undefined) { + delete draftConf[name] + } else { + draftConf[name] = val + } + }) + ) + } + + const mainAction = mondayComConf?.mainAction + const hasFieldMap = + mainAction + && (staticFieldsMap[mainAction]?.length > 0 || needsColumnMap.includes(mainAction)) + + return ( + <> +
+
+ {__('Select Action:', 'bit-integrations')} + handleActionChange(val, 'mainAction')} + options={mondayComConf?.actionLists?.map(actionType => ({ + label: checkIsPro(isPro, actionType.is_pro) + ? actionType.label + : getProLabel(actionType.label), + value: actionType.name, + disabled: !checkIsPro(isPro, actionType.is_pro) + }))} + singleSelect + closeOnSelect + /> +
+ + {mainAction && needsBoard.includes(mainAction) && !loading.board && ( + <> +
+
+ {__('Select Board:', 'bit-integrations')} + ({ label: b.name, value: `${b.id}` })) + } + className="msl-wrp-options dropdown-custom-width" + defaultValue={mondayComConf?.selectedBoard} + onChange={handleBoardChange} + singleSelect + closeOnSelect + disabled={loading.board} + /> + +
+ + )} + + {mainAction + && needsGroup.includes(mainAction) + && mondayComConf?.selectedBoard + && !loading.group && ( + <> +
+
+ {__('Select Group:', 'bit-integrations')} + ({ label: g.name, value: `${g.id}` })) + } + className="msl-wrp-options dropdown-custom-width" + defaultValue={mondayComConf?.selectedGroup} + onChange={val => handleSelectChange(val, 'selectedGroup')} + singleSelect + closeOnSelect + /> + +
+ + )} + + {mainAction === 'create_item' + && mondayComConf?.selectedBoard + && !loading.group && ( + <> +
+
+ {__('Group (Optional):', 'bit-integrations')} + ({ label: g.name, value: `${g.id}` })) + } + className="msl-wrp-options dropdown-custom-width" + defaultValue={mondayComConf?.selectedGroup} + onChange={val => handleSelectChange(val, 'selectedGroup')} + singleSelect + closeOnSelect + /> + +
+ + )} + + {mainAction + && needsItem.includes(mainAction) + && mondayComConf?.selectedBoard + && !loading.item && ( + <> +
+
+ {__('Select Item:', 'bit-integrations')} + ({ label: it.name, value: `${it.id}` })) + } + className="msl-wrp-options dropdown-custom-width" + defaultValue={mondayComConf?.selectedItem} + onChange={val => handleSelectChange(val, 'selectedItem')} + singleSelect + closeOnSelect + /> + +
+ + )} + + {mainAction === 'create_column' && ( + <> +
+
+ {__('Column Type:', 'bit-integrations')} + handleSelectChange(val, 'columnType')} + singleSelect + closeOnSelect + /> +
+ + )} + + {mainAction === 'duplicate_group' && ( + <> +
+
+ {__('Add To Top:', 'bit-integrations')} + handleSelectChange(e.target.checked, 'addToTop')} + /> +
+ + )} + + {(loading.board || loading.group || loading.column || loading.item) && ( + + )} + + {mainAction && hasFieldMap && !isLoading && ( +
+
+
+ {__('Field Map', 'bit-integrations')} +
+
+
+
+
+ {__('Form Fields', 'bit-integrations')} +
+
+ {__('Monday.com Fields', 'bit-integrations')} +
+
+ {mondayComConf?.field_map?.map((itm, i) => ( + + ))} + {needsColumnMap.includes(mainAction) && ( +
+ +
+ )} +
+
+ )} + + ) +} diff --git a/frontend/src/components/AllIntegrations/MondayCom/staticData.js b/frontend/src/components/AllIntegrations/MondayCom/staticData.js new file mode 100644 index 000000000..d3c3bd658 --- /dev/null +++ b/frontend/src/components/AllIntegrations/MondayCom/staticData.js @@ -0,0 +1,78 @@ +import { __ } from '../../../Utils/i18nwrap' + +export const actionLists = [ + { name: 'create_item', label: __('Create Item', 'bit-integrations'), is_pro: false }, + { name: 'update_item', label: __('Update Item', 'bit-integrations'), is_pro: true }, + { name: 'create_subitem', label: __('Create Subitem', 'bit-integrations'), is_pro: true }, + { name: 'move_item_to_group', label: __('Move Item to Group', 'bit-integrations'), is_pro: true }, + { name: 'archive_item', label: __('Archive Item', 'bit-integrations'), is_pro: true }, + { name: 'delete_item', label: __('Delete Item', 'bit-integrations'), is_pro: true }, + { name: 'archive_board', label: __('Archive Board', 'bit-integrations'), is_pro: true }, + { name: 'create_group', label: __('Create Group', 'bit-integrations'), is_pro: true }, + { name: 'duplicate_group', label: __('Duplicate Group', 'bit-integrations'), is_pro: true }, + { name: 'archive_group', label: __('Archive Group', 'bit-integrations'), is_pro: true }, + { name: 'delete_group', label: __('Delete Group', 'bit-integrations'), is_pro: true }, + { name: 'create_column', label: __('Create Column', 'bit-integrations'), is_pro: true } +] + +export const staticFieldsMap = { + create_item: [{ label: __('Item Name', 'bit-integrations'), key: 'item_name', required: true }], + update_item: [], + create_subitem: [ + { label: __('Subitem Name', 'bit-integrations'), key: 'subitem_name', required: true } + ], + move_item_to_group: [], + archive_item: [], + delete_item: [], + archive_board: [], + create_group: [{ label: __('Group Name', 'bit-integrations'), key: 'group_name', required: true }], + duplicate_group: [ + { label: __('Group Title', 'bit-integrations'), key: 'group_title', required: true } + ], + archive_group: [], + delete_group: [], + create_column: [{ label: __('Column Title', 'bit-integrations'), key: 'column_title', required: true }] +} + +export const columnTypeList = [ + { label: 'Text', value: 'text' }, + { label: 'Long Text', value: 'long_text' }, + { label: 'Number', value: 'numbers' }, + { label: 'Status', value: 'status' }, + { label: 'Date', value: 'date' }, + { label: 'Checkbox', value: 'checkbox' }, + { label: 'Email', value: 'email' }, + { label: 'Phone', value: 'phone' }, + { label: 'Link', value: 'link' }, + { label: 'Rating', value: 'rating' }, + { label: 'Tags', value: 'tag' }, + { label: 'People', value: 'people' }, + { label: 'Timeline', value: 'timeline' } +] + +export const needsBoard = [ + 'create_item', + 'update_item', + 'create_subitem', + 'move_item_to_group', + 'archive_item', + 'delete_item', + 'archive_board', + 'archive_group', + 'delete_group', + 'create_group', + 'duplicate_group', + 'create_column' +] + +export const needsGroup = ['move_item_to_group', 'archive_group', 'delete_group', 'duplicate_group'] + +export const needsItem = [ + 'update_item', + 'create_subitem', + 'move_item_to_group', + 'archive_item', + 'delete_item' +] + +export const needsColumnMap = ['create_item', 'update_item'] diff --git a/frontend/src/components/AllIntegrations/NewInteg.jsx b/frontend/src/components/AllIntegrations/NewInteg.jsx index 0db113b5c..d7777a4d3 100644 --- a/frontend/src/components/AllIntegrations/NewInteg.jsx +++ b/frontend/src/components/AllIntegrations/NewInteg.jsx @@ -164,6 +164,7 @@ const TheEventsCalendar = lazy(() => import('./TheEventsCalendar/TheEventsCalend const LMFWC = lazy(() => import('./LMFWC/LMFWC')) const Voxel = lazy(() => import('./Voxel/Voxel')) const SmartSuite = lazy(() => import('./SmartSuite/SmartSuite')) +const MondayCom = lazy(() => import('./MondayCom/MondayCom')) const Bento = lazy(() => import('./Bento/Bento')) const Line = lazy(() => import('./Line/Line')) const ACPT = lazy(() => import('./ACPT/ACPT')) @@ -1605,6 +1606,15 @@ export default function NewInteg({ allIntegURL }) { setFlow={setFlow} /> ) + case 'MondayCom': + return ( + + ) case 'Bento': return ( \ No newline at end of file From d2c371b6ae33ce9958e5748093d5733ad3dbba96 Mon Sep 17 00:00:00 2001 From: Rishad Alam <101513331+RishadAlam@users.noreply.github.com> Date: Thu, 23 Apr 2026 16:58:54 +0600 Subject: [PATCH 2/7] feat: monday.com integration added --- .../Actions/MondayCom/MondayComController.php | 2 +- backend/Actions/MondayCom/RecordApiHelper.php | 101 ++++-------------- backend/Flow/Flow.php | 5 + .../components/AllIntegrations/EditInteg.jsx | 2 +- .../components/AllIntegrations/IntegInfo.jsx | 2 +- .../MondayCom/EditMondayCom.jsx | 10 +- .../AllIntegrations/MondayCom/MondayCom.jsx | 12 +-- .../MondayCom/MondayComActions.jsx | 33 ++++++ .../MondayCom/MondayComAuthorization.jsx | 2 +- .../MondayCom/MondayComIntegLayout.jsx | 37 +++---- .../AllIntegrations/MondayCom/staticData.js | 41 +++---- .../components/AllIntegrations/NewInteg.jsx | 2 +- .../src/components/Flow/New/SelectAction.jsx | 2 +- frontend/src/resource/img/integ/mondayCom.svg | 1 - .../src/resource/img/integ/mondayCom.webp | Bin 0 -> 2936 bytes 15 files changed, 111 insertions(+), 141 deletions(-) create mode 100644 frontend/src/components/AllIntegrations/MondayCom/MondayComActions.jsx delete mode 100644 frontend/src/resource/img/integ/mondayCom.svg create mode 100644 frontend/src/resource/img/integ/mondayCom.webp diff --git a/backend/Actions/MondayCom/MondayComController.php b/backend/Actions/MondayCom/MondayComController.php index eb8d46df4..79a1c4d27 100644 --- a/backend/Actions/MondayCom/MondayComController.php +++ b/backend/Actions/MondayCom/MondayComController.php @@ -119,7 +119,7 @@ public function getColumns($requestParams) 'type' => $c->type, 'required' => false, ], - $response->data->boards[0]->columns + reset($response->data->boards)->columns ); wp_send_json_success($columns, 200); diff --git a/backend/Actions/MondayCom/RecordApiHelper.php b/backend/Actions/MondayCom/RecordApiHelper.php index 572093f28..7b84b22bf 100644 --- a/backend/Actions/MondayCom/RecordApiHelper.php +++ b/backend/Actions/MondayCom/RecordApiHelper.php @@ -8,16 +8,11 @@ use BitApps\Integrations\Config; use BitApps\Integrations\Core\Util\Common; -use BitApps\Integrations\Core\Util\HttpHelper; use BitApps\Integrations\Core\Util\Hooks; use BitApps\Integrations\Log\LogHandler; class RecordApiHelper { - private const API_URL = 'https://api.monday.com/v2'; - - private const API_VERSION = '2023-10'; - private $integrationDetails; private $integrationId; @@ -42,45 +37,7 @@ public function handleFilterResponse($response) } // translators: %s: Placeholder value - return (object) ['error' => wp_sprintf(__('%s plugin is not installed or activate', 'bit-integrations'), 'Bit Integrations Pro')]; - } - - public function createItem($fieldData) - { - $boardId = $this->integrationDetails->selectedBoard ?? ''; - $groupId = $this->integrationDetails->selectedGroup ?? ''; - $itemName = $fieldData['item_name'] ?? ''; - - if (empty($boardId) || empty($itemName) || empty($this->apiToken)) { - return (object) ['error' => __('Required params are empty!', 'bit-integrations')]; - } - - $columnValues = $fieldData; - unset($columnValues['item_name']); - - $query = <<<'GRAPHQL' - mutation ($boardId: ID!, $groupId: String, $itemName: String!, $columnValues: JSON) { - create_item ( - board_id: $boardId, - group_id: $groupId, - item_name: $itemName, - column_values: $columnValues - ) { - id - name - } - } - GRAPHQL; - - return $this->request( - $query, - [ - 'boardId' => (string) $boardId, - 'groupId' => $groupId ? (string) $groupId : null, - 'itemName' => (string) $itemName, - 'columnValues' => wp_json_encode((object) $columnValues), - ] - ); + return (object) ['error' => wp_sprintf(__('%s plugin is not installed or activated', 'bit-integrations'), 'Bit Integrations Pro')]; } public function generateReqDataFromFieldMap($fieldValues, $fieldMap) @@ -107,105 +64,91 @@ public function generateReqDataFromFieldMap($fieldValues, $fieldMap) public function execute($fieldValues, $fieldMap) { $fieldData = $this->generateReqDataFromFieldMap($fieldValues, $fieldMap); - $mainAction = $this->integrationDetails->mainAction ?? 'create_item'; + $mainAction = $this->integrationDetails->mainAction ?? ''; + $apiResponse = null; + $responseType = null; + $default = null; + $this->type = 'item'; $this->typeName = $mainAction; - $default = (object) ['error' => wp_sprintf(__('%s plugin is not installed or activate', 'bit-integrations'), 'Bit Integrations Pro')]; + $default = (object) ['error' => wp_sprintf(__('%s plugin is not installed or activated', 'bit-integrations'), 'Bit Integrations Pro')]; switch ($mainAction) { case 'create_item': $this->type = 'item'; - $apiResponse = $this->createItem($fieldData); + $apiResponse = Hooks::apply(Config::withPrefix('mondayCom_create_item'), false, $fieldData, $this->integrationDetails, $this->apiToken); break; case 'update_item': $this->type = 'item'; - $apiResponse = $this->handleFilterResponse(Hooks::apply(Config::withPrefix('mondayCom_update_item'), false, $fieldData, $this->integrationDetails, $this->apiToken)); + $apiResponse = Hooks::apply(Config::withPrefix('mondayCom_update_item'), false, $fieldData, $this->integrationDetails, $this->apiToken); break; case 'create_subitem': $this->type = 'subitem'; - $apiResponse = $this->handleFilterResponse(Hooks::apply(Config::withPrefix('mondayCom_create_subitem'), false, $fieldData, $this->integrationDetails, $this->apiToken)); + $apiResponse = Hooks::apply(Config::withPrefix('mondayCom_create_subitem'), false, $fieldData, $this->integrationDetails, $this->apiToken); break; case 'move_item_to_group': $this->type = 'item'; - $apiResponse = $this->handleFilterResponse(Hooks::apply(Config::withPrefix('mondayCom_move_item_to_group'), false, $fieldData, $this->integrationDetails, $this->apiToken)); + $apiResponse = Hooks::apply(Config::withPrefix('mondayCom_move_item_to_group'), false, $fieldData, $this->apiToken); break; case 'archive_item': $this->type = 'item'; - $apiResponse = $this->handleFilterResponse(Hooks::apply(Config::withPrefix('mondayCom_archive_item'), false, $fieldData, $this->integrationDetails, $this->apiToken)); + $apiResponse = Hooks::apply(Config::withPrefix('mondayCom_archive_item'), false, $fieldData, $this->apiToken); break; case 'delete_item': $this->type = 'item'; - $apiResponse = $this->handleFilterResponse(Hooks::apply(Config::withPrefix('mondayCom_delete_item'), false, $fieldData, $this->integrationDetails, $this->apiToken)); + $apiResponse = Hooks::apply(Config::withPrefix('mondayCom_delete_item'), false, $fieldData, $this->apiToken); break; case 'archive_board': $this->type = 'board'; - $apiResponse = $this->handleFilterResponse(Hooks::apply(Config::withPrefix('mondayCom_archive_board'), false, $fieldData, $this->integrationDetails, $this->apiToken)); + $apiResponse = Hooks::apply(Config::withPrefix('mondayCom_archive_board'), false, $fieldData, $this->integrationDetails, $this->apiToken); break; case 'archive_group': $this->type = 'group'; - $apiResponse = $this->handleFilterResponse(Hooks::apply(Config::withPrefix('mondayCom_archive_group'), false, $fieldData, $this->integrationDetails, $this->apiToken)); + $apiResponse = Hooks::apply(Config::withPrefix('mondayCom_archive_group'), false, $fieldData, $this->integrationDetails, $this->apiToken); break; case 'delete_group': $this->type = 'group'; - $apiResponse = $this->handleFilterResponse(Hooks::apply(Config::withPrefix('mondayCom_delete_group'), false, $fieldData, $this->integrationDetails, $this->apiToken)); + $apiResponse = Hooks::apply(Config::withPrefix('mondayCom_delete_group'), false, $fieldData, $this->integrationDetails, $this->apiToken); break; case 'create_group': $this->type = 'group'; - $apiResponse = $this->handleFilterResponse(Hooks::apply(Config::withPrefix('mondayCom_create_group'), false, $fieldData, $this->integrationDetails, $this->apiToken)); + $apiResponse = Hooks::apply(Config::withPrefix('mondayCom_create_group'), false, $fieldData, $this->integrationDetails, $this->apiToken); break; case 'duplicate_group': $this->type = 'group'; - $apiResponse = $this->handleFilterResponse(Hooks::apply(Config::withPrefix('mondayCom_duplicate_group'), false, $fieldData, $this->integrationDetails, $this->apiToken)); + $apiResponse = Hooks::apply(Config::withPrefix('mondayCom_duplicate_group'), false, $fieldData, $this->integrationDetails, $this->apiToken); break; case 'create_column': $this->type = 'column'; - $apiResponse = $this->handleFilterResponse(Hooks::apply(Config::withPrefix('mondayCom_create_column'), false, $fieldData, $this->integrationDetails, $this->apiToken)); + $apiResponse = Hooks::apply(Config::withPrefix('mondayCom_create_column'), false, $fieldData, $this->integrationDetails, $this->apiToken); break; default: - $apiResponse = $default; + $apiResponse = null; } + $apiResponse = $this->handleFilterResponse($apiResponse); $responseType = $this->hasErrors($apiResponse) || !isset($apiResponse->data) ? 'error' : 'success'; + LogHandler::save($this->integrationId, wp_json_encode(['type' => $this->type, 'type_name' => $this->typeName]), $responseType, wp_json_encode($apiResponse)); return $apiResponse; } - private function request($query, $variables = []) - { - $body = ['query' => $query]; - - if (!empty($variables)) { - $body['variables'] = $variables; - } - - return HttpHelper::post(self::API_URL, wp_json_encode($body), $this->setHeaders()); - } - private function hasErrors($response) { return is_wp_error($response) || !empty($response->errors) || !empty($response->error); } - - private function setHeaders() - { - return [ - 'Authorization' => $this->apiToken, - 'Content-Type' => 'application/json', - 'API-Version' => self::API_VERSION, - ]; - } } diff --git a/backend/Flow/Flow.php b/backend/Flow/Flow.php index 3450a1d79..194cc22c6 100644 --- a/backend/Flow/Flow.php +++ b/backend/Flow/Flow.php @@ -498,6 +498,11 @@ public static function execute($triggered_entity, $triggered_entity_id, $data, $ break; + case 'Monday.Com': + $integrationName = 'MondayCom'; + + break; + default: $integrationName = $integrationName; diff --git a/frontend/src/components/AllIntegrations/EditInteg.jsx b/frontend/src/components/AllIntegrations/EditInteg.jsx index 03b529c98..b13a35dfe 100644 --- a/frontend/src/components/AllIntegrations/EditInteg.jsx +++ b/frontend/src/components/AllIntegrations/EditInteg.jsx @@ -580,7 +580,7 @@ const IntegType = memo(({ allIntegURL, flow }) => { return case 'SmartSuite': return - case 'MondayCom': + case 'Monday.Com': return case 'Bento': return diff --git a/frontend/src/components/AllIntegrations/IntegInfo.jsx b/frontend/src/components/AllIntegrations/IntegInfo.jsx index bee87024c..e47127693 100644 --- a/frontend/src/components/AllIntegrations/IntegInfo.jsx +++ b/frontend/src/components/AllIntegrations/IntegInfo.jsx @@ -617,7 +617,7 @@ export default function IntegInfo() { return case 'SmartSuite': return - case 'MondayCom': + case 'Monday.Com': return case 'Bento': return diff --git a/frontend/src/components/AllIntegrations/MondayCom/EditMondayCom.jsx b/frontend/src/components/AllIntegrations/MondayCom/EditMondayCom.jsx index 0dd9ae198..9f174dd3b 100644 --- a/frontend/src/components/AllIntegrations/MondayCom/EditMondayCom.jsx +++ b/frontend/src/components/AllIntegrations/MondayCom/EditMondayCom.jsx @@ -6,12 +6,12 @@ import { useRecoilState, useRecoilValue } from 'recoil' import { $actionConf, $formFields, $newFlow } from '../../../GlobalStates' import { __ } from '../../../Utils/i18nwrap' import SnackMsg from '../../Utilities/SnackMsg' -import SetEditIntegComponents from '../IntegrationHelpers/SetEditIntegComponents' import { saveActionConf } from '../IntegrationHelpers/IntegrationHelpers' import IntegrationStepThree from '../IntegrationHelpers/IntegrationStepThree' +import SetEditIntegComponents from '../IntegrationHelpers/SetEditIntegComponents' import { checkMappedFields, handleInput } from './MondayComCommonFunc' import MondayComIntegLayout from './MondayComIntegLayout' -import { needsBoard, needsGroup, needsItem } from './staticData' +import { needsBoard, needsItem } from './staticData' function EditMondayCom({ allIntegURL }) { const navigate = useNavigate() @@ -32,10 +32,6 @@ function EditMondayCom({ allIntegURL }) { toast.error(__('Please select a board', 'bit-integrations')) return } - if (needsGroup.includes(action) && !mondayComConf.selectedGroup) { - toast.error(__('Please select a group', 'bit-integrations')) - return - } if (needsItem.includes(action) && !mondayComConf.selectedItem) { toast.error(__('Please select an item', 'bit-integrations')) return @@ -57,7 +53,7 @@ function EditMondayCom({ allIntegURL }) { } return ( -
+
diff --git a/frontend/src/components/AllIntegrations/MondayCom/MondayCom.jsx b/frontend/src/components/AllIntegrations/MondayCom/MondayCom.jsx index 514049e49..9660f78bb 100644 --- a/frontend/src/components/AllIntegrations/MondayCom/MondayCom.jsx +++ b/frontend/src/components/AllIntegrations/MondayCom/MondayCom.jsx @@ -12,7 +12,7 @@ import IntegrationStepThree from '../IntegrationHelpers/IntegrationStepThree' import MondayComAuthorization from './MondayComAuthorization' import { checkMappedFields, generateMappedField } from './MondayComCommonFunc' import MondayComIntegLayout from './MondayComIntegLayout' -import { actionLists, needsBoard, needsGroup, needsItem } from './staticData' +import { actionLists, needsBoard, needsItem } from './staticData' function MondayCom({ formFields, setFlow, flow, allIntegURL }) { const navigate = useNavigate() @@ -24,8 +24,8 @@ function MondayCom({ formFields, setFlow, flow, allIntegURL }) { const mondayComFields = [] const [mondayComConf, setMondayComConf] = useState({ - name: 'MondayCom', - type: 'MondayCom', + name: 'Monday.Com', + type: 'Monday.Com', apiToken: '', field_map: generateMappedField(mondayComFields), mainAction: '', @@ -70,10 +70,6 @@ function MondayCom({ formFields, setFlow, flow, allIntegURL }) { toast.error(__('Please select a board', 'bit-integrations')) return } - if (needsGroup.includes(action) && !mondayComConf.selectedGroup) { - toast.error(__('Please select a group', 'bit-integrations')) - return - } if (needsItem.includes(action) && !mondayComConf.selectedItem) { toast.error(__('Please select an item', 'bit-integrations')) return @@ -106,7 +102,7 @@ function MondayCom({ formFields, setFlow, flow, allIntegURL }) { {/* STEP 2 */}
+ style={{ ...(step === 2 && { width: 900, minHeight: 500, overflow: 'visible' }) }}> { + const newConf = { ...mondayComConf } + + if (typ === 'addToTop') { + if (val.target.checked) { + newConf.addToTop = true + } else { + delete newConf.addToTop + } + } + + setMondayComConf({ ...newConf }) + } + + return ( +
+
+ actionHandler(e, 'addToTop')} + checked={!!mondayComConf?.addToTop} + className="wdt-200 mt-4 mr-2" + value="addToTop" + title={__('Add To Top', 'bit-integrations')} + subTitle={__('Duplicate selected group at the top of the board', 'bit-integrations')} + /> +
+
+ ) +} diff --git a/frontend/src/components/AllIntegrations/MondayCom/MondayComAuthorization.jsx b/frontend/src/components/AllIntegrations/MondayCom/MondayComAuthorization.jsx index cdd9d9b09..8fe6f8e3b 100644 --- a/frontend/src/components/AllIntegrations/MondayCom/MondayComAuthorization.jsx +++ b/frontend/src/components/AllIntegrations/MondayCom/MondayComAuthorization.jsx @@ -46,7 +46,7 @@ export default function MondayComAuthorization({
  • ${__('Log in to your Monday.com account.', 'bit-integrations')}
  • ${__('Click on your avatar in the bottom left corner.', 'bit-integrations')}
  • -
  • ${__('Select Developers → My access tokens.', 'bit-integrations')}
  • +
  • ${__('Select Developers → API Token.', 'bit-integrations')}
  • ${__('Copy your personal API token (v2).', 'bit-integrations')}
` diff --git a/frontend/src/components/AllIntegrations/MondayCom/MondayComIntegLayout.jsx b/frontend/src/components/AllIntegrations/MondayCom/MondayComIntegLayout.jsx index df1670434..3ac50afdf 100644 --- a/frontend/src/components/AllIntegrations/MondayCom/MondayComIntegLayout.jsx +++ b/frontend/src/components/AllIntegrations/MondayCom/MondayComIntegLayout.jsx @@ -18,12 +18,12 @@ import { staticFieldsMap, columnTypeList, needsBoard, - needsGroup, needsItem, needsColumnMap } from './staticData' import { checkIsPro, getProLabel } from '../../Utilities/ProUtilHelpers' import { create } from 'mutative' +import MondayComActions from './MondayComActions' export default function MondayComIntegLayout({ formFields, @@ -85,9 +85,6 @@ export default function MondayComIntegLayout({ if (needsColumnMap.includes(action)) { getAllColumns(mondayComConf, setMondayComConf, val, setLoading) } - if (needsGroup.includes(action) || action === 'create_item') { - getAllGroups(mondayComConf, setMondayComConf, val, setLoading) - } if (needsItem.includes(action)) { getAllItems(mondayComConf, setMondayComConf, val, setLoading) } @@ -163,7 +160,6 @@ export default function MondayComIntegLayout({ )} {mainAction - && needsGroup.includes(mainAction) && mondayComConf?.selectedBoard && !loading.group && ( <> @@ -198,7 +194,7 @@ export default function MondayComIntegLayout({
- )} + )} {mainAction === 'create_item' && mondayComConf?.selectedBoard @@ -235,7 +231,7 @@ export default function MondayComIntegLayout({
- )} + )} {mainAction && needsItem.includes(mainAction) @@ -273,7 +269,7 @@ export default function MondayComIntegLayout({
- )} + )} {mainAction === 'create_column' && ( <> @@ -292,20 +288,6 @@ export default function MondayComIntegLayout({ )} - {mainAction === 'duplicate_group' && ( - <> -
-
- {__('Add To Top:', 'bit-integrations')} - handleSelectChange(e.target.checked, 'addToTop')} - /> -
- - )} - {(loading.board || loading.group || loading.column || loading.item) && (
)} + + {mainAction === 'duplicate_group' && ( + <> +
+
+ {__('Utilities', 'bit-integrations')} +
+
+ + + )} ) } diff --git a/frontend/src/components/AllIntegrations/MondayCom/staticData.js b/frontend/src/components/AllIntegrations/MondayCom/staticData.js index d3c3bd658..87a0772e0 100644 --- a/frontend/src/components/AllIntegrations/MondayCom/staticData.js +++ b/frontend/src/components/AllIntegrations/MondayCom/staticData.js @@ -1,7 +1,7 @@ import { __ } from '../../../Utils/i18nwrap' export const actionLists = [ - { name: 'create_item', label: __('Create Item', 'bit-integrations'), is_pro: false }, + { name: 'create_item', label: __('Create Item', 'bit-integrations'), is_pro: true }, { name: 'update_item', label: __('Update Item', 'bit-integrations'), is_pro: true }, { name: 'create_subitem', label: __('Create Subitem', 'bit-integrations'), is_pro: true }, { name: 'move_item_to_group', label: __('Move Item to Group', 'bit-integrations'), is_pro: true }, @@ -17,20 +17,34 @@ export const actionLists = [ export const staticFieldsMap = { create_item: [{ label: __('Item Name', 'bit-integrations'), key: 'item_name', required: true }], - update_item: [], + update_item: [{ label: __('Item ID', 'bit-integrations'), key: 'item_id', required: true }], create_subitem: [ { label: __('Subitem Name', 'bit-integrations'), key: 'subitem_name', required: true } ], - move_item_to_group: [], - archive_item: [], - delete_item: [], - archive_board: [], + move_item_to_group: [ + { label: __('Group ID', 'bit-integrations'), key: 'group_id', required: true }, + { label: __('Item ID', 'bit-integrations'), key: 'item_id', required: true } + ], + archive_item: [ + { label: __('Item ID', 'bit-integrations'), key: 'item_id', required: true } + ], + delete_item: [ + { label: __('Item ID', 'bit-integrations'), key: 'item_id', required: true } + ], + archive_board: [ + { label: __('Board ID', 'bit-integrations'), key: 'board_id', required: true } + ], create_group: [{ label: __('Group Name', 'bit-integrations'), key: 'group_name', required: true }], duplicate_group: [ + { label: __('Group ID', 'bit-integrations'), key: 'group_id', required: true }, { label: __('Group Title', 'bit-integrations'), key: 'group_title', required: true } ], - archive_group: [], - delete_group: [], + archive_group: [ + { label: __('Group ID', 'bit-integrations'), key: 'group_id', required: true } + ], + delete_group: [ + { label: __('Group ID', 'bit-integrations'), key: 'group_id', required: true } + ], create_column: [{ label: __('Column Title', 'bit-integrations'), key: 'column_title', required: true }] } @@ -57,7 +71,6 @@ export const needsBoard = [ 'move_item_to_group', 'archive_item', 'delete_item', - 'archive_board', 'archive_group', 'delete_group', 'create_group', @@ -65,14 +78,6 @@ export const needsBoard = [ 'create_column' ] -export const needsGroup = ['move_item_to_group', 'archive_group', 'delete_group', 'duplicate_group'] - -export const needsItem = [ - 'update_item', - 'create_subitem', - 'move_item_to_group', - 'archive_item', - 'delete_item' -] +export const needsItem = [ 'create_subitem',] export const needsColumnMap = ['create_item', 'update_item'] diff --git a/frontend/src/components/AllIntegrations/NewInteg.jsx b/frontend/src/components/AllIntegrations/NewInteg.jsx index d7777a4d3..1dded749a 100644 --- a/frontend/src/components/AllIntegrations/NewInteg.jsx +++ b/frontend/src/components/AllIntegrations/NewInteg.jsx @@ -1606,7 +1606,7 @@ export default function NewInteg({ allIntegURL }) { setFlow={setFlow} /> ) - case 'MondayCom': + case 'Monday.Com': return ( \ No newline at end of file diff --git a/frontend/src/resource/img/integ/mondayCom.webp b/frontend/src/resource/img/integ/mondayCom.webp new file mode 100644 index 0000000000000000000000000000000000000000..c98a5a3186c190ac7379d8fbdf2504827c54e568 GIT binary patch literal 2936 zcmV-;3y1VlNk&F+3jhFDMM6+kP&goD3jhF+K>(crDmVeS06vjMoJl35BOxo5D7df^ z2~FRRlI;4-kmM$IKJ>C-a}x z{|gUgZhfsk|N8)c|KL0I z7iAu2*I9Bt$7K@|Mn?*^o;SX`*h`+sTT@LO4&RSB`hgReo1D4k{#6p&>&2*~bW&*q=O!2|fnfHcv8PDf05ouNID8}{y zcgLJr3DpM)NPhM9=U_?itS9ea)W7gM@?H6!XITdGQ84qZlrz`IhiEnl5V)}NeFk!H z+OuCvQYKo{0PFvH-3$(hF*;h1Pv>Z<*yQPec(-d7p|%4!FdA1=1+?pAid@q552CeK zSu!+Dw6u0Q7Nd@WW@(hM1mD_>cI3o6?tQqo!9r^`@vPp!Wfu;{1;PoM!>~Vo>J;q~ zbqyph4W(enxV39LAP`<4claUTV&dIf5{irJ95NcLIw1u3J*gHx#|*B&OQ2d_x4- z0fG(Xf*8~Kn70lKF@Cqcn4S+EZO!Pm#ecMkSGxl2kmW&cOjY*N0s4orL5y{3;* zK~5vQPqV)~qGuQFFcc|BF^X3#d<;65 zdjB*Ej>9fGQ5NV;vD{=nRG{0tSWfEXMEO(H+r^lmLy#jOb^Sm#$ zNg_Yz2@$@?QBnng0L#Dx?VA&j8VG5?nLq{YC?+hr=? zS;aFOuC;|LyAWHFxzG?uE0G%hiZ0_qxthuBueH1&5Eu)*2R^$0BQBfA+Lg~9@IZmZ zP+Xozw4vQm!j1Dzh*y)XeBdH5~zCc=Kv-+hlOciIyS_BP0tv7mUXs^y)_)@ zJ$S!@>JEGzhCT!Bi)dVPE4}$R)8*3etS+e&VuIjn?3Nbb?(cQsow90O|8iAlL%R-8y&B=wSj>KlUC^BhP|WmgFo112C<#V&pBJ zI<`hNPFUkQumi=7uA})wn`8VS-e)sqe?pypHGreZdaiIGIZmz$AeZ!6Mx2|jnl!yr zA&a$H#ln7OY40KE{>%%g_>#+6T?+_S>uyE2rw+_qc-x@~lRh<35C6D|!iU)6#$fGZ zZB&=jm=$8740h)k;xrEFqF)*XrJH6s;6s%EPhQOF^!Mlp78|;y?N`ZE%OqYN!|;ga zgVE`Vh06pP-gmkfpQU|Pp1VGeTsN|-F@o@_DmYuO4p7vi=j|jaTc+T^Gzp!E={{|Y za4e{o%WEEYRJ&(hKx}9Tta&GFn7F9s=)PZUFrazl6oSdGl}FcXRTARyg-#ED&ha&N z-Fd72FFAo$T*Z=S`>g*+%^Qu-1+SZl-6eQI+JK0OFIA*NB|@kAE9l07m>mQxIHI8B zdvdEwG-$eFOd6iDAi~{(fT#)pV%{;G0h&&V7?d+re9=ixg1JKJ8O1vQ6Tj>`KS-=1 zIHG_HV3H}25O^Ti7SVr=%R!F{YQlPtMR?^;SQ;~|$nHNusmqy5B@hA;hH{>c;aun3 z`BE0&h-$=ODS8p|HAClMvHt+xzXpy6VDty-=;i^~G_I!g2QFH5D0zWofI%x%^`G0a zHc1j`=cwL$w@FQsxuU5j-^w$2gP4fh0UibZOi9n}c7!xbT6?nPZ zYd`jnQb);B!55%{OtSURG-bg@inSyxokW0#b@$;NE0V+0dB6-I@N(bByD{)^O*NCG z6lk5nOHB*tX*JmTE>opJt}r#{BEt^sv`j;o1NntHvt|cBE8U-LbX1sT8SxlP4?}Sk zY#lN=8Wq30Xw=^Q#svFN)w+M;Y9bg=94HoGeI2R&i;=mRF}*7|`B?pUr242pgz~85 zQaZE*TG=ly5`{#}mQ6XzAoSG`Ba|WGujkTVA4cUlp_xcXGR77!v<;LX+VdoMX|r2S zQdhITs3>6Lz9u{jPVad3YPFOu#GuPwXm9VZpS!pgbrnS7S?Fvd`r$NnsDN(qcZJp` zj)Lz2^q!+y#(6#U1VDykV&PV)R6|vcm`616RjEPymv-uil?Kd}!&SR2h;S%e+KH{9 zy~y4q$HwB&#Mseb6R5&8+b1#3wMe#=EV0R1kSIg?{Y(tD6$P9OQO+UOIys=&`k^_% z&>5za;r276B2}Anz~7&Rvz5rg$1zXBv-6n(GH24wIW&Gx%z?drnzXN2Ptl(gybIM9 z`!Jf-R@iX=f>l=DmNh{p0#&65Sh}7D9y6cmPOPbd(!GBETb(K+(8&MQ#C^JuW~&%t zWEs=EyPmFC2n=`s5=|r8T6epaLk+-bM7lo6NU~`dHOGC-ce+iXpTFQwc(vf4y4n!0 zLw(1}v3RSp*Wl3%d$!yVpTsC_en=60MOqS4Yv(JUsr6kkU$i9+n2ZkcZibxk=~IV+ z(ufwATB5Ris7?jMU}5;B1_7V$xcoTo!G$E3Y=O)M8S8mi%W8siyrwzVfJj9Xi|@uO i4gfi=u6WqLx>5jydY{M8?A`t|*1Y9)i%Cly00003I-Ljr literal 0 HcmV?d00001 From 33daea31ca950a88f715ab0e3c6597fb065c8bef Mon Sep 17 00:00:00 2001 From: Rishad Alam <101513331+RishadAlam@users.noreply.github.com> Date: Thu, 23 Apr 2026 17:00:47 +0600 Subject: [PATCH 3/7] refactor: monday.com pro action hooks params --- backend/Actions/MondayCom/RecordApiHelper.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/Actions/MondayCom/RecordApiHelper.php b/backend/Actions/MondayCom/RecordApiHelper.php index 7b84b22bf..9fcfcba56 100644 --- a/backend/Actions/MondayCom/RecordApiHelper.php +++ b/backend/Actions/MondayCom/RecordApiHelper.php @@ -107,7 +107,7 @@ public function execute($fieldValues, $fieldMap) break; case 'archive_board': $this->type = 'board'; - $apiResponse = Hooks::apply(Config::withPrefix('mondayCom_archive_board'), false, $fieldData, $this->integrationDetails, $this->apiToken); + $apiResponse = Hooks::apply(Config::withPrefix('mondayCom_archive_board'), false, $fieldData, $this->apiToken); break; case 'archive_group': From 15fd2d389aac04ba48f27eb71f28a331265a0b3f Mon Sep 17 00:00:00 2001 From: Rishad Alam <101513331+RishadAlam@users.noreply.github.com> Date: Thu, 23 Apr 2026 17:24:21 +0600 Subject: [PATCH 4/7] refactor: monday.com frontend --- backend/Actions/MondayCom/RecordApiHelper.php | 3 -- .../MondayCom/EditMondayCom.jsx | 4 +- .../AllIntegrations/MondayCom/MondayCom.jsx | 2 - .../MondayCom/MondayComCommonFunc.js | 7 +++- .../MondayCom/MondayComIntegLayout.jsx | 37 ------------------- 5 files changed, 7 insertions(+), 46 deletions(-) diff --git a/backend/Actions/MondayCom/RecordApiHelper.php b/backend/Actions/MondayCom/RecordApiHelper.php index 9fcfcba56..560bc0548 100644 --- a/backend/Actions/MondayCom/RecordApiHelper.php +++ b/backend/Actions/MondayCom/RecordApiHelper.php @@ -67,13 +67,10 @@ public function execute($fieldValues, $fieldMap) $mainAction = $this->integrationDetails->mainAction ?? ''; $apiResponse = null; $responseType = null; - $default = null; $this->type = 'item'; $this->typeName = $mainAction; - $default = (object) ['error' => wp_sprintf(__('%s plugin is not installed or activated', 'bit-integrations'), 'Bit Integrations Pro')]; - switch ($mainAction) { case 'create_item': $this->type = 'item'; diff --git a/frontend/src/components/AllIntegrations/MondayCom/EditMondayCom.jsx b/frontend/src/components/AllIntegrations/MondayCom/EditMondayCom.jsx index 9f174dd3b..65a0ab4ff 100644 --- a/frontend/src/components/AllIntegrations/MondayCom/EditMondayCom.jsx +++ b/frontend/src/components/AllIntegrations/MondayCom/EditMondayCom.jsx @@ -71,14 +71,12 @@ function EditMondayCom({ allIntegURL }) { {mondayComConf?.mainAction && ( diff --git a/frontend/src/components/AllIntegrations/MondayCom/MondayComCommonFunc.js b/frontend/src/components/AllIntegrations/MondayCom/MondayComCommonFunc.js index f5eb086e9..dcfccbd86 100644 --- a/frontend/src/components/AllIntegrations/MondayCom/MondayComCommonFunc.js +++ b/frontend/src/components/AllIntegrations/MondayCom/MondayComCommonFunc.js @@ -71,7 +71,12 @@ export const mondayComAuthentication = (confTmp, setError, setIsAuthorized, load return } setLoading({ ...loading, auth: false }) - toast.error(__('Authorized failed', 'bit-integrations')) + const authErrorMessage = result?.message || result?.error || result?.data?.message + toast.error( + authErrorMessage + ? `${__('Authorization failed', 'bit-integrations')}: ${authErrorMessage}` + : __('Authorization failed', 'bit-integrations') + ) }) } diff --git a/frontend/src/components/AllIntegrations/MondayCom/MondayComIntegLayout.jsx b/frontend/src/components/AllIntegrations/MondayCom/MondayComIntegLayout.jsx index 3ac50afdf..1c5f2433f 100644 --- a/frontend/src/components/AllIntegrations/MondayCom/MondayComIntegLayout.jsx +++ b/frontend/src/components/AllIntegrations/MondayCom/MondayComIntegLayout.jsx @@ -196,43 +196,6 @@ export default function MondayComIntegLayout({ )} - {mainAction === 'create_item' - && mondayComConf?.selectedBoard - && !loading.group && ( - <> -
-
- {__('Group (Optional):', 'bit-integrations')} - ({ label: g.name, value: `${g.id}` })) - } - className="msl-wrp-options dropdown-custom-width" - defaultValue={mondayComConf?.selectedGroup} - onChange={val => handleSelectChange(val, 'selectedGroup')} - singleSelect - closeOnSelect - /> - -
- - )} - {mainAction && needsItem.includes(mainAction) && mondayComConf?.selectedBoard From 0ad652e083e46eb134388ff5a506e1fbc82f71fa Mon Sep 17 00:00:00 2001 From: Rishad Alam <101513331+RishadAlam@users.noreply.github.com> Date: Tue, 28 Apr 2026 13:54:40 +0600 Subject: [PATCH 5/7] fix: filter out 'file' type columns in getColumns and log items in getItems --- .../Actions/MondayCom/MondayComController.php | 22 +++++++++++-------- .../MondayCom/MondayComIntegLayout.jsx | 3 +++ 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/backend/Actions/MondayCom/MondayComController.php b/backend/Actions/MondayCom/MondayComController.php index 79a1c4d27..9f8729b12 100644 --- a/backend/Actions/MondayCom/MondayComController.php +++ b/backend/Actions/MondayCom/MondayComController.php @@ -112,15 +112,17 @@ public function getColumns($requestParams) wp_send_json_error(self::errorMessage($response, __('Columns fetching failed', 'bit-integrations')), 400); } - $columns = array_map( - fn ($c) => (object) [ - 'key' => $c->id, - 'label' => $c->title, - 'type' => $c->type, - 'required' => false, - ], - reset($response->data->boards)->columns - ); + $columns = []; + foreach (reset($response->data->boards)->columns as $column) { + if ($column->type !== 'file') { + $columns[] = (object) [ + 'key' => $column->id, + 'label' => $column->title, + 'type' => $column->type, + 'required' => false, + ]; + } + } wp_send_json_success($columns, 200); } @@ -162,6 +164,8 @@ public function getItems($requestParams) $response->data->boards[0]->items_page->items ); + error_log(print_r($items, true)); + wp_send_json_success($items, 200); } diff --git a/frontend/src/components/AllIntegrations/MondayCom/MondayComIntegLayout.jsx b/frontend/src/components/AllIntegrations/MondayCom/MondayComIntegLayout.jsx index 1c5f2433f..4ee59ea0c 100644 --- a/frontend/src/components/AllIntegrations/MondayCom/MondayComIntegLayout.jsx +++ b/frontend/src/components/AllIntegrations/MondayCom/MondayComIntegLayout.jsx @@ -82,6 +82,8 @@ export default function MondayComIntegLayout({ const action = mondayComConf.mainAction + getAllGroups(mondayComConf, setMondayComConf, val, setLoading) + if (needsColumnMap.includes(action)) { getAllColumns(mondayComConf, setMondayComConf, val, setLoading) } @@ -160,6 +162,7 @@ export default function MondayComIntegLayout({ )} {mainAction + && !['create_column', 'delete_group', 'archive_group', 'duplicate_group', 'archive_item', 'delete_item', 'move_item_to_group'].includes(mainAction) && mondayComConf?.selectedBoard && !loading.group && ( <> From fffbe86966ef7262e4bbf32e9d10b90609083c42 Mon Sep 17 00:00:00 2001 From: Rishad Alam <101513331+RishadAlam@users.noreply.github.com> Date: Tue, 28 Apr 2026 14:27:40 +0600 Subject: [PATCH 6/7] fix: remove debug logging for items in getItems method --- backend/Actions/MondayCom/MondayComController.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/backend/Actions/MondayCom/MondayComController.php b/backend/Actions/MondayCom/MondayComController.php index 9f8729b12..9a3f01a77 100644 --- a/backend/Actions/MondayCom/MondayComController.php +++ b/backend/Actions/MondayCom/MondayComController.php @@ -164,8 +164,6 @@ public function getItems($requestParams) $response->data->boards[0]->items_page->items ); - error_log(print_r($items, true)); - wp_send_json_success($items, 200); } From 13e003f66ea0449daee3ffe26bc671da82b65034 Mon Sep 17 00:00:00 2001 From: Rishad Alam <101513331+RishadAlam@users.noreply.github.com> Date: Wed, 6 May 2026 11:33:30 +0600 Subject: [PATCH 7/7] fix: improve error handling in authentication and enhance accessibility for field mapping --- .../MondayCom/MondayComCommonFunc.js | 3 +- .../MondayCom/MondayComFieldMap.jsx | 2 +- .../MondayCom/MondayComIntegLayout.jsx | 9 ++---- .../AllIntegrations/MondayCom/staticData.js | 28 +++++++++---------- 4 files changed, 20 insertions(+), 22 deletions(-) diff --git a/frontend/src/components/AllIntegrations/MondayCom/MondayComCommonFunc.js b/frontend/src/components/AllIntegrations/MondayCom/MondayComCommonFunc.js index dcfccbd86..12fa97eb6 100644 --- a/frontend/src/components/AllIntegrations/MondayCom/MondayComCommonFunc.js +++ b/frontend/src/components/AllIntegrations/MondayCom/MondayComCommonFunc.js @@ -71,7 +71,8 @@ export const mondayComAuthentication = (confTmp, setError, setIsAuthorized, load return } setLoading({ ...loading, auth: false }) - const authErrorMessage = result?.message || result?.error || result?.data?.message + const message = typeof result?.data === 'string' ? result.data : result?.data?.message + const authErrorMessage = result?.message || result?.error || message toast.error( authErrorMessage ? `${__('Authorization failed', 'bit-integrations')}: ${authErrorMessage}` diff --git a/frontend/src/components/AllIntegrations/MondayCom/MondayComFieldMap.jsx b/frontend/src/components/AllIntegrations/MondayCom/MondayComFieldMap.jsx index 80232e5d0..1f7664352 100644 --- a/frontend/src/components/AllIntegrations/MondayCom/MondayComFieldMap.jsx +++ b/frontend/src/components/AllIntegrations/MondayCom/MondayComFieldMap.jsx @@ -99,7 +99,7 @@ export default function MondayComFieldMap({ onClick={() => delFieldMap(i, mondayComConf, setMondayComConf)} className="icn-btn sh-sm ml-1" type="button" - aria-label="btn"> + aria-label={__('Remove field mapping', 'bit-integrations')}> diff --git a/frontend/src/components/AllIntegrations/MondayCom/MondayComIntegLayout.jsx b/frontend/src/components/AllIntegrations/MondayCom/MondayComIntegLayout.jsx index 4ee59ea0c..3f9645125 100644 --- a/frontend/src/components/AllIntegrations/MondayCom/MondayComIntegLayout.jsx +++ b/frontend/src/components/AllIntegrations/MondayCom/MondayComIntegLayout.jsx @@ -139,8 +139,7 @@ export default function MondayComIntegLayout({ {__('Select Board:', 'bit-integrations')} ({ label: b.name, value: `${b.id}` })) + mondayComConf?.boards?.map(b => ({ label: b.name, value: `${b.id}` })) || [] } className="msl-wrp-options dropdown-custom-width" defaultValue={mondayComConf?.selectedBoard} @@ -171,8 +170,7 @@ export default function MondayComIntegLayout({ {__('Select Group:', 'bit-integrations')} ({ label: g.name, value: `${g.id}` })) + mondayComConf?.groups?.map(g => ({ label: g.name, value: `${g.id}` })) || [] } className="msl-wrp-options dropdown-custom-width" defaultValue={mondayComConf?.selectedGroup} @@ -209,8 +207,7 @@ export default function MondayComIntegLayout({ {__('Select Item:', 'bit-integrations')} ({ label: it.name, value: `${it.id}` })) + mondayComConf?.items?.map(it => ({ label: it.name, value: `${it.id}` })) || [] } className="msl-wrp-options dropdown-custom-width" defaultValue={mondayComConf?.selectedItem} diff --git a/frontend/src/components/AllIntegrations/MondayCom/staticData.js b/frontend/src/components/AllIntegrations/MondayCom/staticData.js index 87a0772e0..96131d4ab 100644 --- a/frontend/src/components/AllIntegrations/MondayCom/staticData.js +++ b/frontend/src/components/AllIntegrations/MondayCom/staticData.js @@ -49,19 +49,19 @@ export const staticFieldsMap = { } export const columnTypeList = [ - { label: 'Text', value: 'text' }, - { label: 'Long Text', value: 'long_text' }, - { label: 'Number', value: 'numbers' }, - { label: 'Status', value: 'status' }, - { label: 'Date', value: 'date' }, - { label: 'Checkbox', value: 'checkbox' }, - { label: 'Email', value: 'email' }, - { label: 'Phone', value: 'phone' }, - { label: 'Link', value: 'link' }, - { label: 'Rating', value: 'rating' }, - { label: 'Tags', value: 'tag' }, - { label: 'People', value: 'people' }, - { label: 'Timeline', value: 'timeline' } + { label: __('Text', 'bit-integrations'), value: 'text' }, + { label: __('Long Text', 'bit-integrations'), value: 'long_text' }, + { label: __('Number', 'bit-integrations'), value: 'numbers' }, + { label: __('Status', 'bit-integrations'), value: 'status' }, + { label: __('Date', 'bit-integrations'), value: 'date' }, + { label: __('Checkbox', 'bit-integrations'), value: 'checkbox' }, + { label: __('Email', 'bit-integrations'), value: 'email' }, + { label: __('Phone', 'bit-integrations'), value: 'phone' }, + { label: __('Link', 'bit-integrations'), value: 'link' }, + { label: __('Rating', 'bit-integrations'), value: 'rating' }, + { label: __('Tags', 'bit-integrations'), value: 'tag' }, + { label: __('People', 'bit-integrations'), value: 'people' }, + { label: __('Timeline', 'bit-integrations'), value: 'timeline' } ] export const needsBoard = [ @@ -78,6 +78,6 @@ export const needsBoard = [ 'create_column' ] -export const needsItem = [ 'create_subitem',] +export const needsItem = ['create_subitem'] export const needsColumnMap = ['create_item', 'update_item']