-
Notifications
You must be signed in to change notification settings - Fork 148
Display Container Publish status and confirm before publish #2186
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
Open
pomegranited
wants to merge
14
commits into
openedx:master
Choose a base branch
from
open-craft:jill/FAL-4178-publish-container
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+1,081
−86
Open
Changes from all commits
Commits
Show all changes
14 commits
Select commit
Hold shift + click to select a range
c4b90ae
refactor: move draftChipText message to containers
pomegranited caef8df
refactor: make status widget styles extendable
pomegranited 583a30a
feat: show container publish status and confirm publish box (text only)
pomegranited 1f096b7
feat: add custom warning message to container publish box
pomegranited 7ab9e25
Merge remote-tracking branch 'origin/master' into jill/FAL-4178-publi…
pomegranited 2e52679
chore: use import @src/... syntax for files modified here
pomegranited 244d6af
Merge remote-tracking branch 'origin/master' into jill/FAL-4178-publi…
pomegranited 72cc747
feat: adds ContainerHierarchy component
pomegranited 96d9445
test: fix invalidated query key count
pomegranited 6363d70
feat: show container hierarchy with publish status
pomegranited 0b76212
Merge branch 'master' into jill/FAL-4178-publish-container
rpenido 299f37e
fix: invalidate item hierarchy on add/remove to/from container
rpenido b235683
Merge branch 'master' into jill/FAL-4178-publish-container
rpenido 301b2fe
test: fix test
rpenido File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
.content-hierarchy { | ||
margin-bottom: var(--pgn-spacing-paragraph-margin-bottom); | ||
|
||
.hierarchy-row { | ||
border: 1px solid var(--pgn-color-light-500); | ||
border-radius: 4px; | ||
background-color: var(--pgn-color-white); | ||
padding: 0; | ||
margin: 0; | ||
|
||
&.selected { | ||
border: 3px solid var(--pgn-color-primary-500); | ||
border-radius: 4px; | ||
} | ||
|
||
.icon { | ||
background-color: var(--pgn-color-light-300); | ||
border-top: 2px solid var(--pgn-color-light-300); | ||
border-bottom: 2px solid var(--pgn-color-light-300); | ||
border-right: 1px solid var(--pgn-color-light-500); | ||
border-radius: 1px 0 0 1px; | ||
padding: 8px 12px; | ||
} | ||
|
||
&.selected .icon { | ||
background-color: var(--pgn-color-primary-500); | ||
border-color: var(--pgn-color-primary-500); | ||
color: var(--pgn-color-white); | ||
} | ||
|
||
.text { | ||
padding: 8px 12px; | ||
flex-grow: 2; | ||
} | ||
|
||
.publish-status { | ||
background-color: var(--pgn-color-info-200); | ||
white-space: nowrap; | ||
padding: 8px 12px; | ||
} | ||
} | ||
|
||
.hierarchy-arrow { | ||
color: var(--pgn-color-light-500); | ||
padding: 0 0 0 14px; | ||
position: relative; | ||
top: -4px; | ||
height: 20px; | ||
|
||
&.selected { | ||
color: var(--pgn-color-primary-500); | ||
} | ||
} | ||
} |
211 changes: 211 additions & 0 deletions
211
src/library-authoring/containers/ContainerHierarchy.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,211 @@ | ||
import type { MessageDescriptor } from 'react-intl'; | ||
import { FormattedMessage, useIntl } from '@edx/frontend-platform/i18n'; | ||
import { Container, Icon, Stack } from '@openedx/paragon'; | ||
import { ArrowDownward, Check, Description } from '@openedx/paragon/icons'; | ||
import classNames from 'classnames'; | ||
import { getItemIcon } from '@src/generic/block-type-utils'; | ||
import Loading from '@src/generic/Loading'; | ||
import { ContainerType } from '@src/generic/key-utils'; | ||
import type { ContainerHierarchyMember } from '../data/api'; | ||
import { useContainerHierarchy } from '../data/apiHooks'; | ||
import { useSidebarContext } from '../common/context/SidebarContext'; | ||
import messages from './messages'; | ||
|
||
const ContainerHierarchyRow = ({ | ||
containerType, | ||
text, | ||
selected, | ||
showArrow, | ||
willPublish = false, | ||
publishMessage = undefined, | ||
}: { | ||
containerType: ContainerType, | ||
text: string, | ||
selected: boolean, | ||
showArrow: boolean, | ||
willPublish?: boolean, | ||
publishMessage?: MessageDescriptor, | ||
}) => ( | ||
<Stack> | ||
<Container | ||
className={classNames('hierarchy-row', { selected })} | ||
> | ||
<Stack | ||
direction="horizontal" | ||
gap={2} | ||
> | ||
<div className="icon"> | ||
<Icon | ||
src={getItemIcon(containerType)} | ||
screenReaderText={containerType} | ||
title={containerType} | ||
/> | ||
</div> | ||
<div className="text text-truncate"> | ||
{text} | ||
</div> | ||
{publishMessage && ( | ||
<Stack | ||
direction="horizontal" | ||
gap={2} | ||
className="publish-status" | ||
> | ||
<Icon src={willPublish ? Check : Description} /> | ||
<FormattedMessage {...(willPublish ? messages.willPublishChipText : publishMessage)} /> | ||
</Stack> | ||
)} | ||
</Stack> | ||
</Container> | ||
{showArrow && ( | ||
<div | ||
className={classNames('hierarchy-arrow', { selected })} | ||
> | ||
<Icon | ||
src={ArrowDownward} | ||
screenReaderText={' '} | ||
/> | ||
</div> | ||
)} | ||
</Stack> | ||
); | ||
|
||
const ContainerHierarchy = ({ | ||
showPublishStatus = false, | ||
}: { | ||
showPublishStatus?: boolean, | ||
}) => { | ||
const intl = useIntl(); | ||
const { sidebarItemInfo } = useSidebarContext(); | ||
const containerId = sidebarItemInfo?.id; | ||
|
||
// istanbul ignore if: this should never happen | ||
if (!containerId) { | ||
throw new Error('containerId is required'); | ||
} | ||
|
||
const { | ||
data, | ||
isLoading, | ||
isError, | ||
} = useContainerHierarchy(containerId); | ||
|
||
if (isLoading) { | ||
return <Loading />; | ||
} | ||
|
||
// istanbul ignore if: this should never happen | ||
if (isError) { | ||
return null; | ||
} | ||
|
||
const { | ||
sections, | ||
subsections, | ||
units, | ||
components, | ||
} = data; | ||
|
||
// Returns a message describing the publish status of the given hierarchy row. | ||
const publishMessage = (contents: ContainerHierarchyMember[]) => { | ||
// If we're not showing publish status, then we don't need a publish message | ||
if (!showPublishStatus) { | ||
return undefined; | ||
} | ||
|
||
// If any item has unpublished changes, mark this row as Draft. | ||
if (contents.some((item) => item.hasUnpublishedChanges)) { | ||
return messages.draftChipText; | ||
} | ||
|
||
// Otherwise, it's Published | ||
return messages.publishedChipText; | ||
}; | ||
|
||
// Returns True if any of the items in the list match the currently selected container. | ||
const selected = (contents: ContainerHierarchyMember[]): boolean => ( | ||
contents.some((item) => item.id === containerId) | ||
); | ||
|
||
// Use the "selected" status to determine the selected row. | ||
// If showPublishStatus, that row and its children will be marked "willPublish". | ||
const selectedSections = selected(sections); | ||
const selectedSubsections = selected(subsections); | ||
const selectedUnits = selected(units); | ||
const selectedComponents = selected(components); | ||
|
||
const showSections = sections && sections.length > 0; | ||
const showSubsections = subsections && subsections.length > 0; | ||
const showUnits = units && units.length > 0; | ||
const showComponents = components && components.length > 0; | ||
|
||
return ( | ||
<Stack className="content-hierarchy"> | ||
{showSections && ( | ||
<ContainerHierarchyRow | ||
containerType={ContainerType.Section} | ||
text={intl.formatMessage( | ||
messages.hierarchySections, | ||
{ | ||
displayName: sections[0].displayName, | ||
count: sections.length, | ||
}, | ||
)} | ||
showArrow={showSubsections} | ||
selected={selectedSections} | ||
willPublish={selectedSections} | ||
publishMessage={publishMessage(sections)} | ||
/> | ||
)} | ||
{showSubsections && ( | ||
<ContainerHierarchyRow | ||
containerType={ContainerType.Subsection} | ||
text={intl.formatMessage( | ||
messages.hierarchySubsections, | ||
{ | ||
displayName: subsections[0].displayName, | ||
count: subsections.length, | ||
}, | ||
)} | ||
showArrow={showUnits} | ||
selected={selectedSubsections} | ||
willPublish={selectedSubsections || selectedSections} | ||
publishMessage={publishMessage(subsections)} | ||
/> | ||
)} | ||
{showUnits && ( | ||
<ContainerHierarchyRow | ||
containerType={ContainerType.Unit} | ||
text={intl.formatMessage( | ||
messages.hierarchyUnits, | ||
{ | ||
displayName: units[0].displayName, | ||
count: units.length, | ||
}, | ||
)} | ||
showArrow={showComponents} | ||
selected={selectedUnits} | ||
willPublish={selectedUnits || selectedSubsections || selectedSections} | ||
publishMessage={publishMessage(units)} | ||
/> | ||
)} | ||
{showComponents && ( | ||
<ContainerHierarchyRow | ||
containerType={ContainerType.Components} | ||
text={intl.formatMessage( | ||
messages.hierarchyComponents, | ||
{ | ||
displayName: components[0].displayName, | ||
count: components.length, | ||
}, | ||
)} | ||
showArrow={false} | ||
selected={selectedComponents} | ||
willPublish={selectedComponents || selectedUnits || selectedSubsections || selectedSections} | ||
publishMessage={publishMessage(components)} | ||
/> | ||
)} | ||
</Stack> | ||
); | ||
}; | ||
|
||
export default ContainerHierarchy; |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.