Skip to content

Commit

Permalink
Merge pull request #2785 from the-deep/project/auto-extraction
Browse files Browse the repository at this point in the history
Project/Auto Extraction and Tagging
  • Loading branch information
AdityaKhatri authored Dec 21, 2023
2 parents 2bb8b2e + 3235ac2 commit deff650
Show file tree
Hide file tree
Showing 20 changed files with 1,455 additions and 122 deletions.
9 changes: 8 additions & 1 deletion app/components/entry/EntryInput/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,9 @@ interface EntryInputProps<T extends string | number | undefined> {
allWidgets: Widget[] | undefined | null;
rightComponent?: React.ReactNode;
noPaddingInWidgetContainer?: boolean;

excerptShown?: boolean;
displayHorizontally?: boolean;
}

function EntryInput<T extends string | number | undefined>(props: EntryInputProps<T>) {
Expand Down Expand Up @@ -111,6 +114,8 @@ function EntryInput<T extends string | number | undefined>(props: EntryInputProp
onApplyToAll,
rightComponent,
noPaddingInWidgetContainer = false,
excerptShown = false,
displayHorizontally = false,
} = props;

const error = getErrorObject(riskyError);
Expand Down Expand Up @@ -194,11 +199,12 @@ function EntryInput<T extends string | number | undefined>(props: EntryInputProp
className={_cs(
className,
compactMode && styles.compact,
displayHorizontally && styles.horizontal,
styles.entryInput,
)}
>
<NonFieldError error={error} />
{!compactMode && (
{(!compactMode || excerptShown) && (
<Container
className={styles.excerpt}
heading={(
Expand Down Expand Up @@ -244,6 +250,7 @@ function EntryInput<T extends string | number | undefined>(props: EntryInputProp
styles.section,
sectionContainerClassName,
compactMode && styles.compact,
displayHorizontally && styles.horizontal,
)}
renderer={CompactSection}
keySelector={sectionKeySelector}
Expand Down
11 changes: 11 additions & 0 deletions app/components/entry/EntryInput/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,24 @@
}
}

&.horizontal {
flex-direction: row;
.excerpt {
width: 100%;
max-width: 30rem;
}
}

.section {
background-color: var(--dui-color-foreground);
width: var(--inner-width);

&.compact {
border-bottom: var(--dui-width-separator-thin) solid var(--dui-color-separator);
}
&.horizontal {
border-bottom: unset;
}
}

.secondary-tagging {
Expand Down
145 changes: 145 additions & 0 deletions app/components/selections/FrameworkTagSelectInput/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
import React, { useMemo, useCallback } from 'react';
import {
Button,
BadgeInput,
BadgeInputProps,
} from '@the-deep/deep-ui';
import { useQuery, gql } from '@apollo/client';

import {
FrameworkTagOptionsQuery,
FrameworkTagOptionsQueryVariables,
} from '#generated/types';

import styles from './styles.css';

const FRAMEWORK_TAGS = gql`
query FrameworkTagOptions(
$page: Int,
$pageSize: Int,
) {
analysisFrameworkTags(
page: $page,
pageSize: $pageSize,
) {
page
pageSize
results {
description
id
title
icon {
name
url
}
}
totalCount
}
}
`;

const PAGE_SIZE = 10;

type BasicFrameworkTag = NonNullable<NonNullable<NonNullable<FrameworkTagOptionsQuery>['analysisFrameworkTags']>['results']>[number];
const keySelector = (item: BasicFrameworkTag) => item.id;
const labelSelector = (item: BasicFrameworkTag) => item.title;
const titleSelector = (item: BasicFrameworkTag) => item.description;
function iconSelector(item: BasicFrameworkTag) {
if (!item.icon?.url) {
return undefined;
}
return (
<img
className={styles.icon}
src={item.icon.url}
alt={item.icon.url}
/>
);
}

type Props<N extends string> = Omit<
BadgeInputProps<BasicFrameworkTag, N, string>,
'options' | 'keySelector' | 'labelSelector'
>;

function FrameworkTagSelectInput<N extends string>(
props: Props<N>,
) {
const variables = useMemo(() => ({
page: 1,
pageSize: PAGE_SIZE,
}), []);

const {
data,
fetchMore,
} = useQuery<FrameworkTagOptionsQuery, FrameworkTagOptionsQueryVariables>(
FRAMEWORK_TAGS,
{
variables,
},
);

const handleShowMoreClick = useCallback(() => {
fetchMore({
variables: {
...variables,
page: (data?.analysisFrameworkTags?.page ?? 1) + 1,
},
updateQuery: (previousResult, { fetchMoreResult }) => {
if (!previousResult.analysisFrameworkTags) {
return previousResult;
}

const oldFrameworkTags = previousResult.analysisFrameworkTags;
const newFrameworkTags = fetchMoreResult?.analysisFrameworkTags;

if (!newFrameworkTags) {
return previousResult;
}

return ({
...previousResult,
analysisFrameworkTags: {
...newFrameworkTags,
results: [
...(oldFrameworkTags.results ?? []),
...(newFrameworkTags.results ?? []),
],
},
});
},
});
}, [
data?.analysisFrameworkTags?.page,
fetchMore,
variables,
]);

return (
<>
<BadgeInput
{...props}
keySelector={keySelector}
labelSelector={labelSelector}
titleSelector={titleSelector}
iconSelector={iconSelector}
options={data?.analysisFrameworkTags?.results ?? undefined}
smallButtons
/>
{(data?.analysisFrameworkTags?.totalCount ?? 0)
> (data?.analysisFrameworkTags?.results ?? []).length && (
<Button
onClick={handleShowMoreClick}
name={undefined}
spacing="compact"
variant="transparent"
>
Show more tags
</Button>
)}
</>
);
}

export default FrameworkTagSelectInput;
5 changes: 5 additions & 0 deletions app/components/selections/FrameworkTagSelectInput/styles.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.icon {
width: auto;
height: 1rem;
object-fit: contain;
}
4 changes: 2 additions & 2 deletions app/types/user.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,12 @@ export interface Assignment {
displayName: string;
email: string;
};
contentObjectDetails: {
contentObjectDetails?: {
id: number;
title: string;
lead?: string;
entry?: string;
};
} | undefined;
isDone: boolean;
contentObjectType: 'lead' | 'entryreviewcomment' | 'entrycomment';
}
61 changes: 22 additions & 39 deletions app/views/EntryEdit/LeftPane/AssistItem/AssistPopup/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,11 @@ import {
Kraken,
Container,
Message,
QuickActionButton,
} from '@the-deep/deep-ui';
import {
SetValueArg,
Error,
} from '@togglecorp/toggle-form';
import {
IoClose,
} from 'react-icons/io5';
import { FiEdit2 } from 'react-icons/fi';

import EntryInput from '#components/entry/EntryInput';
import { GeoArea } from '#components/GeoMultiSelectInput';
Expand All @@ -26,45 +21,52 @@ import {

import styles from './styles.css';

interface Props {
interface Props<NAME extends string | number | undefined> {
className?: string;
entryInputClassName?: string;
frameworkDetails: Framework;
leadId: string;
value: PartialEntryType;
onChange: (val: SetValueArg<PartialEntryType>, name: undefined) => void;
onChange: (val: SetValueArg<PartialEntryType>, name: NAME) => void;
error: Error<PartialEntryType> | undefined;
onEntryCreateButtonClick: () => void;
variant?: 'normal' | 'compact' | 'nlp';
// NOTE: Normal entry creation refers to entry created without use of
// recommendations
onNormalEntryCreateButtonClick: () => void;
onEntryDiscardButtonClick: () => void;
geoAreaOptions: GeoArea[] | undefined | null;
onGeoAreaOptionsChange: React.Dispatch<React.SetStateAction<GeoArea[] | undefined | null>>;
predictionsLoading?: boolean;
hints: WidgetHint[] | undefined;
recommendations: PartialAttributeType[] | undefined;
predictionsErrored: boolean;
name: NAME;
messageText: string | undefined;
excerptShown?: boolean;
displayHorizontally?: boolean;

footerActions: React.ReactNode;
}

function AssistPopup(props: Props) {
function AssistPopup<NAME extends string | number | undefined>(props: Props<NAME>) {
const {
className,
entryInputClassName,
variant = 'nlp',
leadId,
value,
onChange,
name,
error,
frameworkDetails,
onEntryCreateButtonClick,
onNormalEntryCreateButtonClick,
onEntryDiscardButtonClick,
geoAreaOptions,
onGeoAreaOptionsChange,
predictionsLoading,
hints,
predictionsErrored,
messageText,
recommendations,
excerptShown = false,
displayHorizontally = false,
footerActions,
} = props;

const allWidgets = useMemo(() => {
Expand All @@ -89,28 +91,7 @@ function AssistPopup(props: Props) {
// heading="Assisted Tagging"
headingSize="extraSmall"
spacing="compact"
footerQuickActions={(
<>
<QuickActionButton
name={undefined}
onClick={onEntryDiscardButtonClick}
title="Discard Entry"
variant="nlp-secondary"
>
<IoClose />
</QuickActionButton>
<QuickActionButton
name={undefined}
onClick={(predictionsErrored || !!messageText)
? onNormalEntryCreateButtonClick : onEntryCreateButtonClick}
disabled={predictionsLoading}
variant="nlp-primary"
title="Create Entry"
>
<FiEdit2 />
</QuickActionButton>
</>
)}
footerQuickActions={footerActions}
contentClassName={styles.body}
>
{isMessageShown ? (
Expand All @@ -136,9 +117,9 @@ function AssistPopup(props: Props) {
/>
) : (
<EntryInput
className={styles.entryInput}
className={_cs(styles.entryInput, entryInputClassName)}
leadId={leadId}
name={undefined}
name={name}
error={error}
value={value}
onChange={onChange}
Expand All @@ -153,7 +134,9 @@ function AssistPopup(props: Props) {
recommendations={recommendations}
emptyValueHidden
addButtonHidden
variant="nlp"
variant={variant}
excerptShown={excerptShown}
displayHorizontally={displayHorizontally}
/>
)}
</Container>
Expand Down
Loading

0 comments on commit deff650

Please sign in to comment.