more fixes ui
This commit is contained in:
@@ -19,6 +19,7 @@ import { Cluster } from '../../services/api';
|
|||||||
import Input from '../../components/form/input/InputField';
|
import Input from '../../components/form/input/InputField';
|
||||||
import Label from '../../components/form/Label';
|
import Label from '../../components/form/Label';
|
||||||
import Button from '../../components/ui/button/Button';
|
import Button from '../../components/ui/button/Button';
|
||||||
|
import { BoltIcon } from '../../icons';
|
||||||
|
|
||||||
export interface ColumnConfig {
|
export interface ColumnConfig {
|
||||||
key: string;
|
key: string;
|
||||||
@@ -93,6 +94,7 @@ export const createClustersPageConfig = (
|
|||||||
volumeDropdownRef: React.RefObject<HTMLDivElement | null>;
|
volumeDropdownRef: React.RefObject<HTMLDivElement | null>;
|
||||||
setCurrentPage: (page: number) => void;
|
setCurrentPage: (page: number) => void;
|
||||||
loadClusters: () => Promise<void>;
|
loadClusters: () => Promise<void>;
|
||||||
|
onGenerateIdeas?: (clusterId: number) => void; // Handler for generate ideas button
|
||||||
}
|
}
|
||||||
): ClustersPageConfig => {
|
): ClustersPageConfig => {
|
||||||
const showSectorColumn = !handlers.activeSector; // Show when viewing all sectors
|
const showSectorColumn = !handlers.activeSector; // Show when viewing all sectors
|
||||||
@@ -129,6 +131,7 @@ export const createClustersPageConfig = (
|
|||||||
sortable: true,
|
sortable: true,
|
||||||
sortField: 'keywords_count',
|
sortField: 'keywords_count',
|
||||||
width: '120px',
|
width: '120px',
|
||||||
|
align: 'center' as const,
|
||||||
render: (value: number) => value.toLocaleString(),
|
render: (value: number) => value.toLocaleString(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -137,6 +140,7 @@ export const createClustersPageConfig = (
|
|||||||
sortable: false, // Backend doesn't support sorting by ideas_count
|
sortable: false, // Backend doesn't support sorting by ideas_count
|
||||||
sortField: 'ideas_count',
|
sortField: 'ideas_count',
|
||||||
width: '120px',
|
width: '120px',
|
||||||
|
align: 'center' as const,
|
||||||
render: (value: number) => (
|
render: (value: number) => (
|
||||||
<Badge
|
<Badge
|
||||||
color={value > 0 ? 'success' : 'light'}
|
color={value > 0 ? 'success' : 'light'}
|
||||||
@@ -155,6 +159,7 @@ export const createClustersPageConfig = (
|
|||||||
sortable: true,
|
sortable: true,
|
||||||
sortField: 'volume',
|
sortField: 'volume',
|
||||||
width: '120px',
|
width: '120px',
|
||||||
|
align: 'center' as const,
|
||||||
render: (value: number) => value.toLocaleString(),
|
render: (value: number) => value.toLocaleString(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -193,6 +198,7 @@ export const createClustersPageConfig = (
|
|||||||
sortable: false, // Backend doesn't support sorting by content_count
|
sortable: false, // Backend doesn't support sorting by content_count
|
||||||
sortField: 'content_count',
|
sortField: 'content_count',
|
||||||
width: '120px',
|
width: '120px',
|
||||||
|
align: 'center' as const,
|
||||||
render: (value: number) => value.toLocaleString(),
|
render: (value: number) => value.toLocaleString(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -244,6 +250,32 @@ export const createClustersPageConfig = (
|
|||||||
defaultVisible: false,
|
defaultVisible: false,
|
||||||
render: (value: string) => formatRelativeDate(value),
|
render: (value: string) => formatRelativeDate(value),
|
||||||
},
|
},
|
||||||
|
// Generate Ideas action column - only shows button for status = 'new'
|
||||||
|
{
|
||||||
|
key: 'generate_action',
|
||||||
|
label: 'Actions',
|
||||||
|
sortable: false,
|
||||||
|
width: '120px',
|
||||||
|
render: (_value: any, row: Cluster) => {
|
||||||
|
// Only show generate button for clusters with status 'new'
|
||||||
|
if (row.status === 'new' && handlers.onGenerateIdeas) {
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
handlers.onGenerateIdeas!(row.id);
|
||||||
|
}}
|
||||||
|
className="inline-flex items-center gap-1 px-3 py-1.5 text-sm font-medium text-white bg-brand-500 hover:bg-brand-600 rounded transition-colors"
|
||||||
|
title="Generate Ideas"
|
||||||
|
>
|
||||||
|
<BoltIcon className="w-4 h-4" />
|
||||||
|
Generate
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return <span className="text-gray-400 dark:text-gray-500 text-sm">-</span>;
|
||||||
|
},
|
||||||
|
},
|
||||||
],
|
],
|
||||||
filters: [
|
filters: [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -296,7 +296,7 @@ export const createContentPageConfig = (
|
|||||||
sortable: true,
|
sortable: true,
|
||||||
sortField: 'word_count',
|
sortField: 'word_count',
|
||||||
width: '100px',
|
width: '100px',
|
||||||
align: 'right',
|
align: 'center' as const,
|
||||||
render: (value: number) => (
|
render: (value: number) => (
|
||||||
<span className="font-mono text-sm text-gray-700 dark:text-gray-300">
|
<span className="font-mono text-sm text-gray-700 dark:text-gray-300">
|
||||||
{value?.toLocaleString() || 0}
|
{value?.toLocaleString() || 0}
|
||||||
|
|||||||
@@ -203,6 +203,7 @@ export const createIdeasPageConfig = (
|
|||||||
sortable: true,
|
sortable: true,
|
||||||
sortField: 'estimated_word_count',
|
sortField: 'estimated_word_count',
|
||||||
width: '100px',
|
width: '100px',
|
||||||
|
align: 'center' as const,
|
||||||
render: (value: number) => value.toLocaleString(),
|
render: (value: number) => value.toLocaleString(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -160,6 +160,7 @@ export const createKeywordsPageConfig = (
|
|||||||
...volumeColumn,
|
...volumeColumn,
|
||||||
sortable: true,
|
sortable: true,
|
||||||
sortField: 'seed_keyword__volume', // Backend expects seed_keyword__volume
|
sortField: 'seed_keyword__volume', // Backend expects seed_keyword__volume
|
||||||
|
align: 'center' as const,
|
||||||
render: (value: number) => value.toLocaleString(),
|
render: (value: number) => value.toLocaleString(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -200,6 +201,7 @@ export const createKeywordsPageConfig = (
|
|||||||
...countryColumn,
|
...countryColumn,
|
||||||
sortable: false, // Backend doesn't support sorting by country
|
sortable: false, // Backend doesn't support sorting by country
|
||||||
sortField: 'seed_keyword__country',
|
sortField: 'seed_keyword__country',
|
||||||
|
align: 'center' as const,
|
||||||
render: (value: string) => {
|
render: (value: string) => {
|
||||||
const countryNames: Record<string, string> = {
|
const countryNames: Record<string, string> = {
|
||||||
'US': 'United States',
|
'US': 'United States',
|
||||||
|
|||||||
@@ -155,12 +155,7 @@ const tableActionsConfigs: Record<string, TableActionsConfig> = {
|
|||||||
icon: EditIcon,
|
icon: EditIcon,
|
||||||
variant: 'primary',
|
variant: 'primary',
|
||||||
},
|
},
|
||||||
{
|
// Generate Ideas moved to dedicated column - only shows for status='new'
|
||||||
key: 'generate_ideas',
|
|
||||||
label: 'Generate Ideas',
|
|
||||||
icon: <BoltIcon className="w-5 h-5" />,
|
|
||||||
variant: 'primary',
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
bulkActions: [
|
bulkActions: [
|
||||||
{
|
{
|
||||||
@@ -175,12 +170,7 @@ const tableActionsConfigs: Record<string, TableActionsConfig> = {
|
|||||||
icon: <DownloadIcon className="w-4 h-4 text-blue-light-500" />,
|
icon: <DownloadIcon className="w-4 h-4 text-blue-light-500" />,
|
||||||
variant: 'secondary',
|
variant: 'secondary',
|
||||||
},
|
},
|
||||||
{
|
// Removed auto_generate_ideas - now row-level only
|
||||||
key: 'auto_generate_ideas',
|
|
||||||
label: 'Generate Ideas',
|
|
||||||
icon: <BoltIcon className="w-4 h-4 text-warning-500" />,
|
|
||||||
variant: 'secondary',
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
'/planner/ideas': {
|
'/planner/ideas': {
|
||||||
|
|||||||
@@ -215,6 +215,7 @@ export const createTasksPageConfig = (
|
|||||||
...wordCountColumn,
|
...wordCountColumn,
|
||||||
sortable: true,
|
sortable: true,
|
||||||
sortField: 'word_count',
|
sortField: 'word_count',
|
||||||
|
align: 'center' as const,
|
||||||
render: (value: number | null | undefined) => (value != null ? value.toLocaleString() : '-'),
|
render: (value: number | null | undefined) => (value != null ? value.toLocaleString() : '-'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -452,16 +452,17 @@ const AppSidebar: React.FC = () => {
|
|||||||
onMouseEnter={() => !isExpanded && setIsHovered(true)}
|
onMouseEnter={() => !isExpanded && setIsHovered(true)}
|
||||||
onMouseLeave={() => setIsHovered(false)}
|
onMouseLeave={() => setIsHovered(false)}
|
||||||
>
|
>
|
||||||
{/* Collapse/Expand Toggle Button - Position changes based on state */}
|
{/* Collapse/Expand Toggle Button - Fixed 5px from sidebar edge, does not move with hover */}
|
||||||
<button
|
<button
|
||||||
onClick={toggleSidebar}
|
onClick={toggleSidebar}
|
||||||
className={`hidden lg:flex absolute top-20 w-6 h-6 items-center justify-center bg-white dark:bg-gray-900 border border-gray-200 dark:border-gray-700 rounded-full shadow-sm hover:bg-gray-50 dark:hover:bg-gray-800 transition-all duration-300 z-50 ${
|
className={`hidden lg:flex absolute top-20 w-6 h-6 items-center justify-center bg-white dark:bg-gray-900 border border-gray-200 dark:border-gray-700 rounded-full shadow-sm hover:bg-gray-50 dark:hover:bg-gray-800 transition-colors z-[60] ${
|
||||||
isExpanded || isHovered ? '-right-3' : 'right-3'
|
isExpanded ? 'left-[295px]' : 'left-[95px]'
|
||||||
}`}
|
}`}
|
||||||
|
style={{ position: 'fixed' }}
|
||||||
aria-label={isExpanded ? "Collapse Sidebar" : "Expand Sidebar"}
|
aria-label={isExpanded ? "Collapse Sidebar" : "Expand Sidebar"}
|
||||||
>
|
>
|
||||||
<svg
|
<svg
|
||||||
className={`w-3.5 h-3.5 text-gray-500 dark:text-gray-400 transition-transform duration-300 ${isExpanded || isHovered ? 'rotate-180' : ''}`}
|
className={`w-3.5 h-3.5 text-gray-500 dark:text-gray-400 transition-transform duration-300 ${isExpanded ? 'rotate-180' : ''}`}
|
||||||
fill="none"
|
fill="none"
|
||||||
stroke="currentColor"
|
stroke="currentColor"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
|
|||||||
@@ -331,6 +331,7 @@ export default function Clusters() {
|
|||||||
volumeDropdownRef,
|
volumeDropdownRef,
|
||||||
setCurrentPage,
|
setCurrentPage,
|
||||||
loadClusters,
|
loadClusters,
|
||||||
|
onGenerateIdeas: (clusterId: number) => handleRowAction('generate_ideas', { id: clusterId } as Cluster),
|
||||||
});
|
});
|
||||||
}, [
|
}, [
|
||||||
activeSector,
|
activeSector,
|
||||||
@@ -344,6 +345,7 @@ export default function Clusters() {
|
|||||||
tempVolumeMin,
|
tempVolumeMin,
|
||||||
tempVolumeMax,
|
tempVolumeMax,
|
||||||
loadClusters,
|
loadClusters,
|
||||||
|
handleRowAction,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Calculate header metrics
|
// Calculate header metrics
|
||||||
@@ -405,12 +407,6 @@ export default function Clusters() {
|
|||||||
volumeMin: volumeMin,
|
volumeMin: volumeMin,
|
||||||
volumeMax: volumeMax,
|
volumeMax: volumeMax,
|
||||||
}}
|
}}
|
||||||
primaryAction={{
|
|
||||||
label: 'Generate Ideas',
|
|
||||||
icon: <BoltIcon className="w-4 h-4" />,
|
|
||||||
onClick: () => handleBulkAction('auto_generate_ideas', selectedIds),
|
|
||||||
variant: 'success',
|
|
||||||
}}
|
|
||||||
onFilterChange={(key, value) => {
|
onFilterChange={(key, value) => {
|
||||||
const stringValue = value === null || value === undefined ? '' : String(value);
|
const stringValue = value === null || value === undefined ? '' : String(value);
|
||||||
if (key === 'search') {
|
if (key === 'search') {
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { useState, useEffect, useMemo, useCallback, useRef } from 'react';
|
import { useState, useEffect, useMemo, useCallback, useRef } from 'react';
|
||||||
|
import { Link, useNavigate } from 'react-router-dom';
|
||||||
import TablePageTemplate from '../../templates/TablePageTemplate';
|
import TablePageTemplate from '../../templates/TablePageTemplate';
|
||||||
import {
|
import {
|
||||||
fetchContent,
|
fetchContent,
|
||||||
@@ -14,9 +15,8 @@ import {
|
|||||||
bulkDeleteContent,
|
bulkDeleteContent,
|
||||||
} from '../../services/api';
|
} from '../../services/api';
|
||||||
import { optimizerApi } from '../../api/optimizer.api';
|
import { optimizerApi } from '../../api/optimizer.api';
|
||||||
import { useNavigate } from 'react-router-dom';
|
|
||||||
import { useToast } from '../../components/ui/toast/ToastContainer';
|
import { useToast } from '../../components/ui/toast/ToastContainer';
|
||||||
import { FileIcon, TaskIcon, CheckCircleIcon } from '../../icons';
|
import { FileIcon, TaskIcon, CheckCircleIcon, ArrowRightIcon } from '../../icons';
|
||||||
import { createContentPageConfig } from '../../config/pages/content.config';
|
import { createContentPageConfig } from '../../config/pages/content.config';
|
||||||
import { useSectorStore } from '../../store/sectorStore';
|
import { useSectorStore } from '../../store/sectorStore';
|
||||||
import { usePageSizeStore } from '../../store/pageSizeStore';
|
import { usePageSizeStore } from '../../store/pageSizeStore';
|
||||||
@@ -273,6 +273,28 @@ export default function Content() {
|
|||||||
onDelete={handleDelete}
|
onDelete={handleDelete}
|
||||||
onBulkDelete={handleBulkDelete}
|
onBulkDelete={handleBulkDelete}
|
||||||
getItemDisplayName={(row: ContentType) => row.title || `Content #${row.id}`}
|
getItemDisplayName={(row: ContentType) => row.title || `Content #${row.id}`}
|
||||||
|
statusExplainer={
|
||||||
|
<div className="text-xs text-gray-600 dark:text-gray-400 space-y-1">
|
||||||
|
<div className="font-medium text-gray-700 dark:text-gray-300">
|
||||||
|
Currently Generated (Draft): {content.filter(c => c.status === 'draft').length}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
Image Prompts: {content.filter(c => c.has_image_prompts).length}/{content.length}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
Images Generated: {content.filter(c => c.has_generated_images).length}/{content.length}
|
||||||
|
</div>
|
||||||
|
<div className="pt-2 border-t border-gray-200 dark:border-gray-700 mt-2">
|
||||||
|
<Link
|
||||||
|
to="/writer/review"
|
||||||
|
className="text-brand-500 hover:text-brand-600 flex items-center gap-1"
|
||||||
|
>
|
||||||
|
<span>Review ({content.filter(c => c.status === 'review').length})</span>
|
||||||
|
<ArrowRightIcon className="w-3 h-3" />
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* Module Metrics Footer - Pipeline Style with Cross-Module Links */}
|
{/* Module Metrics Footer - Pipeline Style with Cross-Module Links */}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { useState, useEffect, useMemo, useCallback, useRef } from 'react';
|
import { useState, useEffect, useMemo, useCallback, useRef } from 'react';
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
import TablePageTemplate from '../../templates/TablePageTemplate';
|
import TablePageTemplate from '../../templates/TablePageTemplate';
|
||||||
import {
|
import {
|
||||||
fetchContentImages,
|
fetchContentImages,
|
||||||
@@ -18,7 +19,7 @@ import {
|
|||||||
bulkDeleteContent,
|
bulkDeleteContent,
|
||||||
} from '../../services/api';
|
} from '../../services/api';
|
||||||
import { useToast } from '../../components/ui/toast/ToastContainer';
|
import { useToast } from '../../components/ui/toast/ToastContainer';
|
||||||
import { FileIcon, DownloadIcon } from '../../icons';
|
import { FileIcon, DownloadIcon, ArrowRightIcon } from '../../icons';
|
||||||
import { PhotoIcon } from '@heroicons/react/24/outline';
|
import { PhotoIcon } from '@heroicons/react/24/outline';
|
||||||
import { createImagesPageConfig } from '../../config/pages/images.config';
|
import { createImagesPageConfig } from '../../config/pages/images.config';
|
||||||
import ImageQueueModal, { ImageQueueItem } from '../../components/common/ImageQueueModal';
|
import ImageQueueModal, { ImageQueueItem } from '../../components/common/ImageQueueModal';
|
||||||
@@ -514,6 +515,28 @@ export default function Images() {
|
|||||||
setCurrentPage(1);
|
setCurrentPage(1);
|
||||||
}}
|
}}
|
||||||
onRowAction={handleRowAction}
|
onRowAction={handleRowAction}
|
||||||
|
statusExplainer={
|
||||||
|
<div className="text-xs text-gray-600 dark:text-gray-400 space-y-1">
|
||||||
|
<div className="font-medium text-gray-700 dark:text-gray-300">
|
||||||
|
Content Images Status
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
Need Images: {images.filter(i => i.overall_status === 'pending').length}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
Images Complete: {images.filter(i => i.overall_status === 'complete').length}
|
||||||
|
</div>
|
||||||
|
<div className="pt-2 border-t border-gray-200 dark:border-gray-700 mt-2">
|
||||||
|
<Link
|
||||||
|
to="/writer/review"
|
||||||
|
className="text-brand-500 hover:text-brand-600 flex items-center gap-1"
|
||||||
|
>
|
||||||
|
<span>Go to Review</span>
|
||||||
|
<ArrowRightIcon className="w-3 h-3" />
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
<ImageQueueModal
|
<ImageQueueModal
|
||||||
isOpen={isQueueModalOpen}
|
isOpen={isQueueModalOpen}
|
||||||
|
|||||||
@@ -453,6 +453,13 @@ export default function Review() {
|
|||||||
setCurrentPage(1);
|
setCurrentPage(1);
|
||||||
}}
|
}}
|
||||||
onRowAction={handleRowAction}
|
onRowAction={handleRowAction}
|
||||||
|
statusExplainer={
|
||||||
|
<div className="text-xs text-gray-600 dark:text-gray-400 space-y-1">
|
||||||
|
<div className="font-medium text-gray-700 dark:text-gray-300">
|
||||||
|
Approve {totalCount} content pages/articles awaiting approval
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
<ModuleMetricsFooter
|
<ModuleMetricsFooter
|
||||||
metrics={[
|
metrics={[
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
* Consistent with Keywords page layout, structure and design
|
* Consistent with Keywords page layout, structure and design
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { useState, useEffect, useCallback, useRef } from 'react';
|
import { useState, useEffect, useCallback, useRef, useMemo } from 'react';
|
||||||
import TablePageTemplate from '../../templates/TablePageTemplate';
|
import TablePageTemplate from '../../templates/TablePageTemplate';
|
||||||
import {
|
import {
|
||||||
fetchTasks,
|
fetchTasks,
|
||||||
|
|||||||
@@ -164,6 +164,8 @@ interface TablePageTemplateProps {
|
|||||||
};
|
};
|
||||||
// Custom row highlight function (returns bg class based on row data)
|
// Custom row highlight function (returns bg class based on row data)
|
||||||
getRowClassName?: (row: any) => string;
|
getRowClassName?: (row: any) => string;
|
||||||
|
// Status explainer component to display on right side of table actions row
|
||||||
|
statusExplainer?: ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function TablePageTemplate({
|
export default function TablePageTemplate({
|
||||||
@@ -202,6 +204,7 @@ export default function TablePageTemplate({
|
|||||||
bulkActions: customBulkActions,
|
bulkActions: customBulkActions,
|
||||||
primaryAction,
|
primaryAction,
|
||||||
getRowClassName,
|
getRowClassName,
|
||||||
|
statusExplainer,
|
||||||
}: TablePageTemplateProps) {
|
}: TablePageTemplateProps) {
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const [isBulkActionsDropdownOpen, setIsBulkActionsDropdownOpen] = useState(false);
|
const [isBulkActionsDropdownOpen, setIsBulkActionsDropdownOpen] = useState(false);
|
||||||
@@ -752,7 +755,16 @@ export default function TablePageTemplate({
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Right side - Action Buttons */}
|
{/* Right side - Status Explainer and Action Buttons */}
|
||||||
|
<div className="flex gap-4 items-start">
|
||||||
|
{/* Status Explainer */}
|
||||||
|
{statusExplainer && (
|
||||||
|
<div className="text-right">
|
||||||
|
{statusExplainer}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Action Buttons */}
|
||||||
<div className="flex gap-2 items-center">
|
<div className="flex gap-2 items-center">
|
||||||
{/* Custom Actions */}
|
{/* Custom Actions */}
|
||||||
{customActions}
|
{customActions}
|
||||||
@@ -788,6 +800,7 @@ export default function TablePageTemplate({
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
{/* Data Table - Match Keywords.tsx exact styling */}
|
{/* Data Table - Match Keywords.tsx exact styling */}
|
||||||
<div className={`rounded-xl border border-gray-200 bg-white dark:border-white/[0.05] dark:bg-white/[0.03] igny8-table-container ${!showContent ? 'loading' : 'loaded'}`} style={{ overflowX: 'auto', overflowY: 'visible' }}>
|
<div className={`rounded-xl border border-gray-200 bg-white dark:border-white/[0.05] dark:bg-white/[0.03] igny8-table-container ${!showContent ? 'loading' : 'loaded'}`} style={{ overflowX: 'auto', overflowY: 'visible' }}>
|
||||||
|
|||||||
Reference in New Issue
Block a user