Skip to content
This repository has been archived by the owner on Apr 18, 2024. It is now read-only.

feat: DIA-601: [FE] User understands that similarity search sometimes automatically filters results #261

Open
wants to merge 17 commits into
base: master
Choose a base branch
from
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
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
"start": "node dev-server.js",
"test": "echo \"Error: no test specified\" && exit 0",
"lint": "yarn run eslint ./src"
},
},
"author": "Heartex, Inc.",
"license": "ISC",
"devDependencies": {
Expand Down Expand Up @@ -80,7 +80,7 @@
"react-dom": "^17.0.2",
"react-hot-loader": "^4.12.20",
"react-hotkeys-hook": "^2.4.0",
"react-icons": "^3.11.0",
"react-icons": "^4.11.0",
"react-virtualized-auto-sizer": "^1.0.2",
"react-window": "^1.8.6",
"react-window-infinite-loader": "^1.0.5",
Expand Down
8 changes: 8 additions & 0 deletions src/components/DataManager/DataManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import { DataView } from "../MainView";
import "./DataManager.styl";
import { Toolbar } from "./Toolbar/Toolbar";

const SIMILARITY_UPPER_LIMIT_PRECISION = 10;

const injector = inject(({ store }) => {
const { sidebarEnabled, sidebarVisible } = store.viewsStore ?? {};

Expand All @@ -33,11 +35,17 @@ const summaryInjector = inject(({ store }) => {
SDK,
};
} else {
const similarityUpperLimit = taskStore?.similarityUpperLimit ?
(Math.ceil(taskStore?.similarityUpperLimit * SIMILARITY_UPPER_LIMIT_PRECISION) / SIMILARITY_UPPER_LIMIT_PRECISION)
:
null;

return {
totalTasks: project?.task_count ?? project?.task_number ?? 0,
totalFoundTasks: taskStore?.total ?? 0,
totalAnnotations: taskStore?.totalAnnotations ?? 0,
totalPredictions: taskStore?.totalPredictions ?? 0,
similarityUpperLimit,
cloudSync: project.target_syncing ?? project.source_syncing ?? false,
};
}
Expand Down
2 changes: 1 addition & 1 deletion src/components/DataManager/DataManager.styl
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@
width 100%

&_shrink
width calc(100% - 350px)
width calc(100% - 420px)
60 changes: 48 additions & 12 deletions src/components/Filters/FilterLine/FilterLine.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import { observer } from "mobx-react";
import { inject, observer } from "mobx-react";
import React, { Fragment } from "react";
import { FaTrash } from "react-icons/fa";
import { LiaTimesSolid } from "react-icons/lia";
import { BemWithSpecifiContext } from "../../../utils/bem";
import { Button } from "../../Common/Button/Button";
import { Icon } from "../../Common/Icon/Icon";
import { Tag } from "../../Common/Tag/Tag";
import { FilterDropdown } from "../FilterDropdown";
import "./FilterLine.styl";
import { FilterOperation } from "./FilterOperation";
import { getRoot } from "mobx-state-tree";

const { Block, Elem } = BemWithSpecifiContext();

Expand All @@ -29,15 +30,31 @@ const Conjunction = observer(({ index, view }) => {
const GroupWrapper = ({ children, wrap = false }) => {
return wrap ? <Elem name="group">{children}</Elem> : children;
};
const injector = inject(({ store }) => ({
store,
}));
const CustomFilter = ({ CustomFilterLine, ...rest }) => <CustomFilterLine {...rest} />;

export const FilterLine = observer(({
export const FilterLine = injector(observer(({
filter,
availableFilters,
index,
view,
sidebar,
dropdownClassName,
store,
}) => {
const customColumn = getRoot(view).SDK?.customColumns?.[filter.field.alias];
const CustomFilterLine = customColumn?.renderFilter?.(
filter,
availableFilters,
index,
view,
sidebar,
dropdownClassName,
store,
);

return (
<Block name="filter-line" tag={Fragment}>
<GroupWrapper wrap={sidebar}>
Expand All @@ -56,7 +73,12 @@ export const FilterLine = observer(({
width={80}
dropdownWidth={120}
dropdownClassName={dropdownClassName}
onChange={(value) => filter.setFilterDelayed(value)}
onChange={(value) => {
const selectedAlias = value.split(":").pop();
const customFilter = getRoot(view).SDK?.customColumns?.[selectedAlias];

customFilter ? customFilter.onFilterAdd?.(value, filter, view) : filter.setFilterDelayed(value);
}}
optionRender={({ item: { original: filter } }) => (
<Elem name="selector">
{filter.field.title}
Expand All @@ -76,24 +98,38 @@ export const FilterLine = observer(({
</Elem>
</GroupWrapper>
<GroupWrapper wrap={sidebar}>
<FilterOperation
filter={filter}
value={filter.currentValue}
operator={filter.operator}
field={filter.field}
/>
{CustomFilterLine ? (
<Elem name='column' mod={{ customFilterLine: true }}>
<CustomFilter
filter={filter}
field={filter.field}
view={view}
CustomFilterLine={CustomFilterLine}
/>
</Elem>
) : (
<FilterOperation
filter={filter}
value={filter.currentValue}
operator={filter.operator}
field={filter.field}
/>
)}
</GroupWrapper>
<Elem name="remove">
<Button
type="link"
onClick={(e) => {
e.stopPropagation();
const customFilter = getRoot(view).SDK?.customColumns?.[filter.field.alias];

customFilter?.onFilterDelete?.(filter, view);
filter.delete();
}}
icon={<Icon icon={FaTrash} size={12} />}
icon={<Icon icon={LiaTimesSolid} size={12} />}
/>
</Elem>
</Block>
);
},
);
));
3 changes: 3 additions & 0 deletions src/components/Filters/FilterLine/FilterLine.styl
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@
display grid
grid-auto-flow column

&_customFilterLine
grid-column 3/5;

&__group
flex 0
display grid
Expand Down
45 changes: 22 additions & 23 deletions src/components/Filters/Filters.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { inject } from "mobx-react";
import React from "react";
import { FaCaretSquareRight, FaPlus } from "react-icons/fa";
import { BsPin } from "react-icons/bs";
import { Block, cn, Elem } from "../../utils/bem";
import { Button } from "../Common/Button/Button";
import { Icon } from "../Common/Icon/Icon";
Expand Down Expand Up @@ -51,32 +51,13 @@ export const Filters = injector(({ views, currentView, filters }) => {

return (
<Block name="filters" mod={{ sidebar: sidebarEnabled }}>
<Elem name="list" mod={{ withFilters: !!filters.length }}>
{filters.length ? (
filters.map((filter, i) => (
<FilterLine
index={i}
filter={filter}
view={currentView}
sidebar={sidebarEnabled}
value={filter.currentValue}
key={`${filter.filter.id}-${i}`}
availableFilters={Object.values(fields)}
dropdownClassName={cn("filters").elem("selector")}
/>
))
) : (
<Elem name="empty">No filters applied</Elem>
)}
</Elem>
<Elem name="actions">
<Button
type="primary"
size="small"
onClick={() => currentView.createFilter()}
icon={<FaPlus />}
>
Add {filters.length ? "Another Filter" : "Filter"}
Add Filter
</Button>

{!sidebarEnabled ? (
Expand All @@ -86,12 +67,30 @@ export const Filters = injector(({ views, currentView, filters }) => {
size="small"
about="Pin to sidebar"
onClick={() => views.expandFilters()}
style={{ display: "inline-flex", alignItems: "center" }}
icon={<Icon icon={FaCaretSquareRight} size={18} />}
style={{ display: "inline-flex", alignItems: "center", border: "none" }}
icon={<Icon icon={BsPin} size={18} />}
/>
</Tooltip>
) : null}
</Elem>
<Elem name="list" mod={{ withFilters: !!filters.length }}>
{filters.length ? (
filters.map((filter, i) => (
<FilterLine
index={i}
filter={filter}
view={currentView}
sidebar={sidebarEnabled}
value={filter.currentValue}
key={`${filter.filter.id}-${i}`}
availableFilters={Object.values(fields)}
dropdownClassName={cn("filters").elem("selector")}
/>
))
) : (
<Elem name="empty">No filters applied</Elem>
)}
</Elem>
</Block>
);
});
31 changes: 27 additions & 4 deletions src/components/Filters/Filters.styl
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
.filters
background-color white
position relative
padding-top 15px

&:not(&_sidebar)
padding-top 10px
min-width: 400px;
min-width 625px
border-radius: 2px;
box-shadow: 0 3px 6px -4px rgba(0, 0, 0, 0.12),
0 6px 16px 0 rgba(0, 0, 0, 0.08), 0 9px 28px 8px rgba(0, 0, 0, 0.05);
Expand Down Expand Up @@ -37,8 +38,7 @@

&__actions
display flex
margin-top 10px
padding 0 10px 10px
padding 0 16px 16px
justify-content space-between

&__empty
Expand All @@ -47,12 +47,13 @@
color #585858

&__list
padding 0 10px
padding 0 10px 15px

&_withFilters
display grid
grid-template-columns 65px min-content min-content 1fr 24px
grid-gap 3px 4px
align-items center

&_sidebar &__list
&_withFilters
Expand All @@ -61,6 +62,28 @@
grid-auto-flow row
align-items center

.button
--button-color rgba(9, 109, 217, 1)
box-shadow none
border 1px solid rgba(9, 109, 217, 0.16)
height 32px
font-size 16px
font-style normal
font-weight 500
line-height 24px
letter-spacing 0.15px
padding 8px 16px
&_withIcon
padding 0
.icon
svg
width 18px
height 18px

&__list
.button
border 0 none
--button-color rgba(137, 128, 152, 1)
.filter-data-tag
margin 1px
font-size 12px
Expand Down
3 changes: 2 additions & 1 deletion src/sdk/dm-sdk.js
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ export class DataManager {
edit: true,
duplicate: true,
}
customColumns = {};

/** @type {"dm" | "labelops"} */
type = "dm";
Expand Down Expand Up @@ -199,7 +200,7 @@ export class DataManager {
this.actions.set(action.id, { action, callback });
});
}

this.customColumns = config.customColumns ?? {};
this.type = config.type ?? "dm";

this.initApp();
Expand Down
2 changes: 2 additions & 0 deletions src/stores/AppStore.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ export const AppStore = types
interfaces: types.map(types.boolean),

toolbar: types.string,

customColumns: types.optional(CustomJSON, {}),
})
.views((self) => ({
/** @returns {import("../sdk/dm-sdk").DataManager} */
Expand Down
7 changes: 5 additions & 2 deletions src/stores/DataStores/tasks.js
Original file line number Diff line number Diff line change
Expand Up @@ -218,17 +218,19 @@ export const create = (columns) => {
},

postProcessData(data) {
const { total_annotations, total_predictions } = data;
const { total_annotations, total_predictions, similarity_score_upper_limit } = data;

if (total_annotations !== null)
self.totalAnnotations = total_annotations;
if (total_predictions !== null)
self.totalPredictions = total_predictions;
if (total_predictions !== null)
self.similarityUpperLimit = similarity_score_upper_limit;
},

}))
.preProcessSnapshot((snapshot) => {
const { total_annotations, total_predictions, ...sn } = snapshot;
const { total_annotations, total_predictions, similarity_score_upper_limit, ...sn } = snapshot;

return {
...sn,
Expand All @@ -239,6 +241,7 @@ export const create = (columns) => {
})),
totalAnnotations: total_annotations,
totalPredictions: total_predictions,
similarityUpperLimit: similarity_score_upper_limit,
};
});
};
6 changes: 5 additions & 1 deletion src/stores/Tabs/store.js
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,8 @@ export const TabStore = types
fetchColumns() {
const columns = self.columnsRaw;
const targets = unique(columns.map((c) => c.target));
const rootSDK = getRoot(self).SDK;
const customColumns = rootSDK.customColumns ?? {};
const hiddenColumns = {};
const addedColumns = new Set();

Expand Down Expand Up @@ -434,7 +436,9 @@ export const TabStore = types

addedColumns.add(column.id);

if (!col.children && column.filterable && (col?.visibility_defaults?.filter ?? true)) {
if (!col.children && column.filterable && (
(col?.visibility_defaults?.filter ?? true) || (customColumns[col.id]?.filterable ?? false)
)) {
self.availableFilters.push({
id: `filter:${columnID}`,
type: col.type,
Expand Down
Loading