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 && (
+
nextPage(3)}
+ disabled={!checkMappedFields(mondayComConf)}
+ className="btn f-right btcd-btn-lg purple sh-sm flx"
+ type="button">
+ {__('Next', 'bit-integrations')}
+
+
+ )}
+
+
+ {/* 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 && (
+
+
+ mondayComAuthentication(mondayComConf, setError, setIsAuthorized, loading, setLoading)
+ }
+ className="btn btcd-btn-lg purple sh-sm flx"
+ type="button"
+ disabled={isAuthorized || loading.auth}>
+ {isAuthorized ? __('Authorized ✔', 'bit-integrations') : __('Authorize', 'bit-integrations')}
+ {loading.auth && }
+
+
+
+ {__('Next', 'bit-integrations')}
+
+
+
+ )}
+
+
+ )
+}
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 (
+
+
+
+ handleFieldMapping(ev, i, mondayComConf, setMondayComConf)}>
+ {__('Select Field', 'bit-integrations')}
+
+ {formFields?.map(f => (
+
+ {f.label}
+
+ ))}
+
+ {__('Custom...', 'bit-integrations')}
+
+ {isPro &&
+ SmartTagField?.map(f => (
+
+ {f.label}
+
+ ))}
+
+
+
+ {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}
+ />
+ )}
+
+ handleFieldMapping(ev, i, mondayComConf, setMondayComConf)}>
+ {__('Select Field', 'bit-integrations')}
+ {i < requiredFields.length ? (
+
+ {requiredFields[i].label}
+
+ ) : (
+ nonRequiredFields.map(({ key, label }) => (
+
+ {label}
+
+ ))
+ )}
+
+
+ {i >= requiredFields.length && (
+ <>
+
addFieldMap(i, mondayComConf, setMondayComConf)}
+ className="icn-btn sh-sm ml-2 mr-1"
+ type="button">
+ +
+
+
delFieldMap(i, mondayComConf, setMondayComConf)}
+ className="icn-btn sh-sm ml-1"
+ type="button"
+ aria-label="btn">
+
+
+ >
+ )}
+
+
+ )
+}
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}
+ />
+ getAllBoards(mondayComConf, setMondayComConf, setLoading)}
+ className="icn-btn sh-sm ml-2 mr-2 tooltip"
+ style={{ '--tooltip-txt': `'${__('Refresh Boards', 'bit-integrations')}'` }}
+ type="button"
+ 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
+ />
+
+ getAllGroups(
+ mondayComConf,
+ setMondayComConf,
+ mondayComConf.selectedBoard,
+ setLoading
+ )
+ }
+ className="icn-btn sh-sm ml-2 mr-2 tooltip"
+ style={{ '--tooltip-txt': `'${__('Refresh Groups', 'bit-integrations')}'` }}
+ type="button"
+ disabled={loading.group}>
+ ↻
+
+
+ >
+ )}
+
+ {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
+ />
+
+ getAllGroups(
+ mondayComConf,
+ setMondayComConf,
+ mondayComConf.selectedBoard,
+ setLoading
+ )
+ }
+ className="icn-btn sh-sm ml-2 mr-2 tooltip"
+ style={{ '--tooltip-txt': `'${__('Refresh Groups', 'bit-integrations')}'` }}
+ type="button"
+ disabled={loading.group}>
+ ↻
+
+
+ >
+ )}
+
+ {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
+ />
+
+ getAllItems(
+ mondayComConf,
+ setMondayComConf,
+ mondayComConf.selectedBoard,
+ setLoading
+ )
+ }
+ className="icn-btn sh-sm ml-2 mr-2 tooltip"
+ style={{ '--tooltip-txt': `'${__('Refresh Items', 'bit-integrations')}'` }}
+ type="button"
+ disabled={loading.item}>
+ ↻
+
+
+ >
+ )}
+
+ {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) && (
+
+
+ addFieldMap(
+ mondayComConf.field_map.length,
+ mondayComConf,
+ setMondayComConf,
+ false
+ )
+ }
+ className="icn-btn sh-sm"
+ type="button">
+ +
+
+
+ )}
+
+
+ )}
+ >
+ )
+}
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$HwBMseb6R5&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
- />
-
- getAllGroups(
- mondayComConf,
- setMondayComConf,
- mondayComConf.selectedBoard,
- setLoading
- )
- }
- className="icn-btn sh-sm ml-2 mr-2 tooltip"
- style={{ '--tooltip-txt': `'${__('Refresh Groups', 'bit-integrations')}'` }}
- type="button"
- disabled={loading.group}>
- ↻
-
-
- >
- )}
-
{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']