chore: New standard fields on People (#1104)
* Add New standard fields on People Co-authored-by: Thiago Nascimbeni <tnascimbeni@gmail.com> * Add requested changes Co-authored-by: v1b3m <vibenjamin6@gmail.com> Co-authored-by: Thiago Nascimbeni <tnascimbeni@gmail.com> Co-authored-by: Matheus <matheus_benini@hotmail.com> --------- Co-authored-by: Thiago Nascimbeni <tnascimbeni@gmail.com> Co-authored-by: v1b3m <vibenjamin6@gmail.com> Co-authored-by: Matheus <matheus_benini@hotmail.com>
This commit is contained in:
@ -51,5 +51,6 @@ export { IconUserCircle } from '@tabler/icons-react';
|
||||
export { IconCalendar } from '@tabler/icons-react';
|
||||
export { IconPencil } from '@tabler/icons-react';
|
||||
export { IconCircleDot } from '@tabler/icons-react';
|
||||
export { IconBrandX } from '@tabler/icons-react';
|
||||
export { IconTag } from '@tabler/icons-react';
|
||||
export { IconHelpCircle } from '@tabler/icons-react';
|
||||
|
||||
@ -2,6 +2,7 @@ import { MouseEvent } from 'react';
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
import { RoundedLink } from '@/ui/link/components/RoundedLink';
|
||||
import { LinkType, SocialLink } from '@/ui/link/components/SocialLink';
|
||||
|
||||
const StyledRawLink = styled(RoundedLink)`
|
||||
overflow: hidden;
|
||||
@ -17,17 +18,40 @@ type OwnProps = {
|
||||
value: string;
|
||||
};
|
||||
|
||||
const checkUrlType = (url: string) => {
|
||||
if (
|
||||
/^(http|https):\/\/(?:www\.)?linkedin.com(\w+:{0,1}\w*@)?(\S+)(:([0-9])+)?(\/|\/([\w#!:.?+=&%@!\-/]))?$/.test(
|
||||
url,
|
||||
)
|
||||
) {
|
||||
return LinkType.LinkedIn;
|
||||
}
|
||||
if (url.match(/^((http|https):\/\/)?(?:www\.)?twitter\.com\/(\w+)?$/i)) {
|
||||
return LinkType.Twitter;
|
||||
}
|
||||
|
||||
return LinkType.Url;
|
||||
};
|
||||
|
||||
export function InplaceInputURLDisplayMode({ value }: OwnProps) {
|
||||
function handleClick(event: MouseEvent<HTMLElement>) {
|
||||
event.stopPropagation();
|
||||
}
|
||||
|
||||
const absoluteUrl = value
|
||||
? value.startsWith('http')
|
||||
? value
|
||||
: 'https://' + value
|
||||
: '';
|
||||
|
||||
const type = checkUrlType(absoluteUrl);
|
||||
|
||||
if (type === LinkType.LinkedIn || type === LinkType.Twitter) {
|
||||
return (
|
||||
<SocialLink href={absoluteUrl} onClick={handleClick} type={type}>
|
||||
{value}
|
||||
</SocialLink>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<StyledRawLink href={absoluteUrl} onClick={handleClick}>
|
||||
{value}
|
||||
|
||||
50
front/src/modules/ui/link/components/SocialLink.tsx
Normal file
50
front/src/modules/ui/link/components/SocialLink.tsx
Normal file
@ -0,0 +1,50 @@
|
||||
import * as React from 'react';
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
import { RoundedLink } from './RoundedLink';
|
||||
|
||||
export enum LinkType {
|
||||
Url = 'url',
|
||||
LinkedIn = 'linkedin',
|
||||
Twitter = 'twitter',
|
||||
}
|
||||
|
||||
type OwnProps = {
|
||||
href: string;
|
||||
children?: React.ReactNode;
|
||||
type?: LinkType;
|
||||
onClick?: (event: React.MouseEvent<HTMLElement>) => void;
|
||||
};
|
||||
|
||||
const StyledRawLink = styled(RoundedLink)`
|
||||
overflow: hidden;
|
||||
|
||||
a {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
`;
|
||||
|
||||
export function SocialLink({ children, href, onClick, type }: OwnProps) {
|
||||
let displayValue = children;
|
||||
|
||||
if (type === 'linkedin') {
|
||||
const splitUrl = href.split('/');
|
||||
const splitName = splitUrl[4].split('-');
|
||||
displayValue = splitName[2]
|
||||
? `${splitName[0]}-${splitName[1]}`
|
||||
: splitName[0];
|
||||
}
|
||||
|
||||
if (type === 'twitter') {
|
||||
const splitUrl = href.split('/');
|
||||
displayValue = `@${splitUrl[3]}`;
|
||||
}
|
||||
|
||||
return (
|
||||
<StyledRawLink href={href} onClick={onClick}>
|
||||
{displayValue}
|
||||
</StyledRawLink>
|
||||
);
|
||||
}
|
||||
@ -1,6 +1,9 @@
|
||||
import { ReactElement } from 'react';
|
||||
import { ReactElement, useState } from 'react';
|
||||
import styled from '@emotion/styled';
|
||||
import { IconPencil } from '@tabler/icons-react';
|
||||
import { motion } from 'framer-motion';
|
||||
|
||||
import { IconButton } from '@/ui/button/components/IconButton';
|
||||
import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope';
|
||||
|
||||
import { CellHotkeyScopeContext } from '../../states/CellHotkeyScopeContext';
|
||||
@ -12,6 +15,11 @@ import { EditableCellDisplayMode } from './EditableCellDisplayMode';
|
||||
import { EditableCellEditMode } from './EditableCellEditMode';
|
||||
import { EditableCellSoftFocusMode } from './EditableCellSoftFocusMode';
|
||||
|
||||
const StyledEditButtonContainer = styled(motion.div)`
|
||||
position: absolute;
|
||||
right: 5px;
|
||||
`;
|
||||
|
||||
export const CellBaseContainer = styled.div`
|
||||
align-items: center;
|
||||
box-sizing: border-box;
|
||||
@ -48,7 +56,38 @@ export function EditableCell({
|
||||
transparent = false,
|
||||
maxContentWidth,
|
||||
}: OwnProps) {
|
||||
const { isCurrentCellInEditMode } = useCurrentCellEditMode();
|
||||
const { isCurrentCellInEditMode, setCurrentCellInEditMode } =
|
||||
useCurrentCellEditMode();
|
||||
const [isHovered, setIsHovered] = useState(false);
|
||||
|
||||
function isValidUrl(value: string) {
|
||||
let testUrl = value;
|
||||
if (testUrl && !testUrl.startsWith('http')) {
|
||||
testUrl = 'http://' + testUrl;
|
||||
}
|
||||
try {
|
||||
new URL(testUrl);
|
||||
return true;
|
||||
} catch (err) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const handleClick = () => {
|
||||
setCurrentCellInEditMode();
|
||||
};
|
||||
|
||||
function handleContainerMouseEnter() {
|
||||
setIsHovered(true);
|
||||
}
|
||||
|
||||
function handleContainerMouseLeave() {
|
||||
setIsHovered(false);
|
||||
}
|
||||
|
||||
const value = nonEditModeContent.props.value;
|
||||
const showEditButton =
|
||||
!isCurrentCellInEditMode && isValidUrl(value) && isHovered;
|
||||
|
||||
const hasSoftFocus = useIsSoftFocusOnCurrentCell();
|
||||
|
||||
@ -56,7 +95,10 @@ export function EditableCell({
|
||||
<CellHotkeyScopeContext.Provider
|
||||
value={editHotkeyScope ?? DEFAULT_CELL_SCOPE}
|
||||
>
|
||||
<CellBaseContainer>
|
||||
<CellBaseContainer
|
||||
onMouseEnter={handleContainerMouseEnter}
|
||||
onMouseLeave={handleContainerMouseLeave}
|
||||
>
|
||||
{isCurrentCellInEditMode ? (
|
||||
<EditableCellEditMode
|
||||
maxContentWidth={maxContentWidth}
|
||||
@ -71,9 +113,27 @@ export function EditableCell({
|
||||
{nonEditModeContent}
|
||||
</EditableCellSoftFocusMode>
|
||||
) : (
|
||||
<EditableCellDisplayMode>
|
||||
{nonEditModeContent}
|
||||
</EditableCellDisplayMode>
|
||||
<>
|
||||
{showEditButton && (
|
||||
<StyledEditButtonContainer
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
transition={{ duration: 0.1 }}
|
||||
whileHover={{ scale: 1.04 }}
|
||||
>
|
||||
<IconButton
|
||||
variant="shadow"
|
||||
size="small"
|
||||
onClick={handleClick}
|
||||
icon={<IconPencil size={14} />}
|
||||
/>
|
||||
</StyledEditButtonContainer>
|
||||
)}
|
||||
|
||||
<EditableCellDisplayMode>
|
||||
{nonEditModeContent}
|
||||
</EditableCellDisplayMode>
|
||||
</>
|
||||
)}
|
||||
</CellBaseContainer>
|
||||
</CellHotkeyScopeContext.Provider>
|
||||
|
||||
Reference in New Issue
Block a user