import { DeleteOutlined, EditOutlined } from '@ant-design/icons'; import { Button, Checkbox, Form, Input, Modal, Space, Table, Typography } from 'antd'; import _ from 'lodash'; import React, { useContext, useEffect, useState } from 'react'; import { FormStatusIndicator } from '../../components/config/FormStatusIndicator'; import { ExternalAction } from '../../interfaces/external-action'; import { API_EXTERNAL_ACTIONS, postConfigUpdateToAPI, RESET_TIMEOUT, } from '../../utils/config-constants'; import { createInputStatus, STATUS_ERROR, STATUS_SUCCESS } from '../../utils/input-statuses'; import { ServerStatusContext } from '../../utils/server-status-context'; import isValidUrl, { DEFAULT_TEXTFIELD_URL_PATTERN } from '../../utils/urls'; const { Title, Paragraph } = Typography; let resetTimer = null; interface Props { onCancel: () => void; onOk: ( oldAction: ExternalAction | null, actionUrl: string, actionTitle: string, actionDescription: string, actionIcon: string, actionColor: string, openExternally: boolean, ) => void; open: boolean; action: ExternalAction | null; } const ActionModal = (props: Props) => { const { onOk, onCancel, open, action } = props; const [actionUrl, setActionUrl] = useState(''); const [actionTitle, setActionTitle] = useState(''); const [actionDescription, setActionDescription] = useState(''); const [actionIcon, setActionIcon] = useState(''); const [actionColor, setActionColor] = useState(''); const [openExternally, setOpenExternally] = useState(false); useEffect(() => { setActionUrl(action?.url || ''); setActionTitle(action?.title || ''); setActionDescription(action?.description || ''); setActionIcon(action?.icon || ''); setActionColor(action?.color || ''); setOpenExternally(action?.openExternally || false); }, [action]); function save() { onOk( action, actionUrl, actionTitle, actionDescription, actionIcon, actionColor, openExternally, ); setActionUrl(''); setActionTitle(''); setActionDescription(''); setActionIcon(''); setActionColor(''); setOpenExternally(false); } function canSave(): Boolean { try { const validationObject = new URL(actionUrl); if (validationObject.protocol !== 'https:') { return false; } } catch { return false; } return isValidUrl(actionUrl) && actionTitle !== ''; } const okButtonProps = { disabled: !canSave(), }; const onOpenExternallyChanged = checkbox => { setOpenExternally(checkbox.target.checked); }; return (
Add the URL for the external action you want to present.{' '} Only HTTPS urls are supported.

Read more about external actions.

setActionUrl(input.currentTarget.value.trim())} type="url" pattern={DEFAULT_TEXTFIELD_URL_PATTERN} /> setActionTitle(input.currentTarget.value)} /> setActionDescription(input.currentTarget.value)} /> setActionIcon(input.currentTarget.value)} />
setActionColor(input.currentTarget.value)} /> Optional background color of the action button.
Open in a new tab instead of within your page.
); }; const Actions = () => { const serverStatusData = useContext(ServerStatusContext); const { serverConfig, setFieldInConfigState } = serverStatusData || {}; const { externalActions } = serverConfig; const [actions, setActions] = useState(null); const [isModalOpen, setIsModalOpen] = useState(false); const [submitStatus, setSubmitStatus] = useState(null); const [editAction, setEditAction] = useState(null); const resetStates = () => { setSubmitStatus(null); resetTimer = null; clearTimeout(resetTimer); }; useEffect(() => { setActions(externalActions || []); }, [externalActions]); async function save(actionsData) { await postConfigUpdateToAPI({ apiPath: API_EXTERNAL_ACTIONS, data: { value: actionsData }, onSuccess: () => { setFieldInConfigState({ fieldName: 'externalActions', value: actionsData, path: '' }); setSubmitStatus(createInputStatus(STATUS_SUCCESS, 'Updated.')); resetTimer = setTimeout(resetStates, RESET_TIMEOUT); }, onError: (message: string) => { console.log(message); setSubmitStatus(createInputStatus(STATUS_ERROR, message)); resetTimer = setTimeout(resetStates, RESET_TIMEOUT); }, }); } async function handleDelete(action) { const actionsData = [...actions]; const index = actions.findIndex(item => item.url === action.url); actionsData.splice(index, 1); try { setActions(actionsData); save(actionsData); } catch (error) { console.error(error); } } async function handleSave( oldAction: ExternalAction | null, url: string, title: string, description: string, icon: string, color: string, openExternally: boolean, ) { try { const actionsData = [...actions]; const newAction: ExternalAction = { url, title, description, icon, color, openExternally, }; // Replace old action if edited or append the new action const index = oldAction ? actions.findIndex(item => _.isEqual(item, oldAction)) : -1; if (index >= 0) { actionsData[index] = newAction; } else { actionsData.push(newAction); } setActions(actionsData); await save(actionsData); } catch (error) { console.error(error); } } async function handleEdit(action: ExternalAction) { setEditAction(action); setIsModalOpen(true); } const showCreateModal = () => { setEditAction(null); setIsModalOpen(true); }; const handleModalSaveButton = ( oldAction: ExternalAction | null, actionUrl: string, actionTitle: string, actionDescription: string, actionIcon: string, actionColor: string, openExternally: boolean, ) => { setIsModalOpen(false); handleSave( oldAction, actionUrl, actionTitle, actionDescription, actionIcon, actionColor, openExternally, ); setEditAction(null); }; const handleModalCancelButton = () => { setIsModalOpen(false); }; const columns = [ { title: '', key: 'delete-edit', render: (text, record) => (