ui: fixed card and tag removal, alert buttons, kai input disable state
This commit is contained in:
parent
75230d72ec
commit
0d9c8d70c8
7 changed files with 96 additions and 82 deletions
|
|
@ -1,10 +1,10 @@
|
|||
import React from 'react';
|
||||
import { Button, Form, Input, Space, Modal } from 'antd';
|
||||
import { Button, Form, Input, Space } from 'antd';
|
||||
import { Trash } from 'UI/Icons';
|
||||
import { useStore } from '@/mstore';
|
||||
import { useModal } from 'Components/ModalContext';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import { confirm } from 'UI';
|
||||
interface Props {
|
||||
tag: any;
|
||||
projectId: number;
|
||||
|
|
@ -23,14 +23,16 @@ function TagForm(props: Props) {
|
|||
};
|
||||
|
||||
const onDelete = async () => {
|
||||
Modal.confirm({
|
||||
title: t('Tag'),
|
||||
content: t('Are you sure you want to remove?'),
|
||||
onOk: async () => {
|
||||
await tagWatchStore.deleteTag(tag.tagId, projectId);
|
||||
closeModal();
|
||||
},
|
||||
});
|
||||
if (
|
||||
await confirm({
|
||||
header: t('Remove Tag'),
|
||||
confirmButton: t('Remove'),
|
||||
confirmation: t('Are you sure you want to remove this tag?'),
|
||||
})
|
||||
) {
|
||||
await tagWatchStore.deleteTag(tag.tagId, projectId);
|
||||
closeModal();
|
||||
}
|
||||
};
|
||||
|
||||
const onSave = async () => {
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ function BottomButtons({
|
|||
<Button
|
||||
loading={loading}
|
||||
type="primary"
|
||||
htmlType="submit"
|
||||
disabled={loading || !instance.validate()}
|
||||
id="submit-button"
|
||||
>
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ function Condition({
|
|||
<label className="w-1/6 flex-shrink-0 font-normal">{t('is')}</label>
|
||||
<div className="w-2/6 flex items-center">
|
||||
<Select
|
||||
popupMatchSelectWidth={false}
|
||||
placeholder={t('Select Condition')}
|
||||
options={localizedConditions}
|
||||
name="operator"
|
||||
|
|
|
|||
|
|
@ -7,19 +7,18 @@ import {
|
|||
Button,
|
||||
Dropdown,
|
||||
Modal as AntdModal,
|
||||
Avatar, TableColumnType, Spin
|
||||
Avatar,
|
||||
TableColumnType,
|
||||
Spin,
|
||||
} from 'antd';
|
||||
import {
|
||||
EditOutlined,
|
||||
DeleteOutlined,
|
||||
} from '@ant-design/icons';
|
||||
import { EditOutlined, DeleteOutlined } from '@ant-design/icons';
|
||||
import { EllipsisVertical } from 'lucide-react';
|
||||
import { TablePaginationConfig, SorterResult } from 'antd/lib/table/interface';
|
||||
import { useStore } from 'App/mstore';
|
||||
import { toast } from 'react-toastify';
|
||||
import { useHistory } from 'react-router';
|
||||
import { withSiteId } from 'App/routes';
|
||||
import { Icon } from 'UI';
|
||||
import { Icon, confirm } from 'UI';
|
||||
import cn from 'classnames';
|
||||
import { TYPE_ICONS, TYPE_NAMES } from 'App/constants/card';
|
||||
import Widget from 'App/mstore/types/widget';
|
||||
|
|
@ -45,7 +44,7 @@ const ListView: React.FC<Props> = ({
|
|||
toggleSelection,
|
||||
disableSelection = false,
|
||||
inLibrary = false,
|
||||
loading = false
|
||||
loading = false,
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const [editingMetricId, setEditingMetricId] = useState<number | null>(null);
|
||||
|
|
@ -63,7 +62,7 @@ const ListView: React.FC<Props> = ({
|
|||
<Text strong>
|
||||
{Math.min(
|
||||
(metricStore.pageSize || 10) * (metricStore.page || 1),
|
||||
list.length
|
||||
list.length,
|
||||
)}
|
||||
</Text>{' '}
|
||||
{t('of')} <Text strong>{list.length}</Text> {t('cards')}
|
||||
|
|
@ -124,15 +123,17 @@ const ListView: React.FC<Props> = ({
|
|||
|
||||
const onMenuClick = async (metric: Widget, { key }: { key: string }) => {
|
||||
if (key === 'delete') {
|
||||
AntdModal.confirm({
|
||||
title: t('Confirm'),
|
||||
content: t('Are you sure you want to permanently delete this card?'),
|
||||
okText: t('Yes, delete'),
|
||||
cancelText: t('No'),
|
||||
onOk: async () => {
|
||||
await metricStore.delete(metric);
|
||||
}
|
||||
});
|
||||
if (
|
||||
await confirm({
|
||||
header: t('Delete Card'),
|
||||
confirmButton: t('Delete'),
|
||||
confirmation: t(
|
||||
'Are you sure you want to permanently delete this card? This action cannot be undone.',
|
||||
),
|
||||
})
|
||||
) {
|
||||
await metricStore.delete(metric);
|
||||
}
|
||||
}
|
||||
if (key === 'rename') {
|
||||
setEditingMetricId(metric.metricId);
|
||||
|
|
@ -155,7 +156,7 @@ const ListView: React.FC<Props> = ({
|
|||
|
||||
const menuItems = [
|
||||
{ key: 'rename', icon: <EditOutlined />, label: t('Rename') },
|
||||
{ key: 'delete', icon: <DeleteOutlined />, label: t('Delete') }
|
||||
{ key: 'delete', icon: <DeleteOutlined />, label: t('Delete') },
|
||||
];
|
||||
|
||||
const renderTitle = (_text: string, metric: Widget) => (
|
||||
|
|
@ -201,9 +202,10 @@ const ListView: React.FC<Props> = ({
|
|||
key: 'title',
|
||||
className: 'cap-first pl-4',
|
||||
sorter: true,
|
||||
sortOrder: metricStore.sort.field === 'name' ? metricStore.sort.order : undefined,
|
||||
sortOrder:
|
||||
metricStore.sort.field === 'name' ? metricStore.sort.order : undefined,
|
||||
width: inLibrary ? '31%' : '25%',
|
||||
render: renderTitle
|
||||
render: renderTitle,
|
||||
},
|
||||
{
|
||||
title: t('Owner'),
|
||||
|
|
@ -211,19 +213,25 @@ const ListView: React.FC<Props> = ({
|
|||
key: 'owner',
|
||||
className: 'capitalize',
|
||||
sorter: true,
|
||||
sortOrder: metricStore.sort.field === 'owner_email' ? metricStore.sort.order : undefined,
|
||||
sortOrder:
|
||||
metricStore.sort.field === 'owner_email'
|
||||
? metricStore.sort.order
|
||||
: undefined,
|
||||
width: inLibrary ? '31%' : '25%',
|
||||
render: renderOwner
|
||||
render: renderOwner,
|
||||
},
|
||||
{
|
||||
title: t('Last Modified'),
|
||||
dataIndex: 'edited_at',
|
||||
key: 'lastModified',
|
||||
sorter: true,
|
||||
sortOrder: metricStore.sort.field === 'edited_at' ? metricStore.sort.order : undefined,
|
||||
sortOrder:
|
||||
metricStore.sort.field === 'edited_at'
|
||||
? metricStore.sort.order
|
||||
: undefined,
|
||||
width: inLibrary ? '31%' : '25%',
|
||||
render: renderLastModified
|
||||
}
|
||||
render: renderLastModified,
|
||||
},
|
||||
];
|
||||
|
||||
if (!inLibrary) {
|
||||
|
|
@ -232,14 +240,14 @@ const ListView: React.FC<Props> = ({
|
|||
key: 'options',
|
||||
className: 'text-right',
|
||||
width: '5%',
|
||||
render: renderOptions
|
||||
render: renderOptions,
|
||||
});
|
||||
}
|
||||
|
||||
const handleTableChange = (
|
||||
pag: TablePaginationConfig,
|
||||
_filters: Record<string, (string | number | boolean)[] | null>,
|
||||
sorterParam: SorterResult<Widget> | SorterResult<Widget>[]
|
||||
sorterParam: SorterResult<Widget> | SorterResult<Widget>[],
|
||||
) => {
|
||||
const sorter = Array.isArray(sorterParam) ? sorterParam[0] : sorterParam;
|
||||
let order = sorter.order;
|
||||
|
|
@ -268,19 +276,19 @@ const ListView: React.FC<Props> = ({
|
|||
onRow={
|
||||
inLibrary
|
||||
? (record) => ({
|
||||
onClick: () => {
|
||||
if (!disableSelection) toggleSelection?.(record?.metricId);
|
||||
}
|
||||
})
|
||||
onClick: () => {
|
||||
if (!disableSelection) toggleSelection?.(record?.metricId);
|
||||
},
|
||||
})
|
||||
: undefined
|
||||
}
|
||||
rowSelection={
|
||||
!disableSelection
|
||||
? {
|
||||
selectedRowKeys: selectedList,
|
||||
onChange: (keys) => toggleSelection && toggleSelection(keys),
|
||||
columnWidth: 16
|
||||
}
|
||||
selectedRowKeys: selectedList,
|
||||
onChange: (keys) => toggleSelection && toggleSelection(keys),
|
||||
columnWidth: 16,
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
pagination={{
|
||||
|
|
@ -292,7 +300,7 @@ const ListView: React.FC<Props> = ({
|
|||
showLessItems: true,
|
||||
showTotal: () => totalMessage,
|
||||
size: 'small',
|
||||
simple: true
|
||||
simple: true,
|
||||
}}
|
||||
/>
|
||||
<AntdModal
|
||||
|
|
|
|||
|
|
@ -10,10 +10,10 @@ import AddCardSection from '../AddCardSection/AddCardSection';
|
|||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
function MetricsList({
|
||||
siteId,
|
||||
onSelectionChange,
|
||||
inLibrary
|
||||
}: {
|
||||
siteId,
|
||||
onSelectionChange,
|
||||
inLibrary,
|
||||
}: {
|
||||
siteId: string;
|
||||
onSelectionChange?: (selected: any[]) => void;
|
||||
inLibrary?: boolean;
|
||||
|
|
@ -26,16 +26,16 @@ function MetricsList({
|
|||
const dashboard = dashboardStore.selectedDashboard;
|
||||
const existingCardIds = useMemo(
|
||||
() => dashboard?.widgets?.map((i) => parseInt(i.metricId)),
|
||||
[dashboard]
|
||||
[dashboard],
|
||||
);
|
||||
const cards = useMemo(
|
||||
() =>
|
||||
onSelectionChange
|
||||
? metricStore.filteredCards.filter(
|
||||
(i) => !existingCardIds?.includes(parseInt(i.metricId))
|
||||
)
|
||||
(i) => !existingCardIds?.includes(parseInt(i.metricId)),
|
||||
)
|
||||
: metricStore.filteredCards,
|
||||
[metricStore.filteredCards, existingCardIds, onSelectionChange]
|
||||
[metricStore.filteredCards, existingCardIds, onSelectionChange],
|
||||
);
|
||||
const loading = metricStore.isLoading;
|
||||
|
||||
|
|
@ -66,7 +66,8 @@ function MetricsList({
|
|||
metricStore.updateKey('sessionsPage', 1);
|
||||
}, [metricStore]);
|
||||
|
||||
const isFiltered = metricStore.filter.query !== '' || metricStore.filter.type !== '';
|
||||
const isFiltered =
|
||||
metricStore.filter.query !== '' || metricStore.filter.type !== '';
|
||||
|
||||
const searchImageDimensions = { width: 60, height: 'auto' };
|
||||
const defaultImageDimensions = { width: 600, height: 'auto' };
|
||||
|
|
@ -93,7 +94,9 @@ function MetricsList({
|
|||
) : (
|
||||
<div className="flex flex-col items-center">
|
||||
<div>
|
||||
{t('Create and customize cards to analyze trends and user behavior effectively.')}
|
||||
{t(
|
||||
'Create and customize cards to analyze trends and user behavior effectively.',
|
||||
)}
|
||||
</div>
|
||||
<Popover
|
||||
arrow={false}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { useHistory } from 'react-router';
|
||||
import { useStore } from 'App/mstore';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import { Button, Dropdown, MenuProps, Modal } from 'antd';
|
||||
import { Button, Dropdown, MenuProps } from 'antd';
|
||||
import {
|
||||
BellIcon,
|
||||
EllipsisVertical,
|
||||
|
|
@ -14,6 +14,7 @@ import { useModal } from 'Components/ModalContext';
|
|||
import AlertFormModal from 'Components/Alerts/AlertFormModal/AlertFormModal';
|
||||
import { showAddToDashboardModal } from 'Components/Dashboard/components/AddToDashboardButton';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { confirm } from 'UI';
|
||||
|
||||
function CardViewMenu() {
|
||||
const { t } = useTranslation();
|
||||
|
|
@ -51,29 +52,25 @@ function CardViewMenu() {
|
|||
label: t('Delete'),
|
||||
icon: <TrashIcon size={15} />,
|
||||
disabled: !widget.exists(),
|
||||
onClick: () => {
|
||||
Modal.confirm({
|
||||
title: t('Confirm Card Deletion'),
|
||||
icon: null,
|
||||
content:
|
||||
t('Are you sure you want to remove this card? This action is permanent and cannot be undone.'),
|
||||
footer: (_, { OkBtn, CancelBtn }) => (
|
||||
<>
|
||||
<CancelBtn />
|
||||
<OkBtn />
|
||||
</>
|
||||
),
|
||||
onOk: () => {
|
||||
metricStore
|
||||
.delete(widget)
|
||||
.then(() => {
|
||||
history.goBack();
|
||||
})
|
||||
.catch(() => {
|
||||
toast.error(t('Failed to remove card'));
|
||||
});
|
||||
},
|
||||
});
|
||||
onClick: async () => {
|
||||
if (
|
||||
await confirm({
|
||||
header: t('Remove Card'),
|
||||
confirmButton: t('Remove'),
|
||||
confirmation: t(
|
||||
'Are you sure you want to remove this card? This action is permanent and cannot be undone.',
|
||||
),
|
||||
})
|
||||
) {
|
||||
metricStore
|
||||
.delete(widget)
|
||||
.then(() => {
|
||||
history.goBack();
|
||||
})
|
||||
.catch(() => {
|
||||
toast.error(t('Failed to remove card'));
|
||||
});
|
||||
}
|
||||
},
|
||||
},
|
||||
];
|
||||
|
|
|
|||
|
|
@ -25,7 +25,9 @@ function ChatInput({
|
|||
kaiStore.setQueryText(text);
|
||||
};
|
||||
|
||||
const submit = () => {
|
||||
const submit = (e: any) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
if (limited) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -80,7 +82,7 @@ function ChatInput({
|
|||
);
|
||||
}
|
||||
return (
|
||||
<div className="relative">
|
||||
<div className="relative bg-white">
|
||||
<Input
|
||||
onPressEnter={submit}
|
||||
onKeyDown={(e) => {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue