-
Notifications
You must be signed in to change notification settings - Fork 345
feat(metadata-instance-editor): support for cascade extraction #4613
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
c48c477
8baf71b
9ee9373
3058c25
7a2a1da
2e4108e
4dcac64
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,81 @@ | ||
| // @flow | ||
| import * as React from 'react'; | ||
| import { FormattedMessage, useIntl } from 'react-intl'; | ||
| import { ActionableInlineNotice } from '@box/blueprint-web'; | ||
| // $FlowFixMe - blueprint-web-assets icons not typed for Flow | ||
| import { Lock } from '@box/blueprint-web-assets/icons/Line'; | ||
|
|
||
| import TemplatedInstance from './TemplatedInstance'; | ||
| import CustomInstance from './CustomInstance'; | ||
| import messages from './messages'; | ||
| import { TEMPLATE_CUSTOM_PROPERTIES } from './constants'; | ||
| import { getCustomExtractAgentId } from './metadataUtil'; | ||
| import type { MetadataFields, MetadataTemplate } from '../../common/types/metadata'; | ||
| import './CustomExtractAgentInstanceBody.scss'; | ||
|
|
||
| type Props = { | ||
| // Raw agent configuration value from the cascade policy (e.g. `extract_agent_<id>`). | ||
| // The navigable numeric id is resolved from this here. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "resolved from this here" seems a bit ambiguous. Maybe change into something like "The navigable numeric id is extracted from this value via getCustomExtractAgentId"? |
||
| agentConfiguration?: string, | ||
| data: MetadataFields, | ||
| isEditing: boolean, | ||
| onManageExtractAgent?: (agentId: string) => void, | ||
| template: MetadataTemplate, | ||
| }; | ||
|
|
||
| /** | ||
| * Presentational interior for a metadata instance managed by a custom Box AI | ||
| * extract agent. When collapsed it shows read-only field values; when the user | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Is there a test to verify this is true? Correct me if my understanding of this component is incorrect: the InstanceCard parent controls collapsed/expanded state via a Collapsible — when collapsed, the entire body (including this component) is hidden and nothing renders. This component only deals with editing vs. not-editing via the isEditing prop. |
||
| * enters edit mode it replaces the form with an informational notice and a button | ||
| * to manage the agent (instead of allowing inline edits). | ||
| * | ||
| * The "manage agent" button is only shown when a navigable numeric agent id can be | ||
| * resolved from the configuration; otherwise the notice is shown without an action. | ||
| */ | ||
| const CustomExtractAgentInstanceBody = ({ | ||
| agentConfiguration, | ||
| data, | ||
| isEditing, | ||
| onManageExtractAgent, | ||
| template, | ||
| }: Props) => { | ||
| const { formatMessage } = useIntl(); | ||
| const isProperties = template.templateKey === TEMPLATE_CUSTOM_PROPERTIES; | ||
| const customExtractAgentId = getCustomExtractAgentId(agentConfiguration); | ||
|
|
||
| if (isEditing) { | ||
| return ( | ||
| <div className="metadata-instance-editor-custom-extract-agent"> | ||
| <ActionableInlineNotice | ||
| icon={Lock} | ||
| iconAriaLabel={formatMessage(messages.customExtractAgentNoticeIconAriaLabel)} | ||
| text={formatMessage(messages.customExtractAgentNoticeDescription)} | ||
| title={formatMessage(messages.customExtractAgentNoticeTitle)} | ||
| > | ||
| {!!customExtractAgentId && onManageExtractAgent && ( | ||
| <ActionableInlineNotice.PrimaryAction | ||
| onClick={() => onManageExtractAgent(customExtractAgentId)} | ||
| > | ||
| {formatMessage(messages.customExtractAgentManageButton)} | ||
| </ActionableInlineNotice.PrimaryAction> | ||
| )} | ||
| </ActionableInlineNotice> | ||
| </div> | ||
| ); | ||
| } | ||
|
|
||
| return ( | ||
| <div className="metadata-instance-editor-instance"> | ||
| <div className="metadata-cascade-notice"> | ||
| <FormattedMessage {...messages.metadataCascadePolicyEnabledInfo} /> | ||
| </div> | ||
| {isProperties ? ( | ||
| <CustomInstance canEdit={false} data={data} /> | ||
| ) : ( | ||
| <TemplatedInstance canEdit={false} data={data} errors={{}} template={template} /> | ||
| )} | ||
| </div> | ||
| ); | ||
| }; | ||
|
|
||
| export default CustomExtractAgentInstanceBody; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| .metadata-instance-editor-custom-extract-agent { | ||
| padding: 8px; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,145 @@ | ||
| // @flow | ||
| import * as React from 'react'; | ||
| import noop from 'lodash/noop'; | ||
|
|
||
| import type { AgentType } from '@box/box-ai-agent-selector'; | ||
| import Form from '../../components/form-elements/form/Form'; | ||
| import LoadingIndicatorWrapper from '../../components/loading-indicator/LoadingIndicatorWrapper'; | ||
|
|
||
| import CascadePolicy from './CascadePolicy'; | ||
| import TemplatedInstance from './TemplatedInstance'; | ||
| import CustomInstance from './CustomInstance'; | ||
| import MetadataInstanceConfirmDialog from './MetadataInstanceConfirmDialog'; | ||
| import Footer from './Footer'; | ||
| import type { | ||
| MetadataCascadePolicy, | ||
| MetadataFields, | ||
| MetadataTemplate, | ||
| MetadataFieldValue, | ||
| } from '../../common/types/metadata'; | ||
|
|
||
| type Props = { | ||
| canUseAIFolderExtraction: boolean, | ||
| cascadePolicy: MetadataCascadePolicy, | ||
| confirmationMessage: React.Node, | ||
| data: MetadataFields, | ||
| errors: { [string]: React.Node }, | ||
| isAIFolderExtractionEnabled: boolean, | ||
| isBusy: boolean, | ||
| isCascadingEnabled: boolean, | ||
| isCascadingOverwritten: boolean, | ||
| isCascadingPolicyApplicable?: boolean, | ||
| isDirty: boolean, | ||
| isEditing: boolean, | ||
| isExistingCascadePolicy: boolean, | ||
| isProperties: boolean, | ||
| onAIAgentSelect: (agent: AgentType | null) => void, | ||
| onAIFolderExtractionToggle: (value: boolean) => void, | ||
| onCancel: () => void, | ||
| onCascadeModeChange: (value: boolean) => void, | ||
| onCascadeToggle: (value: boolean) => void, | ||
| onConfirmCancel: () => void, | ||
| onConfirmRemove: () => void, | ||
| onFieldChange: (key: string, value: MetadataFieldValue, type: string) => void, | ||
| onFieldRemove: (key: string) => void, | ||
| onRemove: () => void, | ||
| onSave: () => void, | ||
| shouldConfirmRemove: boolean, | ||
| shouldShowCascadeOptions: boolean, | ||
| template: MetadataTemplate, | ||
| }; | ||
|
|
||
| /** | ||
| * Presentational interior for an editable metadata instance: the confirm-remove | ||
| * dialog, the form with cascade policy + fields, and the save/remove footer. | ||
| * All state and handlers are owned by the parent Instance and supplied via props. | ||
| */ | ||
| const EditableInstanceBody = ({ | ||
| canUseAIFolderExtraction, | ||
| cascadePolicy = {}, | ||
| confirmationMessage, | ||
| data, | ||
| errors, | ||
| isAIFolderExtractionEnabled, | ||
| isBusy, | ||
| isCascadingEnabled, | ||
| isCascadingOverwritten, | ||
| isCascadingPolicyApplicable, | ||
| isDirty, | ||
| isEditing, | ||
| isExistingCascadePolicy, | ||
| isProperties, | ||
| onAIAgentSelect, | ||
| onAIFolderExtractionToggle, | ||
| onCancel, | ||
| onCascadeModeChange, | ||
| onCascadeToggle, | ||
| onConfirmCancel, | ||
| onConfirmRemove, | ||
| onFieldChange, | ||
| onFieldRemove, | ||
| onRemove, | ||
| onSave, | ||
| shouldConfirmRemove, | ||
| shouldShowCascadeOptions, | ||
| template, | ||
| }: Props) => { | ||
| if (shouldConfirmRemove) { | ||
| return ( | ||
| <LoadingIndicatorWrapper isLoading={isBusy}> | ||
| <MetadataInstanceConfirmDialog | ||
| confirmationMessage={confirmationMessage} | ||
| onCancel={onConfirmCancel} | ||
| onConfirm={onRemove} | ||
| /> | ||
| </LoadingIndicatorWrapper> | ||
| ); | ||
| } | ||
|
|
||
| return ( | ||
| <LoadingIndicatorWrapper isLoading={isBusy}> | ||
| <Form onValidSubmit={isDirty ? onSave : noop}> | ||
| <div className="metadata-instance-editor-instance"> | ||
| {isCascadingPolicyApplicable && ( | ||
| <CascadePolicy | ||
| cascadePolicyConfiguration={cascadePolicy?.cascadePolicyConfiguration} | ||
| canEdit={isEditing && !!cascadePolicy.canEdit} | ||
| canUseAIFolderExtraction={canUseAIFolderExtraction} | ||
| isAIFolderExtractionEnabled={isAIFolderExtractionEnabled} | ||
| isCascadingEnabled={isCascadingEnabled} | ||
| isCascadingOverwritten={isCascadingOverwritten} | ||
| isCustomMetadata={isProperties} | ||
| isExistingCascadePolicy={isExistingCascadePolicy} | ||
| onAIAgentSelect={onAIAgentSelect} | ||
| onAIFolderExtractionToggle={onAIFolderExtractionToggle} | ||
| onCascadeModeChange={onCascadeModeChange} | ||
| onCascadeToggle={onCascadeToggle} | ||
| shouldShowCascadeOptions={shouldShowCascadeOptions} | ||
| /> | ||
| )} | ||
| {isProperties ? ( | ||
| <CustomInstance | ||
| canEdit={isEditing} | ||
| data={data} | ||
| onFieldChange={onFieldChange} | ||
| onFieldRemove={onFieldRemove} | ||
| /> | ||
| ) : ( | ||
| <TemplatedInstance | ||
| canEdit={isEditing} | ||
| data={data} | ||
| errors={errors} | ||
| isDisabled={isAIFolderExtractionEnabled} | ||
| onFieldChange={onFieldChange} | ||
| onFieldRemove={onFieldRemove} | ||
| template={template} | ||
| /> | ||
| )} | ||
| </div> | ||
| {isEditing && <Footer onCancel={onCancel} onRemove={onConfirmRemove} showSave={isDirty} />} | ||
| </Form> | ||
| </LoadingIndicatorWrapper> | ||
| ); | ||
| }; | ||
|
|
||
| export default EditableInstanceBody; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nit] Follow the import order convention