Skip to content
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

feat: GROWI AI Next #9492

Open
wants to merge 97 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
97 commits
Select commit Hold shift + click to select a range
3db8fc0
Show Knowledge Assistant in Sidebar
miya Dec 16, 2024
d942b27
Hides icon when AI is disabled
miya Dec 16, 2024
c5974f5
add en
miya Dec 16, 2024
16f5b5e
impl KnowledgeAssistantContent
miya Dec 16, 2024
830dba6
Impl KnowledgeAssistantManegementModal
miya Dec 16, 2024
a31763f
Add TODO
miya Dec 16, 2024
7bfe97d
Relocated directories
miya Dec 16, 2024
d454fe1
fix styles
miya Dec 16, 2024
67e1bd3
Add styles
miya Dec 16, 2024
c15bcaf
impl modal body
miya Dec 16, 2024
7ee7719
rm unnec modules
miya Dec 16, 2024
f6a83ad
Merge pull request #9490 from weseek/feat/159143-assistant-create-modal
mergify[bot] Dec 16, 2024
95f7011
KnowledgeAssistant -> AiAssistant
miya Dec 17, 2024
4c74a8f
knowledge_assistant -> ai_assistant
miya Dec 17, 2024
821203c
impl AiAssistantModel
miya Dec 17, 2024
26713ca
clean code
miya Dec 17, 2024
9930e20
rm unnec opt
miya Dec 17, 2024
a8b3143
Add types (to be implemented in the future)
miya Dec 17, 2024
caf1db1
type -> types
miya Dec 17, 2024
b52554d
clean code
miya Dec 17, 2024
6a505a4
Add field (isDeleted)
miya Dec 17, 2024
b143f57
add grantedGroups
miya Dec 17, 2024
9167954
add creator
miya Dec 17, 2024
3fc841c
fix types
miya Dec 17, 2024
df996cb
optional
miya Dec 17, 2024
847c5e2
Merge pull request #9493 from weseek/fix/159236-module-name
yuki-takei Dec 17, 2024
6c028d3
Merge branch 'master' into feat/growi-ai-next
miya Dec 18, 2024
c5c8529
change field name
miya Dec 18, 2024
03cd4e9
impl
miya Dec 18, 2024
f575ce6
Refactor PageSelectModal
miya Dec 18, 2024
a148e69
fix return value
miya Dec 18, 2024
4ec6dbc
Refactor PageSelectModal (2)
miya Dec 18, 2024
4b939dd
impl SelectedPageList
miya Dec 18, 2024
29c6277
Selected pages are not duplicated
miya Dec 18, 2024
f6c934a
memorization
miya Dec 18, 2024
e8d1667
impl
miya Dec 18, 2024
9bff6da
Merge pull request #9496 from weseek/feat/159149-open-pageselectmodal…
yuki-takei Dec 18, 2024
43cbf79
Merge branch 'master' into feat/growi-ai-next
miya Dec 19, 2024
254109d
Add checkbox to include subordinated pages in modal
miya Dec 19, 2024
9081d95
Merge branch 'feat/growi-ai-next' into feat/159152-ai-assistant-model
miya Dec 19, 2024
c0c9bc0
not optional
miya Dec 19, 2024
5f4ba68
Revert "Add field (isDeleted)"
miya Dec 19, 2024
eafecf9
Refactor AiAssistant model to use vectorStore reference and export Ve…
miya Dec 19, 2024
d754820
Add option to include subordinated pages in page selection modal
miya Dec 19, 2024
5714a18
rm debug log
miya Dec 19, 2024
a6f79e0
Add grantedUsers field to AiAssistant model for user-specific sharing
miya Dec 20, 2024
f3b97fb
Merge pull request #9505 from weseek/imprv/159329-modify-page-select-…
yuki-takei Dec 20, 2024
d63af50
Merge branch 'feat/growi-ai-next' into feat/159152-ai-assistant-model
miya Dec 23, 2024
568a4e6
Merge branch 'master' into feat/growi-ai-next
miya Dec 24, 2024
90bf8f8
Add assistant description and update icon in AiChatModal component
miya Dec 24, 2024
820784a
Create SelectedPageList.tsx
miya Dec 24, 2024
815deee
Merge branch 'feat/growi-ai-next' into feat/159152-ai-assistant-model
miya Dec 24, 2024
10c7773
Rename learningScope to ownerAccessScope in AiAssistant model for cla…
miya Dec 24, 2024
f661d11
Rename AiAssistantSharingScope to AiAssistantShareScope for consistency
miya Dec 24, 2024
752768a
Update enum reference for shareScope to use AiAssistantShareScope
miya Dec 24, 2024
0775170
Add pagePaths property to AiAssistant model for enhanced functionality
miya Dec 24, 2024
52db218
Update AiAssistantManagementModal to enhance user instructions and ad…
miya Dec 24, 2024
c19d6a9
Add remove functionality for selected pages in AiAssistantManagementM…
miya Dec 24, 2024
99796c1
onClickOpenPageSelectModalButton -> clickOpenPageSelectModalHandle
miya Dec 24, 2024
1919825
Add select input and buttons for assistant functionality
miya Dec 24, 2024
a65c48d
fix styles
miya Dec 25, 2024
c5e73e7
pagePath -> pagePathPatterns
miya Dec 25, 2024
0dfb8ef
Merge pull request #9494 from weseek/feat/159152-ai-assistant-model
yuki-takei Dec 25, 2024
67fa754
Merge pull request #9519 from weseek/feat/159566-knowledge-assistant-…
yuki-takei Dec 25, 2024
436b76b
Merge pull request #9518 from weseek/feat/159531-chat-modal
yuki-takei Dec 25, 2024
69a5165
Merge branch 'master' into feat/growi-ai-next
miya Dec 27, 2024
744f588
Merge branch 'feat/growi-ai-next' into feat/159153-implement-ai-assis…
miya Dec 27, 2024
319925c
Merge branch 'master' into feat/growi-ai-next
miya Jan 6, 2025
9839181
Merge branch 'feat/growi-ai-next' into feat/159153-implement-ai-assis…
miya Jan 6, 2025
66be0a2
Add AI assistant types and scopes interfaces
miya Jan 9, 2025
2e9ca2d
Enhance validation for AI assistant creation API
miya Jan 9, 2025
adc175f
createAssistantFactory -> createAiAssistantFactory
miya Jan 9, 2025
be160c3
Omit AiAssistant.type
miya Jan 9, 2025
7c5e43f
Refactor AI assistant interfaces and service implementation
miya Jan 9, 2025
1d58f5d
Refactor AI assistant service to use OpenAI service for assistant cre…
miya Jan 9, 2025
f8c5918
fix path
miya Jan 9, 2025
fac67f0
imprv validation
miya Jan 9, 2025
5c2de9d
create-assistant -> create-ai-assistant
miya Jan 9, 2025
abda9dc
clean code
miya Jan 9, 2025
e4002ed
Impl addConditionToListByPathsArrayWithGlob
miya Jan 10, 2025
d703468
Enabled to create a specialized vectorStore
miya Jan 10, 2025
2df37fd
Remove scopeType from VectorStore and related methods
miya Jan 10, 2025
b18d188
Comment out currently unavailable methods
miya Jan 10, 2025
93c382a
rm addConditionToListByPathsArrayWithGlob method
miya Jan 10, 2025
28c128f
create-ai-assistant -> ai-assistant
miya Jan 16, 2025
0c224e5
AssistantOwnerAccessScope -> AssistantAccessScope
miya Jan 16, 2025
caeb96b
Omit grantedUsers
miya Jan 16, 2025
d56ce31
Merge pull request #9497 from weseek/feat/159153-implement-ai-assista…
miya Jan 16, 2025
211e444
Merge branch 'feat/growi-ai-next' into feat/160044-implement-logic-fo…
miya Jan 16, 2025
42d437b
add shash
miya Jan 16, 2025
6002af9
ownerAccessScope -> accessScope
miya Jan 16, 2025
c991c71
Add TODO
miya Jan 16, 2025
b0a65dc
Refactor createVectorStore method to accept a name parameter for dyna…
miya Jan 16, 2025
ade8f95
Add grob pattern path validation
miya Jan 16, 2025
f38352c
Refactor path condition creation to use convertPathPatternsToRegExp f…
miya Jan 16, 2025
da0041c
VectorStoreFile no longer waits for creation
miya Jan 16, 2025
03377b8
Merge pull request #9545 from weseek/feat/160044-implement-logic-for-…
miya Jan 16, 2025
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
2 changes: 2 additions & 0 deletions apps/app/public/static/locales/en_US/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,8 @@
"Page Tree": "Page Tree",
"Bookmarks": "Bookmarks",
"In-App Notification": "Notifications",
"AI Assistant": "AI Assistant",
"Knowledge Assistant": "Knowledge Assistant",
"original_path": "Original path",
"new_path": "New path",
"duplicated_path": "Duplicated path",
Expand Down
2 changes: 2 additions & 0 deletions apps/app/public/static/locales/fr_FR/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,8 @@
"Page Tree": "Arbre",
"Bookmarks": "Favoris",
"In-App Notification": "Notifications",
"AI Assistant": "Assistant IA",
"Knowledge Assistant": "Assistant de Connaissance",
"original_path": "Chemin originel",
"new_path": "Nouveau chemin",
"duplicated_path": "Chemin dupliqué",
Expand Down
2 changes: 2 additions & 0 deletions apps/app/public/static/locales/ja_JP/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,8 @@
"Page Tree": "ページツリー",
"Bookmarks": "ブックマーク",
"In-App Notification": "通知",
"AI Assistant": "AI アシスタント",
"Knowledge Assistant": "ナレッジアシスタント",
"original_path": "元のパス",
"new_path": "新しいパス",
"duplicated_path": "重複したパス",
Expand Down
2 changes: 2 additions & 0 deletions apps/app/public/static/locales/zh_CN/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,8 @@
"Page Tree": "页面树",
"Bookmarks": "书签",
"In-App Notification": "通知",
"AI Assistant": "AI助手",
"Knowledge Assistant": "知识助手",
"original_path": "Original path",
"new_path": "New path",
"duplicated_path": "Duplicated path",
Expand Down
25 changes: 19 additions & 6 deletions apps/app/src/client/components/PageHeader/PagePathHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import {
useState, useCallback, memo,
} from 'react';

