mirror of
https://github.com/plankanban/planka.git
synced 2025-07-18 20:59:44 +02:00
feat: Move webhooks configuration from environment variable to UI
This commit is contained in:
parent
f0680831c2
commit
b22dba0d11
128 changed files with 2077 additions and 206 deletions
|
@ -8,6 +8,7 @@ import ActionTypes from '../constants/ActionTypes';
|
||||||
const initializeCore = (
|
const initializeCore = (
|
||||||
user,
|
user,
|
||||||
board,
|
board,
|
||||||
|
webhooks,
|
||||||
users,
|
users,
|
||||||
projects,
|
projects,
|
||||||
projectManagers,
|
projectManagers,
|
||||||
|
@ -33,6 +34,7 @@ const initializeCore = (
|
||||||
payload: {
|
payload: {
|
||||||
user,
|
user,
|
||||||
board,
|
board,
|
||||||
|
webhooks,
|
||||||
users,
|
users,
|
||||||
projects,
|
projects,
|
||||||
projectManagers,
|
projectManagers,
|
||||||
|
|
|
@ -8,6 +8,7 @@ import socket from './socket';
|
||||||
import login from './login';
|
import login from './login';
|
||||||
import core from './core';
|
import core from './core';
|
||||||
import modals from './modals';
|
import modals from './modals';
|
||||||
|
import webhooks from './webhooks';
|
||||||
import users from './users';
|
import users from './users';
|
||||||
import projects from './projects';
|
import projects from './projects';
|
||||||
import projectManagers from './project-managers';
|
import projectManagers from './project-managers';
|
||||||
|
@ -35,6 +36,7 @@ export default {
|
||||||
...login,
|
...login,
|
||||||
...core,
|
...core,
|
||||||
...modals,
|
...modals,
|
||||||
|
...webhooks,
|
||||||
...users,
|
...users,
|
||||||
...projects,
|
...projects,
|
||||||
...projectManagers,
|
...projectManagers,
|
||||||
|
|
|
@ -14,6 +14,7 @@ const handleSocketReconnect = (
|
||||||
config,
|
config,
|
||||||
user,
|
user,
|
||||||
board,
|
board,
|
||||||
|
webhooks,
|
||||||
users,
|
users,
|
||||||
projects,
|
projects,
|
||||||
projectManagers,
|
projectManagers,
|
||||||
|
@ -40,6 +41,7 @@ const handleSocketReconnect = (
|
||||||
config,
|
config,
|
||||||
user,
|
user,
|
||||||
board,
|
board,
|
||||||
|
webhooks,
|
||||||
users,
|
users,
|
||||||
projects,
|
projects,
|
||||||
projectManagers,
|
projectManagers,
|
||||||
|
|
|
@ -67,6 +67,7 @@ const handleUserUpdate = (
|
||||||
boardIds,
|
boardIds,
|
||||||
config,
|
config,
|
||||||
board,
|
board,
|
||||||
|
webhooks,
|
||||||
users,
|
users,
|
||||||
projects,
|
projects,
|
||||||
projectManagers,
|
projectManagers,
|
||||||
|
@ -95,6 +96,7 @@ const handleUserUpdate = (
|
||||||
boardIds,
|
boardIds,
|
||||||
config,
|
config,
|
||||||
board,
|
board,
|
||||||
|
webhooks,
|
||||||
users,
|
users,
|
||||||
projects,
|
projects,
|
||||||
projectManagers,
|
projectManagers,
|
||||||
|
|
104
client/src/actions/webhooks.js
Normal file
104
client/src/actions/webhooks.js
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
/*!
|
||||||
|
* Copyright (c) 2024 PLANKA Software GmbH
|
||||||
|
* Licensed under the Fair Use License: https://github.com/plankanban/planka/blob/master/LICENSE.md
|
||||||
|
*/
|
||||||
|
|
||||||
|
import ActionTypes from '../constants/ActionTypes';
|
||||||
|
|
||||||
|
const createWebhook = (webhook) => ({
|
||||||
|
type: ActionTypes.WEBHOOK_CREATE,
|
||||||
|
payload: {
|
||||||
|
webhook,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
createWebhook.success = (localId, webhook) => ({
|
||||||
|
type: ActionTypes.WEBHOOK_CREATE__SUCCESS,
|
||||||
|
payload: {
|
||||||
|
localId,
|
||||||
|
webhook,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
createWebhook.failure = (localId, error) => ({
|
||||||
|
type: ActionTypes.WEBHOOK_CREATE__FAILURE,
|
||||||
|
payload: {
|
||||||
|
localId,
|
||||||
|
error,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleWebhookCreate = (webhook) => ({
|
||||||
|
type: ActionTypes.WEBHOOK_CREATE_HANDLE,
|
||||||
|
payload: {
|
||||||
|
webhook,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const updateWebhook = (id, data) => ({
|
||||||
|
type: ActionTypes.WEBHOOK_UPDATE,
|
||||||
|
payload: {
|
||||||
|
id,
|
||||||
|
data,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
updateWebhook.success = (webhook) => ({
|
||||||
|
type: ActionTypes.WEBHOOK_UPDATE__SUCCESS,
|
||||||
|
payload: {
|
||||||
|
webhook,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
updateWebhook.failure = (id, error) => ({
|
||||||
|
type: ActionTypes.WEBHOOK_UPDATE__FAILURE,
|
||||||
|
payload: {
|
||||||
|
id,
|
||||||
|
error,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleWebhookUpdate = (webhook) => ({
|
||||||
|
type: ActionTypes.WEBHOOK_UPDATE_HANDLE,
|
||||||
|
payload: {
|
||||||
|
webhook,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const deleteWebhook = (id) => ({
|
||||||
|
type: ActionTypes.WEBHOOK_DELETE,
|
||||||
|
payload: {
|
||||||
|
id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
deleteWebhook.success = (webhook) => ({
|
||||||
|
type: ActionTypes.WEBHOOK_DELETE__SUCCESS,
|
||||||
|
payload: {
|
||||||
|
webhook,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
deleteWebhook.failure = (id, error) => ({
|
||||||
|
type: ActionTypes.WEBHOOK_DELETE__FAILURE,
|
||||||
|
payload: {
|
||||||
|
id,
|
||||||
|
error,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleWebhookDelete = (webhook) => ({
|
||||||
|
type: ActionTypes.WEBHOOK_DELETE_HANDLE,
|
||||||
|
payload: {
|
||||||
|
webhook,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default {
|
||||||
|
createWebhook,
|
||||||
|
handleWebhookCreate,
|
||||||
|
updateWebhook,
|
||||||
|
handleWebhookUpdate,
|
||||||
|
deleteWebhook,
|
||||||
|
handleWebhookDelete,
|
||||||
|
};
|
|
@ -7,6 +7,7 @@ import http from './http';
|
||||||
import socket from './socket';
|
import socket from './socket';
|
||||||
import config from './config';
|
import config from './config';
|
||||||
import accessTokens from './access-tokens';
|
import accessTokens from './access-tokens';
|
||||||
|
import webhooks from './webhooks';
|
||||||
import users from './users';
|
import users from './users';
|
||||||
import projects from './projects';
|
import projects from './projects';
|
||||||
import projectManagers from './project-managers';
|
import projectManagers from './project-managers';
|
||||||
|
@ -35,6 +36,7 @@ export { http, socket };
|
||||||
export default {
|
export default {
|
||||||
...config,
|
...config,
|
||||||
...accessTokens,
|
...accessTokens,
|
||||||
|
...webhooks,
|
||||||
...users,
|
...users,
|
||||||
...projects,
|
...projects,
|
||||||
...projectManagers,
|
...projectManagers,
|
||||||
|
|
23
client/src/api/webhooks.js
Executable file
23
client/src/api/webhooks.js
Executable file
|
@ -0,0 +1,23 @@
|
||||||
|
/*!
|
||||||
|
* Copyright (c) 2024 PLANKA Software GmbH
|
||||||
|
* Licensed under the Fair Use License: https://github.com/plankanban/planka/blob/master/LICENSE.md
|
||||||
|
*/
|
||||||
|
|
||||||
|
import socket from './socket';
|
||||||
|
|
||||||
|
/* Actions */
|
||||||
|
|
||||||
|
const getWebhooks = (headers) => socket.get('/webhooks', undefined, headers);
|
||||||
|
|
||||||
|
const createWebhook = (data, headers) => socket.post('/webhooks', data, headers);
|
||||||
|
|
||||||
|
const updateWebhook = (id, data, headers) => socket.patch(`/webhooks/${id}`, data, headers);
|
||||||
|
|
||||||
|
const deleteWebhook = (id, headers) => socket.delete(`/webhooks/${id}`, undefined, headers);
|
||||||
|
|
||||||
|
export default {
|
||||||
|
getWebhooks,
|
||||||
|
createWebhook,
|
||||||
|
updateWebhook,
|
||||||
|
deleteWebhook,
|
||||||
|
};
|
|
@ -12,6 +12,7 @@ import { Modal, Tab } from 'semantic-ui-react';
|
||||||
import entryActions from '../../../entry-actions';
|
import entryActions from '../../../entry-actions';
|
||||||
import { useClosableModal } from '../../../hooks';
|
import { useClosableModal } from '../../../hooks';
|
||||||
import UsersPane from './UsersPane';
|
import UsersPane from './UsersPane';
|
||||||
|
import WebhooksPane from './WebhooksPane';
|
||||||
|
|
||||||
import styles from './AdministrationModal.module.scss';
|
import styles from './AdministrationModal.module.scss';
|
||||||
|
|
||||||
|
@ -37,6 +38,12 @@ const AdministrationModal = React.memo(() => {
|
||||||
}),
|
}),
|
||||||
render: () => <UsersPane />,
|
render: () => <UsersPane />,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
menuItem: t('common.webhooks', {
|
||||||
|
context: 'title',
|
||||||
|
}),
|
||||||
|
render: () => <WebhooksPane />,
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const isUsersPaneActive = activeTabIndex === 0;
|
const isUsersPaneActive = activeTabIndex === 0;
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
/*!
|
||||||
|
* Copyright (c) 2024 PLANKA Software GmbH
|
||||||
|
* Licensed under the Fair Use License: https://github.com/plankanban/planka/blob/master/LICENSE.md
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React, { useCallback } from 'react';
|
||||||
|
import { useDispatch, useSelector } from 'react-redux';
|
||||||
|
import { Tab } from 'semantic-ui-react';
|
||||||
|
|
||||||
|
import selectors from '../../../selectors';
|
||||||
|
import entryActions from '../../../entry-actions';
|
||||||
|
import Webhooks from '../../webhooks/Webhooks';
|
||||||
|
|
||||||
|
import styles from './WebhooksPane.module.scss';
|
||||||
|
|
||||||
|
const WebhooksPane = React.memo(() => {
|
||||||
|
const webhookIds = useSelector(selectors.selectWebhookIds);
|
||||||
|
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
|
const handleCreate = useCallback(
|
||||||
|
(data) => {
|
||||||
|
dispatch(entryActions.createWebhook(data));
|
||||||
|
},
|
||||||
|
[dispatch],
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Tab.Pane attached={false} className={styles.wrapper}>
|
||||||
|
<Webhooks ids={webhookIds} onCreate={handleCreate} />
|
||||||
|
</Tab.Pane>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
export default WebhooksPane;
|
|
@ -0,0 +1,11 @@
|
||||||
|
/*!
|
||||||
|
* Copyright (c) 2024 PLANKA Software GmbH
|
||||||
|
* Licensed under the Fair Use License: https://github.com/plankanban/planka/blob/master/LICENSE.md
|
||||||
|
*/
|
||||||
|
|
||||||
|
:global(#app) {
|
||||||
|
.wrapper {
|
||||||
|
border: none;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
}
|
|
@ -28,21 +28,26 @@ const ConfirmationStep = React.memo(
|
||||||
|
|
||||||
const [nameFieldRef, handleNameFieldRef] = useNestedRef('inputRef');
|
const [nameFieldRef, handleNameFieldRef] = useNestedRef('inputRef');
|
||||||
|
|
||||||
const handleSubmit = useCallback(() => {
|
const handleSubmit = useCallback(
|
||||||
if (typeValue) {
|
(event) => {
|
||||||
const cleanData = {
|
event.stopPropagation();
|
||||||
...data,
|
|
||||||
typeValue: data.typeValue.trim(),
|
|
||||||
};
|
|
||||||
|
|
||||||
if (cleanData.typeValue.toLowerCase() !== typeValue.toLowerCase()) {
|
if (typeValue) {
|
||||||
nameFieldRef.current.select();
|
const cleanData = {
|
||||||
return;
|
...data,
|
||||||
|
typeValue: data.typeValue.trim(),
|
||||||
|
};
|
||||||
|
|
||||||
|
if (cleanData.typeValue.toLowerCase() !== typeValue.toLowerCase()) {
|
||||||
|
nameFieldRef.current.select();
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
onConfirm();
|
onConfirm();
|
||||||
}, [typeValue, onConfirm, data, nameFieldRef]);
|
},
|
||||||
|
[typeValue, onConfirm, data, nameFieldRef],
|
||||||
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (typeValue) {
|
if (typeValue) {
|
||||||
|
|
|
@ -125,7 +125,7 @@ const Item = React.memo(({ id }) => {
|
||||||
dispatch(entryActions.deleteNotificationService(id));
|
dispatch(entryActions.deleteNotificationService(id));
|
||||||
}, [id, dispatch]);
|
}, [id, dispatch]);
|
||||||
|
|
||||||
const handleUpdateSubmit = useCallback(() => {
|
const handleSubmit = useCallback(() => {
|
||||||
urlFieldRef.current.blur();
|
urlFieldRef.current.blur();
|
||||||
}, [urlFieldRef]);
|
}, [urlFieldRef]);
|
||||||
|
|
||||||
|
@ -153,7 +153,7 @@ const Item = React.memo(({ id }) => {
|
||||||
const ConfirmationPopup = usePopupInClosableContext(ConfirmationStep);
|
const ConfirmationPopup = usePopupInClosableContext(ConfirmationStep);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Form className={styles.wrapper} onSubmit={handleUpdateSubmit}>
|
<Form className={styles.wrapper} onSubmit={handleSubmit}>
|
||||||
<Input
|
<Input
|
||||||
ref={handleUrlFieldRef}
|
ref={handleUrlFieldRef}
|
||||||
name="url"
|
name="url"
|
||||||
|
|
152
client/src/components/webhooks/Webhooks/Editor.jsx
Normal file
152
client/src/components/webhooks/Webhooks/Editor.jsx
Normal file
|
@ -0,0 +1,152 @@
|
||||||
|
/*!
|
||||||
|
* Copyright (c) 2024 PLANKA Software GmbH
|
||||||
|
* Licensed under the Fair Use License: https://github.com/plankanban/planka/blob/master/LICENSE.md
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React, { useCallback, useImperativeHandle } from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { Dropdown, Input } from 'semantic-ui-react';
|
||||||
|
|
||||||
|
import { useNestedRef } from '../../../hooks';
|
||||||
|
import WEBHOOK_EVENTS from '../../../constants/WebhookEvents';
|
||||||
|
|
||||||
|
import styles from './Editor.module.scss';
|
||||||
|
|
||||||
|
const Editor = React.forwardRef(({ data, isReadOnly, onFieldChange }, ref) => {
|
||||||
|
const [t] = useTranslation();
|
||||||
|
|
||||||
|
const [nameFieldRef, handleNameFieldRef] = useNestedRef('inputRef');
|
||||||
|
const [urlFieldRef, handleUrlFieldRef] = useNestedRef('inputRef');
|
||||||
|
|
||||||
|
const focusNameField = useCallback(() => {
|
||||||
|
nameFieldRef.current.focus({
|
||||||
|
preventScroll: true,
|
||||||
|
});
|
||||||
|
}, [nameFieldRef]);
|
||||||
|
|
||||||
|
const selectNameField = useCallback(() => {
|
||||||
|
nameFieldRef.current.select();
|
||||||
|
}, [nameFieldRef]);
|
||||||
|
|
||||||
|
const selectUrlField = useCallback(() => {
|
||||||
|
urlFieldRef.current.select();
|
||||||
|
}, [urlFieldRef]);
|
||||||
|
|
||||||
|
useImperativeHandle(
|
||||||
|
ref,
|
||||||
|
() => ({
|
||||||
|
focusNameField,
|
||||||
|
selectNameField,
|
||||||
|
selectUrlField,
|
||||||
|
}),
|
||||||
|
[focusNameField, selectNameField, selectUrlField],
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className={styles.text}>{t('common.title')}</div>
|
||||||
|
<Input
|
||||||
|
fluid
|
||||||
|
ref={handleNameFieldRef}
|
||||||
|
name="name"
|
||||||
|
value={data.name}
|
||||||
|
maxLength={128}
|
||||||
|
readOnly={isReadOnly}
|
||||||
|
className={styles.field}
|
||||||
|
onChange={onFieldChange}
|
||||||
|
/>
|
||||||
|
<div className={styles.text}>{t('common.url')}</div>
|
||||||
|
<Input
|
||||||
|
fluid
|
||||||
|
ref={handleUrlFieldRef}
|
||||||
|
name="url"
|
||||||
|
value={data.url}
|
||||||
|
maxLength={2048}
|
||||||
|
readOnly={isReadOnly}
|
||||||
|
className={styles.field}
|
||||||
|
onChange={onFieldChange}
|
||||||
|
/>
|
||||||
|
<div className={styles.text}>
|
||||||
|
{t('common.accessToken')} (
|
||||||
|
{t('common.optional', {
|
||||||
|
context: 'inline',
|
||||||
|
})}
|
||||||
|
)
|
||||||
|
</div>
|
||||||
|
<Input
|
||||||
|
fluid
|
||||||
|
name="accessToken"
|
||||||
|
value={data.accessToken}
|
||||||
|
maxLength={512}
|
||||||
|
readOnly={isReadOnly}
|
||||||
|
className={styles.field}
|
||||||
|
onChange={onFieldChange}
|
||||||
|
/>
|
||||||
|
{data.excludedEvents.length === 0 && (
|
||||||
|
<>
|
||||||
|
<div className={styles.text}>
|
||||||
|
{t('common.events')} (
|
||||||
|
{t('common.optional', {
|
||||||
|
context: 'inline',
|
||||||
|
})}
|
||||||
|
)
|
||||||
|
</div>
|
||||||
|
<Dropdown
|
||||||
|
selection
|
||||||
|
multiple
|
||||||
|
fluid
|
||||||
|
name="events"
|
||||||
|
options={WEBHOOK_EVENTS.map((event) => ({
|
||||||
|
text: event,
|
||||||
|
value: event,
|
||||||
|
}))}
|
||||||
|
value={data.events}
|
||||||
|
placeholder="All"
|
||||||
|
readOnly={isReadOnly}
|
||||||
|
className={styles.field}
|
||||||
|
onChange={onFieldChange}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{data.events.length === 0 && (
|
||||||
|
<>
|
||||||
|
<div className={styles.text}>
|
||||||
|
{t('common.excludedEvents')} (
|
||||||
|
{t('common.optional', {
|
||||||
|
context: 'inline',
|
||||||
|
})}
|
||||||
|
)
|
||||||
|
</div>
|
||||||
|
<Dropdown
|
||||||
|
selection
|
||||||
|
multiple
|
||||||
|
fluid
|
||||||
|
name="excludedEvents"
|
||||||
|
options={WEBHOOK_EVENTS.map((event) => ({
|
||||||
|
text: event,
|
||||||
|
value: event,
|
||||||
|
}))}
|
||||||
|
value={data.excludedEvents}
|
||||||
|
placeholder="None"
|
||||||
|
readOnly={isReadOnly}
|
||||||
|
className={styles.field}
|
||||||
|
onChange={onFieldChange}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
Editor.propTypes = {
|
||||||
|
data: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types
|
||||||
|
isReadOnly: PropTypes.bool,
|
||||||
|
onFieldChange: PropTypes.func.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
Editor.defaultProps = {
|
||||||
|
isReadOnly: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default React.memo(Editor);
|
17
client/src/components/webhooks/Webhooks/Editor.module.scss
Normal file
17
client/src/components/webhooks/Webhooks/Editor.module.scss
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
/*!
|
||||||
|
* Copyright (c) 2024 PLANKA Software GmbH
|
||||||
|
* Licensed under the Fair Use License: https://github.com/plankanban/planka/blob/master/LICENSE.md
|
||||||
|
*/
|
||||||
|
|
||||||
|
:global(#app) {
|
||||||
|
.field {
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text {
|
||||||
|
color: #444444;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: bold;
|
||||||
|
padding-bottom: 6px;
|
||||||
|
}
|
||||||
|
}
|
137
client/src/components/webhooks/Webhooks/Item.jsx
Normal file
137
client/src/components/webhooks/Webhooks/Item.jsx
Normal file
|
@ -0,0 +1,137 @@
|
||||||
|
/*!
|
||||||
|
* Copyright (c) 2024 PLANKA Software GmbH
|
||||||
|
* Licensed under the Fair Use License: https://github.com/plankanban/planka/blob/master/LICENSE.md
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { dequal } from 'dequal';
|
||||||
|
import React, { useCallback, useMemo, useRef } from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { useDispatch, useSelector } from 'react-redux';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { Accordion, Button, Form, Icon } from 'semantic-ui-react';
|
||||||
|
|
||||||
|
import selectors from '../../../selectors';
|
||||||
|
import entryActions from '../../../entry-actions';
|
||||||
|
import { useForm, usePopupInClosableContext } from '../../../hooks';
|
||||||
|
import { isUrl } from '../../../utils/validator';
|
||||||
|
import Editor from './Editor';
|
||||||
|
import ConfirmationStep from '../../common/ConfirmationStep';
|
||||||
|
|
||||||
|
import styles from './Item.module.scss';
|
||||||
|
import { useToggle } from '../../../lib/hooks';
|
||||||
|
|
||||||
|
const Item = React.memo(({ id }) => {
|
||||||
|
const selectWebhookById = useMemo(() => selectors.makeSelectWebhookById(), []);
|
||||||
|
|
||||||
|
const webhook = useSelector((state) => selectWebhookById(state, id));
|
||||||
|
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
const [t] = useTranslation();
|
||||||
|
const [isOpened, toggleOpened] = useToggle();
|
||||||
|
|
||||||
|
const defaultData = useMemo(
|
||||||
|
() => ({
|
||||||
|
name: webhook.name,
|
||||||
|
url: webhook.url,
|
||||||
|
accessToken: webhook.accessToken,
|
||||||
|
events: webhook.events,
|
||||||
|
excludedEvents: webhook.excludedEvents,
|
||||||
|
}),
|
||||||
|
[webhook],
|
||||||
|
);
|
||||||
|
|
||||||
|
const [data, handleFieldChange] = useForm(() => ({
|
||||||
|
name: '',
|
||||||
|
url: '',
|
||||||
|
...defaultData,
|
||||||
|
accessToken: defaultData.accessToken || '',
|
||||||
|
events: defaultData.events || [],
|
||||||
|
excludedEvents: defaultData.excludedEvents || [],
|
||||||
|
}));
|
||||||
|
|
||||||
|
const cleanData = useMemo(
|
||||||
|
() => ({
|
||||||
|
...data,
|
||||||
|
name: data.name.trim(),
|
||||||
|
url: data.url.trim(),
|
||||||
|
accessToken: data.accessToken.trim() || null,
|
||||||
|
events: data.events.length === 0 ? null : data.events,
|
||||||
|
excludedEvents: data.excludedEvents.length === 0 ? null : data.excludedEvents,
|
||||||
|
}),
|
||||||
|
[data],
|
||||||
|
);
|
||||||
|
|
||||||
|
const editorRef = useRef(null);
|
||||||
|
|
||||||
|
const handleDeleteConfirm = useCallback(() => {
|
||||||
|
dispatch(entryActions.deleteWebhook(id));
|
||||||
|
}, [id, dispatch]);
|
||||||
|
|
||||||
|
const handleSubmit = useCallback(() => {
|
||||||
|
if (!cleanData.name) {
|
||||||
|
editorRef.current.selectNameField();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!cleanData.url || !isUrl(cleanData.url)) {
|
||||||
|
editorRef.current.selectUrlField();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dispatch(entryActions.updateWebhook(id, cleanData));
|
||||||
|
}, [id, dispatch, cleanData]);
|
||||||
|
|
||||||
|
const handleOpenClick = useCallback(() => {
|
||||||
|
toggleOpened();
|
||||||
|
}, [toggleOpened]);
|
||||||
|
|
||||||
|
const ConfirmationPopup = usePopupInClosableContext(ConfirmationStep);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Accordion.Title active={isOpened} className={styles.title} onClick={handleOpenClick}>
|
||||||
|
<Icon name="dropdown" />
|
||||||
|
{defaultData.name}
|
||||||
|
</Accordion.Title>
|
||||||
|
<Accordion.Content active={isOpened}>
|
||||||
|
<div>
|
||||||
|
<Form onSubmit={handleSubmit}>
|
||||||
|
<Editor
|
||||||
|
ref={editorRef}
|
||||||
|
data={data}
|
||||||
|
isReadOnly={!webhook.isPersisted}
|
||||||
|
onFieldChange={handleFieldChange}
|
||||||
|
/>
|
||||||
|
<div className={styles.controls}>
|
||||||
|
<Button
|
||||||
|
positive
|
||||||
|
disabled={dequal(cleanData, defaultData)}
|
||||||
|
content={t('action.save')}
|
||||||
|
/>
|
||||||
|
<ConfirmationPopup
|
||||||
|
title="common.deleteWebhook"
|
||||||
|
content="common.areYouSureYouWantToDeleteThisWebhook"
|
||||||
|
buttonContent="action.deleteWebhook"
|
||||||
|
onConfirm={handleDeleteConfirm}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
type="button"
|
||||||
|
disabled={!webhook.isPersisted}
|
||||||
|
className={styles.deleteButton}
|
||||||
|
>
|
||||||
|
{t('action.delete')}
|
||||||
|
</Button>
|
||||||
|
</ConfirmationPopup>
|
||||||
|
</div>
|
||||||
|
</Form>
|
||||||
|
</div>
|
||||||
|
</Accordion.Content>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
Item.propTypes = {
|
||||||
|
id: PropTypes.string.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Item;
|
22
client/src/components/webhooks/Webhooks/Item.module.scss
Normal file
22
client/src/components/webhooks/Webhooks/Item.module.scss
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
/*!
|
||||||
|
* Copyright (c) 2024 PLANKA Software GmbH
|
||||||
|
* Licensed under the Fair Use License: https://github.com/plankanban/planka/blob/master/LICENSE.md
|
||||||
|
*/
|
||||||
|
|
||||||
|
:global(#app) {
|
||||||
|
.controls {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.deleteButton {
|
||||||
|
box-shadow: 0 1px 0 #cbcccc;
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
}
|
96
client/src/components/webhooks/Webhooks/Webhooks.jsx
Normal file
96
client/src/components/webhooks/Webhooks/Webhooks.jsx
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
/*!
|
||||||
|
* Copyright (c) 2024 PLANKA Software GmbH
|
||||||
|
* Licensed under the Fair Use License: https://github.com/plankanban/planka/blob/master/LICENSE.md
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React, { useCallback, useEffect, useRef } from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { Accordion, Button, Form, Segment } from 'semantic-ui-react';
|
||||||
|
import { useDidUpdate, useToggle } from '../../../lib/hooks';
|
||||||
|
|
||||||
|
import { useForm } from '../../../hooks';
|
||||||
|
import { isUrl } from '../../../utils/validator';
|
||||||
|
import Item from './Item';
|
||||||
|
import Editor from './Editor';
|
||||||
|
|
||||||
|
const DEFAULT_DATA = {
|
||||||
|
name: '',
|
||||||
|
url: '',
|
||||||
|
accessToken: '',
|
||||||
|
events: [],
|
||||||
|
excludedEvents: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
const Webhooks = React.memo(({ ids, onCreate }) => {
|
||||||
|
const [t] = useTranslation();
|
||||||
|
|
||||||
|
const [data, handleFieldChange, setData] = useForm(DEFAULT_DATA);
|
||||||
|
const [focusNameFieldState, focusNameField] = useToggle();
|
||||||
|
|
||||||
|
const editorRef = useRef(null);
|
||||||
|
|
||||||
|
const handleCreateSubmit = useCallback(() => {
|
||||||
|
const cleanData = {
|
||||||
|
...data,
|
||||||
|
name: data.name.trim(),
|
||||||
|
url: data.url.trim(),
|
||||||
|
accessToken: data.accessToken.trim() || null,
|
||||||
|
events: data.events.length === 0 ? null : data.events,
|
||||||
|
excludedEvents: data.excludedEvents.length === 0 ? null : data.excludedEvents,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!cleanData.name) {
|
||||||
|
editorRef.current.selectNameField();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!cleanData.url || !isUrl(cleanData.url)) {
|
||||||
|
editorRef.current.selectUrlField();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
onCreate(cleanData);
|
||||||
|
setData(DEFAULT_DATA);
|
||||||
|
focusNameField();
|
||||||
|
}, [onCreate, data, setData, focusNameField]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (editorRef.current) {
|
||||||
|
editorRef.current.focusNameField();
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useDidUpdate(() => {
|
||||||
|
if (editorRef.current) {
|
||||||
|
editorRef.current.focusNameField();
|
||||||
|
}
|
||||||
|
}, [focusNameFieldState]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{ids.length > 0 && (
|
||||||
|
<Accordion styled fluid>
|
||||||
|
{ids.map((id) => (
|
||||||
|
<Item key={id} id={id} />
|
||||||
|
))}
|
||||||
|
</Accordion>
|
||||||
|
)}
|
||||||
|
{ids.length < 10 && (
|
||||||
|
<Segment>
|
||||||
|
<Form onSubmit={handleCreateSubmit}>
|
||||||
|
<Editor ref={editorRef} data={data} onFieldChange={handleFieldChange} />
|
||||||
|
<Button positive>{t('action.addWebhook')}</Button>
|
||||||
|
</Form>
|
||||||
|
</Segment>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
Webhooks.propTypes = {
|
||||||
|
ids: PropTypes.array.isRequired, // eslint-disable-line react/forbid-prop-types
|
||||||
|
onCreate: PropTypes.func.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Webhooks;
|
8
client/src/components/webhooks/Webhooks/index.js
Normal file
8
client/src/components/webhooks/Webhooks/index.js
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
/*!
|
||||||
|
* Copyright (c) 2024 PLANKA Software GmbH
|
||||||
|
* Licensed under the Fair Use License: https://github.com/plankanban/planka/blob/master/LICENSE.md
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Webhooks from './Webhooks';
|
||||||
|
|
||||||
|
export default Webhooks;
|
|
@ -42,6 +42,21 @@ export default {
|
||||||
MODAL_OPEN: 'MODAL_OPEN',
|
MODAL_OPEN: 'MODAL_OPEN',
|
||||||
MODAL_CLOSE: 'MODAL_CLOSE',
|
MODAL_CLOSE: 'MODAL_CLOSE',
|
||||||
|
|
||||||
|
/* Webhooks */
|
||||||
|
|
||||||
|
WEBHOOK_CREATE: 'WEBHOOK_CREATE',
|
||||||
|
WEBHOOK_CREATE__SUCCESS: 'WEBHOOK_CREATE__SUCCESS',
|
||||||
|
WEBHOOK_CREATE__FAILURE: 'WEBHOOK_CREATE__FAILURE',
|
||||||
|
WEBHOOK_CREATE_HANDLE: 'WEBHOOK_CREATE_HANDLE',
|
||||||
|
WEBHOOK_UPDATE: 'WEBHOOK_UPDATE',
|
||||||
|
WEBHOOK_UPDATE__SUCCESS: 'WEBHOOK_UPDATE__SUCCESS',
|
||||||
|
WEBHOOK_UPDATE__FAILURE: 'WEBHOOK_UPDATE__FAILURE',
|
||||||
|
WEBHOOK_UPDATE_HANDLE: 'WEBHOOK_UPDATE_HANDLE',
|
||||||
|
WEBHOOK_DELETE: 'WEBHOOK_DELETE',
|
||||||
|
WEBHOOK_DELETE__SUCCESS: 'WEBHOOK_DELETE__SUCCESS',
|
||||||
|
WEBHOOK_DELETE__FAILURE: 'WEBHOOK_DELETE__FAILURE',
|
||||||
|
WEBHOOK_DELETE_HANDLE: 'WEBHOOK_DELETE_HANDLE',
|
||||||
|
|
||||||
/* Users */
|
/* Users */
|
||||||
|
|
||||||
USER_CREATE: 'USER_CREATE',
|
USER_CREATE: 'USER_CREATE',
|
||||||
|
|
|
@ -31,6 +31,15 @@ export default {
|
||||||
MODAL_OPEN: `${PREFIX}/MODAL_OPEN`,
|
MODAL_OPEN: `${PREFIX}/MODAL_OPEN`,
|
||||||
MODAL_CLOSE: `${PREFIX}/MODAL_CLOSE`,
|
MODAL_CLOSE: `${PREFIX}/MODAL_CLOSE`,
|
||||||
|
|
||||||
|
/* Webhooks */
|
||||||
|
|
||||||
|
WEBHOOK_CREATE: `${PREFIX}/WEBHOOK_CREATE`,
|
||||||
|
WEBHOOK_CREATE_HANDLE: `${PREFIX}/WEBHOOK_CREATE_HANDLE`,
|
||||||
|
WEBHOOK_UPDATE: `${PREFIX}/WEBHOOK_UPDATE`,
|
||||||
|
WEBHOOK_UPDATE_HANDLE: `${PREFIX}/WEBHOOK_UPDATE_HANDLE`,
|
||||||
|
WEBHOOK_DELETE: `${PREFIX}/WEBHOOK_DELETE`,
|
||||||
|
WEBHOOK_DELETE_HANDLE: `${PREFIX}/WEBHOOK_DELETE_HANDLE`,
|
||||||
|
|
||||||
/* Users */
|
/* Users */
|
||||||
|
|
||||||
USER_CREATE: `${PREFIX}/USER_CREATE`,
|
USER_CREATE: `${PREFIX}/USER_CREATE`,
|
||||||
|
|
91
client/src/constants/WebhookEvents.js
Normal file
91
client/src/constants/WebhookEvents.js
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
/*!
|
||||||
|
* Copyright (c) 2024 PLANKA Software GmbH
|
||||||
|
* Licensed under the Fair Use License: https://github.com/plankanban/planka/blob/master/LICENSE.md
|
||||||
|
*/
|
||||||
|
|
||||||
|
export default [
|
||||||
|
'actionCreate',
|
||||||
|
|
||||||
|
'attachmentCreate',
|
||||||
|
'attachmentUpdate',
|
||||||
|
'attachmentDelete',
|
||||||
|
|
||||||
|
'backgroundImageCreate',
|
||||||
|
'backgroundImageDelete',
|
||||||
|
|
||||||
|
'baseCustomFieldGroupCreate',
|
||||||
|
'baseCustomFieldGroupUpdate',
|
||||||
|
'baseCustomFieldGroupDelete',
|
||||||
|
|
||||||
|
'boardCreate',
|
||||||
|
'boardUpdate',
|
||||||
|
'boardDelete',
|
||||||
|
|
||||||
|
'boardMembershipCreate',
|
||||||
|
'boardMembershipUpdate',
|
||||||
|
'boardMembershipDelete',
|
||||||
|
|
||||||
|
'cardCreate',
|
||||||
|
'cardUpdate',
|
||||||
|
'cardDelete',
|
||||||
|
|
||||||
|
'cardLabelCreate',
|
||||||
|
'cardLabelDelete',
|
||||||
|
|
||||||
|
'cardMembershipCreate',
|
||||||
|
'cardMembershipDelete',
|
||||||
|
|
||||||
|
'commentCreate',
|
||||||
|
'commentUpdate',
|
||||||
|
'commentDelete',
|
||||||
|
|
||||||
|
'customFieldCreate',
|
||||||
|
'customFieldUpdate',
|
||||||
|
'customFieldDelete',
|
||||||
|
|
||||||
|
'customFieldGroupCreate',
|
||||||
|
'customFieldGroupUpdate',
|
||||||
|
'customFieldGroupDelete',
|
||||||
|
|
||||||
|
'customFieldValueUpdate',
|
||||||
|
'customFieldValueDelete',
|
||||||
|
|
||||||
|
'labelCreate',
|
||||||
|
'labelUpdate',
|
||||||
|
'labelDelete',
|
||||||
|
|
||||||
|
'listCreate',
|
||||||
|
'listUpdate',
|
||||||
|
'listClear',
|
||||||
|
'listDelete',
|
||||||
|
|
||||||
|
'notificationCreate',
|
||||||
|
'notificationUpdate',
|
||||||
|
|
||||||
|
'notificationServiceCreate',
|
||||||
|
'notificationServiceUpdate',
|
||||||
|
'notificationServiceDelete',
|
||||||
|
|
||||||
|
'projectCreate',
|
||||||
|
'projectUpdate',
|
||||||
|
'projectDelete',
|
||||||
|
|
||||||
|
'projectManagerCreate',
|
||||||
|
'projectManagerDelete',
|
||||||
|
|
||||||
|
'taskCreate',
|
||||||
|
'taskUpdate',
|
||||||
|
'taskDelete',
|
||||||
|
|
||||||
|
'taskListCreate',
|
||||||
|
'taskListUpdate',
|
||||||
|
'taskListDelete',
|
||||||
|
|
||||||
|
'userCreate',
|
||||||
|
'userUpdate',
|
||||||
|
'userDelete',
|
||||||
|
|
||||||
|
'webhookCreate',
|
||||||
|
'webhookUpdate',
|
||||||
|
'webhookDelete',
|
||||||
|
];
|
|
@ -7,6 +7,7 @@ import socket from './socket';
|
||||||
import login from './login';
|
import login from './login';
|
||||||
import core from './core';
|
import core from './core';
|
||||||
import modals from './modals';
|
import modals from './modals';
|
||||||
|
import webhooks from './webhooks';
|
||||||
import users from './users';
|
import users from './users';
|
||||||
import projects from './projects';
|
import projects from './projects';
|
||||||
import projectManagers from './project-managers';
|
import projectManagers from './project-managers';
|
||||||
|
@ -33,6 +34,7 @@ export default {
|
||||||
...login,
|
...login,
|
||||||
...core,
|
...core,
|
||||||
...modals,
|
...modals,
|
||||||
|
...webhooks,
|
||||||
...users,
|
...users,
|
||||||
...projects,
|
...projects,
|
||||||
...projectManagers,
|
...projectManagers,
|
||||||
|
|
58
client/src/entry-actions/webhooks.js
Normal file
58
client/src/entry-actions/webhooks.js
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
/*!
|
||||||
|
* Copyright (c) 2024 PLANKA Software GmbH
|
||||||
|
* Licensed under the Fair Use License: https://github.com/plankanban/planka/blob/master/LICENSE.md
|
||||||
|
*/
|
||||||
|
|
||||||
|
import EntryActionTypes from '../constants/EntryActionTypes';
|
||||||
|
|
||||||
|
const createWebhook = (data) => ({
|
||||||
|
type: EntryActionTypes.WEBHOOK_CREATE,
|
||||||
|
payload: {
|
||||||
|
data,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleWebhookCreate = (webhook) => ({
|
||||||
|
type: EntryActionTypes.WEBHOOK_CREATE_HANDLE,
|
||||||
|
payload: {
|
||||||
|
webhook,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const updateWebhook = (id, data) => ({
|
||||||
|
type: EntryActionTypes.WEBHOOK_UPDATE,
|
||||||
|
payload: {
|
||||||
|
id,
|
||||||
|
data,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleWebhookUpdate = (webhook) => ({
|
||||||
|
type: EntryActionTypes.WEBHOOK_UPDATE_HANDLE,
|
||||||
|
payload: {
|
||||||
|
webhook,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const deleteWebhook = (id) => ({
|
||||||
|
type: EntryActionTypes.WEBHOOK_DELETE,
|
||||||
|
payload: {
|
||||||
|
id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleWebhookDelete = (webhook) => ({
|
||||||
|
type: EntryActionTypes.WEBHOOK_DELETE_HANDLE,
|
||||||
|
payload: {
|
||||||
|
webhook,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default {
|
||||||
|
createWebhook,
|
||||||
|
handleWebhookCreate,
|
||||||
|
updateWebhook,
|
||||||
|
handleWebhookUpdate,
|
||||||
|
deleteWebhook,
|
||||||
|
handleWebhookDelete,
|
||||||
|
};
|
|
@ -21,6 +21,7 @@ export default {
|
||||||
translation: {
|
translation: {
|
||||||
common: {
|
common: {
|
||||||
aboutPlanka: 'About PLANKA',
|
aboutPlanka: 'About PLANKA',
|
||||||
|
accessToken: 'Access token',
|
||||||
account: 'Account',
|
account: 'Account',
|
||||||
actions: 'Actions',
|
actions: 'Actions',
|
||||||
activateUser_title: 'Activate User',
|
activateUser_title: 'Activate User',
|
||||||
|
@ -69,6 +70,7 @@ export default {
|
||||||
areYouSureYouWantToDeleteThisTask: 'Are you sure you want to delete this task?',
|
areYouSureYouWantToDeleteThisTask: 'Are you sure you want to delete this task?',
|
||||||
areYouSureYouWantToDeleteThisTaskList: 'Are you sure you want to delete this task list?',
|
areYouSureYouWantToDeleteThisTaskList: 'Are you sure you want to delete this task list?',
|
||||||
areYouSureYouWantToDeleteThisUser: 'Are you sure you want to delete this user?',
|
areYouSureYouWantToDeleteThisUser: 'Are you sure you want to delete this user?',
|
||||||
|
areYouSureYouWantToDeleteThisWebhook: 'Are you sure you want to delete this webhook?',
|
||||||
areYouSureYouWantToEmptyTrash: 'Are you sure you want to empty the trash?',
|
areYouSureYouWantToEmptyTrash: 'Are you sure you want to empty the trash?',
|
||||||
areYouSureYouWantToLeaveBoard: 'Are you sure you want to leave the board?',
|
areYouSureYouWantToLeaveBoard: 'Are you sure you want to leave the board?',
|
||||||
areYouSureYouWantToLeaveProject: 'Are you sure you want to leave the project?',
|
areYouSureYouWantToLeaveProject: 'Are you sure you want to leave the project?',
|
||||||
|
@ -152,6 +154,7 @@ export default {
|
||||||
deleteTask_title: 'Delete Task',
|
deleteTask_title: 'Delete Task',
|
||||||
deleteUser_title: 'Delete User',
|
deleteUser_title: 'Delete User',
|
||||||
deletedUser_title: 'Deleted User',
|
deletedUser_title: 'Deleted User',
|
||||||
|
deleteWebhook_title: 'Delete Webhook',
|
||||||
description: 'Description',
|
description: 'Description',
|
||||||
detectAutomatically: 'Detect automatically',
|
detectAutomatically: 'Detect automatically',
|
||||||
display: 'Display',
|
display: 'Display',
|
||||||
|
@ -182,6 +185,8 @@ export default {
|
||||||
enterFilename: 'Enter filename',
|
enterFilename: 'Enter filename',
|
||||||
enterListTitle: 'Enter list title...',
|
enterListTitle: 'Enter list title...',
|
||||||
enterTaskDescription: 'Enter task description...',
|
enterTaskDescription: 'Enter task description...',
|
||||||
|
events: 'Events',
|
||||||
|
excludedEvents: 'Excluded events',
|
||||||
filterByLabels_title: 'Filter By Labels',
|
filterByLabels_title: 'Filter By Labels',
|
||||||
filterByMembers_title: 'Filter By Members',
|
filterByMembers_title: 'Filter By Members',
|
||||||
forPersonalProjects: 'For personal projects.',
|
forPersonalProjects: 'For personal projects.',
|
||||||
|
@ -286,6 +291,7 @@ export default {
|
||||||
typeTitleToConfirm: 'Type the title to confirm.',
|
typeTitleToConfirm: 'Type the title to confirm.',
|
||||||
unsavedChanges: 'Unsaved changes',
|
unsavedChanges: 'Unsaved changes',
|
||||||
uploadedImages: 'Uploaded images',
|
uploadedImages: 'Uploaded images',
|
||||||
|
url: 'URL',
|
||||||
userActions_title: 'User Actions',
|
userActions_title: 'User Actions',
|
||||||
userAddedCardToList: '<0>{{user}}</0> added <2>{{card}}</2> to {{list}}',
|
userAddedCardToList: '<0>{{user}}</0> added <2>{{card}}</2> to {{list}}',
|
||||||
userAddedThisCardToList: '<0>{{user}}</0> added this card to {{list}}',
|
userAddedThisCardToList: '<0>{{user}}</0> added this card to {{list}}',
|
||||||
|
@ -313,6 +319,7 @@ export default {
|
||||||
userRemovedUserFromThisCard: '<0>{{actorUser}}</0> removed {{removedUser}} from this card',
|
userRemovedUserFromThisCard: '<0>{{actorUser}}</0> removed {{removedUser}} from this card',
|
||||||
username: 'Username',
|
username: 'Username',
|
||||||
users: 'Users',
|
users: 'Users',
|
||||||
|
webhooks: 'Webhooks',
|
||||||
viewer: 'Viewer',
|
viewer: 'Viewer',
|
||||||
viewers: 'Viewers',
|
viewers: 'Viewers',
|
||||||
visualTaskManagementWithLists: 'Visual task management with lists.',
|
visualTaskManagementWithLists: 'Visual task management with lists.',
|
||||||
|
@ -338,6 +345,7 @@ export default {
|
||||||
addTaskList: 'Add task list',
|
addTaskList: 'Add task list',
|
||||||
addToCard: 'Add to card',
|
addToCard: 'Add to card',
|
||||||
addUser: 'Add user',
|
addUser: 'Add user',
|
||||||
|
addWebhook: 'Add webhook',
|
||||||
archive: 'Archive',
|
archive: 'Archive',
|
||||||
archiveCard: 'Archive card',
|
archiveCard: 'Archive card',
|
||||||
archiveCard_title: 'Archive Card',
|
archiveCard_title: 'Archive Card',
|
||||||
|
@ -378,6 +386,7 @@ export default {
|
||||||
deleteTask_title: 'Delete Task',
|
deleteTask_title: 'Delete Task',
|
||||||
deleteUser: 'Delete user',
|
deleteUser: 'Delete user',
|
||||||
deleteUser_title: 'Delete User',
|
deleteUser_title: 'Delete User',
|
||||||
|
deleteWebhook: 'Delete webhook',
|
||||||
dismissAll: 'Dismiss all',
|
dismissAll: 'Dismiss all',
|
||||||
duplicate: 'Duplicate',
|
duplicate: 'Duplicate',
|
||||||
duplicateCard_title: 'Duplicate Card',
|
duplicateCard_title: 'Duplicate Card',
|
||||||
|
|
|
@ -16,6 +16,7 @@ export default {
|
||||||
translation: {
|
translation: {
|
||||||
common: {
|
common: {
|
||||||
aboutPlanka: 'About PLANKA',
|
aboutPlanka: 'About PLANKA',
|
||||||
|
accessToken: 'Access token',
|
||||||
account: 'Account',
|
account: 'Account',
|
||||||
actions: 'Actions',
|
actions: 'Actions',
|
||||||
activateUser_title: 'Activate User',
|
activateUser_title: 'Activate User',
|
||||||
|
@ -64,6 +65,7 @@ export default {
|
||||||
areYouSureYouWantToDeleteThisTask: 'Are you sure you want to delete this task?',
|
areYouSureYouWantToDeleteThisTask: 'Are you sure you want to delete this task?',
|
||||||
areYouSureYouWantToDeleteThisTaskList: 'Are you sure you want to delete this task list?',
|
areYouSureYouWantToDeleteThisTaskList: 'Are you sure you want to delete this task list?',
|
||||||
areYouSureYouWantToDeleteThisUser: 'Are you sure you want to delete this user?',
|
areYouSureYouWantToDeleteThisUser: 'Are you sure you want to delete this user?',
|
||||||
|
areYouSureYouWantToDeleteThisWebhook: 'Are you sure you want to delete this webhook?',
|
||||||
areYouSureYouWantToEmptyTrash: 'Are you sure you want to empty the trash?',
|
areYouSureYouWantToEmptyTrash: 'Are you sure you want to empty the trash?',
|
||||||
areYouSureYouWantToLeaveBoard: 'Are you sure you want to leave the board?',
|
areYouSureYouWantToLeaveBoard: 'Are you sure you want to leave the board?',
|
||||||
areYouSureYouWantToLeaveProject: 'Are you sure you want to leave the project?',
|
areYouSureYouWantToLeaveProject: 'Are you sure you want to leave the project?',
|
||||||
|
@ -147,6 +149,7 @@ export default {
|
||||||
deleteTask_title: 'Delete Task',
|
deleteTask_title: 'Delete Task',
|
||||||
deleteUser_title: 'Delete User',
|
deleteUser_title: 'Delete User',
|
||||||
deletedUser_title: 'Deleted User',
|
deletedUser_title: 'Deleted User',
|
||||||
|
deleteWebhook_title: 'Delete Webhook',
|
||||||
description: 'Description',
|
description: 'Description',
|
||||||
detectAutomatically: 'Detect automatically',
|
detectAutomatically: 'Detect automatically',
|
||||||
display: 'Display',
|
display: 'Display',
|
||||||
|
@ -177,6 +180,8 @@ export default {
|
||||||
enterFilename: 'Enter filename',
|
enterFilename: 'Enter filename',
|
||||||
enterListTitle: 'Enter list title...',
|
enterListTitle: 'Enter list title...',
|
||||||
enterTaskDescription: 'Enter task description...',
|
enterTaskDescription: 'Enter task description...',
|
||||||
|
events: 'Events',
|
||||||
|
excludedEvents: 'Excluded events',
|
||||||
filterByLabels_title: 'Filter By Labels',
|
filterByLabels_title: 'Filter By Labels',
|
||||||
filterByMembers_title: 'Filter By Members',
|
filterByMembers_title: 'Filter By Members',
|
||||||
forPersonalProjects: 'For personal projects.',
|
forPersonalProjects: 'For personal projects.',
|
||||||
|
@ -281,6 +286,7 @@ export default {
|
||||||
typeTitleToConfirm: 'Type the title to confirm.',
|
typeTitleToConfirm: 'Type the title to confirm.',
|
||||||
unsavedChanges: 'Unsaved changes',
|
unsavedChanges: 'Unsaved changes',
|
||||||
uploadedImages: 'Uploaded images',
|
uploadedImages: 'Uploaded images',
|
||||||
|
url: 'URL',
|
||||||
userActions_title: 'User Actions',
|
userActions_title: 'User Actions',
|
||||||
userAddedCardToList: '<0>{{user}}</0> added <2>{{card}}</2> to {{list}}',
|
userAddedCardToList: '<0>{{user}}</0> added <2>{{card}}</2> to {{list}}',
|
||||||
userAddedThisCardToList: '<0>{{user}}</0> added this card to {{list}}',
|
userAddedThisCardToList: '<0>{{user}}</0> added this card to {{list}}',
|
||||||
|
@ -308,6 +314,7 @@ export default {
|
||||||
userRemovedUserFromThisCard: '<0>{{actorUser}}</0> removed {{removedUser}} from this card',
|
userRemovedUserFromThisCard: '<0>{{actorUser}}</0> removed {{removedUser}} from this card',
|
||||||
username: 'Username',
|
username: 'Username',
|
||||||
users: 'Users',
|
users: 'Users',
|
||||||
|
webhooks: 'Webhooks',
|
||||||
viewer: 'Viewer',
|
viewer: 'Viewer',
|
||||||
viewers: 'Viewers',
|
viewers: 'Viewers',
|
||||||
visualTaskManagementWithLists: 'Visual task management with lists.',
|
visualTaskManagementWithLists: 'Visual task management with lists.',
|
||||||
|
@ -333,6 +340,7 @@ export default {
|
||||||
addTaskList: 'Add task list',
|
addTaskList: 'Add task list',
|
||||||
addToCard: 'Add to card',
|
addToCard: 'Add to card',
|
||||||
addUser: 'Add user',
|
addUser: 'Add user',
|
||||||
|
addWebhook: 'Add webhook',
|
||||||
archive: 'Archive',
|
archive: 'Archive',
|
||||||
archiveCard: 'Archive card',
|
archiveCard: 'Archive card',
|
||||||
archiveCard_title: 'Archive Card',
|
archiveCard_title: 'Archive Card',
|
||||||
|
@ -373,6 +381,7 @@ export default {
|
||||||
deleteTask_title: 'Delete Task',
|
deleteTask_title: 'Delete Task',
|
||||||
deleteUser: 'Delete user',
|
deleteUser: 'Delete user',
|
||||||
deleteUser_title: 'Delete User',
|
deleteUser_title: 'Delete User',
|
||||||
|
deleteWebhook: 'Delete webhook',
|
||||||
dismissAll: 'Dismiss all',
|
dismissAll: 'Dismiss all',
|
||||||
duplicate: 'Duplicate',
|
duplicate: 'Duplicate',
|
||||||
duplicateCard_title: 'Duplicate Card',
|
duplicateCard_title: 'Duplicate Card',
|
||||||
|
|
88
client/src/models/Webhook.js
Normal file
88
client/src/models/Webhook.js
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
/*!
|
||||||
|
* Copyright (c) 2024 PLANKA Software GmbH
|
||||||
|
* Licensed under the Fair Use License: https://github.com/plankanban/planka/blob/master/LICENSE.md
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { attr, fk } from 'redux-orm';
|
||||||
|
|
||||||
|
import BaseModel from './BaseModel';
|
||||||
|
import ActionTypes from '../constants/ActionTypes';
|
||||||
|
|
||||||
|
export default class extends BaseModel {
|
||||||
|
static modelName = 'Webhook';
|
||||||
|
|
||||||
|
static fields = {
|
||||||
|
id: attr(),
|
||||||
|
name: attr(),
|
||||||
|
url: attr(),
|
||||||
|
accessToken: attr(),
|
||||||
|
events: attr(),
|
||||||
|
excludedEvents: attr(),
|
||||||
|
boardId: fk({
|
||||||
|
to: 'Board',
|
||||||
|
as: 'board',
|
||||||
|
relatedName: 'webhooks',
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
|
||||||
|
static reducer({ type, payload }, Webhook) {
|
||||||
|
switch (type) {
|
||||||
|
case ActionTypes.SOCKET_RECONNECT_HANDLE:
|
||||||
|
Webhook.all().delete();
|
||||||
|
|
||||||
|
payload.webhooks.forEach((webhook) => {
|
||||||
|
Webhook.upsert(webhook);
|
||||||
|
});
|
||||||
|
|
||||||
|
break;
|
||||||
|
case ActionTypes.CORE_INITIALIZE:
|
||||||
|
case ActionTypes.USER_UPDATE_HANDLE:
|
||||||
|
if (payload.webhooks) {
|
||||||
|
payload.webhooks.forEach((webhook) => {
|
||||||
|
Webhook.upsert(webhook);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case ActionTypes.WEBHOOK_CREATE:
|
||||||
|
case ActionTypes.WEBHOOK_CREATE_HANDLE:
|
||||||
|
case ActionTypes.WEBHOOK_UPDATE__SUCCESS:
|
||||||
|
case ActionTypes.WEBHOOK_UPDATE_HANDLE:
|
||||||
|
Webhook.upsert(payload.webhook);
|
||||||
|
|
||||||
|
break;
|
||||||
|
case ActionTypes.WEBHOOK_CREATE__SUCCESS:
|
||||||
|
Webhook.withId(payload.localId).delete();
|
||||||
|
Webhook.upsert(payload.webhook);
|
||||||
|
|
||||||
|
break;
|
||||||
|
case ActionTypes.WEBHOOK_CREATE__FAILURE:
|
||||||
|
Webhook.withId(payload.localId).delete();
|
||||||
|
|
||||||
|
break;
|
||||||
|
case ActionTypes.WEBHOOK_UPDATE:
|
||||||
|
Webhook.withId(payload.id).update(payload.data);
|
||||||
|
|
||||||
|
break;
|
||||||
|
case ActionTypes.WEBHOOK_DELETE:
|
||||||
|
Webhook.withId(payload.id).delete();
|
||||||
|
|
||||||
|
break;
|
||||||
|
case ActionTypes.WEBHOOK_DELETE__SUCCESS:
|
||||||
|
case ActionTypes.WEBHOOK_DELETE_HANDLE: {
|
||||||
|
const webhookModel = Webhook.withId(payload.webhook.id);
|
||||||
|
|
||||||
|
if (webhookModel) {
|
||||||
|
webhookModel.delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static getAllQuerySet() {
|
||||||
|
return this.orderBy(['id.length', 'id']);
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,6 +3,7 @@
|
||||||
* Licensed under the Fair Use License: https://github.com/plankanban/planka/blob/master/LICENSE.md
|
* Licensed under the Fair Use License: https://github.com/plankanban/planka/blob/master/LICENSE.md
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import Webhook from './Webhook';
|
||||||
import User from './User';
|
import User from './User';
|
||||||
import Project from './Project';
|
import Project from './Project';
|
||||||
import ProjectManager from './ProjectManager';
|
import ProjectManager from './ProjectManager';
|
||||||
|
@ -25,6 +26,7 @@ import Notification from './Notification';
|
||||||
import NotificationService from './NotificationService';
|
import NotificationService from './NotificationService';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
|
Webhook,
|
||||||
User,
|
User,
|
||||||
Project,
|
Project,
|
||||||
ProjectManager,
|
ProjectManager,
|
||||||
|
|
|
@ -26,6 +26,7 @@ import {
|
||||||
Task,
|
Task,
|
||||||
TaskList,
|
TaskList,
|
||||||
User,
|
User,
|
||||||
|
Webhook,
|
||||||
} from './models';
|
} from './models';
|
||||||
|
|
||||||
const orm = new ORM({
|
const orm = new ORM({
|
||||||
|
@ -33,6 +34,7 @@ const orm = new ORM({
|
||||||
});
|
});
|
||||||
|
|
||||||
orm.register(
|
orm.register(
|
||||||
|
Webhook,
|
||||||
User,
|
User,
|
||||||
Project,
|
Project,
|
||||||
ProjectManager,
|
ProjectManager,
|
||||||
|
|
|
@ -10,6 +10,7 @@ import request from '../request';
|
||||||
import api from '../../../api';
|
import api from '../../../api';
|
||||||
import mergeRecords from '../../../utils/merge-records';
|
import mergeRecords from '../../../utils/merge-records';
|
||||||
import { isUserAdminOrProjectOwner } from '../../../utils/record-helpers';
|
import { isUserAdminOrProjectOwner } from '../../../utils/record-helpers';
|
||||||
|
import { UserRoles } from '../../../constants/Enums';
|
||||||
|
|
||||||
export function* fetchCore() {
|
export function* fetchCore() {
|
||||||
const {
|
const {
|
||||||
|
@ -17,6 +18,11 @@ export function* fetchCore() {
|
||||||
included: { notificationServices: notificationServices1 },
|
included: { notificationServices: notificationServices1 },
|
||||||
} = yield call(request, api.getCurrentUser, true);
|
} = yield call(request, api.getCurrentUser, true);
|
||||||
|
|
||||||
|
let webhooks;
|
||||||
|
if (user.role === UserRoles.ADMIN) {
|
||||||
|
({ items: webhooks } = yield call(request, api.getWebhooks));
|
||||||
|
}
|
||||||
|
|
||||||
let users1;
|
let users1;
|
||||||
if (isUserAdminOrProjectOwner(user)) {
|
if (isUserAdminOrProjectOwner(user)) {
|
||||||
({ items: users1 } = yield call(request, api.getUsers));
|
({ items: users1 } = yield call(request, api.getUsers));
|
||||||
|
@ -101,6 +107,7 @@ export function* fetchCore() {
|
||||||
return {
|
return {
|
||||||
user,
|
user,
|
||||||
board,
|
board,
|
||||||
|
webhooks,
|
||||||
projectManagers,
|
projectManagers,
|
||||||
backgroundImages,
|
backgroundImages,
|
||||||
baseCustomFieldGroups,
|
baseCustomFieldGroups,
|
||||||
|
|
|
@ -21,6 +21,7 @@ export function* initializeCore() {
|
||||||
const {
|
const {
|
||||||
user,
|
user,
|
||||||
board,
|
board,
|
||||||
|
webhooks,
|
||||||
users,
|
users,
|
||||||
projects,
|
projects,
|
||||||
projectManagers,
|
projectManagers,
|
||||||
|
@ -50,6 +51,7 @@ export function* initializeCore() {
|
||||||
actions.initializeCore(
|
actions.initializeCore(
|
||||||
user,
|
user,
|
||||||
board,
|
board,
|
||||||
|
webhooks,
|
||||||
users,
|
users,
|
||||||
projects,
|
projects,
|
||||||
projectManagers,
|
projectManagers,
|
||||||
|
|
|
@ -7,6 +7,7 @@ import router from './router';
|
||||||
import socket from './socket';
|
import socket from './socket';
|
||||||
import core from './core';
|
import core from './core';
|
||||||
import modals from './modals';
|
import modals from './modals';
|
||||||
|
import webhooks from './webhooks';
|
||||||
import users from './users';
|
import users from './users';
|
||||||
import projects from './projects';
|
import projects from './projects';
|
||||||
import projectManagers from './project-managers';
|
import projectManagers from './project-managers';
|
||||||
|
@ -33,6 +34,7 @@ export default {
|
||||||
...socket,
|
...socket,
|
||||||
...core,
|
...core,
|
||||||
...modals,
|
...modals,
|
||||||
|
...webhooks,
|
||||||
...users,
|
...users,
|
||||||
...projects,
|
...projects,
|
||||||
...projectManagers,
|
...projectManagers,
|
||||||
|
|
|
@ -24,6 +24,7 @@ export function* handleSocketReconnect() {
|
||||||
let config;
|
let config;
|
||||||
let user;
|
let user;
|
||||||
let board;
|
let board;
|
||||||
|
let webhooks;
|
||||||
let users;
|
let users;
|
||||||
let projects;
|
let projects;
|
||||||
let projectManagers;
|
let projectManagers;
|
||||||
|
@ -51,6 +52,7 @@ export function* handleSocketReconnect() {
|
||||||
({
|
({
|
||||||
user,
|
user,
|
||||||
board,
|
board,
|
||||||
|
webhooks,
|
||||||
users,
|
users,
|
||||||
projects,
|
projects,
|
||||||
projectManagers,
|
projectManagers,
|
||||||
|
@ -81,6 +83,7 @@ export function* handleSocketReconnect() {
|
||||||
config,
|
config,
|
||||||
user,
|
user,
|
||||||
board,
|
board,
|
||||||
|
webhooks,
|
||||||
users,
|
users,
|
||||||
projects,
|
projects,
|
||||||
projectManagers,
|
projectManagers,
|
||||||
|
|
|
@ -70,6 +70,7 @@ export function* handleUserUpdate(user) {
|
||||||
|
|
||||||
let config;
|
let config;
|
||||||
let board;
|
let board;
|
||||||
|
let webhooks;
|
||||||
let users1;
|
let users1;
|
||||||
let users2;
|
let users2;
|
||||||
let users3;
|
let users3;
|
||||||
|
@ -102,6 +103,7 @@ export function* handleUserUpdate(user) {
|
||||||
|
|
||||||
if (user.role === UserRoles.ADMIN) {
|
if (user.role === UserRoles.ADMIN) {
|
||||||
({ item: config } = yield call(request, api.getConfig));
|
({ item: config } = yield call(request, api.getConfig));
|
||||||
|
({ items: webhooks } = yield call(request, api.getWebhooks));
|
||||||
|
|
||||||
({
|
({
|
||||||
items: projects,
|
items: projects,
|
||||||
|
@ -164,6 +166,7 @@ export function* handleUserUpdate(user) {
|
||||||
boardIds,
|
boardIds,
|
||||||
config,
|
config,
|
||||||
board,
|
board,
|
||||||
|
webhooks,
|
||||||
mergeRecords(users1, users2, users3),
|
mergeRecords(users1, users2, users3),
|
||||||
projects,
|
projects,
|
||||||
projectManagers,
|
projectManagers,
|
||||||
|
|
89
client/src/sagas/core/services/webhooks.js
Normal file
89
client/src/sagas/core/services/webhooks.js
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
/*!
|
||||||
|
* Copyright (c) 2024 PLANKA Software GmbH
|
||||||
|
* Licensed under the Fair Use License: https://github.com/plankanban/planka/blob/master/LICENSE.md
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { call, put } from 'redux-saga/effects';
|
||||||
|
|
||||||
|
import request from '../request';
|
||||||
|
import actions from '../../../actions';
|
||||||
|
import api from '../../../api';
|
||||||
|
import { createLocalId } from '../../../utils/local-id';
|
||||||
|
|
||||||
|
export function* createWebhook(data) {
|
||||||
|
const localId = yield call(createLocalId);
|
||||||
|
|
||||||
|
yield put(
|
||||||
|
actions.createWebhook({
|
||||||
|
...data,
|
||||||
|
id: localId,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
let webhook;
|
||||||
|
try {
|
||||||
|
({ item: webhook } = yield call(request, api.createWebhook, {
|
||||||
|
...data,
|
||||||
|
events: data.events && data.events.join(','),
|
||||||
|
excludedEvents: data.excludedEvents && data.excludedEvents.join(','),
|
||||||
|
}));
|
||||||
|
} catch (error) {
|
||||||
|
yield put(actions.createWebhook.failure(localId, error));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
yield put(actions.createWebhook.success(localId, webhook));
|
||||||
|
}
|
||||||
|
|
||||||
|
export function* handleWebhookCreate(webhook) {
|
||||||
|
yield put(actions.handleWebhookCreate(webhook));
|
||||||
|
}
|
||||||
|
|
||||||
|
export function* updateWebhook(id, data) {
|
||||||
|
yield put(actions.updateWebhook(id, data));
|
||||||
|
|
||||||
|
let webhook;
|
||||||
|
try {
|
||||||
|
({ item: webhook } = yield call(request, api.updateWebhook, id, {
|
||||||
|
...data,
|
||||||
|
events: data.events && data.events.join(','),
|
||||||
|
excludedEvents: data.excludedEvents && data.excludedEvents.join(','),
|
||||||
|
}));
|
||||||
|
} catch (error) {
|
||||||
|
yield put(actions.updateWebhook.failure(id, error));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
yield put(actions.updateWebhook.success(webhook));
|
||||||
|
}
|
||||||
|
|
||||||
|
export function* handleWebhookUpdate(webhook) {
|
||||||
|
yield put(actions.handleWebhookUpdate(webhook));
|
||||||
|
}
|
||||||
|
|
||||||
|
export function* deleteWebhook(id) {
|
||||||
|
yield put(actions.deleteWebhook(id));
|
||||||
|
|
||||||
|
let webhook;
|
||||||
|
try {
|
||||||
|
({ item: webhook } = yield call(request, api.deleteWebhook, id));
|
||||||
|
} catch (error) {
|
||||||
|
yield put(actions.deleteWebhook.failure(id, error));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
yield put(actions.deleteWebhook.success(webhook));
|
||||||
|
}
|
||||||
|
|
||||||
|
export function* handleWebhookDelete(webhook) {
|
||||||
|
yield put(actions.handleWebhookDelete(webhook));
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
createWebhook,
|
||||||
|
handleWebhookCreate,
|
||||||
|
updateWebhook,
|
||||||
|
handleWebhookUpdate,
|
||||||
|
deleteWebhook,
|
||||||
|
handleWebhookDelete,
|
||||||
|
};
|
|
@ -7,6 +7,7 @@ import router from './router';
|
||||||
import socket from './socket';
|
import socket from './socket';
|
||||||
import core from './core';
|
import core from './core';
|
||||||
import modals from './modals';
|
import modals from './modals';
|
||||||
|
import webhooks from './webhooks';
|
||||||
import users from './users';
|
import users from './users';
|
||||||
import projects from './projects';
|
import projects from './projects';
|
||||||
import projectManagers from './project-managers';
|
import projectManagers from './project-managers';
|
||||||
|
@ -33,6 +34,7 @@ export default [
|
||||||
socket,
|
socket,
|
||||||
core,
|
core,
|
||||||
modals,
|
modals,
|
||||||
|
webhooks,
|
||||||
users,
|
users,
|
||||||
projects,
|
projects,
|
||||||
projectManagers,
|
projectManagers,
|
||||||
|
|
30
client/src/sagas/core/watchers/webhooks.js
Normal file
30
client/src/sagas/core/watchers/webhooks.js
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
/*!
|
||||||
|
* Copyright (c) 2024 PLANKA Software GmbH
|
||||||
|
* Licensed under the Fair Use License: https://github.com/plankanban/planka/blob/master/LICENSE.md
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { all, takeEvery } from 'redux-saga/effects';
|
||||||
|
|
||||||
|
import services from '../services';
|
||||||
|
import EntryActionTypes from '../../../constants/EntryActionTypes';
|
||||||
|
|
||||||
|
export default function* webhooksWatchers() {
|
||||||
|
yield all([
|
||||||
|
takeEvery(EntryActionTypes.WEBHOOK_CREATE, ({ payload: { data } }) =>
|
||||||
|
services.createWebhook(data),
|
||||||
|
),
|
||||||
|
takeEvery(EntryActionTypes.WEBHOOK_CREATE_HANDLE, ({ payload: { webhook } }) =>
|
||||||
|
services.handleWebhookCreate(webhook),
|
||||||
|
),
|
||||||
|
takeEvery(EntryActionTypes.WEBHOOK_UPDATE, ({ payload: { id, data } }) =>
|
||||||
|
services.updateWebhook(id, data),
|
||||||
|
),
|
||||||
|
takeEvery(EntryActionTypes.WEBHOOK_UPDATE_HANDLE, ({ payload: { webhook } }) =>
|
||||||
|
services.handleWebhookUpdate(webhook),
|
||||||
|
),
|
||||||
|
takeEvery(EntryActionTypes.WEBHOOK_DELETE, ({ payload: { id } }) => services.deleteWebhook(id)),
|
||||||
|
takeEvery(EntryActionTypes.WEBHOOK_DELETE_HANDLE, ({ payload: { webhook } }) =>
|
||||||
|
services.handleWebhookDelete(webhook),
|
||||||
|
),
|
||||||
|
]);
|
||||||
|
}
|
|
@ -8,6 +8,7 @@ import common from './common';
|
||||||
import core from './core';
|
import core from './core';
|
||||||
import modals from './modals';
|
import modals from './modals';
|
||||||
import positioning from './positioning';
|
import positioning from './positioning';
|
||||||
|
import webhooks from './webhooks';
|
||||||
import users from './users';
|
import users from './users';
|
||||||
import projects from './projects';
|
import projects from './projects';
|
||||||
import projectManagers from './project-managers';
|
import projectManagers from './project-managers';
|
||||||
|
@ -35,6 +36,7 @@ export default {
|
||||||
...core,
|
...core,
|
||||||
...modals,
|
...modals,
|
||||||
...positioning,
|
...positioning,
|
||||||
|
...webhooks,
|
||||||
...users,
|
...users,
|
||||||
...projects,
|
...projects,
|
||||||
...projectManagers,
|
...projectManagers,
|
||||||
|
|
41
client/src/selectors/webhooks.js
Normal file
41
client/src/selectors/webhooks.js
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
/*!
|
||||||
|
* Copyright (c) 2024 PLANKA Software GmbH
|
||||||
|
* Licensed under the Fair Use License: https://github.com/plankanban/planka/blob/master/LICENSE.md
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { createSelector } from 'redux-orm';
|
||||||
|
|
||||||
|
import orm from '../orm';
|
||||||
|
import { isLocalId } from '../utils/local-id';
|
||||||
|
|
||||||
|
export const makeSelectWebhookById = () =>
|
||||||
|
createSelector(
|
||||||
|
orm,
|
||||||
|
(_, id) => id,
|
||||||
|
({ Webhook }, id) => {
|
||||||
|
const webhookModel = Webhook.withId(id);
|
||||||
|
|
||||||
|
if (!webhookModel) {
|
||||||
|
return webhookModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
...webhookModel.ref,
|
||||||
|
isPersisted: !isLocalId(webhookModel.id),
|
||||||
|
};
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
export const selectWebhookById = makeSelectWebhookById();
|
||||||
|
|
||||||
|
export const selectWebhookIds = createSelector(orm, ({ Webhook }) =>
|
||||||
|
Webhook.getAllQuerySet()
|
||||||
|
.toRefArray()
|
||||||
|
.map((webhook) => webhook.id),
|
||||||
|
);
|
||||||
|
|
||||||
|
export default {
|
||||||
|
makeSelectWebhookById,
|
||||||
|
selectWebhookById,
|
||||||
|
selectWebhookIds,
|
||||||
|
};
|
|
@ -80,15 +80,6 @@ services:
|
||||||
# - SMTP_PASSWORD=
|
# - SMTP_PASSWORD=
|
||||||
# - SMTP_FROM="Demo Demo" <demo@demo.demo>
|
# - SMTP_FROM="Demo Demo" <demo@demo.demo>
|
||||||
# - SMTP_TLS_REJECT_UNAUTHORIZED=false
|
# - SMTP_TLS_REJECT_UNAUTHORIZED=false
|
||||||
|
|
||||||
# Optional fields: accessToken, events, excludedEvents
|
|
||||||
# - |
|
|
||||||
# WEBHOOKS=[{
|
|
||||||
# "url": "http://localhost:3001",
|
|
||||||
# "accessToken": "notaccesstoken",
|
|
||||||
# "events": ["cardCreate", "cardUpdate", "cardDelete"],
|
|
||||||
# "excludedEvents": ["notificationCreate", "notificationUpdate"]
|
|
||||||
# }]
|
|
||||||
depends_on:
|
depends_on:
|
||||||
postgres:
|
postgres:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
|
|
|
@ -100,15 +100,6 @@ services:
|
||||||
# - SMTP_PASSWORD__FILE=/run/secrets/smtp_password
|
# - SMTP_PASSWORD__FILE=/run/secrets/smtp_password
|
||||||
# - SMTP_FROM="Demo Demo" <demo@demo.demo>
|
# - SMTP_FROM="Demo Demo" <demo@demo.demo>
|
||||||
# - SMTP_TLS_REJECT_UNAUTHORIZED=false
|
# - SMTP_TLS_REJECT_UNAUTHORIZED=false
|
||||||
|
|
||||||
# Optional fields: accessToken, events, excludedEvents
|
|
||||||
# - |
|
|
||||||
# WEBHOOKS=[{
|
|
||||||
# "url": "http://localhost:3001",
|
|
||||||
# "accessToken": "notaccesstoken",
|
|
||||||
# "events": ["cardCreate", "cardUpdate", "cardDelete"],
|
|
||||||
# "excludedEvents": ["notificationCreate", "notificationUpdate"]
|
|
||||||
# }]
|
|
||||||
depends_on:
|
depends_on:
|
||||||
postgres:
|
postgres:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
|
|
|
@ -72,14 +72,6 @@ SECRET_KEY=notsecretkey
|
||||||
# SMTP_FROM="Demo Demo" <demo@demo.demo>
|
# SMTP_FROM="Demo Demo" <demo@demo.demo>
|
||||||
# SMTP_TLS_REJECT_UNAUTHORIZED=false
|
# SMTP_TLS_REJECT_UNAUTHORIZED=false
|
||||||
|
|
||||||
# Optional fields: accessToken, events, excludedEvents
|
|
||||||
# WEBHOOKS='[{
|
|
||||||
# "url": "http://localhost:3001",
|
|
||||||
# "accessToken": "notaccesstoken",
|
|
||||||
# "events": ["cardCreate", "cardUpdate", "cardDelete"],
|
|
||||||
# "excludedEvents": ["notificationCreate", "notificationUpdate"]
|
|
||||||
# }]'
|
|
||||||
|
|
||||||
## Do not edit this
|
## Do not edit this
|
||||||
|
|
||||||
TZ=UTC
|
TZ=UTC
|
||||||
|
|
76
server/api/controllers/webhooks/create.js
Normal file
76
server/api/controllers/webhooks/create.js
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
/*!
|
||||||
|
* Copyright (c) 2024 PLANKA Software GmbH
|
||||||
|
* Licensed under the Fair Use License: https://github.com/plankanban/planka/blob/master/LICENSE.md
|
||||||
|
*/
|
||||||
|
|
||||||
|
const { isUrl } = require('../../../utils/validators');
|
||||||
|
|
||||||
|
const Errors = {
|
||||||
|
LIMIT_REACHED: {
|
||||||
|
limitReached: 'Limit reached',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
inputs: {
|
||||||
|
name: {
|
||||||
|
type: 'string',
|
||||||
|
maxLength: 128,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
url: {
|
||||||
|
type: 'string',
|
||||||
|
maxLength: 2048,
|
||||||
|
custom: isUrl,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
accessToken: {
|
||||||
|
type: 'string',
|
||||||
|
isNotEmptyString: true,
|
||||||
|
maxLength: 512,
|
||||||
|
allowNull: true,
|
||||||
|
},
|
||||||
|
events: {
|
||||||
|
type: 'string',
|
||||||
|
isNotEmptyString: true,
|
||||||
|
maxLength: 2048,
|
||||||
|
allowNull: true,
|
||||||
|
},
|
||||||
|
excludedEvents: {
|
||||||
|
type: 'string',
|
||||||
|
isNotEmptyString: true,
|
||||||
|
maxLength: 2048,
|
||||||
|
allowNull: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
exits: {
|
||||||
|
limitReached: {
|
||||||
|
responseType: 'conflict',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
async fn(inputs) {
|
||||||
|
const { currentUser } = this.req;
|
||||||
|
|
||||||
|
const values = _.pick(inputs, ['name', 'url', 'accessToken']);
|
||||||
|
const events = inputs.events && inputs.events.split(',');
|
||||||
|
const excludedEvents = inputs.excludedEvents && inputs.excludedEvents.split(',');
|
||||||
|
|
||||||
|
const webhook = await sails.helpers.webhooks.createOne
|
||||||
|
.with({
|
||||||
|
values: {
|
||||||
|
...values,
|
||||||
|
events,
|
||||||
|
excludedEvents,
|
||||||
|
},
|
||||||
|
actorUser: currentUser,
|
||||||
|
request: this.req,
|
||||||
|
})
|
||||||
|
.intercept('limitReached', () => Errors.LIMIT_REACHED);
|
||||||
|
|
||||||
|
return {
|
||||||
|
item: webhook,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
};
|
51
server/api/controllers/webhooks/delete.js
Normal file
51
server/api/controllers/webhooks/delete.js
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
/*!
|
||||||
|
* Copyright (c) 2024 PLANKA Software GmbH
|
||||||
|
* Licensed under the Fair Use License: https://github.com/plankanban/planka/blob/master/LICENSE.md
|
||||||
|
*/
|
||||||
|
|
||||||
|
const { idInput } = require('../../../utils/inputs');
|
||||||
|
|
||||||
|
const Errors = {
|
||||||
|
WEBHOOK_NOT_FOUND: {
|
||||||
|
webhookNotFound: 'Webhook not found',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
inputs: {
|
||||||
|
id: {
|
||||||
|
...idInput,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
exits: {
|
||||||
|
webhookNotFound: {
|
||||||
|
responseType: 'notFound',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
async fn(inputs) {
|
||||||
|
const { currentUser } = this.req;
|
||||||
|
|
||||||
|
let webhook = await Webhook.qm.getOneById(inputs.id);
|
||||||
|
|
||||||
|
if (!webhook) {
|
||||||
|
throw Errors.WEBHOOK_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
webhook = await sails.helpers.webhooks.deleteOne.with({
|
||||||
|
record: webhook,
|
||||||
|
actorUser: currentUser,
|
||||||
|
request: this.req,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!webhook) {
|
||||||
|
throw Errors.WEBHOOK_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
item: webhook,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
};
|
14
server/api/controllers/webhooks/index.js
Normal file
14
server/api/controllers/webhooks/index.js
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
/*!
|
||||||
|
* Copyright (c) 2024 PLANKA Software GmbH
|
||||||
|
* Licensed under the Fair Use License: https://github.com/plankanban/planka/blob/master/LICENSE.md
|
||||||
|
*/
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
async fn() {
|
||||||
|
const webhooks = await Webhook.qm.getAll();
|
||||||
|
|
||||||
|
return {
|
||||||
|
items: webhooks,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
};
|
89
server/api/controllers/webhooks/update.js
Normal file
89
server/api/controllers/webhooks/update.js
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
/*!
|
||||||
|
* Copyright (c) 2024 PLANKA Software GmbH
|
||||||
|
* Licensed under the Fair Use License: https://github.com/plankanban/planka/blob/master/LICENSE.md
|
||||||
|
*/
|
||||||
|
|
||||||
|
const { isUrl } = require('../../../utils/validators');
|
||||||
|
const { idInput } = require('../../../utils/inputs');
|
||||||
|
|
||||||
|
const Errors = {
|
||||||
|
WEBHOOK_NOT_FOUND: {
|
||||||
|
webhookNotFound: 'Webhook not found',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
inputs: {
|
||||||
|
id: {
|
||||||
|
...idInput,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
name: {
|
||||||
|
type: 'string',
|
||||||
|
isNotEmptyString: true,
|
||||||
|
maxLength: 128,
|
||||||
|
},
|
||||||
|
url: {
|
||||||
|
type: 'string',
|
||||||
|
maxLength: 2048,
|
||||||
|
custom: isUrl,
|
||||||
|
},
|
||||||
|
accessToken: {
|
||||||
|
type: 'string',
|
||||||
|
isNotEmptyString: true,
|
||||||
|
maxLength: 512,
|
||||||
|
allowNull: true,
|
||||||
|
},
|
||||||
|
events: {
|
||||||
|
type: 'string',
|
||||||
|
isNotEmptyString: true,
|
||||||
|
maxLength: 2048,
|
||||||
|
allowNull: true,
|
||||||
|
},
|
||||||
|
excludedEvents: {
|
||||||
|
type: 'string',
|
||||||
|
isNotEmptyString: true,
|
||||||
|
maxLength: 2048,
|
||||||
|
allowNull: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
exits: {
|
||||||
|
webhookNotFound: {
|
||||||
|
responseType: 'notFound',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
async fn(inputs) {
|
||||||
|
const { currentUser } = this.req;
|
||||||
|
|
||||||
|
let webhook = await Webhook.qm.getOneById(inputs.id);
|
||||||
|
|
||||||
|
if (!webhook) {
|
||||||
|
throw Errors.WEBHOOK_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
const values = _.pick(inputs, ['name', 'url', 'accessToken']);
|
||||||
|
const events = inputs.events && inputs.events.split(',');
|
||||||
|
const excludedEvents = inputs.excludedEvents && inputs.excludedEvents.split(',');
|
||||||
|
|
||||||
|
webhook = await sails.helpers.webhooks.updateOne.with({
|
||||||
|
record: webhook,
|
||||||
|
values: {
|
||||||
|
...values,
|
||||||
|
events,
|
||||||
|
excludedEvents,
|
||||||
|
},
|
||||||
|
actorUser: currentUser,
|
||||||
|
request: this.req,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!webhook) {
|
||||||
|
throw Errors.WEBHOOK_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
item: webhook,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
};
|
|
@ -105,6 +105,10 @@ module.exports = {
|
||||||
type: 'ref',
|
type: 'ref',
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
|
webhooks: {
|
||||||
|
type: 'ref',
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
request: {
|
request: {
|
||||||
type: 'ref',
|
type: 'ref',
|
||||||
},
|
},
|
||||||
|
@ -130,7 +134,8 @@ module.exports = {
|
||||||
);
|
);
|
||||||
|
|
||||||
sails.helpers.utils.sendWebhooks.with({
|
sails.helpers.utils.sendWebhooks.with({
|
||||||
event: 'actionCreate',
|
webhooks: inputs.webhooks,
|
||||||
|
event: Webhook.Events.ACTION_CREATE,
|
||||||
buildData: () => ({
|
buildData: () => ({
|
||||||
item: action,
|
item: action,
|
||||||
included: {
|
included: {
|
||||||
|
@ -158,6 +163,7 @@ module.exports = {
|
||||||
project: inputs.project,
|
project: inputs.project,
|
||||||
board: inputs.board,
|
board: inputs.board,
|
||||||
list: inputs.list,
|
list: inputs.list,
|
||||||
|
webhooks: inputs.webhooks,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -187,6 +193,7 @@ module.exports = {
|
||||||
project: inputs.project,
|
project: inputs.project,
|
||||||
board: inputs.board,
|
board: inputs.board,
|
||||||
list: inputs.list,
|
list: inputs.list,
|
||||||
|
webhooks: inputs.webhooks,
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
|
@ -48,8 +48,11 @@ module.exports = {
|
||||||
inputs.request,
|
inputs.request,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const webhooks = await Webhook.qm.getAll();
|
||||||
|
|
||||||
sails.helpers.utils.sendWebhooks.with({
|
sails.helpers.utils.sendWebhooks.with({
|
||||||
event: 'attachmentCreate',
|
webhooks,
|
||||||
|
event: Webhook.Events.ATTACHMENT_CREATE,
|
||||||
buildData: () => ({
|
buildData: () => ({
|
||||||
item: sails.helpers.attachments.presentOne(attachment),
|
item: sails.helpers.attachments.presentOne(attachment),
|
||||||
included: {
|
included: {
|
||||||
|
@ -65,6 +68,7 @@ module.exports = {
|
||||||
if (!values.card.coverAttachmentId) {
|
if (!values.card.coverAttachmentId) {
|
||||||
if (attachment.type === Attachment.Types.FILE && attachment.data.image) {
|
if (attachment.type === Attachment.Types.FILE && attachment.data.image) {
|
||||||
await sails.helpers.cards.updateOne.with({
|
await sails.helpers.cards.updateOne.with({
|
||||||
|
webhooks,
|
||||||
record: values.card,
|
record: values.card,
|
||||||
values: {
|
values: {
|
||||||
coverAttachmentId: attachment.id,
|
coverAttachmentId: attachment.id,
|
||||||
|
|
|
@ -37,6 +37,7 @@ module.exports = {
|
||||||
async fn(inputs) {
|
async fn(inputs) {
|
||||||
if (inputs.record.id === inputs.card.coverAttachmentId) {
|
if (inputs.record.id === inputs.card.coverAttachmentId) {
|
||||||
await sails.helpers.cards.updateOne.with({
|
await sails.helpers.cards.updateOne.with({
|
||||||
|
webhooks,
|
||||||
record: inputs.card,
|
record: inputs.card,
|
||||||
values: {
|
values: {
|
||||||
coverAttachmentId: null,
|
coverAttachmentId: null,
|
||||||
|
@ -66,8 +67,11 @@ module.exports = {
|
||||||
inputs.request,
|
inputs.request,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const webhooks = await Webhook.qm.getAll();
|
||||||
|
|
||||||
sails.helpers.utils.sendWebhooks.with({
|
sails.helpers.utils.sendWebhooks.with({
|
||||||
event: 'attachmentDelete',
|
webhooks,
|
||||||
|
event: Webhook.Events.ATTACHMENT_DELETE,
|
||||||
buildData: () => ({
|
buildData: () => ({
|
||||||
item: sails.helpers.attachments.presentOne(attachment),
|
item: sails.helpers.attachments.presentOne(attachment),
|
||||||
included: {
|
included: {
|
||||||
|
|
|
@ -53,8 +53,11 @@ module.exports = {
|
||||||
inputs.request,
|
inputs.request,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const webhooks = await Webhook.qm.getAll();
|
||||||
|
|
||||||
sails.helpers.utils.sendWebhooks.with({
|
sails.helpers.utils.sendWebhooks.with({
|
||||||
event: 'attachmentUpdate',
|
webhooks,
|
||||||
|
event: Webhook.Events.ATTACHMENT_UPDATE,
|
||||||
buildData: () => ({
|
buildData: () => ({
|
||||||
item: sails.helpers.attachments.presentOne(attachment),
|
item: sails.helpers.attachments.presentOne(attachment),
|
||||||
included: {
|
included: {
|
||||||
|
|
|
@ -47,8 +47,11 @@ module.exports = {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const webhooks = await Webhook.qm.getAll();
|
||||||
|
|
||||||
sails.helpers.utils.sendWebhooks.with({
|
sails.helpers.utils.sendWebhooks.with({
|
||||||
event: 'backgroundImageCreate',
|
webhooks,
|
||||||
|
event: Webhook.Events.BACKGROUND_IMAGE_CREATE,
|
||||||
buildData: () => ({
|
buildData: () => ({
|
||||||
item: sails.helpers.backgroundImages.presentOne(backgroundImage),
|
item: sails.helpers.backgroundImages.presentOne(backgroundImage),
|
||||||
included: {
|
included: {
|
||||||
|
@ -60,6 +63,7 @@ module.exports = {
|
||||||
|
|
||||||
await sails.helpers.projects.updateOne.with({
|
await sails.helpers.projects.updateOne.with({
|
||||||
scoper,
|
scoper,
|
||||||
|
webhooks,
|
||||||
record: values.project,
|
record: values.project,
|
||||||
values: {
|
values: {
|
||||||
backgroundImage,
|
backgroundImage,
|
||||||
|
|
|
@ -31,6 +31,7 @@ module.exports = {
|
||||||
if (inputs.record.id === inputs.project.backgroundImageId) {
|
if (inputs.record.id === inputs.project.backgroundImageId) {
|
||||||
await sails.helpers.projects.updateOne.with({
|
await sails.helpers.projects.updateOne.with({
|
||||||
scoper,
|
scoper,
|
||||||
|
webhooks,
|
||||||
record: inputs.project,
|
record: inputs.project,
|
||||||
values: {
|
values: {
|
||||||
backgroundType: null,
|
backgroundType: null,
|
||||||
|
@ -58,8 +59,11 @@ module.exports = {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const webhooks = await Webhook.qm.getAll();
|
||||||
|
|
||||||
sails.helpers.utils.sendWebhooks.with({
|
sails.helpers.utils.sendWebhooks.with({
|
||||||
event: 'backgroundImageDelete',
|
webhooks,
|
||||||
|
event: Webhook.Events.BACKGROUND_IMAGE_DELETE,
|
||||||
buildData: () => ({
|
buildData: () => ({
|
||||||
item: sails.helpers.backgroundImages.presentOne(backgroundImage),
|
item: sails.helpers.backgroundImages.presentOne(backgroundImage),
|
||||||
included: {
|
included: {
|
||||||
|
|
|
@ -43,8 +43,11 @@ module.exports = {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const webhooks = await Webhook.qm.getAll();
|
||||||
|
|
||||||
sails.helpers.utils.sendWebhooks.with({
|
sails.helpers.utils.sendWebhooks.with({
|
||||||
event: 'baseCustomFieldGroupCreate',
|
webhooks,
|
||||||
|
event: Webhook.Events.BASE_CUSTOM_FIELD_GROUP_CREATE,
|
||||||
buildData: () => ({
|
buildData: () => ({
|
||||||
item: baseCustomFieldGroup,
|
item: baseCustomFieldGroup,
|
||||||
included: {
|
included: {
|
||||||
|
|
|
@ -45,8 +45,11 @@ module.exports = {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const webhooks = await Webhook.qm.getAll();
|
||||||
|
|
||||||
sails.helpers.utils.sendWebhooks.with({
|
sails.helpers.utils.sendWebhooks.with({
|
||||||
event: 'baseCustomFieldGroupDelete',
|
webhooks,
|
||||||
|
event: Webhook.Events.BASE_CUSTOM_FIELD_GROUP_DELETE,
|
||||||
buildData: () => ({
|
buildData: () => ({
|
||||||
item: baseCustomFieldGroup,
|
item: baseCustomFieldGroup,
|
||||||
included: {
|
included: {
|
||||||
|
|
|
@ -49,8 +49,11 @@ module.exports = {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const webhooks = await Webhook.qm.getAll();
|
||||||
|
|
||||||
sails.helpers.utils.sendWebhooks.with({
|
sails.helpers.utils.sendWebhooks.with({
|
||||||
event: 'baseCustomFieldGroupUpdate',
|
webhooks,
|
||||||
|
event: Webhook.Events.BASE_CUSTOM_FIELD_GROUP_UPDATE,
|
||||||
buildData: () => ({
|
buildData: () => ({
|
||||||
item: baseCustomFieldGroup,
|
item: baseCustomFieldGroup,
|
||||||
included: {
|
included: {
|
||||||
|
|
|
@ -86,8 +86,11 @@ module.exports = {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const webhooks = await Webhook.qm.getAll();
|
||||||
|
|
||||||
sails.helpers.utils.sendWebhooks.with({
|
sails.helpers.utils.sendWebhooks.with({
|
||||||
event: 'boardMembershipCreate',
|
webhooks,
|
||||||
|
event: Webhook.Events.BOARD_MEMBERSHIP_CREATE,
|
||||||
buildData: () => ({
|
buildData: () => ({
|
||||||
item: boardMembership,
|
item: boardMembership,
|
||||||
included: {
|
included: {
|
||||||
|
|
|
@ -106,8 +106,11 @@ module.exports = {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const webhooks = await Webhook.qm.getAll();
|
||||||
|
|
||||||
sails.helpers.utils.sendWebhooks.with({
|
sails.helpers.utils.sendWebhooks.with({
|
||||||
event: 'boardMembershipDelete',
|
webhooks,
|
||||||
|
event: Webhook.Events.BOARD_MEMBERSHIP_DELETE,
|
||||||
buildData: () => ({
|
buildData: () => ({
|
||||||
item: boardMembership,
|
item: boardMembership,
|
||||||
included: {
|
included: {
|
||||||
|
|
|
@ -75,8 +75,11 @@ module.exports = {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const webhooks = await Webhook.qm.getAll();
|
||||||
|
|
||||||
sails.helpers.utils.sendWebhooks.with({
|
sails.helpers.utils.sendWebhooks.with({
|
||||||
event: 'boardMembershipUpdate',
|
webhooks,
|
||||||
|
event: Webhook.Events.BOARD_MEMBERSHIP_UPDATE,
|
||||||
buildData: () => ({
|
buildData: () => ({
|
||||||
item: boardMembership,
|
item: boardMembership,
|
||||||
included: {
|
included: {
|
||||||
|
|
|
@ -108,8 +108,11 @@ module.exports = {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const webhooks = await Webhook.qm.getAll();
|
||||||
|
|
||||||
sails.helpers.utils.sendWebhooks.with({
|
sails.helpers.utils.sendWebhooks.with({
|
||||||
event: 'boardCreate',
|
webhooks,
|
||||||
|
event: Webhook.Events.BOARD_CREATE,
|
||||||
buildData: () => ({
|
buildData: () => ({
|
||||||
item: board,
|
item: board,
|
||||||
included: {
|
included: {
|
||||||
|
|
|
@ -49,8 +49,11 @@ module.exports = {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const webhooks = await Webhook.qm.getAll();
|
||||||
|
|
||||||
sails.helpers.utils.sendWebhooks.with({
|
sails.helpers.utils.sendWebhooks.with({
|
||||||
event: 'boardDelete',
|
webhooks,
|
||||||
|
event: Webhook.Events.BOARD_DELETE,
|
||||||
buildData: () => ({
|
buildData: () => ({
|
||||||
item: board,
|
item: board,
|
||||||
included: {
|
included: {
|
||||||
|
|
|
@ -104,8 +104,11 @@ module.exports = {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const webhooks = await Webhook.qm.getAll();
|
||||||
|
|
||||||
sails.helpers.utils.sendWebhooks.with({
|
sails.helpers.utils.sendWebhooks.with({
|
||||||
event: 'boardUpdate',
|
webhooks,
|
||||||
|
event: Webhook.Events.BOARD_UPDATE,
|
||||||
buildData: () => ({
|
buildData: () => ({
|
||||||
item: board,
|
item: board,
|
||||||
included: {
|
included: {
|
||||||
|
|
|
@ -61,8 +61,11 @@ module.exports = {
|
||||||
inputs.request,
|
inputs.request,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const webhooks = await Webhook.qm.getAll();
|
||||||
|
|
||||||
sails.helpers.utils.sendWebhooks.with({
|
sails.helpers.utils.sendWebhooks.with({
|
||||||
event: 'cardLabelCreate',
|
webhooks,
|
||||||
|
event: Webhook.Events.CARD_LABEL_CREATE,
|
||||||
buildData: () => ({
|
buildData: () => ({
|
||||||
item: cardLabel,
|
item: cardLabel,
|
||||||
included: {
|
included: {
|
||||||
|
|
|
@ -47,8 +47,11 @@ module.exports = {
|
||||||
inputs.request,
|
inputs.request,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const webhooks = await Webhook.qm.getAll();
|
||||||
|
|
||||||
sails.helpers.utils.sendWebhooks.with({
|
sails.helpers.utils.sendWebhooks.with({
|
||||||
event: 'cardLabelDelete',
|
webhooks,
|
||||||
|
event: Webhook.Events.CARD_LABEL_DELETE,
|
||||||
buildData: () => ({
|
buildData: () => ({
|
||||||
item: cardLabel,
|
item: cardLabel,
|
||||||
included: {
|
included: {
|
||||||
|
|
|
@ -61,8 +61,11 @@ module.exports = {
|
||||||
inputs.request,
|
inputs.request,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const webhooks = await Webhook.qm.getAll();
|
||||||
|
|
||||||
sails.helpers.utils.sendWebhooks.with({
|
sails.helpers.utils.sendWebhooks.with({
|
||||||
event: 'cardMembershipCreate',
|
webhooks,
|
||||||
|
event: Webhook.Events.CARD_MEMBERSHIP_CREATE,
|
||||||
buildData: () => ({
|
buildData: () => ({
|
||||||
item: cardMembership,
|
item: cardMembership,
|
||||||
included: {
|
included: {
|
||||||
|
@ -106,6 +109,7 @@ module.exports = {
|
||||||
}
|
}
|
||||||
|
|
||||||
await sails.helpers.actions.createOne.with({
|
await sails.helpers.actions.createOne.with({
|
||||||
|
webhooks,
|
||||||
values: {
|
values: {
|
||||||
type: Action.Types.ADD_MEMBER_TO_CARD,
|
type: Action.Types.ADD_MEMBER_TO_CARD,
|
||||||
data: {
|
data: {
|
||||||
|
|
|
@ -51,8 +51,11 @@ module.exports = {
|
||||||
inputs.request,
|
inputs.request,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const webhooks = await Webhook.qm.getAll();
|
||||||
|
|
||||||
sails.helpers.utils.sendWebhooks.with({
|
sails.helpers.utils.sendWebhooks.with({
|
||||||
event: 'cardMembershipDelete',
|
webhooks,
|
||||||
|
event: Webhook.Events.CARD_MEMBERSHIP_DELETE,
|
||||||
buildData: () => ({
|
buildData: () => ({
|
||||||
item: cardMembership,
|
item: cardMembership,
|
||||||
included: {
|
included: {
|
||||||
|
@ -82,6 +85,7 @@ module.exports = {
|
||||||
}
|
}
|
||||||
|
|
||||||
await sails.helpers.actions.createOne.with({
|
await sails.helpers.actions.createOne.with({
|
||||||
|
webhooks,
|
||||||
values: {
|
values: {
|
||||||
type: Action.Types.REMOVE_MEMBER_FROM_CARD,
|
type: Action.Types.REMOVE_MEMBER_FROM_CARD,
|
||||||
data: {
|
data: {
|
||||||
|
|
|
@ -84,8 +84,11 @@ module.exports = {
|
||||||
inputs.request,
|
inputs.request,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const webhooks = await Webhook.qm.getAll();
|
||||||
|
|
||||||
sails.helpers.utils.sendWebhooks.with({
|
sails.helpers.utils.sendWebhooks.with({
|
||||||
event: 'cardCreate',
|
webhooks,
|
||||||
|
event: Webhook.Events.CARD_CREATE,
|
||||||
buildData: () => ({
|
buildData: () => ({
|
||||||
item: card,
|
item: card,
|
||||||
included: {
|
included: {
|
||||||
|
@ -120,6 +123,7 @@ module.exports = {
|
||||||
}
|
}
|
||||||
|
|
||||||
await sails.helpers.actions.createOne.with({
|
await sails.helpers.actions.createOne.with({
|
||||||
|
webhooks,
|
||||||
values: {
|
values: {
|
||||||
card,
|
card,
|
||||||
type: Action.Types.CREATE_CARD,
|
type: Action.Types.CREATE_CARD,
|
||||||
|
|
|
@ -45,8 +45,11 @@ module.exports = {
|
||||||
inputs.request,
|
inputs.request,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const webhooks = await Webhook.qm.getAll();
|
||||||
|
|
||||||
sails.helpers.utils.sendWebhooks.with({
|
sails.helpers.utils.sendWebhooks.with({
|
||||||
event: 'cardDelete',
|
webhooks,
|
||||||
|
event: Webhook.Events.CARD_DELETE,
|
||||||
buildData: () => ({
|
buildData: () => ({
|
||||||
item: card,
|
item: card,
|
||||||
included: {
|
included: {
|
||||||
|
|
|
@ -228,8 +228,11 @@ module.exports = {
|
||||||
inputs.request,
|
inputs.request,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const webhooks = await Webhook.qm.getAll();
|
||||||
|
|
||||||
sails.helpers.utils.sendWebhooks.with({
|
sails.helpers.utils.sendWebhooks.with({
|
||||||
event: 'cardCreate',
|
webhooks,
|
||||||
|
event: Webhook.Events.CARD_CREATE,
|
||||||
buildData: () => ({
|
buildData: () => ({
|
||||||
item: card,
|
item: card,
|
||||||
included: {
|
included: {
|
||||||
|
@ -272,6 +275,7 @@ module.exports = {
|
||||||
}
|
}
|
||||||
|
|
||||||
await sails.helpers.actions.createOne.with({
|
await sails.helpers.actions.createOne.with({
|
||||||
|
webhooks,
|
||||||
values: {
|
values: {
|
||||||
card,
|
card,
|
||||||
type: Action.Types.CREATE_CARD, // TODO: introduce separate type?
|
type: Action.Types.CREATE_CARD, // TODO: introduce separate type?
|
||||||
|
|
|
@ -31,6 +31,8 @@ module.exports = {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const webhooks = await Webhook.qm.getAll();
|
||||||
|
|
||||||
notifications.forEach((notification) => {
|
notifications.forEach((notification) => {
|
||||||
sails.sockets.broadcast(
|
sails.sockets.broadcast(
|
||||||
`user:${notification.userId}`,
|
`user:${notification.userId}`,
|
||||||
|
@ -43,7 +45,8 @@ module.exports = {
|
||||||
|
|
||||||
// TODO: with prevData?
|
// TODO: with prevData?
|
||||||
sails.helpers.utils.sendWebhooks.with({
|
sails.helpers.utils.sendWebhooks.with({
|
||||||
event: 'notificationUpdate',
|
webhooks,
|
||||||
|
event: Webhook.Events.NOTIFICATION_UPDATE,
|
||||||
buildData: () => ({
|
buildData: () => ({
|
||||||
item: notification,
|
item: notification,
|
||||||
}),
|
}),
|
||||||
|
|
|
@ -31,6 +31,9 @@ module.exports = {
|
||||||
type: 'ref',
|
type: 'ref',
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
|
webhooks: {
|
||||||
|
type: 'ref',
|
||||||
|
},
|
||||||
request: {
|
request: {
|
||||||
type: 'ref',
|
type: 'ref',
|
||||||
},
|
},
|
||||||
|
@ -104,6 +107,8 @@ module.exports = {
|
||||||
if (_.isEmpty(values)) {
|
if (_.isEmpty(values)) {
|
||||||
card = inputs.record;
|
card = inputs.record;
|
||||||
} else {
|
} else {
|
||||||
|
const { webhooks = await Webhook.qm.getAll() } = inputs;
|
||||||
|
|
||||||
if (!_.isNil(values.position)) {
|
if (!_.isNil(values.position)) {
|
||||||
const cards = await Card.qm.getByListId(list.id, {
|
const cards = await Card.qm.getByListId(list.id, {
|
||||||
exceptIdOrIds: inputs.record.id,
|
exceptIdOrIds: inputs.record.id,
|
||||||
|
@ -402,6 +407,7 @@ module.exports = {
|
||||||
|
|
||||||
const { id } = await sails.helpers.labels.createOne.with({
|
const { id } = await sails.helpers.labels.createOne.with({
|
||||||
project,
|
project,
|
||||||
|
webhooks,
|
||||||
values: {
|
values: {
|
||||||
..._.omit(label, ['id', 'boardId', 'createdAt', 'updatedAt']),
|
..._.omit(label, ['id', 'boardId', 'createdAt', 'updatedAt']),
|
||||||
board,
|
board,
|
||||||
|
@ -459,6 +465,7 @@ module.exports = {
|
||||||
|
|
||||||
if (values.list) {
|
if (values.list) {
|
||||||
await sails.helpers.actions.createOne.with({
|
await sails.helpers.actions.createOne.with({
|
||||||
|
webhooks,
|
||||||
values: {
|
values: {
|
||||||
card,
|
card,
|
||||||
type: Action.Types.MOVE_CARD,
|
type: Action.Types.MOVE_CARD,
|
||||||
|
@ -477,7 +484,8 @@ module.exports = {
|
||||||
}
|
}
|
||||||
|
|
||||||
sails.helpers.utils.sendWebhooks.with({
|
sails.helpers.utils.sendWebhooks.with({
|
||||||
event: 'cardUpdate',
|
webhooks,
|
||||||
|
event: Webhook.Events.CARD_UPDATE,
|
||||||
buildData: () => ({
|
buildData: () => ({
|
||||||
item: card,
|
item: card,
|
||||||
included: {
|
included: {
|
||||||
|
|
|
@ -79,8 +79,11 @@ module.exports = {
|
||||||
inputs.request,
|
inputs.request,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const webhooks = await Webhook.qm.getAll();
|
||||||
|
|
||||||
sails.helpers.utils.sendWebhooks.with({
|
sails.helpers.utils.sendWebhooks.with({
|
||||||
event: 'commentCreate',
|
webhooks,
|
||||||
|
event: Webhook.Events.COMMENT_CREATE,
|
||||||
buildData: () => ({
|
buildData: () => ({
|
||||||
item: comment,
|
item: comment,
|
||||||
included: {
|
included: {
|
||||||
|
@ -125,6 +128,7 @@ module.exports = {
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
notifiableUserIds.map((userId) =>
|
notifiableUserIds.map((userId) =>
|
||||||
sails.helpers.notifications.createOne.with({
|
sails.helpers.notifications.createOne.with({
|
||||||
|
webhooks,
|
||||||
values: {
|
values: {
|
||||||
userId,
|
userId,
|
||||||
comment,
|
comment,
|
||||||
|
|
|
@ -47,8 +47,11 @@ module.exports = {
|
||||||
inputs.request,
|
inputs.request,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const webhooks = await Webhook.qm.getAll();
|
||||||
|
|
||||||
sails.helpers.utils.sendWebhooks.with({
|
sails.helpers.utils.sendWebhooks.with({
|
||||||
event: 'commentDelete',
|
webhooks,
|
||||||
|
event: Webhook.Events.COMMENT_DELETE,
|
||||||
buildData: () => ({
|
buildData: () => ({
|
||||||
item: comment,
|
item: comment,
|
||||||
included: {
|
included: {
|
||||||
|
|
|
@ -53,8 +53,11 @@ module.exports = {
|
||||||
inputs.request,
|
inputs.request,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const webhooks = await Webhook.qm.getAll();
|
||||||
|
|
||||||
sails.helpers.utils.sendWebhooks.with({
|
sails.helpers.utils.sendWebhooks.with({
|
||||||
event: 'commentUpdate',
|
webhooks,
|
||||||
|
event: Webhook.Events.COMMENT_UPDATE,
|
||||||
buildData: () => ({
|
buildData: () => ({
|
||||||
item: comment,
|
item: comment,
|
||||||
included: {
|
included: {
|
||||||
|
|
|
@ -87,8 +87,11 @@ module.exports = {
|
||||||
inputs.request,
|
inputs.request,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const webhooks = await Webhook.qm.getAll();
|
||||||
|
|
||||||
sails.helpers.utils.sendWebhooks.with({
|
sails.helpers.utils.sendWebhooks.with({
|
||||||
event: 'customFieldGroupCreate',
|
webhooks,
|
||||||
|
event: Webhook.Events.CUSTOM_FIELD_GROUP_CREATE,
|
||||||
buildData: () => ({
|
buildData: () => ({
|
||||||
item: customFieldGroup,
|
item: customFieldGroup,
|
||||||
included: {
|
included: {
|
||||||
|
|
|
@ -95,8 +95,11 @@ module.exports = {
|
||||||
inputs.request,
|
inputs.request,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const webhooks = await Webhook.qm.getAll();
|
||||||
|
|
||||||
sails.helpers.utils.sendWebhooks.with({
|
sails.helpers.utils.sendWebhooks.with({
|
||||||
event: 'customFieldGroupCreate',
|
webhooks,
|
||||||
|
event: Webhook.Events.CUSTOM_FIELD_GROUP_CREATE,
|
||||||
buildData: () => ({
|
buildData: () => ({
|
||||||
item: customFieldGroup,
|
item: customFieldGroup,
|
||||||
included: {
|
included: {
|
||||||
|
|
|
@ -41,8 +41,11 @@ module.exports = {
|
||||||
inputs.request,
|
inputs.request,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const webhooks = await Webhook.qm.getAll();
|
||||||
|
|
||||||
sails.helpers.utils.sendWebhooks.with({
|
sails.helpers.utils.sendWebhooks.with({
|
||||||
event: 'customFieldGroupDelete',
|
webhooks,
|
||||||
|
event: Webhook.Events.CUSTOM_FIELD_GROUP_DELETE,
|
||||||
buildData: () => ({
|
buildData: () => ({
|
||||||
item: customFieldGroup,
|
item: customFieldGroup,
|
||||||
included: {
|
included: {
|
||||||
|
|
|
@ -49,8 +49,11 @@ module.exports = {
|
||||||
inputs.request,
|
inputs.request,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const webhooks = await Webhook.qm.getAll();
|
||||||
|
|
||||||
sails.helpers.utils.sendWebhooks.with({
|
sails.helpers.utils.sendWebhooks.with({
|
||||||
event: 'customFieldGroupDelete',
|
webhooks,
|
||||||
|
event: Webhook.Events.CUSTOM_FIELD_GROUP_DELETE,
|
||||||
buildData: () => ({
|
buildData: () => ({
|
||||||
item: customFieldGroup,
|
item: customFieldGroup,
|
||||||
included: {
|
included: {
|
||||||
|
|
|
@ -91,8 +91,11 @@ module.exports = {
|
||||||
inputs.request,
|
inputs.request,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const webhooks = await Webhook.qm.getAll();
|
||||||
|
|
||||||
sails.helpers.utils.sendWebhooks.with({
|
sails.helpers.utils.sendWebhooks.with({
|
||||||
event: 'customFieldGroupUpdate',
|
webhooks,
|
||||||
|
event: Webhook.Events.CUSTOM_FIELD_GROUP_UPDATE,
|
||||||
buildData: () => ({
|
buildData: () => ({
|
||||||
item: customFieldGroup,
|
item: customFieldGroup,
|
||||||
included: {
|
included: {
|
||||||
|
|
|
@ -99,8 +99,11 @@ module.exports = {
|
||||||
inputs.request,
|
inputs.request,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const webhooks = await Webhook.qm.getAll();
|
||||||
|
|
||||||
sails.helpers.utils.sendWebhooks.with({
|
sails.helpers.utils.sendWebhooks.with({
|
||||||
event: 'customFieldGroupUpdate',
|
webhooks,
|
||||||
|
event: Webhook.Events.CUSTOM_FIELD_GROUP_UPDATE,
|
||||||
buildData: () => ({
|
buildData: () => ({
|
||||||
item: customFieldGroup,
|
item: customFieldGroup,
|
||||||
included: {
|
included: {
|
||||||
|
|
|
@ -49,9 +49,12 @@ module.exports = {
|
||||||
inputs.request,
|
inputs.request,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const webhooks = await Webhook.qm.getAll();
|
||||||
|
|
||||||
// TODO: with prevData?
|
// TODO: with prevData?
|
||||||
sails.helpers.utils.sendWebhooks.with({
|
sails.helpers.utils.sendWebhooks.with({
|
||||||
event: 'customFieldValueUpdate',
|
webhooks,
|
||||||
|
event: Webhook.Events.CUSTOM_FIELD_VALUE_UPDATE,
|
||||||
buildData: () => ({
|
buildData: () => ({
|
||||||
item: customFieldValue,
|
item: customFieldValue,
|
||||||
included: {
|
included: {
|
||||||
|
|
|
@ -51,8 +51,11 @@ module.exports = {
|
||||||
inputs.request,
|
inputs.request,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const webhooks = await Webhook.qm.getAll();
|
||||||
|
|
||||||
sails.helpers.utils.sendWebhooks.with({
|
sails.helpers.utils.sendWebhooks.with({
|
||||||
event: 'customFieldValueDelete',
|
webhooks,
|
||||||
|
event: Webhook.Events.CUSTOM_FIELD_VALUE_DELETE,
|
||||||
buildData: () => ({
|
buildData: () => ({
|
||||||
item: customFieldValue,
|
item: customFieldValue,
|
||||||
included: {
|
included: {
|
||||||
|
|
|
@ -93,8 +93,11 @@ module.exports = {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const webhooks = await Webhook.qm.getAll();
|
||||||
|
|
||||||
sails.helpers.utils.sendWebhooks.with({
|
sails.helpers.utils.sendWebhooks.with({
|
||||||
event: 'customFieldCreate',
|
webhooks,
|
||||||
|
event: Webhook.Events.CUSTOM_FIELD_CREATE,
|
||||||
buildData: () => ({
|
buildData: () => ({
|
||||||
item: customField,
|
item: customField,
|
||||||
included: {
|
included: {
|
||||||
|
|
|
@ -103,8 +103,11 @@ module.exports = {
|
||||||
inputs.request,
|
inputs.request,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const webhooks = await Webhook.qm.getAll();
|
||||||
|
|
||||||
sails.helpers.utils.sendWebhooks.with({
|
sails.helpers.utils.sendWebhooks.with({
|
||||||
event: 'customFieldCreate',
|
webhooks,
|
||||||
|
event: Webhook.Events.CUSTOM_FIELD_CREATE,
|
||||||
buildData: () => ({
|
buildData: () => ({
|
||||||
item: customField,
|
item: customField,
|
||||||
included: {
|
included: {
|
||||||
|
|
|
@ -49,8 +49,11 @@ module.exports = {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const webhooks = await Webhook.qm.getAll();
|
||||||
|
|
||||||
sails.helpers.utils.sendWebhooks.with({
|
sails.helpers.utils.sendWebhooks.with({
|
||||||
event: 'customFieldDelete',
|
webhooks,
|
||||||
|
event: Webhook.Events.CUSTOM_FIELD_DELETE,
|
||||||
buildData: () => ({
|
buildData: () => ({
|
||||||
item: customField,
|
item: customField,
|
||||||
included: {
|
included: {
|
||||||
|
|
|
@ -66,8 +66,11 @@ module.exports = {
|
||||||
inputs.request,
|
inputs.request,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const webhooks = await Webhook.qm.getAll();
|
||||||
|
|
||||||
sails.helpers.utils.sendWebhooks.with({
|
sails.helpers.utils.sendWebhooks.with({
|
||||||
event: 'customFieldDelete',
|
webhooks,
|
||||||
|
event: Webhook.Events.CUSTOM_FIELD_DELETE,
|
||||||
buildData: () => ({
|
buildData: () => ({
|
||||||
item: customField,
|
item: customField,
|
||||||
included: {
|
included: {
|
||||||
|
|
|
@ -94,8 +94,11 @@ module.exports = {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const webhooks = await Webhook.qm.getAll();
|
||||||
|
|
||||||
sails.helpers.utils.sendWebhooks.with({
|
sails.helpers.utils.sendWebhooks.with({
|
||||||
event: 'customFieldUpdate',
|
webhooks,
|
||||||
|
event: Webhook.Events.CUSTOM_FIELD_UPDATE,
|
||||||
buildData: () => ({
|
buildData: () => ({
|
||||||
item: customField,
|
item: customField,
|
||||||
included: {
|
included: {
|
||||||
|
|
|
@ -109,8 +109,11 @@ module.exports = {
|
||||||
inputs.request,
|
inputs.request,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const webhooks = await Webhook.qm.getAll();
|
||||||
|
|
||||||
sails.helpers.utils.sendWebhooks.with({
|
sails.helpers.utils.sendWebhooks.with({
|
||||||
event: 'customFieldUpdate',
|
webhooks,
|
||||||
|
event: Webhook.Events.CUSTOM_FIELD_UPDATE,
|
||||||
buildData: () => ({
|
buildData: () => ({
|
||||||
item: customField,
|
item: customField,
|
||||||
included: {
|
included: {
|
||||||
|
|
|
@ -17,6 +17,9 @@ module.exports = {
|
||||||
type: 'ref',
|
type: 'ref',
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
|
webhooks: {
|
||||||
|
type: 'ref',
|
||||||
|
},
|
||||||
request: {
|
request: {
|
||||||
type: 'ref',
|
type: 'ref',
|
||||||
},
|
},
|
||||||
|
@ -70,8 +73,11 @@ module.exports = {
|
||||||
inputs.request,
|
inputs.request,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const { webhooks = await Webhook.qm.getAll() } = inputs;
|
||||||
|
|
||||||
sails.helpers.utils.sendWebhooks.with({
|
sails.helpers.utils.sendWebhooks.with({
|
||||||
event: 'labelCreate',
|
webhooks,
|
||||||
|
event: Webhook.Events.LABEL_CREATE,
|
||||||
buildData: () => ({
|
buildData: () => ({
|
||||||
item: label,
|
item: label,
|
||||||
included: {
|
included: {
|
||||||
|
|
|
@ -41,8 +41,11 @@ module.exports = {
|
||||||
inputs.request,
|
inputs.request,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const webhooks = await Webhook.qm.getAll();
|
||||||
|
|
||||||
sails.helpers.utils.sendWebhooks.with({
|
sails.helpers.utils.sendWebhooks.with({
|
||||||
event: 'labelDelete',
|
webhooks,
|
||||||
|
event: Webhook.Events.LABEL_DELETE,
|
||||||
buildData: () => ({
|
buildData: () => ({
|
||||||
item: label,
|
item: label,
|
||||||
included: {
|
included: {
|
||||||
|
|
|
@ -81,8 +81,11 @@ module.exports = {
|
||||||
inputs.request,
|
inputs.request,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const webhooks = await Webhook.qm.getAll();
|
||||||
|
|
||||||
sails.helpers.utils.sendWebhooks.with({
|
sails.helpers.utils.sendWebhooks.with({
|
||||||
event: 'labelUpdate',
|
webhooks,
|
||||||
|
event: Webhook.Events.LABEL_UPDATE,
|
||||||
buildData: () => ({
|
buildData: () => ({
|
||||||
item: label,
|
item: label,
|
||||||
included: {
|
included: {
|
||||||
|
|
|
@ -38,8 +38,11 @@ module.exports = {
|
||||||
inputs.request,
|
inputs.request,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const webhooks = await Webhook.qm.getAll();
|
||||||
|
|
||||||
sails.helpers.utils.sendWebhooks.with({
|
sails.helpers.utils.sendWebhooks.with({
|
||||||
event: 'listClear',
|
webhooks,
|
||||||
|
event: Webhook.Events.LIST_CLEAR,
|
||||||
buildData: () => ({
|
buildData: () => ({
|
||||||
item: inputs.record,
|
item: inputs.record,
|
||||||
included: {
|
included: {
|
||||||
|
|
|
@ -72,8 +72,11 @@ module.exports = {
|
||||||
inputs.request,
|
inputs.request,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const webhooks = await Webhook.qm.getAll();
|
||||||
|
|
||||||
sails.helpers.utils.sendWebhooks.with({
|
sails.helpers.utils.sendWebhooks.with({
|
||||||
event: 'listCreate',
|
webhooks,
|
||||||
|
event: Webhook.Events.LIST_CREATE,
|
||||||
buildData: () => ({
|
buildData: () => ({
|
||||||
item: list,
|
item: list,
|
||||||
included: {
|
included: {
|
||||||
|
|
|
@ -57,8 +57,11 @@ module.exports = {
|
||||||
inputs.request,
|
inputs.request,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const webhooks = await Webhook.qm.getAll();
|
||||||
|
|
||||||
sails.helpers.utils.sendWebhooks.with({
|
sails.helpers.utils.sendWebhooks.with({
|
||||||
event: 'listDelete',
|
webhooks,
|
||||||
|
event: Webhook.Events.LIST_DELETE,
|
||||||
buildData: () => ({
|
buildData: () => ({
|
||||||
item: list,
|
item: list,
|
||||||
included: {
|
included: {
|
||||||
|
|
|
@ -91,10 +91,13 @@ module.exports = {
|
||||||
inputs.request,
|
inputs.request,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const webhooks = await Webhook.qm.getAll();
|
||||||
|
|
||||||
cards.forEach((card) => {
|
cards.forEach((card) => {
|
||||||
// TODO: with prevData?
|
// TODO: with prevData?
|
||||||
sails.helpers.utils.sendWebhooks.with({
|
sails.helpers.utils.sendWebhooks.with({
|
||||||
event: 'cardUpdate',
|
webhooks,
|
||||||
|
event: Webhook.Events.CARD_UPDATE,
|
||||||
buildData: () => ({
|
buildData: () => ({
|
||||||
item: card,
|
item: card,
|
||||||
included: {
|
included: {
|
||||||
|
|
|
@ -100,10 +100,13 @@ module.exports = {
|
||||||
inputs.request,
|
inputs.request,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const webhooks = await Webhook.qm.getAll();
|
||||||
|
|
||||||
cards.forEach((card) => {
|
cards.forEach((card) => {
|
||||||
// TODO: with prevData?
|
// TODO: with prevData?
|
||||||
sails.helpers.utils.sendWebhooks.with({
|
sails.helpers.utils.sendWebhooks.with({
|
||||||
event: 'cardUpdate',
|
webhooks,
|
||||||
|
event: Webhook.Events.CARD_UPDATE,
|
||||||
buildData: () => ({
|
buildData: () => ({
|
||||||
item: card,
|
item: card,
|
||||||
included: {
|
included: {
|
||||||
|
|
|
@ -84,8 +84,11 @@ module.exports = {
|
||||||
inputs.request,
|
inputs.request,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const webhooks = await Webhook.qm.getAll();
|
||||||
|
|
||||||
sails.helpers.utils.sendWebhooks.with({
|
sails.helpers.utils.sendWebhooks.with({
|
||||||
event: 'listUpdate',
|
webhooks,
|
||||||
|
event: Webhook.Events.LIST_UPDATE,
|
||||||
buildData: () => ({
|
buildData: () => ({
|
||||||
item: list,
|
item: list,
|
||||||
included: {
|
included: {
|
||||||
|
|
|
@ -62,8 +62,11 @@ module.exports = {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const webhooks = await Webhook.qm.getAll();
|
||||||
|
|
||||||
sails.helpers.utils.sendWebhooks.with({
|
sails.helpers.utils.sendWebhooks.with({
|
||||||
event: 'notificationServiceCreate',
|
webhooks,
|
||||||
|
event: Webhook.Events.NOTIFICATION_SERVICE_CREATE,
|
||||||
buildData: () => ({
|
buildData: () => ({
|
||||||
item: notificationService,
|
item: notificationService,
|
||||||
included: {
|
included: {
|
||||||
|
|
|
@ -48,8 +48,11 @@ module.exports = {
|
||||||
inputs.request,
|
inputs.request,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const webhooks = await Webhook.qm.getAll();
|
||||||
|
|
||||||
sails.helpers.utils.sendWebhooks.with({
|
sails.helpers.utils.sendWebhooks.with({
|
||||||
event: 'notificationServiceCreate',
|
webhooks,
|
||||||
|
event: Webhook.Events.NOTIFICATION_SERVICE_CREATE,
|
||||||
buildData: () => ({
|
buildData: () => ({
|
||||||
item: notificationService,
|
item: notificationService,
|
||||||
included: {
|
included: {
|
||||||
|
|
|
@ -49,8 +49,11 @@ module.exports = {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const webhooks = await Webhook.qm.getAll();
|
||||||
|
|
||||||
sails.helpers.utils.sendWebhooks.with({
|
sails.helpers.utils.sendWebhooks.with({
|
||||||
event: 'notificationServiceDelete',
|
webhooks,
|
||||||
|
event: Webhook.Events.NOTIFICATION_SERVICE_DELETE,
|
||||||
buildData: () => ({
|
buildData: () => ({
|
||||||
item: notificationService,
|
item: notificationService,
|
||||||
included: {
|
included: {
|
||||||
|
|
|
@ -35,8 +35,11 @@ module.exports = {
|
||||||
inputs.request,
|
inputs.request,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const webhooks = await Webhook.qm.getAll();
|
||||||
|
|
||||||
sails.helpers.utils.sendWebhooks.with({
|
sails.helpers.utils.sendWebhooks.with({
|
||||||
event: 'notificationServiceDelete',
|
webhooks,
|
||||||
|
event: Webhook.Events.NOTIFICATION_SERVICE_DELETE,
|
||||||
buildData: () => ({
|
buildData: () => ({
|
||||||
item: notificationService,
|
item: notificationService,
|
||||||
included: {
|
included: {
|
||||||
|
|
|
@ -55,8 +55,11 @@ module.exports = {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const webhooks = await Webhook.qm.getAll();
|
||||||
|
|
||||||
sails.helpers.utils.sendWebhooks.with({
|
sails.helpers.utils.sendWebhooks.with({
|
||||||
event: 'notificationServiceUpdate',
|
webhooks,
|
||||||
|
event: Webhook.Events.NOTIFICATION_SERVICE_UPDATE,
|
||||||
buildData: () => ({
|
buildData: () => ({
|
||||||
item: notificationService,
|
item: notificationService,
|
||||||
included: {
|
included: {
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue