diff --git a/localization/react-intl/src/app/components/article/ChooseExistingArticleButton.json b/localization/react-intl/src/app/components/article/ChooseExistingArticleButton.json index d86588a39d..02c7cd4315 100644 --- a/localization/react-intl/src/app/components/article/ChooseExistingArticleButton.json +++ b/localization/react-intl/src/app/components/article/ChooseExistingArticleButton.json @@ -15,8 +15,8 @@ "defaultMessage": "Search by article title or summary" }, { - "id": "chooseExistingArticleButton.recentArticles", - "description": "Label for the list of articles.", - "defaultMessage": "Recent Articles" + "id": "mediaArticles.chooseRecentArticle", + "description": "Message displayed on articles sidebar when an item has no articles.", + "defaultMessage": "Choose a recent article to add to this media:" } ] \ No newline at end of file diff --git a/localization/react-intl/src/app/components/article/MediaArticles.json b/localization/react-intl/src/app/components/article/MediaArticles.json index 7149e5b808..146e57dc0e 100644 --- a/localization/react-intl/src/app/components/article/MediaArticles.json +++ b/localization/react-intl/src/app/components/article/MediaArticles.json @@ -4,11 +4,6 @@ "description": "Banner displayed after an article is successfully added to an item.", "defaultMessage": "Article added successfully!" }, - { - "id": "mediaArticles.mediaArticlesListTitle", - "description": "Title for the list of articles being delivered to users of the tipline for this cluster of media", - "defaultMessage": "Articles blab alb" - }, { "id": "mediaArticles.noArticlesAddedToItem", "description": "Message displayed on articles sidebar when an item has no articles.", diff --git a/localization/react-intl/src/app/components/article/MediaArticlesDisplay.json b/localization/react-intl/src/app/components/article/MediaArticlesDisplay.json index e3d4e4afd0..545f937165 100644 --- a/localization/react-intl/src/app/components/article/MediaArticlesDisplay.json +++ b/localization/react-intl/src/app/components/article/MediaArticlesDisplay.json @@ -2,7 +2,7 @@ { "id": "mediaArticlesDisplay.listTitle", "description": "Title for the list of articles being delivered to users of the tipline for this cluster of media", - "defaultMessage": "Articles Delivered to Tipline Requests" + "defaultMessage": "Articles Delivered to Tipline Requests:" }, { "id": "mediaArticlesDisplay.readOnlyAlertContent", diff --git a/localization/react-intl/src/app/components/media/ItemTitle.json b/localization/react-intl/src/app/components/media/ItemTitle.json index b2157b01dd..9fe91ec426 100644 --- a/localization/react-intl/src/app/components/media/ItemTitle.json +++ b/localization/react-intl/src/app/components/media/ItemTitle.json @@ -11,8 +11,8 @@ }, { "id": "itemTitle.menuHeader", - "description": "Header for a menu containing content options for item title", - "defaultMessage": "Select Item Name" + "description": "Header for a menu containing content options for title of the cluster of media", + "defaultMessage": "Select Media Cluster Name" }, { "id": "itemTitle.customTitle", diff --git a/localization/react-intl/src/app/components/media/MediaComponent.json b/localization/react-intl/src/app/components/media/MediaComponent.json index 1eae97514d..1f93369610 100644 --- a/localization/react-intl/src/app/components/media/MediaComponent.json +++ b/localization/react-intl/src/app/components/media/MediaComponent.json @@ -8,5 +8,15 @@ "id": "mediaComponent.requests", "description": "Number of times a request has been sent about this media", "defaultMessage": "{count, plural, one {# request} other {# requests}}" + }, + { + "id": "mediaComponent.pinnedMedia", + "description": "Title for the media in this list that is pinned to the top", + "defaultMessage": "Pinned Media" + }, + { + "id": "mediaComponent.similarMediaList", + "description": "Title for the remaining media in this list that are not pinned to the top", + "defaultMessage": "Similar Media in Cluster" } ] \ No newline at end of file diff --git a/src/app/components/article/Articles.module.css b/src/app/components/article/Articles.module.css index 0428d7e09f..87935231bf 100644 --- a/src/app/components/article/Articles.module.css +++ b/src/app/components/article/Articles.module.css @@ -2,22 +2,8 @@ display: flex; flex: 1; flex-direction: column; - overflow-y: auto; - position: relative; + min-height: 0; width: 100%; - z-index: 1; - - &::after { - background-color: var(--color-beige-86); - content: ''; - display: block; - height: 2px; - left: 0; - position: absolute; - right: 16px; - top: 62px; - z-index: 1; - } .articlesSidebarTopBar { background: var(--color-white-100); @@ -28,27 +14,12 @@ padding: 16px; } - .articlesSidebarNoArticleWrapper { - display: flex; - flex: 1 1 auto; - flex-direction: column; - gap: 16px; + .articlesSidebarScroller { + @mixin scroll-indicator-top 16px, var(--color-white-100), var(--color-beige-86); overflow-y: auto; - padding: 0 16px 16px; + padding: 16px; + position: relative; width: 100%; - - &::before { - background-color: var(--color-white-100); - content: ''; - display: block; - flex-shrink: 0; - height: 2px; - left: 0; - margin: auto -16px 0; - position: relative; - right: 0; - z-index: 2; - } } .articlesSidebarNoArticle { @@ -56,7 +27,7 @@ border-radius: var(--border-radius-default); color: var(--color-gray-75); font-style: italic; - margin: 16px 0 32px; + margin: 0 0 32px; padding: 16px; text-align: center; diff --git a/src/app/components/article/ChooseExistingArticleButton.js b/src/app/components/article/ChooseExistingArticleButton.js index 08dddb31c7..fa05ec74a8 100644 --- a/src/app/components/article/ChooseExistingArticleButton.js +++ b/src/app/components/article/ChooseExistingArticleButton.js @@ -73,27 +73,29 @@ const ChooseExistingArticleButton = ({ - - {placeholder => ( - } - id="search-articles" - placeholder={placeholder} - onChange={e => handleType(e.target.value)} - /> - )} - -
+
+ + {placeholder => ( + } + id="search-articles" + placeholder={placeholder} + onChange={e => handleType(e.target.value)} + /> + )} + +
+
{ !search && ( -
+
)} @@ -101,6 +103,7 @@ const ChooseExistingArticleButton = ({
} + contentScrollable={false} footer showCancel title={title} diff --git a/src/app/components/article/ChooseExistingArticleButton.module.css b/src/app/components/article/ChooseExistingArticleButton.module.css index 4714343039..cadd0521f1 100644 --- a/src/app/components/article/ChooseExistingArticleButton.module.css +++ b/src/app/components/article/ChooseExistingArticleButton.module.css @@ -1,7 +1,20 @@ .contentWrapper { display: flex; flex-direction: column; - gap: 16px; + height: 100%; + + .seachHeader, + .seachResults { + padding: 16px; + } + + .seachResults { + @mixin scroll-indicator-top 16px, var(--color-white-100), var(--color-beige-86); + overflow-y: auto; + padding: 16px; + position: relative; + width: 100%; + } } .heading { diff --git a/src/app/components/article/MediaArticles.js b/src/app/components/article/MediaArticles.js index bb5edc4f49..18748c4e96 100644 --- a/src/app/components/article/MediaArticles.js +++ b/src/app/components/article/MediaArticles.js @@ -1,4 +1,3 @@ -/* eslint-disable react/sort-prop-types */ import React from 'react'; import PropTypes from 'prop-types'; import Relay from 'react-relay/classic'; @@ -151,30 +150,32 @@ const MediaArticlesComponent = ({ onCreate={onUpdate} />
- { hasArticle ? ( - - ) : ( -
-
- -
+
+ { hasArticle ? ( + + ) : ( + <> +
+ +
+ +
+
+
-
-
- -
- -
- )} + + + )} +
{/* Confirm dialog for replacing fact-check */} { }; MediaArticles.propTypes = { - teamSlug: PropTypes.string.isRequired, projectMediaDbid: PropTypes.number.isRequired, + teamSlug: PropTypes.string.isRequired, }; export default MediaArticles; diff --git a/src/app/components/article/MediaArticlesDisplay.js b/src/app/components/article/MediaArticlesDisplay.js index 32b26d544b..6f559f8274 100644 --- a/src/app/components/article/MediaArticlesDisplay.js +++ b/src/app/components/article/MediaArticlesDisplay.js @@ -31,7 +31,7 @@ const MediaArticlesDisplay = ({ onUpdate, projectMedia }) => {
diff --git a/src/app/components/article/MediaArticlesDisplay.module.css b/src/app/components/article/MediaArticlesDisplay.module.css index 5cdd26daac..d577e72e56 100644 --- a/src/app/components/article/MediaArticlesDisplay.module.css +++ b/src/app/components/article/MediaArticlesDisplay.module.css @@ -3,8 +3,6 @@ flex: 1 1 auto; flex-direction: column; gap: 16px; - overflow-y: auto; - padding: 0 16px 16px; width: 100%; .explainerCard { @@ -19,17 +17,4 @@ } } } - - &::before { - background-color: var(--color-white-100); - content: ''; - display: block; - flex-shrink: 0; - height: 2px; - left: 0; - margin: auto -16px 0; - position: relative; - right: 0; - z-index: 2; - } } diff --git a/src/app/components/cds/Sandbox.js b/src/app/components/cds/Sandbox.js index a58c59debb..5dc8aba4e6 100644 --- a/src/app/components/cds/Sandbox.js +++ b/src/app/components/cds/Sandbox.js @@ -244,6 +244,7 @@ const SandboxComponent = ({ admin }) => { const [slideoutTitle, setSlideoutTitle] = React.useState(''); const [openSlideout, setOpenSlideout] = React.useState(Boolean(false)); const [slideoutFooter, setSlideoutFooter] = React.useState(Boolean(true)); + const [slideoutScrollable, setSlideoutScrollable] = React.useState(Boolean(true)); const [slideoutCancel, setSlideoutCancel] = React.useState(Boolean(true)); const [slideoutMainAction, setSlideoutMainAction] = React.useState(Boolean(true)); const [slideoutSecondaryAction, setSlideoutSecondaryAction] = React.useState(Boolean(false)); @@ -1876,6 +1877,14 @@ const SandboxComponent = ({ admin }) => { onChange={() => setSlideoutFooter(!slideoutFooter)} /> +
  • + setSlideoutScrollable(!slideoutScrollable)} + /> +
  • {

    } + contentScrollable={slideoutScrollable} footer={slideoutFooter} mainActionButton={slideoutMainAction && } optionalNode={slideoutOptionalNode && } diff --git a/src/app/components/cds/buttons-checkboxes-chips/ButtonMain.module.css b/src/app/components/cds/buttons-checkboxes-chips/ButtonMain.module.css index c6b132a18b..a6c693b381 100644 --- a/src/app/components/cds/buttons-checkboxes-chips/ButtonMain.module.css +++ b/src/app/components/cds/buttons-checkboxes-chips/ButtonMain.module.css @@ -189,7 +189,7 @@ } &.textVariant { - @mixin main-button-text-theme var(--color-blue-54), var(--color-blue-38, var(--color-blue-98)); + @mixin main-button-text-theme var(--color-blue-54), var(--color-blue-38), var(--color-blue-98); } } diff --git a/src/app/components/cds/slideout/Slideout.js b/src/app/components/cds/slideout/Slideout.js index 62ff5850ab..35598e0136 100644 --- a/src/app/components/cds/slideout/Slideout.js +++ b/src/app/components/cds/slideout/Slideout.js @@ -1,4 +1,3 @@ -/* eslint-disable react/sort-prop-types */ // DESIGNS: https://www.figma.com/file/i1LSbpQXKyA7dLc8AkgtKA/Articles?type=design&node-id=106-63346&mode=design&t=o7PouU0Z5ISH5G3K-0 import React, { useEffect } from 'react'; import PropTypes from 'prop-types'; @@ -12,6 +11,7 @@ import styles from './Slideout.module.css'; const Slideout = ({ cancelProps, content, + contentScrollable, footer, mainActionButton, onClose, @@ -63,7 +63,14 @@ const Slideout = ({
  • -
    +
    {content}
    { footer && @@ -111,25 +118,27 @@ const Slideout = ({ }; Slideout.defaultProps = { + cancelProps: {}, content: null, + contentScrollable: true, footer: false, - showCancel: false, - cancelProps: {}, mainActionButton: null, - secondaryActionButton: null, optionalNode: null, + secondaryActionButton: null, + showCancel: false, }; Slideout.propTypes = { - title: PropTypes.oneOfType([PropTypes.object, PropTypes.string]).isRequired, + cancelProps: PropTypes.object, content: PropTypes.node, + contentScrollable: PropTypes.bool, footer: PropTypes.bool, - onClose: PropTypes.func.isRequired, - showCancel: PropTypes.bool, - cancelProps: PropTypes.object, mainActionButton: PropTypes.instanceOf(ButtonMain), - secondaryActionButton: PropTypes.instanceOf(ButtonMain), optionalNode: PropTypes.node, + secondaryActionButton: PropTypes.instanceOf(ButtonMain), + showCancel: PropTypes.bool, + title: PropTypes.oneOfType([PropTypes.object, PropTypes.string]).isRequired, + onClose: PropTypes.func.isRequired, }; export default Slideout; diff --git a/src/app/components/cds/slideout/Slideout.module.css b/src/app/components/cds/slideout/Slideout.module.css index 0b138c06e9..140cf4c7f2 100644 --- a/src/app/components/cds/slideout/Slideout.module.css +++ b/src/app/components/cds/slideout/Slideout.module.css @@ -7,7 +7,7 @@ text-transform: none; top: 0; width: 40vw; - z-index: 3; + z-index: 4; textarea { font-weight: normal; @@ -19,7 +19,7 @@ flex-direction: column; height: 100%; position: relative; - z-index: 4; + z-index: 5; } .slideoutTitle { @@ -46,7 +46,12 @@ .slideoutBody { flex: 1 1 auto; overflow-y: auto; - padding: 10px; + padding: 16px; + + &.slideoutBodyStatic { + overflow: hidden; + padding: 0; + } } .slideoutFooter { diff --git a/src/app/components/drawer/Drawer.module.css b/src/app/components/drawer/Drawer.module.css index 59d2a47fc5..d91b64867d 100644 --- a/src/app/components/drawer/Drawer.module.css +++ b/src/app/components/drawer/Drawer.module.css @@ -5,7 +5,7 @@ height: 100vh; transition: width 225ms cubic-bezier(0, 0, .2, 1) 0ms; width: var(--drawerWidth); - z-index: 1; + z-index: 4; :global(.MuiDrawer-paperAnchorLeft) { background-color: var(--color-beige-93); diff --git a/src/app/components/media/ItemTitle.js b/src/app/components/media/ItemTitle.js index 3609a5afcf..8c313ce281 100644 --- a/src/app/components/media/ItemTitle.js +++ b/src/app/components/media/ItemTitle.js @@ -231,8 +231,8 @@ const ItemTitleComponent = ({ diff --git a/src/app/components/media/MediaComponent.js b/src/app/components/media/MediaComponent.js index dccfa42fb5..558c8222d5 100644 --- a/src/app/components/media/MediaComponent.js +++ b/src/app/components/media/MediaComponent.js @@ -18,6 +18,7 @@ import UserUtil from '../user/UserUtil'; import CheckContext from '../../CheckContext'; import { getSuperAdminMask } from '../../helpers'; import MediaAndRequestsDialogComponent from '../cds/menus-lists-dialogs/MediaAndRequestsDialogComponent'; +import PushPinIcon from '../../icons/push_pin.svg'; import PageTitle from '../PageTitle'; import { withPusher, pusherShape } from '../../pusher'; import styles from './media.module.css'; @@ -188,8 +189,8 @@ class MediaComponent extends Component { { view === 'default' || view === 'similarMedia' ?
    + { (linkPrefix && !isSuggestedOrSimilar) ? : null }
    - { (linkPrefix && !isSuggestedOrSimilar) ? : null } { this.state.openMediaDialog ? this.setState({ openMediaDialog: false })} /> : null } + {projectMedia.linked_items_count > 1 && +
    + + +
    + } + <> + {projectMedia.linked_items_count > 1 && +
    + +  [{projectMedia.linked_items_count - 1}] +
    + } + + }
    @@ -304,6 +327,7 @@ export default createFragmentContainer(withPusher(MediaComponent), graphql` notes_count: annotations_count(annotation_type: "comment") report_status suggested_similar_items_count + linked_items_count imported_from_feed_id imported_from_project_media_id suggested_similar_relationships(first: 10000) { diff --git a/src/app/components/media/MediaComponentRightPanel.js b/src/app/components/media/MediaComponentRightPanel.js index 4000b8873a..dc0a785838 100644 --- a/src/app/components/media/MediaComponentRightPanel.js +++ b/src/app/components/media/MediaComponentRightPanel.js @@ -3,6 +3,7 @@ import PropTypes from 'prop-types'; import { FormattedMessage } from 'react-intl'; import Tab from '@material-ui/core/Tab'; import Tabs from '@material-ui/core/Tabs'; +import cx from 'classnames/bind'; import MediaTasks from './MediaTasks'; import MediaRequests from './MediaRequests'; import MediaSource from './MediaSource'; @@ -10,6 +11,7 @@ import MediaSuggestions from './Similarity/MediaSuggestions'; import MediaSecondaryBanner from './MediaSecondaryBanner'; import MediaArticles from '../article/MediaArticles'; import ErrorBoundary from '../error/ErrorBoundary'; +import styles from './media.module.css'; const MediaComponentRightPanel = ({ projectMedia, @@ -30,7 +32,7 @@ const MediaComponentRightPanel = ({ ( -
    +
    : } size="small" - theme="lightText" + theme="lightBeige" variant="text" onClick={this.triggerInputFile} /> @@ -310,10 +309,13 @@ SearchKeyword.defaultProps = { }; SearchKeyword.propTypes = { - pusher: pusherShape.isRequired, + cleanupQuery: PropTypes.func.isRequired, clientSessionId: PropTypes.string.isRequired, + handleSubmit: PropTypes.func.isRequired, + pusher: pusherShape.isRequired, query: PropTypes.object.isRequired, setStateQuery: PropTypes.func.isRequired, + showExpand: PropTypes.bool, team: PropTypes.shape({ dbid: PropTypes.number.isRequired, pusher_channel: PropTypes.string.isRequired, @@ -330,9 +332,6 @@ SearchKeyword.propTypes = { })), }), }).isRequired, - showExpand: PropTypes.bool, - cleanupQuery: PropTypes.func.isRequired, - handleSubmit: PropTypes.func.isRequired, }; diff --git a/src/app/components/search/SearchKeywordConfig/SearchKeywordMenu.js b/src/app/components/search/SearchKeywordConfig/SearchKeywordMenu.js index 8e2093233e..caf99e77f4 100644 --- a/src/app/components/search/SearchKeywordConfig/SearchKeywordMenu.js +++ b/src/app/components/search/SearchKeywordConfig/SearchKeywordMenu.js @@ -25,7 +25,7 @@ const SearchKeywordMenu = ({ } size="small" - theme="lightText" + theme="lightBeige" variant="text" onClick={e => setAnchorEl(e.currentTarget)} /> diff --git a/src/app/components/search/SearchResults.module.css b/src/app/components/search/SearchResults.module.css index 3d7c88734a..8cb4afc232 100644 --- a/src/app/components/search/SearchResults.module.css +++ b/src/app/components/search/SearchResults.module.css @@ -168,11 +168,13 @@ } .search-results-scroller { + @mixin scroll-indicator-top 16px, var(--color-white-100), var(--color-beige-86); display: flex; flex-direction: column; gap: 8px; overflow: auto; - padding: 1px 16px 16px; + padding: 16px; + position: relative; } } diff --git a/src/app/icons/push_pin.svg b/src/app/icons/push_pin.svg new file mode 100644 index 0000000000..3e1490e59f --- /dev/null +++ b/src/app/icons/push_pin.svg @@ -0,0 +1 @@ + diff --git a/src/app/styles/css/inputs.module.css b/src/app/styles/css/inputs.module.css index e052df7dcd..4ca9fd7255 100644 --- a/src/app/styles/css/inputs.module.css +++ b/src/app/styles/css/inputs.module.css @@ -114,7 +114,7 @@ margin: 0 0 16px; position: sticky; top: -16px; - z-index: 1001; + z-index: 2; } .form-inner-wrapper { diff --git a/src/app/styles/css/mixins/mixins.css b/src/app/styles/css/mixins/mixins.css index 69319113f9..71dca4948e 100644 --- a/src/app/styles/css/mixins/mixins.css +++ b/src/app/styles/css/mixins/mixins.css @@ -31,6 +31,34 @@ } } +@define-mixin scroll-indicator-top $container-padding: 16px, $container-background: var(--color-white-100), $indicator-color: var(--color-beige-86) { + &::before, + &::after { + content: ''; + display: block; + top: 0; + z-index: 3; + } + + &::before { + background-color: $indicator-color; + box-shadow: 0 3px 6px 0 rgba(0 0 0 / .45); + flex: 1 0 2px; + height: 2px; + margin: 0 calc(0% - $(container-padding)); + position: sticky; + transform: translateY(-$container-padding); + } + + &::after { + background-color: $container-background; + height: $container-padding; + left: 0; + position: absolute; + right: 0; + } +} + @define-mixin typography-definition $size: 14px, $weight: 400, $spacing: .15px, $height: 20px { font-size: $(size); font-weight: $(weight);