Fix blank page template

closes RCX-2591
flag=block_editor

test plan:
  - click on +Page
  > expect a blank page template, followed by any other
    global page templates that exist (currently just 1)
  - click on New Blank Page
  > expect a blank page with a ColumnsSection having 1 column
  > expect to be able to add blocks to the column, to
    change column count, etc. Basically, it's a well behaved
    page.
  - start over and hover over the other template
  > expect the "Customize" button to appear
  - click it
  > expect a page of stuff

Change-Id: Ib67db145a42c5e85c5ab8856743e69e55d7cbe0b
Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/360987
Reviewed-by: Luis Oliveira <luis.oliveira@instructure.com>
QA-Review: Luis Oliveira <luis.oliveira@instructure.com>
Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com>
Product-Review: Ed Schiebel <eschiebel@instructure.com>
This commit is contained in:
Ed Schiebel 2024-10-24 16:20:11 -06:00
parent 761b17c2db
commit e7a7916ce9
7 changed files with 197 additions and 22 deletions

View File

@ -56,7 +56,7 @@ describe "Block Editor", :ignore_js_errors do
it "loads the clicked template to the editor" do
expect(template_chooser).to be_displayed
wait_for_ajax_requests
template_chooser_template_for_number(2).send_keys("")
template_chooser_template_for_number(1).send_keys("")
template_chooser_active_customize_template.click
wait_for_ajax_requests
expect(page_block).to be_displayed

View File

