Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 10 additions & 11 deletions components/KernDropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ export default function KernDropdown(props: KernDropdownProps) {
setDropdownCaptions(prepareOptions);
setSearchIndexes(null);
}
}, [props.options, searchText, selectedCheckboxes, props.hasSearchBar, props.hasCheckboxes, props.selectedCheckboxes, props.hasSelectAll, props.valuePropertyPath]);
}, [props.options, searchText, props.hasSearchBar, props.hasCheckboxes, props.valuePropertyPath, props.selectedCheckboxes, props.hasSelectAll]);

useEffect(() => {
if (!props.disabledOptions || !props.options) return;
Expand Down Expand Up @@ -94,8 +94,7 @@ export default function KernDropdown(props: KernDropdownProps) {
return { "maxHeight": `${maxHeight}rem`, "overflowY": "auto" };
}, [props.scrollAfterNOptions]);

function setOptionsWithCheckboxes(options: any[]) {
if (selectedCheckboxes.length > 0) return;
const setOptionsWithCheckboxes = useCallback((options: any[]) => {
const newSelectedCheckboxes = options.map((option: any, index: number) => {
return {
name: option,
Expand All @@ -110,15 +109,15 @@ export default function KernDropdown(props: KernDropdownProps) {
}
setSelectedCheckboxes(newSelectedCheckboxes);
setDropdownCaptions(newSelectedCheckboxes.map((option: any) => option.name));
}
}, [props.hasSelectAll, props.selectedCheckboxes]);

function toggleDropdown() {
if (isDisabled && !props.hasCheckboxes) return; // if the dropdown has checkboxes, it shouldn't be disabled because the user can still select options
if (isOpen && props.keepDrownOpen) return;
setIsOpen(!isOpen);
}

function handleSelectedCheckboxes(option: string, index: number, e: any) {
const handleSelectedCheckboxes = useCallback((option: string, index: number, e: any) => {
let newSelectedCheckboxes = [...selectedCheckboxes];
if (option == SELECT_ALL) {
newSelectedCheckboxes.forEach((checkbox) => {
Expand All @@ -136,7 +135,7 @@ export default function KernDropdown(props: KernDropdownProps) {
newSelectedCheckboxes = newSelectedCheckboxes.filter((checkbox) => checkbox.name != SELECT_ALL);
}
props.selectedOption(newSelectedCheckboxes);
}
}, [selectedCheckboxes, props.hasSelectAll]);

function handleSelectedCheckboxesThreeStates(index: number) {
const optionSave = { ...props.options[index] };
Expand All @@ -161,8 +160,7 @@ export default function KernDropdown(props: KernDropdownProps) {
setSavedIndex(index);
}


function performActionOnClick(option: string, index: number) {
const performActionOnClick = useCallback((option: string, index: number) => {
if (props.hasCheckboxes) {
handleSelectedCheckboxes(option, index, { target: { checked: !selectedCheckboxes[index].checked } });
return;
Expand All @@ -180,8 +178,9 @@ export default function KernDropdown(props: KernDropdownProps) {
props.selectedOption(props.options[index]);
}
setIsOpen(false);
setSelectedCheckboxes([]);
}
}
}, [props, selectedCheckboxes, searchIndexes]);

return (
<Menu ref={dropdownRef} as="div" className={`relative inline-block text-left ${props.dropdownWidth ?? 'w-full'} ${props.dropdownClasses ?? ''} ${props.fontClass ?? ''}`}>
Expand Down Expand Up @@ -213,7 +212,7 @@ export default function KernDropdown(props: KernDropdownProps) {
) : (<Menu.Button onClick={toggleDropdown} className={`inline-flex w-full justify-between items-center rounded-md border border-gray-300 px-4 py-2 text-sm font-semibold text-gray-700 shadow-sm focus:outline-none focus:ring-2
focus:ring-gray-300 focus:ring-offset-2 focus:ring-offset-gray-100 disabled:opacity-50 disabled:cursor-not-allowed ${props.buttonClasses ?? ''} ${props.buttonCaptionBgColor ?? 'bg-white hover:bg-gray-50'}`}
disabled={isDisabled && !props.hasCheckboxes}>
<div className='flex items-center gap-x-1'>
<div className={`flex items-center gap-x-1 ${props.truncateButtonName ? 'max-w-[300px] truncate' : ''}`}>
{props.buttonPrefixIcon}
{!props.hasCheckboxesThreeStates && props.buttonName}
</div>
Expand Down Expand Up @@ -266,7 +265,7 @@ export default function KernDropdown(props: KernDropdownProps) {
if (!props.optionsHaveHoverBox) return;
setHoverBoxPosition(null);
}}>
{props.hasCheckboxes && <input checked={selectedCheckboxes[index].checked} name="option" type="checkbox" className="mr-3 cursor-pointer"
{props.hasCheckboxes && <input checked={!!selectedCheckboxes[index]?.checked} name="option" type="checkbox" className="mr-3 cursor-pointer"
onChange={(e) => handleSelectedCheckboxes(option, index, e)} />}
{props.hasCheckboxesThreeStates && <div className="h-4 w-4 border-gray-300 mr-3 border rounded hover:bg-gray-200 min-w-4"
style={{ backgroundColor: getActiveNegateGroupColor(props.options[index]), borderColor: getActiveNegateGroupColor(props.options[index]) }}>
Expand Down
43 changes: 42 additions & 1 deletion components/kern-table/CellComponents.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -345,4 +345,45 @@ function ConfigReleaseNotificationCell({ onClickView, onClickEdit }) {
</div>;
}

export { OrganizationAndUsersCell, MaxRowsColsCharsCell, CommentsCell, ExportConsumptionAndDeleteCell, BadgeCell, OrganizationUserCell, DeleteCell, LevelCell, ArchiveReasonCell, ProjectNameTaskCell, CancelTaskCell, IconCell, ConfigCell, EditDeleteOrgButtonCell, ViewStackCell, AbortSessionButtonCell, FeedbackMessageCell, FeedbackMessageTextCell, JumpToConversationCell, RemoteVersionCell, ExternalLinkCell, ModelDateCell, FileSizeCell, StatusModelCell, DeleteModelCell, LabelCell, ViewCell, EvaluationRunStateCell, EvaluationRunDetailsCell, EtlApiTokenCell, EmailCell, EditIntegrationCell, ExpiredTokenCell, LinkCell, ConfigReleaseNotificationCell }
function TruncateAndTooltipCell({ value, hasError = false }) {
return <div className="flex items-center">
{hasError && <MemoIconAlertTriangleFilled className="h-5 w-5 text-red-600 mr-2" />}
{value ? <Tooltip content={<span className="whitespace-pre-wrap">{value}</span>} color="invert" hideArrow={true} placement='bottom'>
<span className="block max-w-56 truncate">{value}</span>
</Tooltip> : <NotApplicableBadge />}
</div>;
}

function JumpToConversationAndAssignCell({ onClick }) {
const clickArrow = useCallback(() => {
if (onClick) onClick();
}, [onClick]);

return <div className="flex justify-center">
<Tooltip content="Assign user to the org and jump to conversation" color="invert" className="cursor-auto">
<button onClick={clickArrow}
className='inline-flex p-2 items-center justify-center rounded-lg hover:bg-gray-200'>
<MemoIconArrowRight className='h-4 w-4' />
</button>
</Tooltip>
</div>
}

function TaskStateCell({ value, color }) {
const className = useMemo(() => {
return `inline-flex items-center px-2 py-0.5 rounded text-xs font-medium ${color === 'green'
? 'bg-green-300'
: 'bg-' + color + '-100 text-' + color + '-800'}`;
}, [color]);

return (
<span className={className}>
<svg className={`mr-1.5 h-2 w-2 ${'text-' + color + '-400'}`} fill="currentColor" viewBox="0 0 8 8">
<circle cx="4" cy="4" r="3" />
</svg>
<span className={' text-' + color + '-800'}>{value}</span>
</span>
);
}

export { OrganizationAndUsersCell, MaxRowsColsCharsCell, CommentsCell, ExportConsumptionAndDeleteCell, BadgeCell, OrganizationUserCell, DeleteCell, LevelCell, ArchiveReasonCell, ProjectNameTaskCell, CancelTaskCell, IconCell, ConfigCell, EditDeleteOrgButtonCell, ViewStackCell, AbortSessionButtonCell, FeedbackMessageCell, FeedbackMessageTextCell, JumpToConversationCell, RemoteVersionCell, ExternalLinkCell, ModelDateCell, FileSizeCell, StatusModelCell, DeleteModelCell, LabelCell, ViewCell, EvaluationRunStateCell, EvaluationRunDetailsCell, EtlApiTokenCell, EmailCell, EditIntegrationCell, ExpiredTokenCell, LinkCell, ConfigReleaseNotificationCell, TruncateAndTooltipCell, JumpToConversationAndAssignCell, TaskStateCell }
8 changes: 7 additions & 1 deletion components/kern-table/KernTable.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import SortArrows from "@/submodules/react-components/components/kern-table/SortArrows";
import { KernTableProps } from "../../types/kern-table";
import { AbortSessionButtonCell, ArchiveReasonCell, BadgeCell, CancelTaskCell, CommentsCell, ConfigCell, DeleteModelCell, DeleteCell, EditDeleteOrgButtonCell, EmailCell, EtlApiTokenCell, EvaluationRunDetailsCell, EvaluationRunStateCell, ExportConsumptionAndDeleteCell, ExternalLinkCell, FeedbackMessageCell, FeedbackMessageTextCell, FileSizeCell, IconCell, JumpToConversationCell, LabelCell, LevelCell, MaxRowsColsCharsCell, ModelDateCell, OrganizationAndUsersCell, OrganizationUserCell, ProjectNameTaskCell, RemoteVersionCell, StatusModelCell, ViewCell, ViewStackCell, EditIntegrationCell, ExpiredTokenCell, LinkCell, ConfigReleaseNotificationCell } from "./CellComponents";
import { AbortSessionButtonCell, ArchiveReasonCell, BadgeCell, CancelTaskCell, CommentsCell, ConfigCell, DeleteModelCell, DeleteCell, EditDeleteOrgButtonCell, EmailCell, EtlApiTokenCell, EvaluationRunDetailsCell, EvaluationRunStateCell, ExportConsumptionAndDeleteCell, ExternalLinkCell, FeedbackMessageCell, FeedbackMessageTextCell, FileSizeCell, IconCell, JumpToConversationCell, LabelCell, LevelCell, MaxRowsColsCharsCell, ModelDateCell, OrganizationAndUsersCell, OrganizationUserCell, ProjectNameTaskCell, RemoteVersionCell, StatusModelCell, ViewCell, ViewStackCell, EditIntegrationCell, ExpiredTokenCell, LinkCell, ConfigReleaseNotificationCell, TruncateAndTooltipCell, JumpToConversationAndAssignCell, TaskStateCell } from "./CellComponents";
import { Fragment, useMemo } from "react";
import KernDropdown from "../KernDropdown";
import { NotApplicableBadge } from "@/submodules/react-components/components/Badges";
Expand Down Expand Up @@ -162,6 +162,12 @@ function ComponentMapper(cell: any) {
return <LinkCell {...cell} />;
case 'ConfigReleaseNotificationCell':
return <ConfigReleaseNotificationCell {...cell} />;
case 'TruncateAndTooltipCell':
return <TruncateAndTooltipCell {...cell} />;
case 'JumpToConversationAndAssignCell':
return <JumpToConversationAndAssignCell {...cell} />;
case 'TaskStateCell':
return <TaskStateCell {...cell} />;
case '@provided@':
return cell.jsx ?? <NotApplicableBadge />;
}
Expand Down
2 changes: 2 additions & 0 deletions types/dropdown.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ import React from "react";
* @positionDropdown {string} - The position of the dropdown
* @dropdownAdd {JSX.Element} - array of JSX elements that will be added to the dropdown items
* @forceOverwriteOpen {boolean} - forces the dropdown to stay open until set to false/undefined
* @truncateButtonName {boolean} - If the button name should be truncated when it exceeds the button width
*/
export type KernDropdownProps = {
buttonName?: string;
Expand Down Expand Up @@ -93,6 +94,7 @@ export type KernDropdownProps = {
scrollAfterNOptions?: number;
dropdownAdd?: JSX.Element[];
forceOverwriteOpen?: boolean;
truncateButtonName?: boolean;
}

export type AppSelectionDropdownProps = {
Expand Down