import nodePath from 'path';

import type { IPagePopulatedToShowRevision } from '@growi/core';
import { DevidedPagePath } from '@growi/core/dist/models';
import { normalizePath } from '@growi/core/dist/utils/path-utils';
Expand All @@ -11,13 +13,13 @@ import { debounce } from 'throttle-debounce';

import type { InputValidationResult } from '~/client/util/use-input-validator';
import { ValidationTarget, useInputValidator } from '~/client/util/use-input-validator';
import type { IPageForItem } from '~/interfaces/page';
import LinkedPagePath from '~/models/linked-page-path';
import { usePageSelectModal } from '~/stores/modal';

import { PagePathHierarchicalLink } from '../../../components/Common/PagePathHierarchicalLink';
import { AutosizeSubmittableInput, getAdjustedMaxWidthForAutosizeInput } from '../Common/SubmittableInput';
import { usePagePathRenameHandler } from '../PageEditor/page-path-rename-utils';
import { PageSelectModal } from '../PageSelectModal/PageSelectModal';

import styles from './PagePathHeader.module.scss';

Expand Down Expand Up @@ -45,8 +47,7 @@ export const PagePathHeader = memo((props: Props): JSX.Element => {
const [isRenameInputShown, setRenameInputShown] = useState(false);
const [isHover, setHover] = useState(false);

const { data: PageSelectModalData, open: openPageSelectModal } = usePageSelectModal();
const isOpened = PageSelectModalData?.isOpened ?? false;
const { open: openPageSelectModal } = usePageSelectModal();

const [validationResult, setValidationResult] = useState<InputValidationResult>();

Expand All @@ -61,6 +62,20 @@ export const PagePathHeader = memo((props: Props): JSX.Element => {

const pagePathRenameHandler = usePagePathRenameHandler(currentPage);

const onClickOpenPageSelectModalButton = useCallback(() => {
const onSelected = (page: IPageForItem): void => {
if (page == null || page.path == null) {
return;
}

const currentPageTitle = nodePath.basename(currentPage?.path ?? '') || '/';
const newPagePath = nodePath.resolve(page.path, currentPageTitle);

pagePathRenameHandler(newPagePath);
};

openPageSelectModal({ onSelected });
}, [currentPage?.path, openPageSelectModal, pagePathRenameHandler]);

const rename = useCallback((inputText) => {
const pathToRename = normalizePath(`${inputText}/${dPagePath.latter}`);
Expand Down Expand Up @@ -144,13 +159,11 @@ export const PagePathHeader = memo((props: Props): JSX.Element => {
<button
type="button"
className="btn btn-outline-neutral-secondary d-flex align-items-center justify-content-center"
onClick={openPageSelectModal}
onClick={onClickOpenPageSelectModalButton}
>
<span className="material-symbols-outlined fs-6">account_tree</span>
</button>
</div>

{isOpened && <PageSelectModal />}
</div>
);
});
78 changes: 52 additions & 26 deletions apps/app/src/client/components/PageSelectModal/PageSelectModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,72 +19,63 @@ import { useSWRxCurrentPage } from '~/stores/page';

import { ItemsTree } from '../ItemsTree';
import ItemsTreeContentSkeleton from '../ItemsTree/ItemsTreeContentSkeleton';
import { usePagePathRenameHandler } from '../PageEditor/page-path-rename-utils';

import { TreeItemForModal } from './TreeItemForModal';


export const PageSelectModal: FC = () => {
const PageSelectModalSubstance: FC = () => {
const {
data: PageSelectModalData,
close: closeModal,
} = usePageSelectModal();

const isOpened = PageSelectModalData?.isOpened ?? false;

const [clickedParentPagePath, setClickedParentPagePath] = useState<string | null>(null);
const [clickedParentPage, setClickedParentPage] = useState<IPageForItem | null>(null);
const [isIncludeSubPage, setIsIncludeSubPage] = useState(true);

const { t } = useTranslation();

const { data: isGuestUser } = useIsGuestUser();
const { data: isReadOnlyUser } = useIsReadOnlyUser();
const { data: targetAndAncestorsData } = useTargetAndAncestors();
const { data: currentPage } = useSWRxCurrentPage();
const { data: pageSelectModalData } = usePageSelectModal();

const pagePathRenameHandler = usePagePathRenameHandler(currentPage);
const isHierarchicalSelectionMode = pageSelectModalData?.opts?.isHierarchicalSelectionMode ?? false;

const onClickTreeItem = useCallback((page: IPageForItem) => {
const parentPagePath = page.path;

if (parentPagePath == null) {
return <></>;
return;
}

setClickedParentPagePath(parentPagePath);
setClickedParentPage(page);
}, []);

const onClickCancel = useCallback(() => {
setClickedParentPagePath(null);
setClickedParentPage(null);
closeModal();
}, [closeModal]);

const onClickDone = useCallback(() => {
if (clickedParentPagePath != null) {
const currentPageTitle = nodePath.basename(currentPage?.path ?? '') || '/';
const newPagePath = nodePath.resolve(clickedParentPagePath, currentPageTitle);

pagePathRenameHandler(newPagePath);
if (clickedParentPage != null) {
PageSelectModalData?.opts?.onSelected?.(clickedParentPage, isIncludeSubPage);
}

closeModal();
}, [clickedParentPagePath, closeModal, currentPage?.path, pagePathRenameHandler]);
}, [PageSelectModalData?.opts, clickedParentPage, closeModal, isIncludeSubPage]);

const parentPagePath = pathUtils.addTrailingSlash(nodePath.dirname(currentPage?.path ?? ''));

const targetPathOrId = clickedParentPagePath || parentPagePath;
const targetPathOrId = clickedParentPage?.path || parentPagePath;

const targetPath = clickedParentPagePath || parentPagePath;
const targetPath = clickedParentPage?.path || parentPagePath;

if (isGuestUser == null) {
return <></>;
}

return (
<Modal
isOpen={isOpened}
toggle={closeModal}
centered
>
<>
<ModalHeader toggle={closeModal}>{t('page_select_modal.select_page_location')}</ModalHeader>
<ModalBody className="p-0">
<Suspense fallback={<ItemsTreeContentSkeleton />}>
Expand All @@ -103,10 +94,45 @@ export const PageSelectModal: FC = () => {
</SimpleBar>
</Suspense>
</ModalBody>
<ModalFooter>
<Button color="secondary" onClick={onClickCancel}>{t('Cancel')}</Button>
<Button color="primary" onClick={onClickDone}>{t('Done')}</Button>
<ModalFooter className="border-top d-flex flex-column">
{ isHierarchicalSelectionMode && (
<div className="form-check form-check-info align-self-start ms-4">
<input
type="checkbox"
id="includeSubPages"
className="form-check-input"
name="fileUpload"
checked={isIncludeSubPage}
onChange={() => setIsIncludeSubPage(!isIncludeSubPage)}
/>
<label
className="form-label form-check-label"
htmlFor="includeSubPages"
>
{t('Include Subordinated Page')}
</label>
</div>
)}
<div className="d-flex gap-2 align-self-end">
<Button color="secondary" onClick={onClickCancel}>{t('Cancel')}</Button>
<Button color="primary" onClick={onClickDone}>{t('Done')}</Button>
</div>
</ModalFooter>
</>
);
};

export const PageSelectModal = (): JSX.Element => {
const { data: pageSelectModalData, close: closePageSelectModal } = usePageSelectModal();
const isOpen = pageSelectModalData?.isOpened ?? false;

if (!isOpen) {
return <></>;
}

return (
<Modal isOpen={isOpen} toggle={closePageSelectModal} centered>
<PageSelectModalSubstance />
</Modal>
);
};
3 changes: 3 additions & 0 deletions apps/app/src/client/components/Sidebar/SidebarContents.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React, { memo, useMemo } from 'react';

import { AiAssistant } from '~/features/openai/client/components/AiAssistant/Sidebar/AiAssistant';
import { SidebarContentsType } from '~/interfaces/ui';
import { useCollapsedContentsOpened, useCurrentSidebarContents, useSidebarMode } from '~/stores/ui';

Expand Down Expand Up @@ -32,6 +33,8 @@ export const SidebarContents = memo(() => {
return Bookmarks;
case SidebarContentsType.NOTIFICATION:
return InAppNotification;
case SidebarContentsType.AI_ASSISTANT:
return AiAssistant;
default:
return PageTree;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,15 @@ export type PrimaryItemProps = {
label: string,
iconName: string,
sidebarMode: SidebarMode,
isCustomIcon?: boolean,
badgeContents?: number,
onHover?: (contents: SidebarContentsType) => void,
onClick?: () => void,
}

export const PrimaryItem = (props: PrimaryItemProps): JSX.Element => {
const {
contents, label, iconName, sidebarMode, badgeContents,
contents, label, iconName, sidebarMode, badgeContents, isCustomIcon,
onClick, onHover,
} = props;

Expand Down Expand Up @@ -80,7 +81,10 @@ export const PrimaryItem = (props: PrimaryItemProps): JSX.Element => {
{ badgeContents != null && (
<span className="position-absolute badge rounded-pill bg-primary">{badgeContents}</span>
)}
<span className="material-symbols-outlined">{iconName}</span>
{ isCustomIcon
? (<span className="growi-custom-icons fs-4 align-middle">{iconName}</span>)
: (<span className="material-symbols-outlined">{iconName}</span>)
}
</div>
</button>
{
Expand Down
12 changes: 12 additions & 0 deletions apps/app/src/client/components/Sidebar/SidebarNav/PrimaryItems.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { memo } from 'react';
import dynamic from 'next/dynamic';

import { SidebarContentsType } from '~/interfaces/ui';
import { useIsAiEnabled } from '~/stores-universal/context';
import { useSidebarMode } from '~/stores/ui';

import { PrimaryItem } from './PrimaryItem';
Expand All @@ -22,6 +23,7 @@ export const PrimaryItems = memo((props: Props) => {
const { onItemHover } = props;

const { data: sidebarMode } = useSidebarMode();
const { data: isAiEnabled } = useIsAiEnabled();

if (sidebarMode == null) {
return <></>;
Expand All @@ -35,6 +37,16 @@ export const PrimaryItems = memo((props: Props) => {
<PrimaryItem sidebarMode={sidebarMode} contents={SidebarContentsType.BOOKMARKS} label="Bookmarks" iconName="bookmarks" onHover={onItemHover} />
<PrimaryItem sidebarMode={sidebarMode} contents={SidebarContentsType.TAG} label="Tags" iconName="local_offer" onHover={onItemHover} />
<PrimaryItemForNotification sidebarMode={sidebarMode} onHover={onItemHover} />
{isAiEnabled && (
<PrimaryItem
sidebarMode={sidebarMode}
contents={SidebarContentsType.AI_ASSISTANT}
label="AI Assistant"
iconName="ai_assistant"
isCustomIcon
onHover={onItemHover}
/>
)}
</div>
);
});
7 changes: 7 additions & 0 deletions apps/app/src/components/Layout/BasicLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,11 @@ const DeleteBookmarkFolderModal = dynamic(
);
const SearchModal = dynamic(() => import('../../features/search/client/components/SearchModal'), { ssr: false });
const AiChatModal = dynamic(() => import('~/features/openai/chat/components/AiChatModal').then(mod => mod.AiChatModal), { ssr: false });
const AiAssistantManegementModal = dynamic(
() => import('~/features/openai/client/components/AiAssistant/AiAssistantManegementModal')
.then(mod => mod.AiAssistantManegementModal), { ssr: false },
);
const PageSelectModal = dynamic(() => import('~/client/components/PageSelectModal/PageSelectModal').then(mod => mod.PageSelectModal), { ssr: false });

type Props = {
children?: ReactNode
Expand Down Expand Up @@ -66,8 +71,10 @@ export const BasicLayout = ({ children, className }: Props): JSX.Element => {
<DeleteAttachmentModal />
<DeleteBookmarkFolderModal />
<PutbackPageModal />
<PageSelectModal />
<SearchModal />
<AiChatModal />
<AiAssistantManegementModal />

<PagePresentationModal />
<HotkeysManager />
Expand Down
Loading
Loading