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

fix(chat): fix card design, add copy link and share in context menu, correct mobile icon size (Issues #2943, #2991) #3025

Merged
merged 38 commits into from
Jan 31, 2025
Merged
Show file tree
Hide file tree
Changes from 37 commits
Commits
Show all changes
38 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
5be6ecf
Merge branch 'development' of https://github.com/epam/ai-dial-chat in…
Derikyan Jan 21, 2025
0743a08
Merge branch 'development' of https://github.com/epam/ai-dial-chat in…
Derikyan Jan 23, 2025
5edae7f
Merge branch 'development' of https://github.com/epam/ai-dial-chat in…
Derikyan Jan 24, 2025
7abbfe5
fix(chat): fix card design, add copy link and share in context menu (…
Derikyan Jan 27, 2025
0edefdd
Merge branch 'development' of https://github.com/epam/ai-dial-chat in…
Derikyan Jan 27, 2025
f5476f9
Merge branch 'development' of https://github.com/epam/ai-dial-chat in…
Derikyan Jan 27, 2025
1fdb66a
Merge branch 'development' of https://github.com/epam/ai-dial-chat in…
Derikyan Jan 27, 2025
2f16aae
fix errors
Derikyan Jan 27, 2025
0ac8f53
Merge branch 'development' of https://github.com/epam/ai-dial-chat in…
Derikyan Jan 27, 2025
0100eda
Merge branch 'development' of https://github.com/epam/ai-dial-chat in…
Derikyan Jan 28, 2025
f0e5ebd
card version resizing
Derikyan Jan 28, 2025
e1d879d
Merge branch 'development' of https://github.com/epam/ai-dial-chat in…
Derikyan Jan 28, 2025
187c3a7
Merge branch 'development' into feat/2943-card-redesign
Derikyan Jan 29, 2025
4ade959
Merge branch 'development' of https://github.com/epam/ai-dial-chat in…
Derikyan Jan 30, 2025
2917a4e
Merge branch 'feat/2943-card-redesign' of https://github.com/epam/ai-…
Derikyan Jan 30, 2025
1c7f8d2
fix conflicts
Derikyan Jan 30, 2025
5e10c43
resolve conflicts
Derikyan Jan 30, 2025
6a7cb58
Merge branch 'development' of https://github.com/epam/ai-dial-chat in…
Derikyan Jan 30, 2025
4c0b8e2
resolve conflicts
Derikyan Jan 30, 2025
f24433c
style fix
Derikyan Jan 30, 2025
9d34aee
fix comments
Derikyan Jan 30, 2025
c9c4b2c
Merge branch 'development' of https://github.com/epam/ai-dial-chat in…
Derikyan Jan 30, 2025
3198904
resolve conflicts
Derikyan Jan 31, 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
5 changes: 4 additions & 1 deletion apps/chat/src/components/Chat/ModelVersionSelect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,10 @@ export const ModelVersionSelect = ({
onClick={stopBubbling}
>
{showVersionPrefix && <VersionPrefix />}
<span className="truncate" data-qa="version">
<span
className="max-w-full overflow-hidden truncate whitespace-nowrap"
data-qa="version"
>
{currentEntity.version || currentEntity.id}
</span>
<ChevronDownIcon
Expand Down
57 changes: 12 additions & 45 deletions apps/chat/src/components/Chat/TalkTo/TalkToCard.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import {
IconFileDescription,
IconPencilMinus,
IconPlayerPlay,
IconPlaystationSquare,
IconTrashX,
IconUserShare,
IconWorldShare,
Expand Down Expand Up @@ -31,7 +29,7 @@ import {
SimpleApplicationStatus,
} from '@/src/types/applications';
import { Conversation } from '@/src/types/chat';
import { FeatureType, ScreenState } from '@/src/types/common';
import { FeatureType } from '@/src/types/common';
import { DisplayMenuItemProps } from '@/src/types/menu';
import { DialAIEntityModel } from '@/src/types/models';
import { Translation } from '@/src/types/translation';
Expand All @@ -44,6 +42,11 @@ 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';
import {
CardIconSizes,
PlayerContextIconClasses,
PlayerContextIcons,
} from '@/src/constants/marketplace';

import { ModelVersionSelect } from '@/src/components/Chat/ModelVersionSelect';
import { PlaybackIcon } from '@/src/components/Chat/Playback/PlaybackIcon';
Expand All @@ -56,18 +59,9 @@ import { FunctionStatusIndicator } from '@/src/components/Marketplace/FunctionSt

import ShareIcon from '../../Common/ShareIcon';

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;
const TABLET_ICON_SIZE = 48;
const MOBILE_ICON_SIZE = 40;

const MOBILE_SHARE_ICON_SIZE = 16;
const TABLET_SHARE_ICON_SIZE = 20;
const DESKTOP_SHARE_ICON_SIZE = 30;

const getPlayerCaption = (entity: DialAIEntityModel) => {
switch (entity.functionStatus) {
case ApplicationStatus.DEPLOYED:
Expand Down Expand Up @@ -135,6 +129,8 @@ export const TalkToCard = ({
SettingsSelectors.isFeatureEnabled(state, Feature.ApplicationsSharing),
);

const { iconSize, shareIconSize } = CardIconSizes[screenState];

const versionsToSelect = useMemo(() => {
return allModels.filter(
(model) =>
Expand All @@ -155,17 +151,7 @@ export const TalkToCard = ({
const isModifyDisabled = isApplicationStatusUpdating(entity);
const playerStatus = getApplicationSimpleStatus(entity);

const PlayerIcon = useMemo(() => {
switch (playerStatus) {
case SimpleApplicationStatus.DEPLOY:
return IconPlayerPlay;
case SimpleApplicationStatus.UNDEPLOY:
return IconPlaystationSquare;
case SimpleApplicationStatus.UPDATING:
default:
return LoaderIcon;
}
}, [playerStatus]);
const PlayerContextIcon = PlayerContextIcons[playerStatus];

const handleUpdateFunctionStatus = useCallback(() => {
dispatch(
Expand Down Expand Up @@ -207,14 +193,8 @@ export const TalkToCard = ({
(isAdmin || isMyEntity) &&
!!entity.functionStatus &&
isCodeAppsEnabled,
Icon: PlayerIcon,
iconClassName: classNames({
['text-error']: playerStatus === SimpleApplicationStatus.UNDEPLOY,
['text-accent-secondary']:
playerStatus === SimpleApplicationStatus.DEPLOY,
['animate-spin-steps']:
playerStatus === SimpleApplicationStatus.UPDATING,
}),
Icon: PlayerContextIcon,
iconClassName: PlayerContextIconClasses[playerStatus],
onClick: (e: React.MouseEvent) => {
e.stopPropagation();
handleUpdateFunctionStatus();
Expand Down Expand Up @@ -292,7 +272,7 @@ export const TalkToCard = ({
isAdmin,
isMyEntity,
isCodeAppsEnabled,
PlayerIcon,
PlayerContextIcon,
canWrite,
onEdit,
isApplicationsSharingEnabled,
Expand All @@ -307,23 +287,10 @@ export const TalkToCard = ({
],
);

const iconSize =
screenState === ScreenState.DESKTOP
? DESKTOP_ICON_SIZE
: screenState === ScreenState.TABLET
? TABLET_ICON_SIZE
: MOBILE_ICON_SIZE;
const isOldReplay =
entity.id === REPLAY_AS_IS_MODEL &&
isOldConversationReplay(conversation.replay);

const shareIconSize =
screenState === ScreenState.MOBILE
? MOBILE_SHARE_ICON_SIZE
: screenState === ScreenState.TABLET
? TABLET_SHARE_ICON_SIZE
: DESKTOP_SHARE_ICON_SIZE;

return (
<div
onClick={() => {
Expand Down
57 changes: 14 additions & 43 deletions apps/chat/src/components/Marketplace/ApplicationCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ import {
IconBookmarkFilled,
IconFileDescription,
IconPencilMinus,
IconPlayerPlay,
IconPlaystationSquare,
IconTrashX,
IconUserShare,
IconWorldShare,
Expand All @@ -24,15 +22,14 @@ import {
isExecutableApp,
} from '@/src/utils/app/application';
import { isMyApplication } from '@/src/utils/app/id';
import { isMediumScreen } from '@/src/utils/app/mobile';
import { isEntityIdPublic } from '@/src/utils/app/publications';
import { canWriteSharedWithMe } from '@/src/utils/app/share';

import {
ApplicationStatus,
SimpleApplicationStatus,
} from '@/src/types/applications';
import { FeatureType, ScreenState } from '@/src/types/common';
import { FeatureType } from '@/src/types/common';
import { DisplayMenuItemProps } from '@/src/types/menu';
import { DialAIEntityModel } from '@/src/types/models';
import { Translation } from '@/src/types/translation';
Expand All @@ -44,6 +41,12 @@ 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 {
CardIconSizes,
PlayerContextIconClasses,
PlayerContextIcons,
} from '@/src/constants/marketplace';

import { ModelIcon } from '@/src/components/Chatbar/ModelIcon';
import ContextMenu from '@/src/components/Common/ContextMenu';
import { EntityMarkdownDescription } from '@/src/components/Common/MarkdownDescription';
Expand All @@ -54,27 +57,18 @@ import ShareIcon from '../Common/ShareIcon';
import Tooltip from '../Common/Tooltip';
import { ApplicationLogs } from './ApplicationLogs';

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

const DESKTOP_ICON_SIZE = 80;
const SMALL_ICON_SIZE = 48;

// TODO uncomment in #2943
// const MOBILE_SHARE_ICON_SIZE = 16;
const TABLET_SHARE_ICON_SIZE = 20;
const DESKTOP_SHARE_ICON_SIZE = 30;

interface CardFooterProps {
entity: DialAIEntityModel;
}

const CardFooter = ({ entity }: CardFooterProps) => {
return (
<>
<EntityMarkdownDescription className="mt-3 line-clamp-2 text-ellipsis text-sm leading-[18px] text-secondary xl:hidden">
<EntityMarkdownDescription className="mt-3 hidden text-ellipsis text-sm leading-[18px] text-secondary md:line-clamp-2 xl:hidden">
{getModelShortDescription(entity)}
</EntityMarkdownDescription>
<div className="flex flex-col gap-2 pt-3 md:pt-4">
Expand Down Expand Up @@ -109,7 +103,6 @@ const getPlayerCaption = (entity: DialAIEntityModel) => {

interface ApplicationCardProps {
entity: DialAIEntityModel;
isNotDesktop?: boolean;
onClick: (entity: DialAIEntityModel) => void;
onPublish?: (entity: DialAIEntityModel, action: PublishActions) => void;
onDelete?: (entity: DialAIEntityModel) => void;
Expand All @@ -119,7 +112,6 @@ interface ApplicationCardProps {

export const ApplicationCard = ({
entity,
isNotDesktop,
onClick,
onDelete,
onEdit,
Expand Down Expand Up @@ -150,22 +142,9 @@ export const ApplicationCard = ({
const isExecutable =
isExecutableApp(entity) && (isMyApp || isAdmin || canWrite);

const shareIconSize =
screenState === ScreenState.DESKTOP
? DESKTOP_SHARE_ICON_SIZE
: TABLET_SHARE_ICON_SIZE;
const { iconSize, shareIconSize } = CardIconSizes[screenState];

const PlayerIcon = useMemo(() => {
switch (playerStatus) {
case SimpleApplicationStatus.DEPLOY:
return IconPlayerPlay;
case SimpleApplicationStatus.UNDEPLOY:
return IconPlaystationSquare;
case SimpleApplicationStatus.UPDATING:
default:
return LoaderIcon;
}
}, [playerStatus]);
const PlayerContextIcon = PlayerContextIcons[playerStatus];

const handleUpdateFunctionStatus = useCallback(() => {
dispatch(
Expand Down Expand Up @@ -207,14 +186,8 @@ export const ApplicationCard = ({
disabled: playerStatus === SimpleApplicationStatus.UPDATING,
display:
(isAdmin || isMyApp) && !!entity.functionStatus && isCodeAppsEnabled,
Icon: PlayerIcon,
iconClassName: classNames({
['text-error']: playerStatus === SimpleApplicationStatus.UNDEPLOY,
['text-accent-secondary']:
playerStatus === SimpleApplicationStatus.DEPLOY,
['animate-spin-steps']:
playerStatus === SimpleApplicationStatus.UPDATING,
}),
Icon: PlayerContextIcon,
iconClassName: PlayerContextIconClasses[playerStatus],
onClick: (e: React.MouseEvent) => {
e.stopPropagation();
handleUpdateFunctionStatus();
Expand Down Expand Up @@ -302,7 +275,7 @@ export const ApplicationCard = ({
isAdmin,
isMyApp,
isCodeAppsEnabled,
PlayerIcon,
PlayerContextIcon,
canWrite,
onEdit,
isApplicationsSharingEnabled,
Expand All @@ -316,8 +289,6 @@ export const ApplicationCard = ({
],
);

const iconSize =
(isNotDesktop ?? isMediumScreen()) ? SMALL_ICON_SIZE : DESKTOP_ICON_SIZE;
const Bookmark = installedModelIds.has(entity.reference)
? IconBookmarkFilled
: IconBookmark;
Expand All @@ -326,7 +297,7 @@ export const ApplicationCard = ({
<>
<div
onClick={() => onClick(entity)}
className="group relative h-[162px] cursor-pointer rounded-md bg-layer-2 p-4 shadow-card hover:bg-layer-3 xl:h-[164px] xl:p-5"
className="group relative h-[98px] cursor-pointer rounded-md bg-layer-2 p-3 shadow-card hover:bg-layer-3 md:h-[162px] md:p-4 xl:h-[164px] xl:p-5"
data-qa="agent"
>
<div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,30 +1,42 @@
import { IconCheck, IconLink } from '@tabler/icons-react';
import { MouseEvent, useCallback, useMemo, useRef, useState } from 'react';

import classNames from 'classnames';

import { useTranslation } from '@/src/hooks/useTranslation';

import { PageType } from '@/src/types/common';
import { DialAIEntityModel } from '@/src/types/models';
import { Translation } from '@/src/types/translation';

import { MarketplaceQueryParams } from '@/src/constants/marketplace';

import Tooltip from '../../Common/Tooltip';

interface ApplicationCopyLinkProps {
entity: DialAIEntityModel;
reference: string;
size?: number;
withText?: boolean;
hasTooltip?: boolean;
className?: string;
}

const ICON_SIZE = 20;
const TRIGGER_CLASS =
'flex items-center gap-2 whitespace-nowrap px-3 py-1.5 text-sm text-accent-primary outline-none';

export function ApplicationCopyLink({ entity }: ApplicationCopyLinkProps) {
export function ApplicationCopyLink({
reference,
size = 20,
withText,
hasTooltip,
className,
}: ApplicationCopyLinkProps) {
const { t } = useTranslation(Translation.Marketplace);
const [urlCopied, setUrlCopied] = useState(false);
const timeoutRef = useRef<ReturnType<typeof setTimeout>>();
const link = useMemo(
() =>
`${window.location.origin}/${PageType.Marketplace}?${MarketplaceQueryParams.model}=${entity.reference}`,
[entity.reference],
`${window.location.origin}/${PageType.Marketplace}?${MarketplaceQueryParams.model}=${reference}`,
[reference],
);
const handleCopy = useCallback(
(e: MouseEvent<HTMLAnchorElement>) => {
Expand All @@ -44,23 +56,25 @@ export function ApplicationCopyLink({ entity }: ApplicationCopyLinkProps) {
);

return (
<>
<Tooltip
tooltip={hasTooltip ? t(urlCopied ? 'Copied!' : 'Copy link') : undefined}
>
{urlCopied ? (
<div className={TRIGGER_CLASS}>
<IconCheck size={ICON_SIZE} />
<span>{t('Copied!')}</span>
<div className={classNames(TRIGGER_CLASS, className)}>
<IconCheck size={size} />
{withText && <span>{t('Copied!')}</span>}
</div>
) : (
<a
className={TRIGGER_CLASS}
className={classNames(TRIGGER_CLASS, className)}
onClick={handleCopy}
data-qa="copy-link"
href={link}
>
<IconLink size={ICON_SIZE} />
<span>{t('Copy link')}</span>
<IconLink size={size} />
{withText && <span>{t('Copy link')}</span>}
</a>
)}
</>
</Tooltip>
);
}
Loading