diff --git a/web/src/app/chat/modifiers/ChatFilters.tsx b/web/src/app/chat/modifiers/ChatFilters.tsx
deleted file mode 100644
index 61c45f12d..000000000
--- a/web/src/app/chat/modifiers/ChatFilters.tsx
+++ /dev/null
@@ -1,453 +0,0 @@
-import React, { useEffect, useRef, useState } from "react";
-import { DocumentSet, Tag, ValidSources } from "@/lib/types";
-import { SourceMetadata } from "@/lib/search/interfaces";
-import {
- FiBook,
- FiBookmark,
- FiCalendar,
- FiFilter,
- FiMap,
- FiTag,
- FiX,
-} from "react-icons/fi";
-import { DateRangePickerValue } from "@tremor/react";
-import { listSourceMetadata } from "@/lib/sources";
-import { SourceIcon } from "@/components/SourceIcon";
-import { BasicClickable } from "@/components/BasicClickable";
-import { ControlledPopup, DefaultDropdownElement } from "@/components/Dropdown";
-import { getXDaysAgo } from "@/lib/dateUtils";
-import { SourceSelectorProps } from "@/components/search/filtering/Filters";
-import { containsObject, objectsAreEquivalent } from "@/lib/contains";
-
-enum FilterType {
- Source = "Source",
- KnowledgeSet = "Knowledge Set",
- TimeRange = "Time Range",
- Tag = "Tag",
-}
-
-function SelectedBubble({
- children,
- onClick,
-}: {
- children: string | JSX.Element;
- onClick: () => void;
-}) {
- return (
-
- {children}
-
-
- );
-}
-
-function SelectFilterType({
- onSelect,
- hasSources,
- hasKnowledgeSets,
- hasTags,
-}: {
- onSelect: (filterType: FilterType) => void;
- hasSources: boolean;
- hasKnowledgeSets: boolean;
- hasTags: boolean;
-}) {
- return (
-
- {hasSources && (
- onSelect(FilterType.Source)}
- isSelected={false}
- />
- )}
-
- {hasKnowledgeSets && (
- onSelect(FilterType.KnowledgeSet)}
- isSelected={false}
- />
- )}
-
- {hasTags && (
- onSelect(FilterType.Tag)}
- isSelected={false}
- />
- )}
-
- onSelect(FilterType.TimeRange)}
- isSelected={false}
- />
-
- );
-}
-
-function SourcesSection({
- sources,
- selectedSources,
- onSelect,
-}: {
- sources: SourceMetadata[];
- selectedSources: string[];
- onSelect: (source: SourceMetadata) => void;
-}) {
- return (
-
- {sources.map((source) => (
- onSelect(source)}
- isSelected={selectedSources.includes(source.internalName)}
- includeCheckbox
- />
- ))}
-
- );
-}
-
-function KnowledgeSetsSection({
- documentSets,
- selectedDocumentSets,
- onSelect,
-}: {
- documentSets: DocumentSet[];
- selectedDocumentSets: string[];
- onSelect: (documentSetName: string) => void;
-}) {
- return (
-
- {documentSets.map((documentSet) => (
- onSelect(documentSet.name)}
- isSelected={selectedDocumentSets.includes(documentSet.name)}
- includeCheckbox
- />
- ))}
-
- );
-}
-
-const LAST_30_DAYS = "Last 30 days";
-const LAST_7_DAYS = "Last 7 days";
-const TODAY = "Today";
-
-function TimeRangeSection({
- selectedTimeRange,
- onSelect,
-}: {
- selectedTimeRange: string | null;
- onSelect: (timeRange: DateRangePickerValue) => void;
-}) {
- return (
-
-
- onSelect({
- to: new Date(),
- from: getXDaysAgo(30),
- selectValue: LAST_30_DAYS,
- })
- }
- isSelected={selectedTimeRange === LAST_30_DAYS}
- />
-
-
- onSelect({
- to: new Date(),
- from: getXDaysAgo(7),
- selectValue: LAST_7_DAYS,
- })
- }
- isSelected={selectedTimeRange === LAST_7_DAYS}
- />
-
-
- onSelect({
- to: new Date(),
- from: getXDaysAgo(1),
- selectValue: TODAY,
- })
- }
- isSelected={selectedTimeRange === TODAY}
- />
-
- );
-}
-
-function TagsSection({
- availableTags,
- selectedTags,
- onSelect,
-}: {
- availableTags: Tag[];
- selectedTags: Tag[];
- onSelect: (tag: Tag) => void;
-}) {
- const [filterValue, setFilterValue] = useState("");
- const inputRef = useRef(null);
-
- useEffect(() => {
- if (inputRef.current) {
- inputRef.current.focus();
- }
- }, []);
-
- const filterValueLower = filterValue.toLowerCase();
- const filteredTags = filterValueLower
- ? availableTags.filter(
- (tags) =>
- tags.tag_value.toLowerCase().startsWith(filterValueLower) ||
- tags.tag_key.toLowerCase().startsWith(filterValueLower)
- )
- : availableTags;
-
- return (
-
-
- {filteredTags.length > 0 ? (
- filteredTags.map((tag) => (
-
- {tag.tag_key}
- =
- {tag.tag_value}
-
- }
- onSelect={() => onSelect(tag)}
- isSelected={selectedTags.includes(tag)}
- includeCheckbox
- />
- ))
- ) : (
-
No matching tags found
- )}
-
-
-
- setFilterValue(event.target.value)}
- />
-
-
- );
-}
-
-export function ChatFilters({
- timeRange,
- setTimeRange,
- selectedSources,
- setSelectedSources,
- selectedDocumentSets,
- setSelectedDocumentSets,
- selectedTags,
- setSelectedTags,
- availableDocumentSets,
- existingSources,
- availableTags,
-}: SourceSelectorProps) {
- const [filtersOpen, setFiltersOpen] = useState(false);
- const handleFiltersToggle = (value: boolean) => {
- setSelectedFilterType(null);
- setFiltersOpen(value);
- };
- const [selectedFilterType, setSelectedFilterType] =
- useState(null);
-
- const handleSourceSelect = (source: SourceMetadata) => {
- setSelectedSources((prev: SourceMetadata[]) => {
- const prevSourceNames = prev.map((source) => source.internalName);
- if (prevSourceNames.includes(source.internalName)) {
- return prev.filter((s) => s.internalName !== source.internalName);
- } else {
- return [...prev, source];
- }
- });
- };
-
- const handleDocumentSetSelect = (documentSetName: string) => {
- setSelectedDocumentSets((prev: string[]) => {
- if (prev.includes(documentSetName)) {
- return prev.filter((s) => s !== documentSetName);
- } else {
- return [...prev, documentSetName];
- }
- });
- };
-
- const handleTagToggle = (tag: Tag) => {
- setSelectedTags((prev) => {
- if (containsObject(prev, tag)) {
- return prev.filter((t) => !objectsAreEquivalent(t, tag));
- } else {
- return [...prev, tag];
- }
- });
- };
-
- const allSources = listSourceMetadata();
- const availableSources = allSources.filter((source) =>
- existingSources.includes(source.internalName)
- );
-
- let popupDisplay = null;
- if (selectedFilterType === FilterType.Source) {
- popupDisplay = (
- source.internalName)}
- onSelect={handleSourceSelect}
- />
- );
- } else if (selectedFilterType === FilterType.KnowledgeSet) {
- popupDisplay = (
-
- );
- } else if (selectedFilterType === FilterType.TimeRange) {
- popupDisplay = (
- {
- setTimeRange(timeRange);
- handleFiltersToggle(!filtersOpen);
- }}
- />
- );
- } else if (selectedFilterType === FilterType.Tag) {
- popupDisplay = (
-
- );
- } else {
- popupDisplay = (
- setSelectedFilterType(filterType)}
- hasSources={availableSources.length > 0}
- hasKnowledgeSets={availableDocumentSets.length > 0}
- hasTags={availableTags.length > 0}
- />
- );
- }
-
- return (
-
-
-
-
handleFiltersToggle(!filtersOpen)}>
-
- Filter
-
-
-
-
-
-
- {((timeRange && timeRange.selectValue !== undefined) ||
- selectedSources.length > 0 ||
- selectedDocumentSets.length > 0) && (
-
Currently applied:
- )}
-
- {timeRange && timeRange.selectValue && (
-
setTimeRange(null)}>
- {timeRange.selectValue}
-
- )}
- {existingSources.length > 0 &&
- selectedSources.map((source) => (
-
handleSourceSelect(source)}
- >
- <>
-
- {source.displayName}
- >
-
- ))}
- {selectedDocumentSets.length > 0 &&
- selectedDocumentSets.map((documentSetName) => (
-
handleDocumentSetSelect(documentSetName)}
- >
- <>
-
-
-
- {documentSetName}
- >
-
- ))}
-
- {selectedTags.length > 0 &&
- selectedTags.map((tag) => (
-
handleTagToggle(tag)}
- >
- <>
-
-
-
-
- {tag.tag_key}
- =
- {tag.tag_value}
-
- >
-
- ))}
-
-
-
- );
-}
diff --git a/web/src/app/config/timeRange.tsx b/web/src/app/config/timeRange.tsx
new file mode 100644
index 000000000..ab7cf4768
--- /dev/null
+++ b/web/src/app/config/timeRange.tsx
@@ -0,0 +1,9 @@
+import { getXDaysAgo, getXYearsAgo } from "@/lib/dateUtils";
+
+export const timeRangeValues = [
+ { label: "Last 2 years", value: getXYearsAgo(2) },
+ { label: "Last year", value: getXYearsAgo(1) },
+ { label: "Last 30 days", value: getXDaysAgo(30) },
+ { label: "Last 7 days", value: getXDaysAgo(7) },
+ { label: "Today", value: getXDaysAgo(1) },
+];
diff --git a/web/src/components/filters/TimeRangeSelector.tsx b/web/src/components/filters/TimeRangeSelector.tsx
new file mode 100644
index 000000000..7583a2fd8
--- /dev/null
+++ b/web/src/components/filters/TimeRangeSelector.tsx
@@ -0,0 +1,32 @@
+import { DefaultDropdownElement } from "../Dropdown";
+export function TimeRangeSelector({
+ value,
+ onValueChange,
+ className,
+ timeRangeValues,
+}: {
+ value: any;
+ onValueChange: any;
+ className: any;
+
+ timeRangeValues: { label: string; value: Date }[];
+}) {
+ return (
+
+ {timeRangeValues.map((timeRangeValue) => (
+
+ onValueChange({
+ to: new Date(),
+ from: timeRangeValue.value,
+ selectValue: timeRangeValue.label,
+ })
+ }
+ isSelected={value?.selectValue === timeRangeValue.label}
+ />
+ ))}
+
+ );
+}
diff --git a/web/src/components/search/DateRangeSelector.tsx b/web/src/components/search/DateRangeSelector.tsx
index 13b42887b..dcbd5c1eb 100644
--- a/web/src/components/search/DateRangeSelector.tsx
+++ b/web/src/components/search/DateRangeSelector.tsx
@@ -1,11 +1,8 @@
-import { getXDaysAgo } from "@/lib/dateUtils";
import { DateRangePickerValue } from "@tremor/react";
import { FiCalendar, FiChevronDown, FiXCircle } from "react-icons/fi";
-import { CustomDropdown, DefaultDropdownElement } from "../Dropdown";
-
-export const LAST_30_DAYS = "Last 30 days";
-export const LAST_7_DAYS = "Last 7 days";
-export const TODAY = "Today";
+import { CustomDropdown } from "../Dropdown";
+import { timeRangeValues } from "@/app/config/timeRange";
+import { TimeRangeSelector } from "@/components/filters/TimeRangeSelector";
export function DateRangeSelector({
value,
@@ -20,59 +17,23 @@ export function DateRangeSelector({
-
- onValueChange({
- to: new Date(),
- from: getXDaysAgo(30),
- selectValue: LAST_30_DAYS,
- })
- }
- isSelected={value?.selectValue === LAST_30_DAYS}
- />
-
-
- onValueChange({
- to: new Date(),
- from: getXDaysAgo(7),
- selectValue: LAST_7_DAYS,
- })
- }
- isSelected={value?.selectValue === LAST_7_DAYS}
- />
-
-
- onValueChange({
- to: new Date(),
- from: getXDaysAgo(1),
- selectValue: TODAY,
- })
- }
- isSelected={value?.selectValue === TODAY}
- />
-
+ border
+ border-border
+ bg-background
+ rounded-lg
+ flex
+ flex-col
+ w-64
+ max-h-96
+ overflow-y-auto
+ flex
+ overscroll-contain`}
+ timeRangeValues={timeRangeValues}
+ onValueChange={onValueChange}
+ />
}
>
{
const date = new Date(timestamp);
const year = date.getFullYear();