From 6034f76167e2441919676a49e49b334a192febfb Mon Sep 17 00:00:00 2001 From: kamre Date: Wed, 5 Jan 2022 13:36:46 +0300 Subject: [PATCH 1/9] Initial implementation for `URLProperty` improvements: - show preview with link and button for editing - minor fixes for CSS --- .../src/components/gallery/galleryCard.scss | 4 + .../src/components/properties/link/link.scss | 45 +++++------ .../src/components/properties/link/link.tsx | 76 ++++++++++++------- 3 files changed, 74 insertions(+), 51 deletions(-) diff --git a/webapp/src/components/gallery/galleryCard.scss b/webapp/src/components/gallery/galleryCard.scss index 6e0ac89b3..84d4074f7 100644 --- a/webapp/src/components/gallery/galleryCard.scss +++ b/webapp/src/components/gallery/galleryCard.scss @@ -92,6 +92,10 @@ padding: 5px 10px; overflow-wrap: anywhere; + .octo-tooltip { + max-width: 100%; + } + .octo-icon { margin-right: 5px; } diff --git a/webapp/src/components/properties/link/link.scss b/webapp/src/components/properties/link/link.scss index 5f46c4024..aeec1c234 100644 --- a/webapp/src/components/properties/link/link.scss +++ b/webapp/src/components/properties/link/link.scss @@ -1,39 +1,34 @@ -.property-link { +.URLProperty { display: flex; align-items: center; + overflow: hidden; - &.url { - width: 100%; - display: flex; + .link { + flex: 1 1 auto; + padding-left: 1px; + margin-right: 4px; + white-space: nowrap; overflow: hidden; + color: rgb(var(--center-channel-color-rgb)); + text-overflow: ellipsis; + text-decoration: underline rgb(var(--center-channel-color-rgb), 0.5); } - .Link__button { + .link:hover { + background-color: rgb(var(--center-channel-color-rgb), 0.1); + } + + .Button_Edit { display: none; - flex: 0 0 24px; - width: 24px; - height: 24px; - align-items: center; - justify-content: center; - border-radius: 4px; - color: rgba(var(--center-channel-color-rgb), 0.56); - font-size: 14.4px; - margin-left: 8px; - - &:hover { - color: rgba(var(--center-channel-color-rgb), 0.72); - background: rgba(var(--center-channel-color-rgb), 0.08); - } - - &:active { - color: var(--button-bg-rgb); - background-color: rgb(var(--button-bg-rgb), 0.16); - } } &:hover { - .Link__button { + .Button_Edit { display: flex; } } } + +#focalboard-app .URLProperty .link:visited { + color: rgb(var(--center-channel-color-rgb)); +} diff --git a/webapp/src/components/properties/link/link.tsx b/webapp/src/components/properties/link/link.tsx index 5a3f6b59d..e72ae6356 100644 --- a/webapp/src/components/properties/link/link.tsx +++ b/webapp/src/components/properties/link/link.tsx @@ -1,13 +1,14 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. -import React, {ReactNode} from 'react' +import React, {useEffect, useRef, useState} from 'react' -import Editable from '../../../widgets/editable' +import Editable, {Focusable} from '../../../widgets/editable' import './link.scss' import {Utils} from '../../../utils' -import LinkIcon from '../../../widgets/icons/Link' +import EditIcon from '../../../widgets/icons/edit' +import IconButton from '../../../widgets/buttons/iconButton' type Props = { value: string @@ -20,37 +21,60 @@ type Props = { } const URLProperty = (props: Props): JSX.Element => { - let link: ReactNode = null - const hasValue = Boolean(props.value?.trim()) - if (hasValue) { - link = ( + const [isEditing, setIsEditing] = useState(false) + const isEmpty = !props.value?.trim() + const showEditable = !props.readonly && (isEditing || isEmpty) + const editableRef = useRef(null) + + useEffect(() => { + if (isEditing) { + editableRef.current?.focus() + } + }, [isEditing]) + + if (showEditable) { + return ( +
+ { + setIsEditing(false) + props.onSave() + }} + onCancel={() => { + setIsEditing(false) + props.onCancel() + }} + onFocus={() => setIsEditing(true)} + validator={props.validator} + /> +
+ ) + } + + return ( +
event.stopPropagation()} > - + {props.value} - ) - } - - return ( -
- {(hasValue || props.placeholder) && - } + onClick={() => setIsEditing(true)} />} - {link}
) } From 992ea7080713ce029f37138554632d97e6f55fd9 Mon Sep 17 00:00:00 2001 From: kamre Date: Mon, 10 Jan 2022 23:18:12 +0300 Subject: [PATCH 2/9] Buttons for edit and copy of `URLProperty` added: - Compass icon is used for `EditIcon` - some CSS tweaks for proper hover effects --- webapp/src/components/kanban/kanbanCard.scss | 2 +- webapp/src/components/properties/link/link.scss | 9 +++++++-- webapp/src/components/properties/link/link.tsx | 15 +++++++++++++++ webapp/src/widgets/icons/edit.scss | 1 + webapp/src/widgets/icons/edit.tsx | 16 +++++----------- 5 files changed, 29 insertions(+), 14 deletions(-) diff --git a/webapp/src/components/kanban/kanbanCard.scss b/webapp/src/components/kanban/kanbanCard.scss index 20064b506..a4530f476 100644 --- a/webapp/src/components/kanban/kanbanCard.scss +++ b/webapp/src/components/kanban/kanbanCard.scss @@ -78,7 +78,7 @@ } } - .IconButton { + .optionsMenu .IconButton { border-radius: 3px; margin-right: 6px; padding: 0; diff --git a/webapp/src/components/properties/link/link.scss b/webapp/src/components/properties/link/link.scss index aeec1c234..584069fce 100644 --- a/webapp/src/components/properties/link/link.scss +++ b/webapp/src/components/properties/link/link.scss @@ -18,12 +18,17 @@ background-color: rgb(var(--center-channel-color-rgb), 0.1); } - .Button_Edit { + .IconButton { display: none; + margin-right: 4px; + + &:hover { + background-color: rgb(var(--center-channel-color-rgb), 0.1); + } } &:hover { - .Button_Edit { + .IconButton { display: flex; } } diff --git a/webapp/src/components/properties/link/link.tsx b/webapp/src/components/properties/link/link.tsx index e72ae6356..808bff16a 100644 --- a/webapp/src/components/properties/link/link.tsx +++ b/webapp/src/components/properties/link/link.tsx @@ -2,6 +2,7 @@ // See LICENSE.txt for license information. import React, {useEffect, useRef, useState} from 'react' +import {useIntl} from 'react-intl' import Editable, {Focusable} from '../../../widgets/editable' @@ -9,6 +10,8 @@ import './link.scss' import {Utils} from '../../../utils' import EditIcon from '../../../widgets/icons/edit' import IconButton from '../../../widgets/buttons/iconButton' +import DuplicateIcon from '../../../widgets/icons/duplicate' +import {sendFlashMessage} from '../../flashMessages' type Props = { value: string @@ -25,6 +28,7 @@ const URLProperty = (props: Props): JSX.Element => { const isEmpty = !props.value?.trim() const showEditable = !props.readonly && (isEditing || isEmpty) const editableRef = useRef(null) + const intl = useIntl() useEffect(() => { if (isEditing) { @@ -72,9 +76,20 @@ const URLProperty = (props: Props): JSX.Element => { {!props.readonly && } onClick={() => setIsEditing(true)} />} + } + onClick={(e) => { + e.stopPropagation() + Utils.copyTextToClipboard(props.value) + sendFlashMessage({content: intl.formatMessage({id: 'URLProperty.copiedLink', defaultMessage: 'Copied!'}), severity: 'high'}) + }} + />
) } diff --git a/webapp/src/widgets/icons/edit.scss b/webapp/src/widgets/icons/edit.scss index 6cb7947f1..ed976f7d3 100644 --- a/webapp/src/widgets/icons/edit.scss +++ b/webapp/src/widgets/icons/edit.scss @@ -3,4 +3,5 @@ stroke: none; width: 24px; height: 24px; + font-size: 18px; } diff --git a/webapp/src/widgets/icons/edit.tsx b/webapp/src/widgets/icons/edit.tsx index 3b3a7cd0e..d4b916b56 100644 --- a/webapp/src/widgets/icons/edit.tsx +++ b/webapp/src/widgets/icons/edit.tsx @@ -4,19 +4,13 @@ import React from 'react' import './edit.scss' +import CompassIcon from './compassIcon' export default function EditIcon(): JSX.Element { return ( - - - - - - - + ) } From 6b278cd8cf674eb3fcf92f18a23e3586caf652b7 Mon Sep 17 00:00:00 2001 From: kamre Date: Thu, 13 Jan 2022 22:42:56 +0300 Subject: [PATCH 3/9] Hide copy button for URLProperty in the table. --- webapp/src/components/table/tableRow.scss | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/webapp/src/components/table/tableRow.scss b/webapp/src/components/table/tableRow.scss index 9ee2801b9..186efe2f7 100644 --- a/webapp/src/components/table/tableRow.scss +++ b/webapp/src/components/table/tableRow.scss @@ -27,4 +27,8 @@ display: block; } } + + .URLProperty:hover .Button_Copy { + display: none; + } } From 58b418025dd715d06e8ad55c8b6ad7fbacfce475 Mon Sep 17 00:00:00 2001 From: kamre Date: Sat, 22 Jan 2022 17:59:01 +0300 Subject: [PATCH 4/9] Fix `background-color` of URL property on the calendar cards. --- webapp/src/components/calendar/fullcalendar.scss | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/webapp/src/components/calendar/fullcalendar.scss b/webapp/src/components/calendar/fullcalendar.scss index 1b8ea643b..5250adf3d 100644 --- a/webapp/src/components/calendar/fullcalendar.scss +++ b/webapp/src/components/calendar/fullcalendar.scss @@ -3,12 +3,13 @@ margin-bottom: 10px; overflow: auto; - a { + .fc-daygrid-event, + .fc-daygrid-day-number { text-decoration: none; color: var(--link-color-rgb); &:hover { - background-color: unset !important;; + background-color: unset; } } From 76401862cc5b4b21f889af10e03ad86df2a122c4 Mon Sep 17 00:00:00 2001 From: kamre Date: Sat, 22 Jan 2022 23:41:29 +0300 Subject: [PATCH 5/9] Fixed clicking on the card in the calendar view. --- webapp/src/components/calendar/fullCalendar.tsx | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/webapp/src/components/calendar/fullCalendar.tsx b/webapp/src/components/calendar/fullCalendar.tsx index 0b4c33818..5d3659158 100644 --- a/webapp/src/components/calendar/fullCalendar.tsx +++ b/webapp/src/components/calendar/fullCalendar.tsx @@ -4,7 +4,7 @@ import React, {useCallback, useMemo} from 'react' import {useIntl} from 'react-intl' -import FullCalendar, {EventClickArg, EventChangeArg, EventInput, EventContentArg, DayCellContentArg} from '@fullcalendar/react' +import FullCalendar, {EventChangeArg, EventInput, EventContentArg, DayCellContentArg} from '@fullcalendar/react' import interactionPlugin from '@fullcalendar/interaction' import dayGridPlugin from '@fullcalendar/daygrid' @@ -120,7 +120,7 @@ const CalendarFullView = (props: Props): JSX.Element|null => { const renderEventContent = (eventProps: EventContentArg): JSX.Element|null => { const {event} = eventProps return ( -
+
props.showCard(event.id)}>
{ event.extendedProps.icon ?
{event.extendedProps.icon}
: undefined }
{ ) } - const eventClick = useCallback((eventProps: EventClickArg) => { - const {event} = eventProps - props.showCard(event.id) - }, [props.showCard]) - const eventChange = useCallback((eventProps: EventChangeArg) => { const {event} = eventProps if (!event.start) { @@ -239,7 +234,6 @@ const CalendarFullView = (props: Props): JSX.Element|null => { eventResizableFromStart={isEditable()} headerToolbar={toolbar} buttonText={buttonText} - eventClick={eventClick} eventContent={renderEventContent} eventChange={eventChange} From f8995351c9b477907e18712b0c371eaac3c76e34 Mon Sep 17 00:00:00 2001 From: kamre Date: Sun, 23 Jan 2022 00:04:10 +0300 Subject: [PATCH 6/9] Minor style fix for calendar card. --- webapp/src/components/calendar/fullCalendar.tsx | 5 ++++- webapp/src/components/calendar/fullcalendar.scss | 6 ++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/webapp/src/components/calendar/fullCalendar.tsx b/webapp/src/components/calendar/fullCalendar.tsx index 5d3659158..e0c9e9aef 100644 --- a/webapp/src/components/calendar/fullCalendar.tsx +++ b/webapp/src/components/calendar/fullCalendar.tsx @@ -120,7 +120,10 @@ const CalendarFullView = (props: Props): JSX.Element|null => { const renderEventContent = (eventProps: EventContentArg): JSX.Element|null => { const {event} = eventProps return ( -
props.showCard(event.id)}> +
props.showCard(event.id)} + >
{ event.extendedProps.icon ?
{event.extendedProps.icon}
: undefined }
Date: Sun, 23 Jan 2022 12:50:57 +0300 Subject: [PATCH 7/9] Unit tests fixed (snapshots updated). --- .../propertyValueElement.test.tsx.snap | 105 ++++++++++++------ .../__snapshots__/fullCalendar.test.tsx.snap | 15 ++- .../link/__snapshots__/link.test.tsx.snap | 34 ++++-- .../components/properties/link/link.test.tsx | 7 +- .../newCardButtonTemplateItem.test.tsx.snap | 80 ++----------- 5 files changed, 117 insertions(+), 124 deletions(-) diff --git a/webapp/src/components/__snapshots__/propertyValueElement.test.tsx.snap b/webapp/src/components/__snapshots__/propertyValueElement.test.tsx.snap index 3d5cb49a9..0b6f4ad39 100644 --- a/webapp/src/components/__snapshots__/propertyValueElement.test.tsx.snap +++ b/webapp/src/components/__snapshots__/propertyValueElement.test.tsx.snap @@ -16,25 +16,36 @@ exports[`components/propertyValueElement Generic fields should allow cancel 1`] exports[`components/propertyValueElement URL fields should allow cancel 1`] = ` `; @@ -133,25 +144,36 @@ exports[`components/propertyValueElement should match snapshot, select, read-onl exports[`components/propertyValueElement should match snapshot, url, array value 1`] = ` `; @@ -159,25 +181,36 @@ exports[`components/propertyValueElement should match snapshot, url, array value exports[`components/propertyValueElement should match snapshot, url, array value 2`] = ` `; diff --git a/webapp/src/components/calendar/__snapshots__/fullCalendar.test.tsx.snap b/webapp/src/components/calendar/__snapshots__/fullCalendar.test.tsx.snap index dcb7e6511..2223c2aa3 100644 --- a/webapp/src/components/calendar/__snapshots__/fullCalendar.test.tsx.snap +++ b/webapp/src/components/calendar/__snapshots__/fullCalendar.test.tsx.snap @@ -720,12 +720,13 @@ exports[`components/calendar/toolbar return calendar, no date property 1`] = ` >
-
+
@@ -2979,12 +2980,13 @@ exports[`components/calendar/toolbar return calendar, with date property not set >
-
+
@@ -5936,12 +5938,13 @@ exports[`components/calendar/toolbar return calendar, with date property set 1`] >
-
+
diff --git a/webapp/src/components/properties/link/__snapshots__/link.test.tsx.snap b/webapp/src/components/properties/link/__snapshots__/link.test.tsx.snap index c8e77f355..72f2eb465 100644 --- a/webapp/src/components/properties/link/__snapshots__/link.test.tsx.snap +++ b/webapp/src/components/properties/link/__snapshots__/link.test.tsx.snap @@ -3,24 +3,36 @@ exports[`components/properties/link returns link properties correctly 1`] = ` `; diff --git a/webapp/src/components/properties/link/link.test.tsx b/webapp/src/components/properties/link/link.test.tsx index fb0599f6e..be97b3a41 100644 --- a/webapp/src/components/properties/link/link.test.tsx +++ b/webapp/src/components/properties/link/link.test.tsx @@ -5,11 +5,13 @@ import React from 'react' import {render} from '@testing-library/react' import '@testing-library/jest-dom' +import {wrapIntl} from '../../../testUtils' + import Link from './link' describe('components/properties/link', () => { test('returns link properties correctly', () => { - const component = ( + const {container} = render(wrapIntl(( { return true })} /> - ) - const {container} = render(component) + ))) expect(container).toMatchSnapshot() }) }) diff --git a/webapp/src/components/viewHeader/__snapshots__/newCardButtonTemplateItem.test.tsx.snap b/webapp/src/components/viewHeader/__snapshots__/newCardButtonTemplateItem.test.tsx.snap index bc2448a68..88c2ac181 100644 --- a/webapp/src/components/viewHeader/__snapshots__/newCardButtonTemplateItem.test.tsx.snap +++ b/webapp/src/components/viewHeader/__snapshots__/newCardButtonTemplateItem.test.tsx.snap @@ -67,23 +67,9 @@ exports[`components/viewHeader/newCardButtonTemplateItem return NewCardButtonTem class="MenuOption TextOption menu-option" role="button" > - - - - - - - +