/* * Copyright 2023 Collate. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import { Button, Form, FormProps, Space, Tooltip, Typography } from 'antd'; import { DefaultOptionType } from 'antd/lib/select'; import { AxiosError } from 'axios'; import { filter, isEmpty } from 'lodash'; import React, { useEffect, useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { AsyncSelect } from '../../components/common/AsyncSelect/AsyncSelect'; import ResizablePanels from '../../components/common/ResizablePanels/ResizablePanels'; import TitleBreadcrumb from '../../components/common/TitleBreadcrumb/TitleBreadcrumb.component'; import { TitleBreadcrumbProps } from '../../components/common/TitleBreadcrumb/TitleBreadcrumb.interface'; import SchemaEditor from '../../components/Database/SchemaEditor/SchemaEditor'; import { HTTP_STATUS_CODE } from '../../constants/Auth.constants'; import { getEntityDetailsPath, INITIAL_PAGING_VALUE, PAGE_SIZE_MEDIUM, } from '../../constants/constants'; import { NO_PERMISSION_FOR_ACTION } from '../../constants/HelperTextUtil'; import { usePermissionProvider } from '../../context/PermissionProvider/PermissionProvider'; import { CSMode } from '../../enums/codemirror.enum'; import { EntityType } from '../../enums/entity.enum'; import { SearchIndex } from '../../enums/search.enum'; import { OwnerType } from '../../enums/user.enum'; import { CreateQuery } from '../../generated/api/data/createQuery'; import { Table } from '../../generated/entity/data/table'; import { useApplicationStore } from '../../hooks/useApplicationStore'; import { useFqn } from '../../hooks/useFqn'; import { FieldProp, FieldTypes } from '../../interface/FormUtils.interface'; import { searchData } from '../../rest/miscAPI'; import { postQuery } from '../../rest/queryAPI'; import { getTableDetailsByFQN } from '../../rest/tableAPI'; import { getPartialNameFromFQN } from '../../utils/CommonUtils'; import { getCurrentMillis } from '../../utils/date-time/DateTimeUtils'; import { getEntityBreadcrumbs, getEntityLabel, getEntityName, } from '../../utils/EntityUtils'; import { getField } from '../../utils/formUtils'; import { showErrorToast, showSuccessToast } from '../../utils/ToastUtils'; const AddQueryPage = () => { const { t } = useTranslation(); const { currentUser } = useApplicationStore(); const { fqn: datasetFQN } = useFqn(); const { permissions } = usePermissionProvider(); const [form] = Form.useForm(); const [titleBreadcrumb, setTitleBreadcrumb] = useState< TitleBreadcrumbProps['titleLinks'] >([]); const [description, setDescription] = useState(''); const [table, setTable] = useState(); const [initialOptions, setInitialOptions] = useState(); const [isSaving, setIsSaving] = useState(false); const fetchEntityDetails = async () => { try { const tableRes = await getTableDetailsByFQN(datasetFQN); setTable(tableRes); setTitleBreadcrumb([ ...getEntityBreadcrumbs(tableRes, EntityType.TABLE), { name: getEntityName(tableRes), url: getEntityDetailsPath( EntityType.TABLE, datasetFQN, 'table_queries' ), }, { name: t('label.add-entity', { entity: t('label.query'), }), url: '', activeTitle: true, }, ]); } catch (error) { showErrorToast(error as AxiosError); } }; const fetchTableEntity = async ( searchValue = '' ): Promise => { try { const { data } = await searchData( searchValue, INITIAL_PAGING_VALUE, PAGE_SIZE_MEDIUM, '', '', '', SearchIndex.TABLE ); const options = data.hits.hits.map((value) => ({ label: getEntityLabel(value._source), value: value._source.id, })); return table ? filter(options, ({ value }) => value !== table.id) : options; } catch (error) { return []; } }; useEffect(() => { if (datasetFQN) { fetchEntityDetails(); } }, [datasetFQN]); const getInitialOptions = async () => { try { const option = await fetchTableEntity(); setInitialOptions(option); } catch (error) { setInitialOptions([]); } }; useEffect(() => { if (table) { getInitialOptions(); } }, [table]); const handleCancelClick = () => { history.back(); }; const handleSubmit: FormProps['onFinish'] = async (values): Promise => { setIsSaving(true); const updatedValues: CreateQuery = { ...values, description: isEmpty(description) ? undefined : description, owners: [ { id: currentUser?.id ?? '', type: OwnerType.USER, }, ], queryUsedIn: [ { id: table?.id ?? '', type: EntityType.TABLE, }, ...(values.queryUsedIn || []).map((id: string) => ({ id, type: EntityType.TABLE, })), ], queryDate: getCurrentMillis(), service: getPartialNameFromFQN(datasetFQN, ['service']), }; try { await postQuery(updatedValues); showSuccessToast( t('server.create-entity-success', { entity: t('label.query') }) ); handleCancelClick(); } catch (error) { if ( (error as AxiosError).response?.status === HTTP_STATUS_CODE.CONFLICT ) { showErrorToast( t('server.entity-already-exist-message-without-name', { entity: t('label.query'), entityPlural: t('label.query-lowercase-plural'), }) ); } else { showErrorToast( t('server.create-entity-error', { entity: t('label.query-plural'), }) ); } } finally { setIsSaving(false); } }; const descriptionField: FieldProp = useMemo( () => ({ name: 'description', required: false, label: `${t('label.description')}:`, id: 'root/description', type: FieldTypes.DESCRIPTION, props: { 'data-testid': 'description', initialValue: '', style: { margin: 0, }, placeHolder: t('message.write-your-description'), onTextChange: (value: string) => setDescription(value), }, }), [] ); return (
{t('label.add-new-entity', { entity: t('label.query') })}
{getField(descriptionField)}
), minWidth: 700, flex: 0.7, }} pageTitle={t('label.add-entity', { entity: t('label.query') })} secondPanel={{ children: ( <> {t('label.add-entity', { entity: t('label.query'), })} {t('message.add-query-helper-message')} ), className: 'p-md p-t-xl content-resizable-panel-container', minWidth: 400, flex: 0.3, }} /> ); }; export default AddQueryPage;