@ -39,18 +39,26 @@ export default function CreateFromTemplate(props: {course_id: string}) {
const {actions} = useEditor()
const [isOpen, setIsOpen] = useState<boolean>(!ENV.WIKI_PAGE)
const [blockTemplates, setBlockTemplates] = useState<BlockTemplate[]>([])
const [blankPageTemplate, setBlankPageTemplate] = useState<BlockTemplate>(() => {
return {node_tree: {}} as BlockTemplate
})
const close = () => {
setIsOpen(false)
}
const loadTemplateOnRoot = (node_tree: TemplateNodeTree) => {
actions.deserialize(JSON.stringify(node_tree.nodes).replaceAll(node_tree.rootNodeId, 'ROOT'))
actions.deserialize(JSON.stringify(node_tree.nodes))
}
useEffect(() => {
if (isOpen) {
getGlobalPageTemplates()
.then(setBlockTemplates)
.then((templates: BlockTemplate[]) => {
const idx = templates.findIndex(template => template.id === 'blank_page')
const blankPage = templates.splice(idx, 1)[0]
setBlankPageTemplate(blankPage)
setBlockTemplates(templates)
})
.catch((err: Error) => {
showFlashError(I18n.t('Cannot get block custom templates'))(err)
})
@ -97,7 +105,15 @@ export default function CreateFromTemplate(props: {course_id: string}) {
</Modal.Header>
<Modal.Body>
<Flex padding="small" wrap="wrap" gap="large">
<TemplateCardSkeleton createAction={close} />
<TemplateCardSkeleton
template={blankPageTemplate}
createAction={() => {
if (blankPageTemplate.node_tree) {
loadTemplateOnRoot(blankPageTemplate.node_tree)
}
close()
}}
/>
{blockTemplates.map(blockTemplate => {
return (
<TemplateCardSkeleton

View File

@ -0,0 +1,112 @@
{
"name": "Blank Page",
"description": "",
"workflow_state": "active",
"node_tree": {
"rootNodeId": "ROOT",
"nodes": {
"ROOT": {
"type": {
"resolvedName": "PageBlock"
},
"isCanvas": true,
"props": {},
"displayName": "Page",
"custom": {
"displayName": "Blank Page"
},
"hidden": false,
"nodes": [
"yue4mpUChN"
],
"linkedNodes": {}
},
"yue4mpUChN": {
"type": {
"resolvedName": "ColumnsSection"
},
"isCanvas": false,
"props": {
"columns": 1
},
"displayName": "Columns",
"custom": {
"isSection": true
},
"parent": "ROOT",
"hidden": false,
"nodes": [],
"linkedNodes": {
"columns__inner": "_LWmxgLGU8"
}
},
"_LWmxgLGU8": {
"type": {
"resolvedName": "ColumnsSectionInner"
},
"isCanvas": true,
"props": {},
"displayName": "Columns Inner",
"custom": {
"noToolbar": true
},
"parent": "yue4mpUChN",
"hidden": false,
"nodes": [
"13kQFSc-L3"
],
"linkedNodes": {}
},
"13kQFSc-L3": {
"type": {
"resolvedName": "GroupBlock"
},
"isCanvas": true,
"props": {
"alignment": "start",
"verticalAlignment": "start",
"layout": "column",
"resizable": false,
"isColumn": true,
"id": "columns-pEdeFvz6_0-1"
},
"displayName": "Group",
"custom": {
"isResizable": false,
"isBlock": true,
"isExpanded": false,
"displayName": "Column"
},
"parent": "_LWmxgLGU8",
"hidden": false,
"nodes": [],
"linkedNodes": {
"group__inner": "Ef7hf8YVK5"
}
},
"Ef7hf8YVK5": {
"type": {
"resolvedName": "NoSections"
},
"isCanvas": true,
"props": {
"className": "",
"placeholderText": "Drop a block to add it here"
},
"displayName": "NoSections",
"custom": {
"noToolbar": true
},
"parent": "13kQFSc-L3",
"hidden": false,
"nodes": [],
"linkedNodes": {}
}
}
},
"template_type": "page",
"template_category": "global",
"thumbnail": "",
"id": "blank_page",
"global_id": "blank_page"
}

File diff suppressed because one or more lines are too long

View File

@ -25,6 +25,7 @@ import {type BlockTemplate} from '../../types'
import blank from './blank.json'
import knowledgeCheck from './knowledgeCheck.json'
import homePage from './homePage1.json'
import blankPage from './blankPage.json'
// returning a promise will make this easier to replace with a real API call
export const getGlobalTemplates = (): Promise<BlockTemplate[]> => {
@ -34,5 +35,5 @@ export const getGlobalTemplates = (): Promise<BlockTemplate[]> => {
export const getGlobalPageTemplates = (): Promise<BlockTemplate[]> => {
// @ts-expect-error
return Promise.resolve([blank, homePage])
return Promise.resolve([blankPage, homePage])
}

View File

@ -29,23 +29,25 @@ export default function TemplateCardSkeleton({
template,
createAction,
}: {
template?: BlockTemplate | undefined
createAction: () => void | undefined
template: BlockTemplate
createAction: () => void
}) {
return (
<View
as="div"
className={`block-template-preview-card ${template ? '' : 'blank-card'}`}
className={`block-template-preview-card ${template.id === 'blank_page' ? 'blank-card' : ''}`}
display="flex"
position="relative"
height="241px"
shadow="above"
tabIndex={0}
style={{backgroundImage: template?.thumbnail && `url(${template.thumbnail})`}}
width="341px"
>
{template.id === 'blank_page' && <div className="curl" />}
<Flex alignItems="center" height="241px" justifyItems="center" width="100%">
{template ? (
<>
{template.id !== 'blank_page' ? (
<div className="buttons">
{/* Not yet */}
{/* <Button color="secondary" margin="0 x-small 0 0" size="small"> */}
{/* {I18n.t('Quick Look')} */}
@ -53,7 +55,7 @@ export default function TemplateCardSkeleton({
<Button color="primary" size="small" onClick={createAction}>
{I18n.t('Customize')}
</Button>
</>
</div>
) : (
<Button color="primary" size="small" onClick={createAction}>
{I18n.t('New Blank Page')}

View File

@ -619,6 +619,50 @@
}
}
.curl {
width: 75px;
height: 75px;
position: absolute;
right: 0;
bottom: 0;
background:
linear-gradient(
135deg,
#fff,
#f3f3f3 45%,
#ddd 50%,
#aaa 50%,
#bbb 56%,
#ccc 62%,
#f3f3f3 80%,
#fff 100%
);
box-shadow: 0 0 10px rgba(0, 0, 0, .5);
transition: all .5s ease;
}
.curl:before,
.curl:after {
content: '';
position: absolute;
z-index: -1;
left: 12.5%;
bottom: 5.8%;
width: 70%;
max-width: 300px;
max-height: 100px;
height: 55%;
box-shadow: 0 12px 15px rgba(0, 0, 0, .3);
transform: skew(-10deg) rotate(-6deg);
}
.curl:after {
left: auto;
right: 5.8%;
bottom: auto;
top: 14.16%;
transform: skew(-15deg) rotate(-84deg);
}
@container block-editor-view (width <= 320px) {
.page-block {
padding: 0;