Skip to content

Commit

Permalink
feat(content-answers): Upgrade Content Answers (#3658)
Browse files Browse the repository at this point in the history
* fix(docgen-sidebar): add collapsible component to hide nested tags (#3626)

* fix(docgen-sidebar): add collapsible component to hide nested tags

* fix(docgen-sidebar): nesting of tags in tag tree

* fix(docgen-tags): update styles to use blueprint tokens

* fix(docgen-tags): replace bdl tokens with blueprint tokens

* fix(docgen-tags): convert test from enzyme to rtl

* fix(docgen-tags): remove snapshots, reuse blueprint loader

* fix(docgen-tags): address code review comments

* fix(docgen-tags): remove the sidebar test file

* fix(docgen-tags): file with updated name

* Update src/elements/content-sidebar/__tests__/DocGenSidebar.test.tsx

Co-authored-by: greg-in-a-box <103291617+greg-in-a-box@users.noreply.github.com>

* Update src/elements/content-sidebar/__tests__/DocGenSidebar.test.tsx

Co-authored-by: greg-in-a-box <103291617+greg-in-a-box@users.noreply.github.com>

* fix(docgen-sidebar): address code review comments

* fix(docgen-sidebar): address code review comments

* fix(docgen-sidebar): remove unused mock

---------

Co-authored-by: greg-in-a-box <103291617+greg-in-a-box@users.noreply.github.com>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>

* chore(storybook): Added global types for storybook

* feat(content-answers): Upgrade Content Answers

* feat(content-answers): fix tests

* feat(content-answers): Enabled some new features

* feat(content-answers): Feedback

* chore(content-answers): feedback

* feat(content-answers): Feedback

* feat(content-answers): Feedback

* feat(content-answers): Feedback

* feat(content-answers): vrt width

* feat(content-answers): Feedback

* feat(content-answers): Feedback

* feat(content-answers): Providers

* feat(content-answers): Providers

* feat(content-answers): Feedback

* feat(content-answers): Feedback

* feat(content-answers): tests

* feat(content-answers): Feedback

* feat(content-answers): Feedback

---------

Co-authored-by: rustam-e <6816931+rustam-e@users.noreply.github.com>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
  • Loading branch information
3 people authored Oct 2, 2024
1 parent d2e59c8 commit 002d496
Show file tree
Hide file tree
Showing 69 changed files with 1,335 additions and 1,789 deletions.
3 changes: 2 additions & 1 deletion .storybook/preview-body.html
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,11 @@
}

.be.bcpr {
height: 600px;
height: 900px;
}

.be.bcs {
width: 1000px;
height: 900px;
}
</style>
13 changes: 12 additions & 1 deletion .storybook/preview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,18 @@ initialize();

const preview = {
parameters: {
chromatic: { disableSnapshot: true },
chromatic: {
disableSnapshot: true,
cropToViewport: true,
modes: {
specific: {
viewport: {
height: 1000,
width: 1200,
},
},
},
},
controls: {
matchers: {
color: /(background|color)$/i,
Expand Down
2 changes: 1 addition & 1 deletion flow-typed/box-ui-elements.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import type FileAPI from '../src/api/File';
import type WebLinkAPI from '../src/api/WebLink';
import type MultiputUploadAPI from '../src/api/uploads/MultiputUpload';
import type PlainUploadAPI from '../src/api/uploads/PlainUpload';
import type { ContentAnswersProps } from '../src/features/content-answers';
import type { ContentAnswersProps } from '../src/elements/common/content-answers';
import type { ContentSidebarProps } from '../src/elements/content-sidebar';
import type { ContentOpenWithProps } from '../src/elements/content-open-with';
import type { ContentPreviewProps } from '../src/elements/content-preview';
Expand Down
44 changes: 20 additions & 24 deletions i18n/en-US.properties
Original file line number Diff line number Diff line change
Expand Up @@ -942,38 +942,34 @@ boxui.collaboratorAvatars.viewAdditionalPeopleText = View additional people
boxui.collapsiblesidebar.collapseBtnLabel = Collapse
# Aria label for toggle button that expands/collapses sidebar (collapsed state)
boxui.collapsiblesidebar.expandBtnLabel = Expand
# Content Answers submit input button text
boxui.contentAnswers.ask = Ask
# Content Answers submit input button disabled tooltip text when answer is generating
boxui.contentAnswers.askDisabledTooltip = You can submit another question once Box AI has finished responding
# Content Answers modal input placeholder
boxui.contentAnswers.askQuestionPlaceholder = Ask anything about this document
# Content Answers feature name shown on menu item and modal title
boxui.contentAnswers.contentAnswersTitle = Box AI
# Default tooltip message for Content Answers entry point button
boxui.contentAnswers.defaultTooltip = Get instant answers about this document using Box AI
# Disabled tooltip message for Content Answers entry point button when the file type is not supported
boxui.contentAnswers.disabledTooltipFileNotCompatible = Box AI is not currently supported for this file type
# Text inside the chip for the first suggested question for documents
boxui.contentAnswers.documentSuggestedQuestionLabel1 = Summarize this document
# Text inside the chip for the second suggested question for documents
boxui.contentAnswers.documentSuggestedQuestionLabel2 = What are the key takeaways?
# Text inside the chip for the third suggested question for documents
boxui.contentAnswers.documentSuggestedQuestionLabel3 = How can this document be improved?
# Text inside the chip for the fourth suggested question for documents
boxui.contentAnswers.documentSuggestedQuestionLabel4 = Are there any next steps defined?
# Actual prompt for the first suggested question for documents
boxui.contentAnswers.documentSuggestedQuestionPrompt1 = Summarize this document
# Actual prompt for the second suggested question for documents
boxui.contentAnswers.documentSuggestedQuestionPrompt2 = What are the key takeaways?
# Actual prompt for the third suggested question for documents
boxui.contentAnswers.documentSuggestedQuestionPrompt3 = How can this document be improved?
# Actual prompt for the fourth suggested question for documents
boxui.contentAnswers.documentSuggestedQuestionPrompt4 = Are there any next steps defined?
# Existing questions tooltip message for Content Answers entry point button
boxui.contentAnswers.hasQuestionsTooltip = Return to Box AI
# Content Answers error message when the service fails
boxui.contentAnswers.inlineErrorText = The Box AI service was unavailable.
# Box AI Q&A service unavailable error description
boxui.contentAnswers.intelligenceUnavailableDescription = The Box AI service is not responding.
# Box AI Q&A service unavailable error title
boxui.contentAnswers.intelligenceUnavailableHeading = Box AI is unavailable
# Box AI Q&A service unavailable error try again later description
boxui.contentAnswers.intelligenceUnavailableTryAgain = Please try again later.
# Error tooltip to show inside text area if the user reached the character limit
boxui.contentAnswers.maxCharactersReachedError = Maximum of {characterLimit} characters reached
# Retry button label to send again the question to the service
boxui.contentAnswers.retryResponse = Retry
# Content Answers welcome message for asking questions
boxui.contentAnswers.welcomeAskQuestionText = Ask questions about {name}
# Content Answers welcome message for clearing the chat
boxui.contentAnswers.welcomeClearChatText = This chat will be cleared when you close this document
# Content Answers welcome message title
boxui.contentAnswers.welcomeMessageTitle = Welcome to Box AI
# Content Answers welcome message spreadsheet notification
boxui.contentAnswers.welcomeMessageSpreadsheetNotice = Spreadsheet support works best for text dense files
# Aria label for the icon inside spreadsheet notification
boxui.contentAnswers.welcomeMessageSpreadsheetNoticeAriaLabel = spreadsheet support notification banner
# Aria label for the folder breadcrumb
boxui.contentExplorer.breadcrumb = Breadcrumb
# Text shown on button used to close the content explorer
Expand Down
8 changes: 6 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@
"@babel/types": "^7.24.7",
"@box/blueprint-web": "^7.30.1",
"@box/blueprint-web-assets": "^4.21.0",
"@box/box-ai-content-answers": "^0.49.1",
"@box/box-ai-content-answers": "^0.50.5",
"@box/cldr-data": "^34.2.0",
"@box/frontend": "^10.0.0",
"@box/languages": "^1.0.0",
Expand Down Expand Up @@ -222,6 +222,7 @@
"flow-typed": "^2.6.2",
"form-serialize": "^0.7.2",
"formik": "^2.0.3",
"highlight.js": "^11.10.0",
"husky": "^4.0.10",
"ilib-tree-node": "^1.2.0",
"immutable": "^3.7.4",
Expand Down Expand Up @@ -271,6 +272,7 @@
"react-tether": "^1.0.5",
"react-textarea-autosize": "^8.5.3",
"regenerator-runtime": "^0.14.1",
"remarkable": "^2.0.1",
"sanitize-html": "^1.21.1",
"sass": "^1.34.1",
"sass-lint": "^1.13.1",
Expand Down Expand Up @@ -302,7 +304,7 @@
"peerDependencies": {
"@box/blueprint-web": "^7.30.1",
"@box/blueprint-web-assets": "^4.21.0",
"@box/box-ai-content-answers": "^0.49.1",
"@box/box-ai-content-answers": "^0.50.5",
"@box/cldr-data": ">=34.2.0",
"@box/metadata-editor": "^0.54.0",
"@box/react-virtualized": "9.22.3-rc-box.9",
Expand All @@ -314,6 +316,7 @@
"filesize": "^4.1.2",
"form-serialize": "^0.7.2",
"formik": "^2.0.0",
"highlight.js": "^11.10.0",
"ilib-tree-node": "^1.2.0",
"immutable": "^3.7.4",
"intl-messageformat": "^7.8.4",
Expand Down Expand Up @@ -341,6 +344,7 @@
"react-tether": "^1.0.5",
"react-textarea-autosize": "^8.5.3",
"regenerator-runtime": "^0.13.2",
"remarkable": "^2.0.1",
"sanitize-html": "^1.21.1",
"sass": "^1.34.1",
"scroll-into-view-if-needed": "^2.2.20",
Expand Down
6 changes: 6 additions & 0 deletions scripts/jest/jest-setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,9 @@ global.setImmediate = cb => {
Object.defineProperty(global, 'TextEncoder', {
value: util.TextEncoder,
});

global.ResizeObserver = jest.fn().mockImplementation(() => ({
observe: jest.fn(),
unobserve: jest.fn(),
disconnect: jest.fn(),
}));
2 changes: 1 addition & 1 deletion scripts/jest/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,6 @@ module.exports = {
testMatch: ['**/__tests__/**/*.test.+(js|jsx|ts|tsx)'],
testPathIgnorePatterns: ['stories.test.js$', 'stories.test.tsx$', 'stories.test.d.ts'],
transformIgnorePatterns: [
'node_modules/(?!(@box/react-virtualized/dist/es|@box/cldr-data|@box/blueprint-web|@box/blueprint-web-assets|@box/metadata-editor)/)',
'node_modules/(?!(@box/react-virtualized/dist/es|@box/cldr-data|@box/blueprint-web|@box/blueprint-web-assets|@box/metadata-editor|@box/box-ai-content-answers)/)',
],
};
66 changes: 34 additions & 32 deletions scripts/styleguide.styles.scss
Original file line number Diff line number Diff line change
@@ -1,44 +1,46 @@
.be {
&.bce,
&.bcp {
height: 600px;
}
#rsg-root {
.be {
&.bce,
&.bcp {
height: 600px;
}

&.bcpr {
.bcs {
box-shadow: initial;
&.bcpr {
.bcs {
box-shadow: initial;
}
}
}

&.bcu {
height: 400px;
}
&.bcu {
height: 400px;
}

&.bcow {
width: 100px;
}
&.bcow {
width: 100px;
}

&.bce,
&.bcp,
&.bcpr,
&.bcs,
&.bcu {
box-shadow: 0 0 20px 0 rgba(85, 85, 85, .42);
&.bce,
&.bcp,
&.bcpr,
&.bcs,
&.bcu {
box-shadow: 0 0 20px 0 rgba(85, 85, 85, .42);
}
}
}

[data-preview='ContentSidebar'] {
> div {
display: inline-block;
}
[data-preview='ContentSidebar'] {
> div {
display: inline-block;
}

.bcs {
height: 1000px;
.bcs {
height: 1000px;
}
}
}

[data-preview='ContentPreview'] {
.bcpr {
height: 600px;
[data-preview='ContentPreview'] {
.bcpr {
height: 600px;
}
}
}
15 changes: 13 additions & 2 deletions src/api/Intelligence.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
*/

import getProp from 'lodash/get';
import { QuestionType } from '@box/box-ai-content-answers';
import type { BoxItem } from '../common/types/core';
import { ERROR_CODE_EXTRACT_STRUCTURED } from '../constants';
import { isUserCorrectableError } from '../utils/error';
Expand All @@ -16,11 +17,19 @@ class Intelligence extends Base {
/**
* API endpoint to ask ai a question
*
* @param {string} prompt - Question
* @param {QuestionType} question - Object should at least contain the prompt, which is the question to ask
* @param {Array<object>} items - Array of items to ask about
* @param {Array<QuestionType>} dialogueHistory - Array of previous questions object that already have answers
* @param {{ include_citations?: boolean }} options - Optional parameters
* @return {Promise}
*/
async ask(prompt: string, items: Array<BoxItem>) {
async ask(
question: QuestionType,
items: Array<BoxItem>,
dialogueHistory: Array<QuestionType> = [],
options: { include_citations?: boolean } = {},
): Promise<any> {
const { prompt } = question;
if (!prompt) {
throw new Error('Missing prompt!');
}
Expand All @@ -44,6 +53,8 @@ class Intelligence extends Base {
mode: 'single_item_qa',
prompt,
items,
dialogue_history: dialogueHistory,
...options,
},
});
}
Expand Down
30 changes: 25 additions & 5 deletions src/api/__tests__/Intelligence.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ describe('api/Intelligence', () => {

const mockItems = [{ id: '123', type: 'file' }];
const mockPrompt = 'summarize';
const mockQuestion = { prompt: mockPrompt };

beforeEach(() => {
intelligence = new Intelligence({});
Expand All @@ -14,7 +15,7 @@ describe('api/Intelligence', () => {
test('should return promise with data', async () => {
const data = { data: 'foo' };
intelligence.xhr.post = jest.fn().mockReturnValueOnce(Promise.resolve(data));
const response = await intelligence.ask(mockPrompt, mockItems);
const response = await intelligence.ask(mockQuestion, mockItems);
expect(response).toEqual(data);
});

Expand All @@ -24,13 +25,32 @@ describe('api/Intelligence', () => {
items: mockItems,
mode: 'single_item_qa',
prompt: mockPrompt,
dialogue_history: [],
},
id: 'file_123',
url: 'https://api.box.com/2.0/ai/ask',
};
const postMock = jest.fn();
intelligence.xhr.post = postMock.mockReturnValueOnce(Promise.resolve({}));
await intelligence.ask(mockPrompt, mockItems);
await intelligence.ask(mockQuestion, mockItems);
expect(postMock).toBeCalledWith(data);
});

test('should make post to xhr with citations', async () => {
const data = {
data: {
items: mockItems,
mode: 'single_item_qa',
prompt: mockPrompt,
dialogue_history: [],
include_citations: true,
},
id: 'file_123',
url: 'https://api.box.com/2.0/ai/ask',
};
const postMock = jest.fn();
intelligence.xhr.post = postMock.mockReturnValueOnce(Promise.resolve({}));
await intelligence.ask(mockQuestion, mockItems, [], { include_citations: true });
expect(postMock).toBeCalledWith(data);
});

Expand All @@ -44,7 +64,7 @@ describe('api/Intelligence', () => {
}),
);
try {
await intelligence.ask(mockPrompt, mockItems);
await intelligence.ask(mockQuestion, mockItems);
} catch (e) {
expect(e).toEqual({
response: {
Expand All @@ -60,7 +80,7 @@ describe('api/Intelligence', () => {
${mockPrompt} | ${[{}]} | ${'Invalid item!'} | ${'item'}
`('should throw error if $missing is missing ', async ({ prompt, items, message }) => {
try {
await intelligence.ask(prompt, items);
await intelligence.ask({ prompt }, items);
expect(true).toEqual(false); // should never hit this line, if it does then the test fails
} catch (e) {
expect(e.message).toEqual(message);
Expand All @@ -73,7 +93,7 @@ describe('api/Intelligence', () => {
${[]} | ${'an empty array'}
`('should throw error if items is $description ', async ({ badItems }) => {
try {
await intelligence.ask(prompt, badItems);
await intelligence.ask(mockQuestion, badItems);
expect(true).toEqual(false); // should never hit this line, if it does then the test fails
} catch (e) {
expect(e.message).toEqual('Missing items!');
Expand Down
2 changes: 1 addition & 1 deletion src/components/media-query/__tests__/useMediaQuery.test.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// @flow

import * as React from 'react';
import { mount } from 'enzyme';

import useMediaQuery from '../useMediaQuery';

const WIDTH = 999;
Expand Down
23 changes: 23 additions & 0 deletions src/elements/common/Providers.js.flow
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// @flow
import * as React from 'react';
import { Notification, TooltipProvider } from '@box/blueprint-web';

export interface ProvideProps {
children: React.Node;
hasProviders: ?boolean;
}

const Provide = ({ children, hasProviders }: ProvideProps) => {
if (hasProviders) {
return (
<Notification.Provider>
<Notification.Viewport />
<TooltipProvider>{children}</TooltipProvider>
</Notification.Provider>
);
}

return React.Children.only(children);
};

export default Provide;
Loading

0 comments on commit 002d496

Please sign in to comment.