diff --git a/.version b/.version index 9db2e998b3..456312b41f 100644 --- a/.version +++ b/.version @@ -1 +1 @@ -2.67.1 +2.67.2 diff --git a/frontend/.version b/frontend/.version index 9db2e998b3..456312b41f 100644 --- a/frontend/.version +++ b/frontend/.version @@ -1 +1 @@ -2.67.1 +2.67.2 diff --git a/frontend/src/Oauth2/Authorize.jsx b/frontend/src/Oauth2/Authorize.jsx index ef0dfaed8c..73c21e7282 100644 --- a/frontend/src/Oauth2/Authorize.jsx +++ b/frontend/src/Oauth2/Authorize.jsx @@ -40,6 +40,14 @@ class AuthorizeComponent extends React.Component { localStorage.setItem('OAuthCode', code); this.setState({ isLoading: false, authSuccess: true }); } + + this.timer = setTimeout(() => { + window.close(); + }, 2000); + } + + componentWillUnmount() { + clearTimeout(this.timer); } render() { @@ -105,7 +113,14 @@ class AuthorizeComponent extends React.Component { Success
-
Authorization successful, you can close this tab now.
+
Authorization successful! You will be redirected in a few seconds.
+
+ Don’t want to wait?{' '} + window.close()}> + Click here + {' '} + to go now. +
)} diff --git a/frontend/src/_components/DynamicForm.jsx b/frontend/src/_components/DynamicForm.jsx index 37fd3104af..c81395beac 100644 --- a/frontend/src/_components/DynamicForm.jsx +++ b/frontend/src/_components/DynamicForm.jsx @@ -19,6 +19,7 @@ import { orgEnvironmentVariableService, orgEnvironmentConstantService } from '.. import { find, isEmpty } from 'lodash'; import { ButtonSolid } from './AppButton'; import { Constants } from '@/_helpers/utils'; +import Sharepoint from '@/_components/Sharepoint'; const DynamicForm = ({ schema, @@ -160,6 +161,8 @@ const DynamicForm = ({ return CondtionSort; case 'react-component-salesforce': return Salesforce; + case 'react-component-sharepoint': + return Sharepoint; default: return
Type is invalid
; } @@ -304,6 +307,7 @@ const DynamicForm = ({ case 'react-component-slack': case 'react-component-zendesk': case 'react-component-salesforce': + case 'react-component-sharepoint': return { optionchanged, createDataSource, diff --git a/frontend/src/_components/Sharepoint.jsx b/frontend/src/_components/Sharepoint.jsx new file mode 100644 index 0000000000..c6d6271378 --- /dev/null +++ b/frontend/src/_components/Sharepoint.jsx @@ -0,0 +1,146 @@ +import React, { useState } from 'react'; +import { datasourceService } from '@/_services'; +import { useTranslation } from 'react-i18next'; +import { toast } from 'react-hot-toast'; +import Button from '@/_ui/Button'; +import Input from '@/_ui/Input'; +import cx from 'classnames'; + +const Sharepoint = ({ + optionchanged, + createDataSource, + options, + isSaving, + selectedDataSource, + currentAppEnvironmentId, + workspaceConstants, + isDisabled, +}) => { + const [authStatus, setAuthStatus] = useState(null); + const { t } = useTranslation(); + + const hostUrl = window.public_config?.TOOLJET_HOST; + const subPathUrl = window.public_config?.SUB_PATH; + const fullUrl = `${hostUrl}${subPathUrl ? subPathUrl : '/'}oauth2/authorize`; + const redirectUri = fullUrl; + + function authSharepoint() { + const provider = 'sharepoint'; + const plugin_id = selectedDataSource?.plugin?.id; + const source_options = options; + setAuthStatus('waiting_for_url'); + + const scope = 'https://graph.microsoft.com/.default+offline_access'; + + datasourceService + .fetchOauth2BaseUrl(provider, plugin_id, source_options) + .then((data) => { + const authUrl = `${data.url}&scope=${scope}&state=12345&response_mode=query`; + localStorage.setItem('sourceWaitingForOAuth', 'newSource'); + localStorage.setItem('currentAppEnvironmentIdForOauth', currentAppEnvironmentId); + optionchanged('provider', provider).then(() => { + optionchanged('oauth2', true); + optionchanged('plugin_id', plugin_id); + }); + setAuthStatus('waiting_for_token'); + openUrl(authUrl); + }) + .catch(({ error }) => { + toast.error(error); + setAuthStatus(null); + }); + } + + function saveDataSource() { + optionchanged('code', localStorage.getItem('OAuthCode')).then(() => { + createDataSource(); + }); + } + + function openUrl(url) { + const width = window.innerWidth * 0.4; + const height = window.innerHeight * 0.8; + const left = window.screenX + (window.innerWidth - width) / 2; + const top = window.screenY + (window.innerHeight - height) / 2; + const windowFeatures = `width=${width},height=${height},top=${top},left=${left},resizable=yes,scrollbars=yes`; + const authWindow = window.open(url, '_blank', windowFeatures); + if (authWindow) { + authWindow.focus(); + } + } + + return ( +
+
+ + optionchanged('sp_client_id', e.target.value)} + value={options?.sp_client_id?.value ?? ''} + placeholder="Enter client ID" + workspaceConstants={workspaceConstants} + /> +
+
+ + optionchanged('sp_client_secret', e.target.value)} + value={options?.sp_client_secret?.value || ''} + placeholder="**************" + workspaceConstants={workspaceConstants} + encrypted={true} + /> +
+
+ + optionchanged('sp_tenant_id', e.target.value)} + value={options?.sp_tenant_id?.value ?? ''} + placeholder="Enter tenant ID" + workspaceConstants={workspaceConstants} + /> +
+
+ + +
+
+
+ {authStatus === 'waiting_for_token' && ( +
+ +
+ )} + + {(!authStatus || authStatus === 'waiting_for_url') && ( + + )} +
+
+
+ ); +}; +export default Sharepoint; diff --git a/marketplace/package-lock.json b/marketplace/package-lock.json index b1b9370125..8b3739b9c0 100644 --- a/marketplace/package-lock.json +++ b/marketplace/package-lock.json @@ -5880,6 +5880,10 @@ "resolved": "plugins/salesforce", "link": true }, + "node_modules/@tooljet-marketplace/sharepoint": { + "resolved": "plugins/sharepoint", + "link": true + }, "node_modules/@tooljet-marketplace/supabase": { "resolved": "plugins/supabase", "link": true @@ -17323,6 +17327,17 @@ "typescript": "^4.7.4" } }, + "plugins/sharepoint": { + "name": "@tooljet-marketplace/sharepoint", + "version": "1.0.0", + "dependencies": { + "@tooljet-marketplace/common": "^1.0.0" + }, + "devDependencies": { + "@vercel/ncc": "^0.34.0", + "typescript": "^4.7.4" + } + }, "plugins/supabase": { "name": "@tooljet-marketplace/supabase", "version": "1.0.0", diff --git a/marketplace/plugins/sharepoint/.gitignore b/marketplace/plugins/sharepoint/.gitignore new file mode 100644 index 0000000000..23e6609462 --- /dev/null +++ b/marketplace/plugins/sharepoint/.gitignore @@ -0,0 +1,5 @@ +node_modules +lib/*.d.* +lib/*.js +lib/*.js.map +dist/* \ No newline at end of file diff --git a/marketplace/plugins/sharepoint/README.md b/marketplace/plugins/sharepoint/README.md new file mode 100644 index 0000000000..dad9d32646 --- /dev/null +++ b/marketplace/plugins/sharepoint/README.md @@ -0,0 +1,4 @@ + +# Sharepoint + +Documentation on: https://docs.tooljet.com/docs/data-sources/sharepoint \ No newline at end of file diff --git a/marketplace/plugins/sharepoint/__tests__/index.js b/marketplace/plugins/sharepoint/__tests__/index.js new file mode 100644 index 0000000000..ba42184604 --- /dev/null +++ b/marketplace/plugins/sharepoint/__tests__/index.js @@ -0,0 +1,7 @@ +'use strict'; + +const sharepoint = require('../lib'); + +describe('sharepoint', () => { + it.todo('needs tests'); +}); diff --git a/marketplace/plugins/sharepoint/lib/icon.svg b/marketplace/plugins/sharepoint/lib/icon.svg new file mode 100644 index 0000000000..455a9482d1 --- /dev/null +++ b/marketplace/plugins/sharepoint/lib/icon.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/marketplace/plugins/sharepoint/lib/index.ts b/marketplace/plugins/sharepoint/lib/index.ts new file mode 100644 index 0000000000..4265a8f007 --- /dev/null +++ b/marketplace/plugins/sharepoint/lib/index.ts @@ -0,0 +1,353 @@ +import { OAuthUnauthorizedClientError, QueryError, QueryResult, QueryService } from '@tooljet-marketplace/common'; +import { SourceOptions, QueryOptions } from './types'; + +export default class Sharepoint implements QueryService { + authUrl(sourceOptions): string { + const host = process.env.TOOLJET_HOST; + const subpath = process.env.SUB_PATH; + const fullUrl = `${host}${subpath ? subpath : '/'}`; + const clientId = sourceOptions.sp_client_id; + const clientSecret = sourceOptions.sp_client_secret.value; + const tenant = sourceOptions.sp_tenant_id; + + if (!clientId || !clientSecret || !tenant) { + throw Error('You need to enter the client ID, client secret and tenant ID for authentication.'); + } + + return ( + 'https://login.microsoftonline.com/common/oauth2/v2.0/authorize' + + `?client_id=${clientId.value}&response_type=code` + + `&redirect_uri=${fullUrl}oauth2/authorize` + ); + } + + async accessDetailsFrom(authCode: string, sourceOptions: any, resetSecureData = false): Promise { + if (resetSecureData) { + return [ + ['access_token', ''], + ['refresh_token', ''], + ]; + } + + let sp_client_id = ''; + let sp_client_secret = ''; + let tenant = ''; + + for (const item of sourceOptions) { + if (item.key === 'sp_client_id') { + sp_client_id = item.value; + } + if (item.key === 'sp_client_secret') { + sp_client_secret = item.value; + } + if (item.key === 'sp_tenant_id') { + tenant = item.value; + } + } + + const accessTokenUrl = `https://login.microsoftonline.com/${tenant}/oauth2/v2.0/token`; + const host = process.env.TOOLJET_HOST; + const subpath = process.env.SUB_PATH; + const fullUrl = `${host}${subpath ? subpath : '/'}`; + const redirectUri = `${fullUrl}oauth2/authorize`; + + const data = new URLSearchParams({ + code: authCode, + client_id: sp_client_id, + client_secret: sp_client_secret, + grant_type: 'authorization_code', + redirect_uri: redirectUri, + scope: 'https://graph.microsoft.com/.default+offline_access', + }); + + const authDetails = []; + + try { + const response = await fetch(accessTokenUrl, { + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + }, + body: data.toString(), + }); + + const result = await response.json(); + + if (!response.ok) { + console.error(`Error occurred: `, result); + throw new Error(result.error_description); + } + + if (result['access_token']) { + authDetails.push(['access_token', result['access_token']]); + } + + if (result['refresh_token']) { + authDetails.push(['refresh_token', result['refresh_token']]); + } + } catch (error) { + throw Error(`Could not connect to Sharepoint:\n${error?.message}`); + } + + return authDetails; + } + + async run(sourceOptions: SourceOptions, queryOptions: QueryOptions, dataSourceId: string): Promise { + const rootApiUrl = 'https://graph.microsoft.com/v1.0/sites'; + const accessToken = sourceOptions.access_token; + let response = null; + let data = null; + + try { + const requestOptions = await this.fetchRequestOptsForOperation(accessToken, queryOptions); + const endpoint = requestOptions?.endpoint; + const apiUrl = `${rootApiUrl}${endpoint}`; + const method = requestOptions?.method; + const header = requestOptions?.headers; + const body = requestOptions.body || {}; + + if (requestOptions?.paginationFeature && queryOptions.sp_page) { + const regex = /^[1-9]\d*(\.\d+)?$/; + if (regex.test(queryOptions.sp_page)) { + const pageNo = parseInt(queryOptions.sp_page || '1'); + const paginatedResponse = await this.getPageData(apiUrl, pageNo, header); + response = paginatedResponse.response; + data = paginatedResponse.data; + } else { + throw new Error('Page field value should be a number >= 1.'); + } + } else { + response = await fetch(apiUrl, { + method: method, + headers: header, + ...(Object.keys(body).length !== 0 && { body: JSON.stringify(body) }), + }); + + if ( + !response.ok && + response.status !== 401 && + response.status !== 403 && + response.status !== 204 && + response.status !== 201 + ) { + const data = await response.json(); + const errorMessage = data?.error?.message || 'An unknown error occurred'; + throw new QueryError('Query could not be completed', errorMessage, { + statusCode: response.status, + ...data?.error, + }); + } + + if (response.status === 204) { + return { + status: 'ok', + data: { + code: response.status, + status: response.statusText, + message: `Item having id '${queryOptions.sp_item_id}' in List '${queryOptions.sp_list_id}' has been deleted.`, + }, + }; + } + + data = await response.json(); + } + } catch (error) { + const errorMessage = error?.message === 'Query could not be completed' ? error?.description : error?.message; + throw new QueryError('Query could not be completed', errorMessage, error?.data || {}); + } + + if (response.status === 401 || response.status === 403) { + throw new OAuthUnauthorizedClientError('Unauthorized client error', response.statusText, data); + } + + return { + status: 'ok', + data: data, + }; + } + + async getPageData(apiUrl: string, pageNo: number, header: any): Promise { + let currentPage = 1; + let nextApiUrl = apiUrl; + let result = null; + + while (currentPage <= pageNo) { + const response = await fetch(nextApiUrl, { + method: 'GET', + headers: header, + }); + + const data = await response.json(); + + if (!response.ok && response.status !== 401 && response.status !== 403) { + throw new QueryError('Query could not be completed', data?.error?.message || 'An unknown error occurred', { + statusCode: response.status, + ...data?.error, + }); + } + + if (currentPage === pageNo) { + result = { response: response, data: data }; + break; + } + + if (!data['@odata.nextLink']) { + throw new Error('No more pages available.'); + } + + nextApiUrl = data['@odata.nextLink']; + currentPage++; + } + + return result; + } + + async fetchRequestOptsForOperation(accessToken: string, queryOptions: QueryOptions): Promise { + const { + sp_operation, + sp_site_id, + sp_time_interval, + sp_list_id, + sp_list_name, + sp_item_id, + sp_list_object, + sp_item_object, + sp_top, + } = queryOptions; + + const authHeader = { + Authorization: `Bearer ${accessToken}`, + }; + + switch (sp_operation) { + case 'get_sites': + return { + method: 'GET', + endpoint: `?search=*${sp_top ? `&$top=${sp_top}` : ''}`, + headers: { ...authHeader }, + paginationFeature: true, + }; + case 'get_site': + return { + method: 'GET', + endpoint: `/${sp_site_id}`, + headers: { ...authHeader }, + }; + case 'get_analytics': + return { + method: 'GET', + endpoint: `/${sp_site_id}/analytics/${sp_time_interval}`, + headers: { ...authHeader }, + }; + case 'get_pages': + return { + method: 'GET', + endpoint: `/${sp_site_id}/pages${sp_top ? `?&$top=${sp_top}` : ''}`, + headers: { ...authHeader, 'Content-Type': 'application/json' }, + paginationFeature: true, + }; + case 'get_lists': + return { + method: 'GET', + endpoint: `/${sp_site_id}/lists`, + headers: { ...authHeader }, + paginationFeature: true, + }; + case 'get_metadata': + return { + method: 'GET', + endpoint: `/${sp_site_id}/lists/${sp_list_id || sp_list_name}?expand=columns,items(expand=fields)`, + headers: { ...authHeader }, + }; + case 'get_items': + return { + method: 'GET', + endpoint: `/${sp_site_id}/lists/${sp_list_id}/items?$expand=fields${sp_top ? `&$top=${sp_top}` : ''}`, + headers: { ...authHeader }, + paginationFeature: true, + }; + case 'create_list': + return { + method: 'POST', + endpoint: `/${sp_site_id}/lists`, + headers: { ...authHeader, 'Content-Type': 'application/json' }, + body: JSON.parse(sp_list_object), + }; + case 'add_item': + return { + method: 'POST', + endpoint: `/${sp_site_id}/lists/${sp_list_id}/items`, + headers: { ...authHeader, 'Content-Type': 'application/json' }, + body: JSON.parse(sp_item_object), + }; + case 'update_item': + return { + method: 'PATCH', + endpoint: `/${sp_site_id}/lists/${sp_list_id}/items/${sp_item_id}/fields`, + headers: { ...authHeader, 'Content-Type': 'application/json' }, + body: JSON.parse(sp_item_object), + }; + case 'delete_item': + return { + method: 'DELETE', + endpoint: `/${sp_site_id}/lists/${sp_list_id}/items/${sp_item_id}`, + headers: { ...authHeader }, + }; + default: + return { method: '', endpoint: '', headers: {}, body: {} }; + } + } + + async refreshToken(sourceOptions) { + if (!sourceOptions['refresh_token']) { + throw new QueryError('Query could not be completed', 'Refresh token empty', {}); + } + + const tenant = sourceOptions.sp_tenant_id; + const accessTokenUrl = `https://login.microsoftonline.com/${tenant}/oauth2/v2.0/token`; + const clientId = sourceOptions.sp_client_id; + const clientSecret = sourceOptions.sp_client_secret; + + const data = new URLSearchParams({ + client_id: clientId, + client_secret: clientSecret, + grant_type: 'refresh_token', + refresh_token: sourceOptions['refresh_token'], + scope: 'https://graph.microsoft.com/.default', + }); + + const accessTokenDetails = {}; + + try { + const response = await fetch(accessTokenUrl, { + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + }, + body: data.toString(), + }); + const result = await response.json(); + + if (result['access_token']) { + accessTokenDetails['access_token'] = result['access_token']; + accessTokenDetails['refresh_token'] = result['refresh_token']; + } else { + throw new QueryError( + 'access_token not found in the response', + {}, + { + responseObject: { + statusCode: response.status, + responseBody: result, + }, + responseHeaders: response.headers, + } + ); + } + } catch (error) { + console.error(`Error while Sharepoint refresh token call. ${JSON.stringify(error)}`); + throw new QueryError('could not connect to Sharepoint', JSON.stringify(error), {}); + } + return accessTokenDetails; + } +} diff --git a/marketplace/plugins/sharepoint/lib/manifest.json b/marketplace/plugins/sharepoint/lib/manifest.json new file mode 100644 index 0000000000..3de7c981ae --- /dev/null +++ b/marketplace/plugins/sharepoint/lib/manifest.json @@ -0,0 +1,56 @@ + +{ + "$schema": "https://raw.githubusercontent.com/ToolJet/ToolJet/develop/plugins/schemas/manifest.schema.json", + "title": "Sharepoint datasource", + "description": "A schema defining Sharepoint datasource", + "type": "api", + "source": { + "name": "Sharepoint", + "kind": "sharepoint", + "exposedVariables": { + "isLoading": false, + "data": {}, + "rawData": {} + }, + "options": { + "sp_client_id": { + "type": "string" + }, + "sp_client_secret": { + "type": "string", + "encrypted": true + }, + "sp_tenant_id": { + "type": "string" + }, + "redirect_url": { + "type": "string" + }, + "provider": { + "type": "string" + }, + "oauth2": { + "type": "boolean" + }, + "plugin_id": { + "type": "string" + } + }, + "customTesting": true, + "hideSave": true + }, + "defaults": { + "redirect_url":{ + "value": "" + } + }, + "properties": { + "sharepoint": { + "label": "", + "key": "sharepoint", + "type": "react-component-sharepoint", + "description": "A component for sharepoint" + } + }, + "required": [] +} \ No newline at end of file diff --git a/marketplace/plugins/sharepoint/lib/operations.json b/marketplace/plugins/sharepoint/lib/operations.json new file mode 100644 index 0000000000..ee0af1ce2e --- /dev/null +++ b/marketplace/plugins/sharepoint/lib/operations.json @@ -0,0 +1,377 @@ + +{ + "$schema": "https://raw.githubusercontent.com/ToolJet/ToolJet/develop/plugins/schemas/operations.schema.json", + "title": "Sharepoint datasource", + "description": "A schema defining Sharepoint datasource", + "type": "api", + "defaults": {}, + "properties": { + "operation": { + "label": "Operation", + "key": "sp_operation", + "type": "dropdown-component-flip", + "description": "Select operation", + "list": [ + { + "name": "Get all sites", + "value": "get_sites" + }, + { + "name": "Get site", + "value": "get_site" + }, + { + "name": "Get analytics", + "value": "get_analytics" + }, + { + "name": "Get pages of a site", + "value": "get_pages" + }, + { + "name": "Get all lists", + "value": "get_lists" + }, + { + "name": "Get metadata of a list", + "value": "get_metadata" + }, + { + "name": "Create a list", + "value": "create_list" + }, + { + "name": "Get items of a list", + "value": "get_items" + }, + { + "name": "Update item of a list", + "value": "update_item" + }, + { + "name": "Delete item of a list", + "value": "delete_item" + }, + { + "name": "Add item to a list", + "value": "add_item" + } + ] + }, + "get_sites": { + "top": { + "label": "Top", + "key": "sp_top", + "description": "Enter the number of items a response page should contain", + "type": "codehinter", + "lineNumbers": false, + "className": "codehinter-plugins", + "placeholder": "Enter the number of items a response page should contain", + "height": "36px" + }, + "page": { + "label": "Page", + "key": "sp_page", + "description": "Enter the page number", + "type": "codehinter", + "lineNumbers": false, + "className": "codehinter-plugins", + "placeholder": "Enter the page number", + "height": "36px" + } + }, + "get_site": { + "site_id": { + "label": "Site id", + "key": "sp_site_id", + "description": "Enter site id", + "type": "codehinter", + "lineNumbers": false, + "className": "codehinter-plugins", + "placeholder": "Enter site id", + "height": "36px" + } + }, + "get_analytics": { + "site_id": { + "label": "Site id", + "key": "sp_site_id", + "description": "Enter site id", + "type": "codehinter", + "lineNumbers": false, + "className": "codehinter-plugins", + "placeholder": "Enter site id", + "height": "36px" + }, + "time_interval": { + "label": "Time interval", + "key": "sp_time_interval", + "description": "Select time interval", + "type": "dropdown", + "list": [ + { + "name": "Last 7 days", + "value": "lastSevenDays" + }, + { + "name": "All time", + "value": "allTime" + } + ] + } + }, + "get_pages": { + "site_id": { + "label": "Site id", + "key": "sp_site_id", + "description": "Enter site id", + "type": "codehinter", + "lineNumbers": false, + "className": "codehinter-plugins", + "placeholder": "Enter site id", + "height": "36px" + }, + "top": { + "label": "Top", + "key": "sp_top", + "description": "Enter the number of items a response page should contain", + "type": "codehinter", + "lineNumbers": false, + "className": "codehinter-plugins", + "placeholder": "Enter the number of items a response page should contain", + "height": "36px" + }, + "page": { + "label": "Page", + "key": "sp_page", + "description": "Enter the page number", + "type": "codehinter", + "lineNumbers": false, + "className": "codehinter-plugins", + "placeholder": "Enter the page number", + "height": "36px" + } + }, + "get_lists": { + "site_id": { + "label": "Site id", + "key": "sp_site_id", + "description": "Enter site id", + "type": "codehinter", + "lineNumbers": false, + "className": "codehinter-plugins", + "placeholder": "Enter site id", + "height": "36px" + }, + "page": { + "label": "Page", + "key": "sp_page", + "description": "Enter the page number", + "type": "codehinter", + "lineNumbers": false, + "className": "codehinter-plugins", + "placeholder": "Enter the page number", + "height": "36px" + } + }, + "get_metadata": { + "site_id": { + "label": "Site id", + "key": "sp_site_id", + "description": "Enter site id", + "type": "codehinter", + "lineNumbers": false, + "className": "codehinter-plugins", + "placeholder": "Enter site id", + "height": "36px" + }, + "list_name": { + "label": "List Name", + "key": "sp_list_name", + "description": "Enter list name", + "type": "codehinter", + "lineNumbers": false, + "className": "codehinter-plugins", + "placeholder": "Enter list name", + "height": "36px" + }, + "list_id": { + "label": "List id", + "key": "sp_list_id", + "description": "Enter list id", + "type": "codehinter", + "lineNumbers": false, + "className": "codehinter-plugins", + "placeholder": "Enter list id", + "height": "36px" + } + }, + "create_list": { + "site_id": { + "label": "Site id", + "key": "sp_site_id", + "description": "Enter site id", + "type": "codehinter", + "lineNumbers": false, + "className": "codehinter-plugins", + "placeholder": "Enter site id", + "height": "36px" + }, + "list_object": { + "label": "Body", + "key": "sp_list_object", + "type": "codehinter", + "mode": "javascript", + "placeholder": "{\n \"displayName\": \"Books\",\n \"columns\": [\n {\n \"name\": \"Author\",\n \"text\": { }\n },\n {\n \"name\": \"PageCount\",\n \"number\": { }\n }\n ],\n \"list\": {\n \"template\": \"genericList\"\n }\n}", + "description": "Enter list object", + "height": "200px" + } + }, + "get_items": { + "site_id": { + "label": "Site id", + "key": "sp_site_id", + "description": "Enter site id", + "type": "codehinter", + "lineNumbers": false, + "className": "codehinter-plugins", + "placeholder": "Enter site id", + "height": "36px" + }, + "list_id": { + "label": "List id", + "key": "sp_list_id", + "description": "Enter list id", + "type": "codehinter", + "lineNumbers": false, + "className": "codehinter-plugins", + "placeholder": "Enter list id", + "height": "36px" + }, + "top": { + "label": "Top", + "key": "sp_top", + "description": "Enter the number of items a response page should contain", + "type": "codehinter", + "lineNumbers": false, + "className": "codehinter-plugins", + "placeholder": "Enter the number of items a response page should contain", + "height": "36px" + }, + "page": { + "label": "Page", + "key": "sp_page", + "description": "Enter the page number", + "type": "codehinter", + "lineNumbers": false, + "className": "codehinter-plugins", + "placeholder": "Enter the page number", + "height": "36px" + } + }, + "update_item": { + "site_id": { + "label": "Site id", + "key": "sp_site_id", + "description": "Enter site id", + "type": "codehinter", + "lineNumbers": false, + "className": "codehinter-plugins", + "placeholder": "Enter site id", + "height": "36px" + }, + "list_id": { + "label": "List id", + "key": "sp_list_id", + "description": "Enter list id", + "type": "codehinter", + "lineNumbers": false, + "className": "codehinter-plugins", + "placeholder": "Enter list id", + "height": "36px" + }, + "item_id": { + "label": "Item id", + "key": "sp_item_id", + "description": "Enter item id", + "type": "codehinter", + "lineNumbers": false, + "className": "codehinter-plugins", + "placeholder": "Enter item id", + "height": "36px" + }, + "item_object": { + "label": "Body", + "key": "sp_item_object", + "type": "codehinter", + "mode": "javascript", + "placeholder": "{\n \"Color\": \"Fuchsia\",\n \"Quantity\": 934\n}", + "description": "Enter item object", + "height": "200px" + } + }, + "delete_item": { + "site_id": { + "label": "Site id", + "key": "sp_site_id", + "description": "Enter site id", + "type": "codehinter", + "lineNumbers": false, + "className": "codehinter-plugins", + "placeholder": "Enter site id", + "height": "36px" + }, + "list_id": { + "label": "List id", + "key": "sp_list_id", + "description": "Enter list id", + "type": "codehinter", + "lineNumbers": false, + "className": "codehinter-plugins", + "placeholder": "Enter list id", + "height": "36px" + }, + "item_id": { + "label": "Item id", + "key": "sp_item_id", + "description": "Enter item id", + "type": "codehinter", + "lineNumbers": false, + "className": "codehinter-plugins", + "placeholder": "Enter item id", + "height": "36px" + } + }, + "add_item": { + "site_id": { + "label": "Site id", + "key": "sp_site_id", + "description": "Enter site id", + "type": "codehinter", + "lineNumbers": false, + "className": "codehinter-plugins", + "placeholder": "Enter site id", + "height": "36px" + }, + "list_id": { + "label": "List id", + "key": "sp_list_id", + "description": "Enter list id", + "type": "codehinter", + "lineNumbers": false, + "className": "codehinter-plugins", + "placeholder": "Enter list id", + "height": "36px" + }, + "item_object": { + "label": "Body", + "key": "sp_item_object", + "type": "codehinter", + "mode": "javascript", + "placeholder": "{\n \"fields\": {\n \"Title\": \"Widget\",\n \"Color\": \"Purple\",\n \"Weight\": 32\n }\n}", + "description": "Enter item object", + "height": "200px" + } + } + } +} \ No newline at end of file diff --git a/marketplace/plugins/sharepoint/lib/types.ts b/marketplace/plugins/sharepoint/lib/types.ts new file mode 100644 index 0000000000..44100234b4 --- /dev/null +++ b/marketplace/plugins/sharepoint/lib/types.ts @@ -0,0 +1,19 @@ +export type SourceOptions = { + sp_client_id: string; + sp_client_secret: string; + sp_tenant_id: string; + access_token: string; +}; +export type QueryOptions = { + operation: string; + sp_operation: string; + sp_site_id: string; + sp_time_interval: string; + sp_list_name: string; + sp_list_id: string; + sp_list_object: string; + sp_item_id: string; + sp_item_object: string; + sp_top: string; + sp_page: string; +}; diff --git a/marketplace/plugins/sharepoint/package.json b/marketplace/plugins/sharepoint/package.json new file mode 100644 index 0000000000..7d7b5d1a3b --- /dev/null +++ b/marketplace/plugins/sharepoint/package.json @@ -0,0 +1,26 @@ +{ + "name": "@tooljet-marketplace/sharepoint", + "version": "1.0.0", + "main": "dist/index.js", + "types": "dist/index.d.ts", + "directories": { + "lib": "lib", + "test": "__tests__" + }, + "files": [ + "lib" + ], + "scripts": { + "test": "echo \"Error: run tests from root\" && exit 1", + "build": "ncc build lib/index.ts -o dist", + "watch": "ncc build lib/index.ts -o dist --watch" + }, + "homepage": "https://github.com/tooljet/tooljet#readme", + "dependencies": { + "@tooljet-marketplace/common": "^1.0.0" + }, + "devDependencies": { + "typescript": "^4.7.4", + "@vercel/ncc": "^0.34.0" + } +} diff --git a/marketplace/plugins/sharepoint/tsconfig.json b/marketplace/plugins/sharepoint/tsconfig.json new file mode 100644 index 0000000000..a18a801b14 --- /dev/null +++ b/marketplace/plugins/sharepoint/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "dist", + "rootDir": "lib" + }, + "exclude": [ + "node_modules", + "dist" + ] +} \ No newline at end of file diff --git a/server/.version b/server/.version index 9db2e998b3..456312b41f 100644 --- a/server/.version +++ b/server/.version @@ -1 +1 @@ -2.67.1 +2.67.2 diff --git a/server/src/assets/marketplace/plugins.json b/server/src/assets/marketplace/plugins.json index 5ea11bb086..adb8c48eb8 100644 --- a/server/src/assets/marketplace/plugins.json +++ b/server/src/assets/marketplace/plugins.json @@ -87,5 +87,29 @@ "id": "salesforce", "author": "Tooljet", "timestamp": "Wed, 06 Mar 2024 11:34:26 GMT" - } -] \ No newline at end of file + }, + { + "name": "Presto", + "description": "Plugin for PrestoDB data source", + "version": "1.0.0", + "id": "presto", + "author": "Tooljet", + "timestamp": "Thu, 08 Aug 2024 11:04:36 GMT" + }, + { + "name": "Sharepoint", + "description": "Plugin for Sharepoint API", + "version": "1.0.0", + "id": "sharepoint", + "author": "Tooljet", + "timestamp": "Wed, 04 Sep 2024 20:18:30 GMT" + }, + { + "name": "Jira", + "description": "Plugin for Jira data source", + "version": "1.0.0", + "id": "jira", + "author": "Tooljet", + "timestamp": "Thu, 08 Aug 2024 11:04:36 GMT" + } +]