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(chat): Add opportunity to share applications (Issue #2044) #2909

Merged
merged 71 commits into from
Jan 20, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
71 commits
Select commit Hold shift + click to select a range
753a8ec
chore(chat): add `bypass_ort`
IlyaBondar Dec 10, 2024
0612dd7
use ort_version: 42.1.0
IlyaBondar Dec 10, 2024
44872fc
Merge branch 'development' of https://github.com/epam/ai-dial-chat in…
Derikyan Dec 12, 2024
9e979d7
Merge branch 'development' of https://github.com/epam/ai-dial-chat in…
Derikyan Dec 12, 2024
9e185f6
Merge branch 'development' of https://github.com/epam/ai-dial-chat in…
Derikyan Dec 12, 2024
96a239a
Merge branch 'development' of https://github.com/epam/ai-dial-chat in…
Derikyan Dec 13, 2024
ae2825c
Merge branch 'development' of https://github.com/epam/ai-dial-chat in…
Derikyan Dec 15, 2024
1677ee5
Merge branch 'development' of https://github.com/epam/ai-dial-chat in…
Derikyan Dec 20, 2024
71cd3fa
Merge branch 'development' of https://github.com/epam/ai-dial-chat in…
Derikyan Dec 25, 2024
88202b9
Merge branch 'development' of https://github.com/epam/ai-dial-chat in…
Derikyan Dec 26, 2024
54d0f31
Merge branch 'development' of https://github.com/epam/ai-dial-chat in…
Derikyan Dec 27, 2024
cc97dd8
Merge branch 'development' of https://github.com/epam/ai-dial-chat in…
Derikyan Jan 3, 2025
c7d7ca8
Merge branch 'development' of https://github.com/epam/ai-dial-chat in…
Derikyan Jan 3, 2025
f8f705d
Merge branch 'development' of https://github.com/epam/ai-dial-chat in…
Derikyan Jan 7, 2025
2730576
Merge branch 'development' of https://github.com/epam/ai-dial-chat in…
Derikyan Jan 8, 2025
80e3914
add share button for application card
Derikyan Jan 8, 2025
57b86f0
add version selector
Derikyan Jan 9, 2025
5b602a6
feat: add simple app sharing
denys-kolomiitsev Jan 9, 2025
0faf4c8
share modal
Derikyan Jan 9, 2025
ffdf525
Merge branch 'feat/2044-share-applications' of https://github.com/epa…
Derikyan Jan 9, 2025
5b79083
Merge branch 'development' of https://github.com/epam/ai-dial-chat in…
Derikyan Jan 9, 2025
dff31a7
add unshare button
Derikyan Jan 9, 2025
43df1c3
Merge branch 'development' of https://github.com/epam/ai-dial-chat in…
Derikyan Jan 9, 2025
baaaf7a
feature flag conditions
Derikyan Jan 10, 2025
33a2c72
feat: add sharing info to the custom apps
denys-kolomiitsev Jan 10, 2025
23ae0d8
Merge branch 'feat/2044-share-applications' of https://github.com/epa…
denys-kolomiitsev Jan 10, 2025
43e9209
feat: add epic to get new models when invitation accepted
denys-kolomiitsev Jan 10, 2025
ea1d387
Merge branch 'development' of https://github.com/epam/ai-dial-chat in…
Derikyan Jan 11, 2025
ebea3d2
Merge branch 'feat/2044-share-applications' of https://github.com/epa…
Derikyan Jan 11, 2025
033bb0e
feat: add unshare
denys-kolomiitsev Jan 12, 2025
090e1c9
feat: app icon to the sharing resources
denys-kolomiitsev Jan 12, 2025
20d7562
Merge branch 'feat/2044-share-applications' of https://github.com/epa…
Derikyan Jan 13, 2025
5a7302e
models reducers
Derikyan Jan 13, 2025
dbf0a77
feat: delete shared app when discard
denys-kolomiitsev Jan 13, 2025
f767f49
change context menu
Derikyan Jan 13, 2025
36f4031
Merge branch 'feat/2044-share-applications' of https://github.com/epa…
Derikyan Jan 13, 2025
3b12fc4
Merge branch 'development' of https://github.com/epam/ai-dial-chat in…
Derikyan Jan 13, 2025
37d1236
fix context menu
Derikyan Jan 13, 2025
608af9e
feat: open marketplace when invitation accepted
denys-kolomiitsev Jan 13, 2025
af67990
Merge branch 'development' into feat/2044-share-applications
denys-kolomiitsev Jan 13, 2025
70a2489
add share and unshare to context menu in talk to card, fix icon field…
Derikyan Jan 13, 2025
3bf1109
Merge branch 'feat/2044-share-applications' of https://github.com/epa…
Derikyan Jan 13, 2025
1b7fbb4
fix
Derikyan Jan 14, 2025
8b301f3
fix: fix update shared application
denys-kolomiitsev Jan 14, 2025
5f594be
Merge branch 'feat/2044-share-applications' of https://github.com/epa…
denys-kolomiitsev Jan 14, 2025
e157e96
fix: fix edit shared application
denys-kolomiitsev Jan 14, 2025
75e013b
Merge branch 'development' into feat/2044-share-applications
denys-kolomiitsev Jan 14, 2025
c12b36a
fix: show logs buttons for the shared applications
denys-kolomiitsev Jan 14, 2025
0a24aed
Merge branch 'feat/2044-share-applications' of https://github.com/epa…
denys-kolomiitsev Jan 14, 2025
25d790b
fix edit x icon disabling, add TODO comment
Derikyan Jan 14, 2025
d20e591
fix docker error
Derikyan Jan 14, 2025
1090894
small fixes
Derikyan Jan 14, 2025
b3e272d
Merge branch 'development' into feat/2044-share-applications
denys-kolomiitsev Jan 14, 2025
b5e2aec
fix: fix write permission and refactoring
denys-kolomiitsev Jan 14, 2025
d13c5fc
Merge branch 'development' into feat/2044-share-applications
denys-kolomiitsev Jan 14, 2025
4df1f53
small fixes
Derikyan Jan 15, 2025
6430af2
fix: fix editing the shared code app
denys-kolomiitsev Jan 15, 2025
540f83f
Merge branch 'feat/2044-share-applications' of https://github.com/epa…
denys-kolomiitsev Jan 15, 2025
e418f7e
fix: fix shared permissions removed after update application
denys-kolomiitsev Jan 15, 2025
2d21c39
fix: fix display context menu items for the shared apps
denys-kolomiitsev Jan 15, 2025
dd6c5ee
Merge branch 'development' into feat/2044-share-applications
denys-kolomiitsev Jan 15, 2025
44dfb85
Merge branch 'development' into feat/2044-share-applications
denys-kolomiitsev Jan 16, 2025
23e39af
Merge branch 'development' into feat/2044-share-applications
IlyaBondar Jan 16, 2025
3a9c447
fix: add feature to the variable
denys-kolomiitsev Jan 16, 2025
1335250
Merge branch 'development' into feat/2044-share-applications
denys-kolomiitsev Jan 16, 2025
b27fcb8
resolve comments
Derikyan Jan 17, 2025
02c6520
fix: resolve comments
denys-kolomiitsev Jan 19, 2025
657b6ce
Merge branch 'development' into feat/2044-share-applications
denys-kolomiitsev Jan 19, 2025
9172b78
feat: update application after sharing revoke
denys-kolomiitsev Jan 20, 2025
121a4b1
fix: resolve comments
denys-kolomiitsev Jan 20, 2025
c3db21a
fix: resolve comments
denys-kolomiitsev Jan 20, 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/chat-e2e/src/testData/expectedConstants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,8 @@ export const ExpectedConstants = {
'This link is temporary and will be active for 3 days. This conversation and future changes to it will be visible to users who follow the link. Only owner will be able to make changes. Renaming or changing the model will stop sharing.',
sharePromptText:
'This link is temporary and will be active for 3 days. This prompt and future changes to it will be visible to users who follow the link. Only owner will be able to make changes. Renaming will stop sharing.',
shareApplicationText:
'This application and its updates will be visible to users with the link. Renaming or changing the version will stop sharing.',
shareConversationFolderText:
'This link is temporary and will be active for 3 days. This conversation folder and future changes to it will be visible to users who follow the link. Only owner will be able to make changes. Renaming will stop sharing.',
sharePromptFolderText:
Expand Down
2 changes: 1 addition & 1 deletion apps/chat/.env.development
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ DIAL_ROLES_FIELD="dial_roles"


# Application UI settings
ENABLED_FEATURES="conversations-section,prompts-section,top-settings,top-clear-conversation,top-chat-info,top-chat-model-settings,empty-chat-settings,header,footer,request-api-key,report-an-issue,likes,conversations-sharing,prompts-sharing,input-files,attachments-manager,conversations-publishing,prompts-publishing,custom-logo,input-links,custom-applications,message-templates,marketplace,quick-apps,code-apps"
ENABLED_FEATURES="conversations-section,prompts-section,top-settings,top-clear-conversation,top-chat-info,top-chat-model-settings,empty-chat-settings,header,footer,request-api-key,report-an-issue,likes,conversations-sharing,prompts-sharing,input-files,attachments-manager,conversations-publishing,prompts-publishing,custom-logo,input-links,custom-applications,message-templates,marketplace,quick-apps,code-apps,applications-sharing"
NEXT_PUBLIC_APP_NAME="Local Development APP Name"
NEXT_PUBLIC_DEFAULT_SYSTEM_PROMPT=""
NEXT_PUBLIC_DEFAULT_TEMPERATURE="1"
Expand Down
3 changes: 3 additions & 0 deletions apps/chat/public/images/icons/unshare-user.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 2 additions & 1 deletion apps/chat/public/locales/en/sidebar.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@
"share.modal.link_conversation": "This conversation and future changes to it will be visible to users who follow the link. Only owner will be able to make changes. Renaming or changing the model will stop sharing.",
"share.modal.link_prompt": "This prompt and future changes to it will be visible to users who follow the link. Only owner will be able to make changes. Renaming will stop sharing.",
"share.modal.link_conversations_folder": "This conversation folder and future changes to it will be visible to users who follow the link. Only owner will be able to make changes. Renaming will stop sharing.",
"share.modal.link_prompts_folder": "This prompt folder and future changes to it will be visible to users who follow the link. Only owner will be able to make changes. Renaming will stop sharing."
"share.modal.link_prompts_folder": "This prompt folder and future changes to it will be visible to users who follow the link. Only owner will be able to make changes. Renaming will stop sharing.",
"share.modal.link_application": "This application and its updates will be visible to users with the link. Renaming or changing the version will stop sharing."
}
78 changes: 76 additions & 2 deletions apps/chat/src/components/Chat/ShareModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { useTranslation } from 'next-i18next';

import { getShareType } from '@/src/utils/app/share';

import { FeatureType } from '@/src/types/common';
import { ModalState } from '@/src/types/modal';
import { Translation } from '@/src/types/translation';

Expand All @@ -24,6 +25,8 @@ import { OUTSIDE_PRESS_AND_MOUSE_EVENT } from '@/src/constants/modal';
import Modal from '../Common/Modal';
import Tooltip from '../Common/Tooltip';

import { SharePermission } from '@epam/ai-dial-shared';

export const ShareModal = () => {
const isShareModalClosed = useAppSelector(
ShareSelectors.selectShareModalClosed,
Expand All @@ -33,6 +36,37 @@ export const ShareModal = () => {
}
};

interface ShareAccessOptionProps {
filterValue: string;
selected: boolean;
onSelect: (value: boolean) => void;
}

const ShareAccessOption = ({
filterValue,
selected,
onSelect,
}: ShareAccessOptionProps) => {
return (
<label
className="relative flex size-[18px] w-full shrink-0 cursor-pointer items-center"
data-qa="share-option"
>
<input
className="checkbox peer size-[18px] bg-layer-3"
type="checkbox"
checked={selected}
onChange={(e) => onSelect(e.target.checked)}
/>
<IconCheck
size={18}
className="invisible absolute text-accent-primary peer-checked:visible"
/>
<span className="ml-2 whitespace-nowrap text-sm">{filterValue}</span>
</label>
);
};

export default function ShareModalView() {
const { t } = useTranslation(Translation.SideBar);
const dispatch = useAppDispatch();
Expand All @@ -42,11 +76,22 @@ export default function ShareModalView() {
const [urlWasCopied, setUrlWasCopied] = useState(false);
const timeoutRef = useRef<ReturnType<typeof setTimeout>>();

const [editAccess, setEditAccess] = useState(false);
const modalState = useAppSelector(ShareSelectors.selectShareModalState);
const invitationId = useAppSelector(ShareSelectors.selectInvitationId);
const readInvitationId = useAppSelector(ShareSelectors.selectInvitationId);
const writeInvitationId = useAppSelector(
ShareSelectors.selectWriteInvitationId,
);
const invitationId = editAccess ? writeInvitationId : readInvitationId;

const shareResourceId = useAppSelector(ShareSelectors.selectShareResourceId);

const shareResourceName = useAppSelector(
ShareSelectors.selectShareResourceName,
);
const shareResourceVersion = useAppSelector(
ShareSelectors.selectShareResourceVersion,
);
const shareFeatureType = useAppSelector(
ShareSelectors.selectShareFeatureType,
);
Expand All @@ -57,6 +102,26 @@ export default function ShareModalView() {
}, [shareFeatureType, isFolder]);
const [url, setUrl] = useState('');

const onChangeSharePermissionHandler = useCallback(
(isWrite: boolean) => {
setEditAccess(isWrite);
const shouldGetNewInvitationId =
(isWrite && !writeInvitationId) || (!isWrite && !readInvitationId);

if (shareResourceId && shouldGetNewInvitationId) {
dispatch(
ShareActions.shareApplication({
resourceId: shareResourceId,
permissions: isWrite
? [SharePermission.READ, SharePermission.WRITE]
: [SharePermission.READ],
}),
);
}
},
[dispatch, readInvitationId, shareResourceId, writeInvitationId],
);

useEffect(() => {
setUrl(`${window?.location.origin}/share/${invitationId || ''}`);
}, [invitationId]);
Expand Down Expand Up @@ -86,7 +151,6 @@ export default function ShareModalView() {
);

useEffect(() => () => clearTimeout(timeoutRef.current), []);

return (
<Modal
portalId="theme-main"
Expand All @@ -98,12 +162,22 @@ export default function ShareModalView() {
dismissProps={OUTSIDE_PRESS_AND_MOUSE_EVENT}
>
<div className="flex flex-col justify-between gap-2">
{shareResourceVersion && <span>Version: {shareResourceVersion}</span>}
<p className="text-sm text-secondary">
{t('share.modal.link.description')}
</p>
<p className="text-sm text-secondary">
{t('share.modal.link', { context: sharingType })}
</p>
{shareFeatureType === FeatureType.Application && (
<div className="my-2 flex flex-col gap-2">
<ShareAccessOption
filterValue="Allow editing by other users"
selected={editAccess}
onSelect={onChangeSharePermissionHandler}
/>
</div>
)}
<div className="relative mt-2">
<Tooltip tooltip={url}>
<input
Expand Down
66 changes: 58 additions & 8 deletions apps/chat/src/components/Chat/TalkTo/TalkToCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ import {
IconPlayerPlay,
IconPlaystationSquare,
IconTrashX,
IconUserShare,
IconWorldShare,
} from '@tabler/icons-react';
import React, { useCallback, useMemo } from 'react';
import React, { useCallback, useMemo, useState } from 'react';

import { useTranslation } from 'next-i18next';

Expand All @@ -22,6 +23,7 @@ import {
isExecutableApp,
} from '@/src/utils/app/application';
import { getRootId } from '@/src/utils/app/id';
import { canWriteSharedWithMe } from '@/src/utils/app/share';
import { PseudoModel, isPseudoModel } from '@/src/utils/server/api';

import {
Expand All @@ -39,6 +41,7 @@ import { AuthSelectors } from '@/src/store/auth/auth.reducers';
import { useAppDispatch, useAppSelector } from '@/src/store/hooks';
import { ModelsSelectors } from '@/src/store/models/models.reducers';
import { SettingsSelectors } from '@/src/store/settings/settings.reducers';
import { ShareActions } from '@/src/store/share/share.reducers';

import { REPLAY_AS_IS_MODEL } from '@/src/constants/chat';

Expand All @@ -51,7 +54,10 @@ import { EntityMarkdownDescription } from '@/src/components/Common/MarkdownDescr
import { ApplicationTopic } from '@/src/components/Marketplace/ApplicationTopic';
import { FunctionStatusIndicator } from '@/src/components/Marketplace/FunctionStatusIndicator';

import UnshareDialog from '../../Common/UnshareDialog';

import LoaderIcon from '@/public/images/icons/loader.svg';
import IconUserUnshare from '@/public/images/icons/unshare-user.svg';
import { Feature } from '@epam/ai-dial-shared';

const DESKTOP_ICON_SIZE = 80;
Expand Down Expand Up @@ -104,6 +110,8 @@ export const TalkToCard = ({

const dispatch = useAppDispatch();

const [isUnshareConfirmOpened, setIsUnshareConfirmOpened] = useState(false);

const installedModelIds = useAppSelector(
ModelsSelectors.selectInstalledModelIds,
);
Expand All @@ -113,12 +121,20 @@ export const TalkToCard = ({
);
const isAdmin = useAppSelector(AuthSelectors.selectIsAdmin);

const isMyApp = entity.id.startsWith(
const isMyEntity = entity.id.startsWith(
getRootId({ featureType: FeatureType.Application }),
);
const isExecutable = isExecutableApp(entity) && (isMyApp || isAdmin);

const canWrite = canWriteSharedWithMe(entity);

const isExecutable =
isExecutableApp(entity) && (isMyEntity || isAdmin || canWrite);
const screenState = useScreenState();

const isApplicationsSharingEnabled = useAppSelector((state) =>
SettingsSelectors.isFeatureEnabled(state, Feature.ApplicationsSharing),
);

const versionsToSelect = useMemo(() => {
return allModels.filter(
(model) =>
Expand All @@ -136,9 +152,6 @@ export const TalkToCard = ({
isSelected,
]);

const isMyEntity = entity.id.startsWith(
getRootId({ featureType: FeatureType.Application }),
);
const isModifyDisabled = isApplicationStatusUpdating(entity);
const playerStatus = getApplicationSimpleStatus(entity);

Expand Down Expand Up @@ -170,6 +183,15 @@ export const TalkToCard = ({
[onSelectVersion],
);

const handleOpenSharing = useCallback(() => {
dispatch(
ShareActions.share({
featureType: FeatureType.Application,
resourceId: entity.id,
}),
);
}, [dispatch, entity.id]);

const isOldReplay = useMemo(() => {
return (
entity.id === REPLAY_AS_IS_MODEL &&
Expand Down Expand Up @@ -208,13 +230,35 @@ export const TalkToCard = ({
{
name: t('Edit'),
dataQa: 'edit',
display: isMyEntity && !!onEdit,
display: (isMyEntity || !!canWrite) && !!onEdit,
Icon: IconPencilMinus,
onClick: (e: React.MouseEvent) => {
e.stopPropagation();
onEdit(entity);
},
},
{
name: t('Share'),
dataQa: 'share',
display: isMyEntity && isApplicationsSharingEnabled,
Icon: IconUserShare,
onClick: (e: React.MouseEvent<HTMLButtonElement>) => {
e.stopPropagation();
handleOpenSharing();
},
},
{
name: t('Unshare'),
dataQa: 'unshare',
display:
(!!entity.sharedWithMe || !!entity.isShared) &&
isApplicationsSharingEnabled,
Icon: IconUserUnshare,
onClick: (e: React.MouseEvent) => {
setIsUnshareConfirmOpened(true);
e.stopPropagation();
},
},
{
name: t('Publish'),
dataQa: 'publish',
Expand All @@ -229,7 +273,7 @@ export const TalkToCard = ({
name: t('Logs'),
dataQa: 'app-logs',
display:
isExecutable && playerStatus === SimpleApplicationStatus.UNDEPLOY,
!!isExecutable && playerStatus === SimpleApplicationStatus.UNDEPLOY,
Icon: IconFileDescription,
onClick: (e: React.MouseEvent) => {
e.preventDefault();
Expand Down Expand Up @@ -259,11 +303,14 @@ export const TalkToCard = ({
isCodeAppsEnabled,
PlayerIcon,
onEdit,
canWrite,
isApplicationsSharingEnabled,
onPublish,
isExecutable,
onDelete,
isModifyDisabled,
handleUpdateFunctionStatus,
handleOpenSharing,
onOpenLogs,
],
);
Expand Down Expand Up @@ -388,6 +435,9 @@ export const TalkToCard = ({
))}
</div>
</div>
{isUnshareConfirmOpened && (
<UnshareDialog entity={entity} setOpened={setIsUnshareConfirmOpened} />
)}
</div>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export const ApplicationWizard: React.FC<ApplicationWizardProps> = ({
const selectedApplication = useAppSelector(
ApplicationSelectors.selectApplicationDetail,
);
const isSharedWithMe = selectedApplication?.sharedWithMe;

const handleClose = useCallback(() => {
onClose(false);
Expand Down Expand Up @@ -81,6 +82,7 @@ export const ApplicationWizard: React.FC<ApplicationWizardProps> = ({
isEdit={isEdit}
currentReference={currentReference}
selectedApplication={isEdit ? selectedApplication : undefined}
isSharedWithMe={!!isSharedWithMe}
/>
</div>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,12 @@ export const ApplicationWizardFooter: FC<ApplicationWizardFooterProps> = ({
<div
className={classNames(
'flex gap-2 border-t border-tertiary p-4 md:px-6',
isEdit ? 'justify-between' : 'justify-end',
isEdit && !selectedApplication?.sharedWithMe
? 'justify-between'
: 'justify-end',
)}
>
{isEdit && (
{isEdit && !selectedApplication?.sharedWithMe && (
<div className="flex items-center gap-2">
<Tooltip
tooltip={
Expand Down
Loading
Loading