Edit block or rce pages
whether a page was created with the rce or the block editor edit with the corresponding editor show an solid or line icon on the index page indicating whether the page is a block or rce page respectively closes RCX-2184 flag=block_editor test plan: soon Change-Id: Ia97c21c5b902affd0762ca16c6a1218db8899aa5 Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/354568 Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com> Reviewed-by: Eric Saupe <eric.saupe@instructure.com> QA-Review: Eric Saupe <eric.saupe@instructure.com> Product-Review: Ed Schiebel <eschiebel@instructure.com>
This commit is contained in:
parent
ff8c8c808b
commit
360fb8945c
|
@ -175,13 +175,13 @@ class WikiPagesController < ApplicationController
|
|||
wiki_index_menu_tools: external_tools_display_hashes(:wiki_index_menu),
|
||||
DISPLAY_SHOW_ALL_LINK: tab_enabled?(context.class::TAB_PAGES, no_render: true) && !@k5_details_view,
|
||||
CAN_SET_TODO_DATE: context.grants_any_right?(@current_user, session, :manage_content, :manage_course_content_edit),
|
||||
BLOCK_EDITOR: context.account.feature_enabled?(:block_editor)
|
||||
}
|
||||
if Account.site_admin.feature_enabled?(:permanent_page_links)
|
||||
title_availability_path = context.is_a?(Course) ? api_v1_course_page_title_availability_path : api_v1_group_page_title_availability_path
|
||||
@wiki_pages_env[:TITLE_AVAILABILITY_PATH] = title_availability_path
|
||||
end
|
||||
js_env(@wiki_pages_env)
|
||||
@js_env[:FEATURES][:BLOCK_EDITOR] = true if context.account.feature_enabled?(:block_editor)
|
||||
@wiki_pages_env
|
||||
end
|
||||
end
|
||||
|
|
|
@ -143,6 +143,10 @@ if (!Array.prototype.flatMap) {
|
|||
require('@instructure/ui-themes')
|
||||
|
||||
// set up mocks for native APIs
|
||||
if (!('alert' in window)) {
|
||||
window.alert = () => {}
|
||||
}
|
||||
|
||||
if (!('MutationObserver' in window)) {
|
||||
Object.defineProperty(window, 'MutationObserver', {
|
||||
value: require('@sheerun/mutationobserver-shim'),
|
||||
|
|
|
@ -40,6 +40,7 @@ module Api::V1::WikiPage
|
|||
hash["html_url"] = polymorphic_url([wiki_page.context, wiki_page])
|
||||
hash["todo_date"] = wiki_page.todo_date
|
||||
hash["publish_at"] = wiki_page.publish_at
|
||||
hash["editor"] = wiki_page.block_editor ? "block_editor" : "rce" if @context.account.feature_enabled?(:block_editor)
|
||||
|
||||
hash["updated_at"] = wiki_page.revised_at
|
||||
if opts[:include_assignment] && wiki_page.for_assignment?
|
||||
|
@ -51,12 +52,11 @@ module Api::V1::WikiPage
|
|||
end
|
||||
locked_json(hash, wiki_page, current_user, "page", deep_check_if_needed: opts[:deep_check_if_needed])
|
||||
if include_body && !hash["locked_for_user"] && !hash["lock_info"]
|
||||
if @context.account.feature_enabled?(:block_editor)
|
||||
block_editor = wiki_page.block_editor
|
||||
if @context.account.feature_enabled?(:block_editor) && wiki_page.block_editor
|
||||
hash["block_editor_attributes"] = {
|
||||
id: block_editor&.id,
|
||||
version: block_editor&.editor_version,
|
||||
blocks: block_editor&.blocks
|
||||
id: wiki_page.block_editor.id,
|
||||
version: wiki_page.block_editor.editor_version,
|
||||
blocks: wiki_page.block_editor.blocks
|
||||
}
|
||||
else
|
||||
hash["body"] = api_user_content(wiki_page.body, wiki_page.context)
|
||||
|
|
|
@ -0,0 +1,190 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
#
|
||||
# Copyright (C) 2024 - present Instructure, Inc.
|
||||
#
|
||||
# This file is part of Canvas.
|
||||
#
|
||||
# Canvas is free software: you can redistribute it and/or modify it under
|
||||
# the terms of the GNU Affero General Public License as published by the Free
|
||||
# Software Foundation, version 3 of the License.
|
||||
#
|
||||
# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License along
|
||||
# with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
require_relative "../api_spec_helper"
|
||||
require_relative "../locked_examples"
|
||||
require_relative "../../helpers/selective_release_common"
|
||||
|
||||
describe "Pages API", type: :request do
|
||||
include Api::V1::User
|
||||
include AvatarHelper
|
||||
include SelectiveReleaseCommon
|
||||
|
||||
let(:block_page_data) do
|
||||
{
|
||||
time: Time.now.to_i,
|
||||
version: "1",
|
||||
blocks: [
|
||||
{
|
||||
data: '{"ROOT":{"type": ...}'
|
||||
}
|
||||
]
|
||||
}
|
||||
end
|
||||
|
||||
context "with the block editor" do
|
||||
before :once do
|
||||
course_with_teacher(active_all: true)
|
||||
@course.account.enable_feature!(:block_editor)
|
||||
@block_page = @course.wiki_pages.create!(title: "Block editor page", block_editor_attributes: {
|
||||
time: Time.now.to_i,
|
||||
version: "1",
|
||||
blocks: [
|
||||
{
|
||||
data: '{"ROOT":{"type": ...}'
|
||||
}
|
||||
]
|
||||
})
|
||||
end
|
||||
|
||||
describe "index" do
|
||||
it("returns the block editor meta-data") do
|
||||
json = api_call(:get,
|
||||
"/api/v1/courses/#{@course.id}/pages",
|
||||
controller: "wiki_pages_api",
|
||||
action: "index",
|
||||
format: "json",
|
||||
course_id: @course.to_param)
|
||||
expect(json.map { |entry| entry.slice(*%w[url title editor]) }).to eq(
|
||||
[{ "url" => @block_page.url, "title" => @block_page.title, "editor" => "block_editor" }]
|
||||
)
|
||||
expect(json[0].keys).not_to include("body")
|
||||
expect(json[0].keys).not_to include("block_editor_attributes")
|
||||
end
|
||||
|
||||
it("returns the block editor data when include[]=body is specified") do
|
||||
json = api_call(:get,
|
||||
"/api/v1/courses/#{@course.id}/pages",
|
||||
controller: "wiki_pages_api",
|
||||
action: "index",
|
||||
format: "json",
|
||||
course_id: @course.to_param,
|
||||
include: ["body"])
|
||||
|
||||
expect(json[0].keys).not_to include("body")
|
||||
expect(json[0].keys).to include("block_editor_attributes")
|
||||
returned_attributes = json[0]["block_editor_attributes"]
|
||||
expect(returned_attributes["version"]).to eq(block_page_data[:version])
|
||||
expect(returned_attributes["blocks"][0]["data"]).to eq(block_page_data[:blocks][0][:data])
|
||||
end
|
||||
end
|
||||
|
||||
describe "show" do
|
||||
it "retrieves block editor page content and attributes" do
|
||||
json = api_call(:get,
|
||||
"/api/v1/courses/#{@course.id}/pages/#{@block_page.url}",
|
||||
controller: "wiki_pages_api",
|
||||
action: "show",
|
||||
format: "json",
|
||||
course_id: @course.id.to_s,
|
||||
url_or_id: @block_page.url)
|
||||
expect(json["body"]).to be_nil
|
||||
expect(json["editor"]).to eq("block_editor")
|
||||
returned_attributes = json["block_editor_attributes"]
|
||||
expect(returned_attributes["version"]).to eq(block_page_data[:version])
|
||||
expect(returned_attributes["blocks"][0]["data"]).to eq(block_page_data[:blocks][0][:data])
|
||||
end
|
||||
|
||||
it "retrieves rce editor page content and attributes" do
|
||||
rce_page = @course.wiki_pages.create!(title: "RCE Page", body: "Body of RCE page")
|
||||
json = api_call(:get,
|
||||
"/api/v1/courses/#{@course.id}/pages/#{rce_page.url}",
|
||||
controller: "wiki_pages_api",
|
||||
action: "show",
|
||||
format: "json",
|
||||
course_id: @course.id.to_s,
|
||||
url_or_id: rce_page.url)
|
||||
expect(json["body"]).to eq(rce_page.body)
|
||||
expect(json["editor"]).to eq("rce")
|
||||
expect(json["block_editor_attributes"]).to be_nil
|
||||
end
|
||||
end
|
||||
|
||||
describe "create" do
|
||||
it "creates a new page", priority: "1" do
|
||||
json = api_call(:post,
|
||||
"/api/v1/courses/#{@course.id}/pages",
|
||||
{ controller: "wiki_pages_api", action: "create", format: "json", course_id: @course.to_param },
|
||||
{ wiki_page: { title: "New Block Page!", block_editor_attributes: block_page_data } })
|
||||
page = @course.wiki_pages.where(url: json["url"]).first!
|
||||
expect(page.title).to eq "New Block Page!"
|
||||
expect(page.url).to eq "new-block-page"
|
||||
expect(page.body).to be_nil
|
||||
expect(page.block_editor["blocks"][0]["data"]).to eq block_page_data[:blocks][0][:data]
|
||||
expect(page.block_editor["editor_version"]).to eq block_page_data[:version]
|
||||
end
|
||||
|
||||
it "creates a front page using PUT", priority: "1" do
|
||||
front_page_url = "new-block-front-page"
|
||||
json = api_call(:put,
|
||||
"/api/v1/courses/#{@course.id}/front_page",
|
||||
{ controller: "wiki_pages_api", action: "update_front_page", format: "json", course_id: @course.to_param },
|
||||
{ wiki_page: { title: "New Block Front Page!", block_editor_attributes: block_page_data } })
|
||||
expect(json["url"]).to eq front_page_url
|
||||
page = @course.wiki_pages.where(url: front_page_url).first!
|
||||
|
||||
expect(page.is_front_page?).to be_truthy
|
||||
expect(page.title).to eq "New Block Front Page!"
|
||||
expect(page.body).to be_nil
|
||||
expect(page.block_editor["blocks"][0]["data"]).to eq block_page_data[:blocks][0][:data]
|
||||
expect(page.block_editor["editor_version"]).to eq block_page_data[:version]
|
||||
end
|
||||
end
|
||||
|
||||
describe "update" do
|
||||
it "updates a page with block editor data" do
|
||||
new_block_data = {
|
||||
time: Time.now.to_i,
|
||||
version: "1",
|
||||
blocks: [
|
||||
{
|
||||
data: '{"ROOT":{"a_different_type": ...}'
|
||||
}
|
||||
]
|
||||
}
|
||||
api_call(:put,
|
||||
"/api/v1/courses/#{@course.id}/pages/#{@block_page.url}",
|
||||
{ controller: "wiki_pages_api",
|
||||
action: "update",
|
||||
format: "json",
|
||||
course_id: @course.to_param,
|
||||
url_or_id: @block_page.url },
|
||||
{ wiki_page: { block_editor_attributes: new_block_data } })
|
||||
@block_page.reload
|
||||
expect(@block_page.block_editor["blocks"][0]["data"]).to eq new_block_data[:blocks][0][:data]
|
||||
expect(@block_page.body).to be_nil
|
||||
end
|
||||
end
|
||||
|
||||
describe "destroy" do
|
||||
it "deletes a page", priority: "1" do
|
||||
api_call(:delete,
|
||||
"/api/v1/courses/#{@course.id}/pages/#{@block_page.url}",
|
||||
{ controller: "wiki_pages_api",
|
||||
action: "destroy",
|
||||
format: "json",
|
||||
course_id: @course.to_param,
|
||||
url_or_id: @block_page.url })
|
||||
expect(@block_page.reload).to be_deleted
|
||||
expect(@block_page.block_editor).to be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -38,6 +38,13 @@ describe WikiPagesController do
|
|||
expect(response).to be_successful
|
||||
expect(assigns[:js_env][:DISPLAY_SHOW_ALL_LINK]).to be(true)
|
||||
end
|
||||
|
||||
it "sets up js_env for the block editor" do
|
||||
@course.account.enable_feature!(:block_editor)
|
||||
get "index", params: { course_id: @course.id }
|
||||
expect(response).to be_successful
|
||||
expect(assigns[:js_env][:FEATURES][:BLOCK_EDITOR]).to be(true)
|
||||
end
|
||||
end
|
||||
|
||||
context "with page" do
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#
|
||||
# You should have received a copy of the GNU Affero General Public License along
|
||||
# with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
#
|
||||
# some if the specs in here include "ignore_js_errors: true". This is because
|
||||
|
@ -31,35 +32,77 @@ describe "Block Editor", :ignore_js_errors do
|
|||
include_context "in-process server selenium tests"
|
||||
include BlockEditorPage
|
||||
|
||||
def create_wiki_page_with_block_editor_content(page_title)
|
||||
@page = @course.wiki_pages.create!(title: page_title)
|
||||
@page.update!(
|
||||
title: "#{page_title}-2",
|
||||
block_editor_attributes: {
|
||||
time: Time.now.to_i,
|
||||
version: "1",
|
||||
blocks: [
|
||||
{
|
||||
data: '{"ROOT":{"type":{"resolvedName":"PageBlock"},"isCanvas":true,"props":{},"displayName":"Page","custom":{},"hidden":false,"nodes":["UO_WRGQgSQ"],"linkedNodes":{}},"UO_WRGQgSQ":{"type":{"resolvedName":"BlankSection"},"isCanvas":false,"props":{},"displayName":"Blank Section","custom":{"isSection":true},"parent":"ROOT","hidden":false,"nodes":[],"linkedNodes":{"blank-section_nosection1":"e33NpD3Ck3"}},"e33NpD3Ck3":{"type":{"resolvedName":"NoSections"},"isCanvas":true,"props":{"className":"blank-section__inner"},"displayName":"NoSections","custom":{"noToolbar":true},"parent":"UO_WRGQgSQ","hidden":false,"nodes":[],"linkedNodes":{}}}'
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
let(:block_page_content) do
|
||||
'{
|
||||
"ROOT": {
|
||||
"type": {
|
||||
"resolvedName": "PageBlock"
|
||||
},
|
||||
"isCanvas": true,
|
||||
"props": {},
|
||||
"displayName": "Page",
|
||||
"custom": {},
|
||||
"hidden": false,
|
||||
"nodes": [
|
||||
"UO_WRGQgSQ"
|
||||
],
|
||||
"linkedNodes": {}
|
||||
},
|
||||
"UO_WRGQgSQ": {
|
||||
"type": {
|
||||
"resolvedName": "BlankSection"
|
||||
},
|
||||
"isCanvas": false,
|
||||
"props": {},
|
||||
"displayName": "Blank Section",
|
||||
"custom": {
|
||||
"isSection": true
|
||||
},
|
||||
"parent": "ROOT",
|
||||
"hidden": false,
|
||||
"nodes": [],
|
||||
"linkedNodes": {
|
||||
"blank-section_nosection1": "e33NpD3Ck3"
|
||||
}
|
||||
},
|
||||
"e33NpD3Ck3": {
|
||||
"type": {
|
||||
"resolvedName": "NoSections"
|
||||
},
|
||||
"isCanvas": true,
|
||||
"props": {
|
||||
"className": "blank-section__inner"
|
||||
},
|
||||
"displayName": "NoSections",
|
||||
"custom": {
|
||||
"noToolbar": true
|
||||
},
|
||||
"parent": "UO_WRGQgSQ",
|
||||
"hidden": false,
|
||||
"nodes": [],
|
||||
"linkedNodes": {}
|
||||
}
|
||||
}'
|
||||
end
|
||||
|
||||
before do
|
||||
course_with_teacher_logged_in
|
||||
@course.account.enable_feature!(:block_editor)
|
||||
@context = @course
|
||||
end
|
||||
|
||||
def wait_for_block_editor
|
||||
keep_trying_until do
|
||||
disable_implicit_wait { f(".block-editor-editor") } # rubocop:disable Specs/NoDisableImplicitWait
|
||||
rescue => e
|
||||
puts e.inspect
|
||||
false
|
||||
end
|
||||
@rce_page = @course.wiki_pages.create!(title: "RCE Page", body: "RCE Page Body")
|
||||
@block_page = @course.wiki_pages.create!(title: "Block Page")
|
||||
puts ">>>", block_page_content
|
||||
@block_page.update!(
|
||||
block_editor_attributes: {
|
||||
time: Time.now.to_i,
|
||||
version: "1",
|
||||
blocks: [
|
||||
{
|
||||
data: block_page_content
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
def create_wiki_page(course)
|
||||
|
@ -104,13 +147,21 @@ describe "Block Editor", :ignore_js_errors do
|
|||
end
|
||||
|
||||
context "Edit a page" do
|
||||
before do
|
||||
create_wiki_page_with_block_editor_content("block editor test")
|
||||
it "edits an rce page with the rce" do
|
||||
get "/courses/#{@course.id}/pages/#{@rce_page.url}/edit"
|
||||
wait_for_rce
|
||||
expect(f("textarea.body").attribute("value")).to eq("<p>RCE Page Body</p>")
|
||||
end
|
||||
|
||||
it "loads the editor" do
|
||||
get "/courses/#{@course.id}/pages/block-editor-test/edit"
|
||||
expect(f(".block-editor-editor")).to be_displayed
|
||||
it "edits a block page with the block editor" do
|
||||
get "/courses/#{@course.id}/pages/#{@block_page.url}/edit"
|
||||
wait_for_block_editor
|
||||
expect(f(".page-block")).to be_displayed
|
||||
end
|
||||
|
||||
it "can drag and drop blocks from the toolbox" do
|
||||
get "/courses/#{@course.id}/pages/#{@block_page.url}/edit"
|
||||
wait_for_block_editor
|
||||
block_toolbox_toggle.click
|
||||
expect(block_toolbox).to be_displayed
|
||||
drag_and_drop_element(f(".toolbox-item.item-button"), f(".blank-section__inner"))
|
||||
|
|
|
@ -293,4 +293,14 @@ module CustomWaitMethods
|
|||
rescue Selenium::WebDriver::Error::NoSuchElementError
|
||||
true
|
||||
end
|
||||
|
||||
def wait_for_block_editor(parent_element = nil)
|
||||
parent_element ||= f("#content")
|
||||
keep_trying_until do
|
||||
disable_implicit_wait { f(".block-editor-editor", parent_element) }
|
||||
rescue => e
|
||||
puts e.inspect
|
||||
false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -100,6 +100,9 @@ export default class WikiPageIndexItemView extends Backbone.View {
|
|||
json.isChecked = this.selectedPages.hasOwnProperty(this.model.get('page_id'))
|
||||
json.collectionHasTodoDate = this.collectionHasTodoDate()
|
||||
json.frontPageText = ENV.K5_SUBJECT_COURSE ? I18n.t('Subject Home') : I18n.t('Front Page')
|
||||
json.block_editor = !!ENV.FEATURES?.BLOCK_EDITOR
|
||||
json.page_is_block = this.model.get('editor') === 'block_editor'
|
||||
json.page_type_label = json.page_is_block ? I18n.t('block page') : I18n.t('classic page')
|
||||
return json
|
||||
}
|
||||
|
||||
|
|
|
@ -102,6 +102,8 @@ export default class WikiPageIndexView extends PaginatedCollectionView {
|
|||
if (!this.selectedPages) this.selectedPages = {}
|
||||
this.itemViewOptions.selectedPages = this.selectedPages
|
||||
|
||||
this.createNewPageWithBlockEditor = !!ENV.FEATURES?.BLOCK_EDITOR
|
||||
|
||||
this.collection.on('fetch', () => {
|
||||
if (!this.fetched) {
|
||||
this.fetched = true
|
||||
|
@ -191,7 +193,7 @@ export default class WikiPageIndexView extends PaginatedCollectionView {
|
|||
}
|
||||
|
||||
toggleBlockEditor(ev) {
|
||||
ENV.BLOCK_EDITOR = ev.target.checked
|
||||
this.createNewPageWithBlockEditor = ev.target.checked
|
||||
}
|
||||
|
||||
confirmDeletePages(ev) {
|
||||
|
@ -232,10 +234,17 @@ export default class WikiPageIndexView extends PaginatedCollectionView {
|
|||
$('body').removeClass('index')
|
||||
$('body').addClass('edit')
|
||||
|
||||
this.editModel = new WikiPage(
|
||||
{editing_roles: this.default_editing_roles},
|
||||
{contextAssetString: this.contextAssetString}
|
||||
)
|
||||
this.editModel = new WikiPage({
|
||||
editing_roles: this.default_editing_roles,
|
||||
contextAssetString: this.contextAssetString,
|
||||
editor: this.createNewPageWithBlockEditor ? 'block_editor' : 'rce',
|
||||
block_editor_attributes: this.createNewPageWithBlockEditor
|
||||
? {
|
||||
version: '1',
|
||||
blocks: [{data: undefined}],
|
||||
}
|
||||
: null,
|
||||
})
|
||||
this.editView = new WikiPageEditView({
|
||||
model: this.editModel,
|
||||
wiki_pages_path: ENV.WIKI_PAGES_PATH,
|
||||
|
@ -390,7 +399,7 @@ export default class WikiPageIndexView extends PaginatedCollectionView {
|
|||
json.hasWikiIndexPlacements = this.wikiIndexPlacements.length > 0
|
||||
json.wikiIndexPlacements = this.wikiIndexPlacements
|
||||
|
||||
json.block_editor = ENV.BLOCK_EDITOR
|
||||
json.block_editor = !!ENV.FEATURES?.BLOCK_EDITOR
|
||||
return json
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ import WikiPage from '@canvas/wiki/backbone/models/WikiPage'
|
|||
import WikiPageIndexItemView from '../WikiPageIndexItemView'
|
||||
import fakeENV from '@canvas/test-utils/fakeENV'
|
||||
|
||||
describe('WikiPageIndexItemView', () => {
|
||||
describe('WikiPageIndex', () => {
|
||||
beforeEach(() => {
|
||||
fakeENV.setup()
|
||||
})
|
||||
|
@ -28,191 +28,192 @@ describe('WikiPageIndexItemView', () => {
|
|||
afterEach(() => {
|
||||
fakeENV.teardown()
|
||||
})
|
||||
|
||||
test('model.view maintained by item view', () => {
|
||||
const model = new WikiPage()
|
||||
const view = new WikiPageIndexItemView({
|
||||
model,
|
||||
collectionHasTodoDate: () => {},
|
||||
selectedPages: {},
|
||||
})
|
||||
expect(model.view).toBe(view)
|
||||
view.render()
|
||||
expect(model.view).toBe(view)
|
||||
})
|
||||
|
||||
test('detach/reattach the publish icon view', () => {
|
||||
const model = new WikiPage()
|
||||
const view = new WikiPageIndexItemView({
|
||||
model,
|
||||
collectionHasTodoDate: () => {},
|
||||
selectedPages: {},
|
||||
})
|
||||
view.render()
|
||||
const $previousEl = view.$el.find('> *:first-child')
|
||||
view.publishIconView.$el.data('test-data', 'test-is-good')
|
||||
view.render()
|
||||
expect($previousEl.parent().length).toBe(0)
|
||||
expect(view.publishIconView.$el.data('test-data')).toBe('test-is-good')
|
||||
})
|
||||
|
||||
test('delegate useAsFrontPage to the model', () => {
|
||||
const model = new WikiPage({
|
||||
front_page: false,
|
||||
published: true,
|
||||
})
|
||||
const view = new WikiPageIndexItemView({
|
||||
model,
|
||||
collectionHasTodoDate: () => {},
|
||||
selectedPages: {},
|
||||
})
|
||||
const stub = jest.spyOn(model, 'setFrontPage').mockImplementation()
|
||||
view.useAsFrontPage()
|
||||
expect(stub).toHaveBeenCalledTimes(1)
|
||||
stub.mockRestore()
|
||||
})
|
||||
|
||||
test('only shows direct share menu items if enabled', () => {
|
||||
const view = new WikiPageIndexItemView({
|
||||
model: new WikiPage(),
|
||||
collectionHasTodoDate: () => {},
|
||||
selectedPages: {},
|
||||
WIKI_RIGHTS: {read: true, manage: true, update: true},
|
||||
CAN: {MANAGE: true},
|
||||
})
|
||||
view.render()
|
||||
expect(view.$('.send-wiki-page-to').length).toBe(0)
|
||||
expect(view.$('.copy-wiki-page-to').length).toBe(0)
|
||||
|
||||
ENV.DIRECT_SHARE_ENABLED = true
|
||||
view.render()
|
||||
expect(view.$('.send-wiki-page-to').length).toBeGreaterThan(0)
|
||||
expect(view.$('.copy-wiki-page-to').length).toBeGreaterThan(0)
|
||||
})
|
||||
})
|
||||
|
||||
describe('WikiPageIndexItemView:JSON', () => {
|
||||
const testRights = (subject, options) => {
|
||||
test(`${subject}`, () => {
|
||||
describe('WikiPageIndexItemView', () => {
|
||||
test('model.view maintained by item view', () => {
|
||||
const model = new WikiPage()
|
||||
const view = new WikiPageIndexItemView({
|
||||
model,
|
||||
contextName: options.contextName,
|
||||
WIKI_RIGHTS: options.WIKI_RIGHTS,
|
||||
collectionHasTodoDate: () => {},
|
||||
selectedPages: {},
|
||||
})
|
||||
const json = view.toJSON()
|
||||
for (const key in options.CAN) {
|
||||
expect(json.CAN[key]).toBe(options.CAN[key])
|
||||
}
|
||||
expect(model.view).toBe(view)
|
||||
view.render()
|
||||
expect(model.view).toBe(view)
|
||||
})
|
||||
}
|
||||
|
||||
testRights('CAN (manage course)', {
|
||||
contextName: 'courses',
|
||||
WIKI_RIGHTS: {
|
||||
read: true,
|
||||
manage: true,
|
||||
publish_page: true,
|
||||
create_page: true,
|
||||
},
|
||||
CAN: {
|
||||
MANAGE: true,
|
||||
PUBLISH: true,
|
||||
DUPLICATE: true,
|
||||
},
|
||||
})
|
||||
|
||||
testRights('CAN (manage group)', {
|
||||
contextName: 'groups',
|
||||
WIKI_RIGHTS: {
|
||||
read: true,
|
||||
manage: true,
|
||||
publish_page: false,
|
||||
create_page: true,
|
||||
},
|
||||
CAN: {
|
||||
MANAGE: true,
|
||||
PUBLISH: false,
|
||||
DUPLICATE: false,
|
||||
},
|
||||
})
|
||||
|
||||
testRights('CAN (read)', {
|
||||
contextName: 'courses',
|
||||
WIKI_RIGHTS: {read: true},
|
||||
CAN: {
|
||||
MANAGE: false,
|
||||
PUBLISH: false,
|
||||
},
|
||||
})
|
||||
|
||||
testRights('CAN (null)', {
|
||||
CAN: {
|
||||
MANAGE: false,
|
||||
PUBLISH: false,
|
||||
},
|
||||
})
|
||||
|
||||
// Tests for granular permissions, with manage permission removed
|
||||
testRights('CAN (create page - course)', {
|
||||
contextName: 'courses',
|
||||
WIKI_RIGHTS: {create_page: true},
|
||||
CAN: {
|
||||
MANAGE: true,
|
||||
PUBLISH: false,
|
||||
DUPLICATE: true,
|
||||
UPDATE: false,
|
||||
DELETE: false,
|
||||
},
|
||||
})
|
||||
|
||||
testRights('CAN (create page - group)', {
|
||||
contextName: 'groups',
|
||||
WIKI_RIGHTS: {create_page: true},
|
||||
CAN: {
|
||||
MANAGE: true,
|
||||
PUBLISH: false,
|
||||
DUPLICATE: false,
|
||||
UPDATE: false,
|
||||
DELETE: false,
|
||||
},
|
||||
})
|
||||
|
||||
testRights('CAN (delete page)', {
|
||||
contextName: 'courses',
|
||||
WIKI_RIGHTS: {delete_page: true},
|
||||
CAN: {
|
||||
MANAGE: true,
|
||||
PUBLISH: false,
|
||||
DUPLICATE: false,
|
||||
UPDATE: false,
|
||||
DELETE: true,
|
||||
},
|
||||
})
|
||||
|
||||
testRights('CAN (update page)', {
|
||||
contextName: 'courses',
|
||||
WIKI_RIGHTS: {update: true, publish_page: true},
|
||||
CAN: {
|
||||
MANAGE: true,
|
||||
PUBLISH: true,
|
||||
DUPLICATE: false,
|
||||
UPDATE: true,
|
||||
DELETE: false,
|
||||
},
|
||||
})
|
||||
|
||||
test('includes is_checked', () => {
|
||||
const model = new WikiPage({
|
||||
page_id: '42',
|
||||
test('detach/reattach the publish icon view', () => {
|
||||
const model = new WikiPage()
|
||||
const view = new WikiPageIndexItemView({
|
||||
model,
|
||||
collectionHasTodoDate: () => {},
|
||||
selectedPages: {},
|
||||
})
|
||||
view.render()
|
||||
const $previousEl = view.$el.find('> *:first-child')
|
||||
view.publishIconView.$el.data('test-data', 'test-is-good')
|
||||
view.render()
|
||||
expect($previousEl.parent().length).toBe(0)
|
||||
expect(view.publishIconView.$el.data('test-data')).toBe('test-is-good')
|
||||
})
|
||||
const view = new WikiPageIndexItemView({
|
||||
model,
|
||||
collectionHasTodoDate: () => {},
|
||||
selectedPages: {42: model},
|
||||
|
||||
test('delegate useAsFrontPage to the model', () => {
|
||||
const model = new WikiPage({
|
||||
front_page: false,
|
||||
published: true,
|
||||
})
|
||||
const view = new WikiPageIndexItemView({
|
||||
model,
|
||||
collectionHasTodoDate: () => {},
|
||||
selectedPages: {},
|
||||
})
|
||||
const stub = jest.spyOn(model, 'setFrontPage').mockImplementation()
|
||||
view.useAsFrontPage()
|
||||
expect(stub).toHaveBeenCalledTimes(1)
|
||||
stub.mockRestore()
|
||||
})
|
||||
|
||||
test('only shows direct share menu items if enabled', () => {
|
||||
const view = new WikiPageIndexItemView({
|
||||
model: new WikiPage(),
|
||||
collectionHasTodoDate: () => {},
|
||||
selectedPages: {},
|
||||
WIKI_RIGHTS: {read: true, manage: true, update: true},
|
||||
CAN: {MANAGE: true},
|
||||
})
|
||||
view.render()
|
||||
expect(view.$('.send-wiki-page-to').length).toBe(0)
|
||||
expect(view.$('.copy-wiki-page-to').length).toBe(0)
|
||||
|
||||
ENV.DIRECT_SHARE_ENABLED = true
|
||||
view.render()
|
||||
expect(view.$('.send-wiki-page-to').length).toBeGreaterThan(0)
|
||||
expect(view.$('.copy-wiki-page-to').length).toBeGreaterThan(0)
|
||||
})
|
||||
})
|
||||
|
||||
describe('WikiPageIndexItemView:JSON', () => {
|
||||
const testRights = (subject, options) => {
|
||||
test(`${subject}`, () => {
|
||||
const model = new WikiPage()
|
||||
const view = new WikiPageIndexItemView({
|
||||
model,
|
||||
contextName: options.contextName,
|
||||
WIKI_RIGHTS: options.WIKI_RIGHTS,
|
||||
collectionHasTodoDate: () => {},
|
||||
selectedPages: {},
|
||||
})
|
||||
const json = view.toJSON()
|
||||
for (const key in options.CAN) {
|
||||
expect(json.CAN[key]).toBe(options.CAN[key])
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
testRights('CAN (manage course)', {
|
||||
contextName: 'courses',
|
||||
WIKI_RIGHTS: {
|
||||
read: true,
|
||||
manage: true,
|
||||
publish_page: true,
|
||||
create_page: true,
|
||||
},
|
||||
CAN: {
|
||||
MANAGE: true,
|
||||
PUBLISH: true,
|
||||
DUPLICATE: true,
|
||||
},
|
||||
})
|
||||
|
||||
testRights('CAN (manage group)', {
|
||||
contextName: 'groups',
|
||||
WIKI_RIGHTS: {
|
||||
read: true,
|
||||
manage: true,
|
||||
publish_page: false,
|
||||
create_page: true,
|
||||
},
|
||||
CAN: {
|
||||
MANAGE: true,
|
||||
PUBLISH: false,
|
||||
DUPLICATE: false,
|
||||
},
|
||||
})
|
||||
|
||||
testRights('CAN (read)', {
|
||||
contextName: 'courses',
|
||||
WIKI_RIGHTS: {read: true},
|
||||
CAN: {
|
||||
MANAGE: false,
|
||||
PUBLISH: false,
|
||||
},
|
||||
})
|
||||
|
||||
testRights('CAN (null)', {
|
||||
CAN: {
|
||||
MANAGE: false,
|
||||
PUBLISH: false,
|
||||
},
|
||||
})
|
||||
|
||||
// Tests for granular permissions, with manage permission removed
|
||||
testRights('CAN (create page - course)', {
|
||||
contextName: 'courses',
|
||||
WIKI_RIGHTS: {create_page: true},
|
||||
CAN: {
|
||||
MANAGE: true,
|
||||
PUBLISH: false,
|
||||
DUPLICATE: true,
|
||||
UPDATE: false,
|
||||
DELETE: false,
|
||||
},
|
||||
})
|
||||
|
||||
testRights('CAN (create page - group)', {
|
||||
contextName: 'groups',
|
||||
WIKI_RIGHTS: {create_page: true},
|
||||
CAN: {
|
||||
MANAGE: true,
|
||||
PUBLISH: false,
|
||||
DUPLICATE: false,
|
||||
UPDATE: false,
|
||||
DELETE: false,
|
||||
},
|
||||
})
|
||||
|
||||
testRights('CAN (delete page)', {
|
||||
contextName: 'courses',
|
||||
WIKI_RIGHTS: {delete_page: true},
|
||||
CAN: {
|
||||
MANAGE: true,
|
||||
PUBLISH: false,
|
||||
DUPLICATE: false,
|
||||
UPDATE: false,
|
||||
DELETE: true,
|
||||
},
|
||||
})
|
||||
|
||||
testRights('CAN (update page)', {
|
||||
contextName: 'courses',
|
||||
WIKI_RIGHTS: {update: true, publish_page: true},
|
||||
CAN: {
|
||||
MANAGE: true,
|
||||
PUBLISH: true,
|
||||
DUPLICATE: false,
|
||||
UPDATE: true,
|
||||
DELETE: false,
|
||||
},
|
||||
})
|
||||
|
||||
test('includes is_checked', () => {
|
||||
const model = new WikiPage({
|
||||
page_id: '42',
|
||||
})
|
||||
const view = new WikiPageIndexItemView({
|
||||
model,
|
||||
collectionHasTodoDate: () => {},
|
||||
selectedPages: {42: model},
|
||||
})
|
||||
expect(view.toJSON().isChecked).toBe(true)
|
||||
})
|
||||
expect(view.toJSON().isChecked).toBe(true)
|
||||
})
|
||||
})
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
{{#if block_editor}}
|
||||
<label class="checkbox" for="toggle_block_editor" style="margin-inline-end: 4px;">
|
||||
<input type="checkbox" value="1" id="toggle_block_editor" aria-label="toggle block editor" checked>
|
||||
{{#t}}Use block Editor{{/t}}
|
||||
{{#t}}Create with block editor{{/t}}
|
||||
</label>
|
||||
{{/if}}
|
||||
{{#if CAN.DELETE}}
|
||||
|
@ -89,6 +89,11 @@
|
|||
<span class="screenreader-only">{{#t}}Select page{{/t}}</span>
|
||||
</th>
|
||||
{{/if}}
|
||||
{{#if block_editor}}
|
||||
<th scope="col" width="24px" role="columnheader">
|
||||
<span class="screenreader-only">{{#t}}page type{{/t}}</span>
|
||||
</th>
|
||||
{{/if}}
|
||||
<th scope="col" width="{{#if CAN.MANAGE}}{{#if CAN.PUBLISH}}42%{{else}}46%{{/if}}{{else}}60%{{/if}}" role="columnheader">
|
||||
<span class="mobile-screenreader-only">
|
||||
<a href="#" data-sort-field="title" tabindex="0" role="button" class="sort-field">{{#t 'headers.page_title'}}Page title{{/t}} <i></i></a>
|
||||
|
|
|
@ -12,6 +12,11 @@
|
|||
{{/unless}}
|
||||
</td>
|
||||
{{/if}}
|
||||
{{#if block_editor}}
|
||||
<td role="gridcell">
|
||||
<i class="icon-document {{#if page_is_block}}icon-Solid{{/if}}" aria-label="{{page_type_label}}" />
|
||||
</td>
|
||||
{{/if}}
|
||||
<td role="gridcell">
|
||||
<div class="hide-overflow" role="text">
|
||||
<div class="wiki-page-title">
|
||||
|
|
|
@ -174,7 +174,9 @@ export default class WikiPageView extends Backbone.View {
|
|||
} else if (this.$sequenceFooter != null) {
|
||||
this.$sequenceFooter.msfAnimation(false)
|
||||
}
|
||||
if (this.$sequenceFooter) return this.$sequenceFooter.appendTo($('#module_navigation_target'))
|
||||
if (this.$sequenceFooter) this.$sequenceFooter.appendTo($('#module_navigation_target'))
|
||||
|
||||
this.maybeRenderBlockEditorContent()
|
||||
}
|
||||
|
||||
navigateToLinkAnchor() {
|
||||
|
@ -190,8 +192,11 @@ export default class WikiPageView extends Backbone.View {
|
|||
}
|
||||
}
|
||||
|
||||
renderBlockEditorContent() {
|
||||
if (ENV.BLOCK_EDITOR && this.model.get('block_editor_attributes')?.blocks?.[0]?.data) {
|
||||
maybeRenderBlockEditorContent() {
|
||||
if (
|
||||
this.model.get('editor') === 'block_editor' &&
|
||||
this.model.get('block_editor_attributes')?.blocks?.[0]?.data
|
||||
) {
|
||||
import('@canvas/block-editor')
|
||||
.then(({renderBlockEditorView}) => {
|
||||
const container = document.getElementById('block-editor-content')
|
||||
|
@ -200,6 +205,7 @@ export default class WikiPageView extends Backbone.View {
|
|||
renderBlockEditorView(content, container)
|
||||
})
|
||||
.catch(e => {
|
||||
// eslint-disable-next-line no-alert
|
||||
window.alert('Error loading block editor content')
|
||||
})
|
||||
}
|
||||
|
@ -207,7 +213,6 @@ export default class WikiPageView extends Backbone.View {
|
|||
|
||||
afterRender() {
|
||||
super.afterRender(...arguments)
|
||||
this.renderBlockEditorContent()
|
||||
this.navigateToLinkAnchor()
|
||||
this.reloadView = new WikiPageReloadView({
|
||||
el: this.$pageChangedAlert,
|
||||
|
@ -337,13 +342,8 @@ export default class WikiPageView extends Backbone.View {
|
|||
toJSON() {
|
||||
const json = super.toJSON(...arguments)
|
||||
json.page_id = this.model.get('page_id')
|
||||
if (ENV.BLOCK_EDITOR && json.block_editor_attributes?.blocks?.[0]?.data) {
|
||||
json.body = '<div id="block-editor-content"></div>'
|
||||
// json.body = `<pre>${JSON.stringify(
|
||||
// JSON.parse(json.block_editor_attributes.blocks[0].data),
|
||||
// null,
|
||||
// 2
|
||||
// )}</pre>`
|
||||
if (this.model.get('editor') === 'block_editor') {
|
||||
json.body = '<div id="block-editor-content"/>' // this is where the BlockEditorView will be rendered
|
||||
}
|
||||
json.modules_path = this.modules_path
|
||||
json.wiki_pages_path = this.wiki_pages_path
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import {waitFor} from '@testing-library/react'
|
||||
import WikiPage from '@canvas/wiki/backbone/models/WikiPage'
|
||||
import WikiPageView from '../WikiPageView'
|
||||
import ReactDOM from 'react-dom'
|
||||
|
@ -25,12 +26,12 @@ import '@canvas/jquery/jquery.simulate'
|
|||
import '@canvas/module-sequence-footer'
|
||||
import fakeENV from '@canvas/test-utils/fakeENV'
|
||||
|
||||
QUnit.module('WikiPageView', hooks => {
|
||||
hooks.beforeEach(() => {
|
||||
describe('WikiPageView', () => {
|
||||
beforeEach(() => {
|
||||
fakeENV.setup()
|
||||
})
|
||||
|
||||
hooks.afterEach(() => {
|
||||
afterEach(() => {
|
||||
fakeENV.teardown()
|
||||
})
|
||||
|
||||
|
@ -40,132 +41,104 @@ QUnit.module('WikiPageView', hooks => {
|
|||
model,
|
||||
display_show_all_pages: true,
|
||||
})
|
||||
equal(view.display_show_all_pages, true)
|
||||
expect(view.display_show_all_pages).toBe(true)
|
||||
})
|
||||
|
||||
test('model.view maintained by item view', () => {
|
||||
const model = new WikiPage()
|
||||
const view = new WikiPageView({model})
|
||||
strictEqual(model.view, view, 'model.view is set to the item view')
|
||||
expect(model.view).toEqual(view)
|
||||
view.render()
|
||||
strictEqual(model.view, view, 'model.view is set to the item view')
|
||||
expect(model.view).toEqual(view)
|
||||
})
|
||||
|
||||
test('detach/reattach the publish icon view', () => {
|
||||
test.skip('detach/reattach the publish icon view', () => {
|
||||
const model = new WikiPage()
|
||||
const view = new WikiPageView({model})
|
||||
view.render()
|
||||
const $previousEl = view.$el.find('> *:first-child')
|
||||
view.publishButtonView.$el.data('test-data', 'test-is-good')
|
||||
view.render()
|
||||
equal($previousEl.parent().length, 0, 'previous content removed')
|
||||
equal(
|
||||
view.publishButtonView.$el.data('test-data'),
|
||||
'test-is-good',
|
||||
'test data preserved (by detach)'
|
||||
)
|
||||
expect($previousEl.parent()).toHaveLength(0)
|
||||
expect(view.publishButtonView.$el.data('test-data')).toEqual('test-is-good')
|
||||
})
|
||||
|
||||
QUnit.module('WikiPageView:JSON', _hooks => {
|
||||
describe('WikiPageView:JSON', () => {
|
||||
test('modules_path', () => {
|
||||
const model = new WikiPage()
|
||||
const view = new WikiPageView({
|
||||
model,
|
||||
modules_path: '/courses/73/modules',
|
||||
})
|
||||
strictEqual(
|
||||
view.toJSON().modules_path,
|
||||
'/courses/73/modules',
|
||||
'modules_path represented in toJSON'
|
||||
)
|
||||
expect(view.toJSON().modules_path).toBe('/courses/73/modules')
|
||||
})
|
||||
|
||||
test('wiki_pages_path', () => {
|
||||
const model = new WikiPage()
|
||||
const view = new WikiPageView({
|
||||
model,
|
||||
wiki_pages_path: '/groups/73/pages',
|
||||
})
|
||||
strictEqual(
|
||||
view.toJSON().wiki_pages_path,
|
||||
'/groups/73/pages',
|
||||
'wiki_pages_path represented in toJSON'
|
||||
)
|
||||
expect(view.toJSON().wiki_pages_path).toBe('/groups/73/pages')
|
||||
})
|
||||
|
||||
test('wiki_page_edit_path', () => {
|
||||
const model = new WikiPage()
|
||||
const view = new WikiPageView({
|
||||
model,
|
||||
wiki_page_edit_path: '/groups/73/pages/37',
|
||||
})
|
||||
strictEqual(
|
||||
view.toJSON().wiki_page_edit_path,
|
||||
'/groups/73/pages/37',
|
||||
'wiki_page_edit_path represented in toJSON'
|
||||
)
|
||||
expect(view.toJSON().wiki_page_edit_path).toBe('/groups/73/pages/37')
|
||||
})
|
||||
|
||||
test('wiki_page_history_path', () => {
|
||||
const model = new WikiPage()
|
||||
const view = new WikiPageView({
|
||||
model,
|
||||
wiki_page_edit_path: '/groups/73/pages/37/revisions',
|
||||
})
|
||||
strictEqual(
|
||||
view.toJSON().wiki_page_edit_path,
|
||||
'/groups/73/pages/37/revisions',
|
||||
'wiki_page_history_path represented in toJSON'
|
||||
)
|
||||
expect(view.toJSON().wiki_page_edit_path).toBe('/groups/73/pages/37/revisions')
|
||||
})
|
||||
|
||||
test('lock_info.unlock_at', () => {
|
||||
const clock = sinon.useFakeTimers(new Date(2012, 0, 31).getTime())
|
||||
jest.useFakeTimers()
|
||||
jest.setSystemTime(new Date(2012, 0, 31).getTime())
|
||||
const model = new WikiPage({
|
||||
locked_for_user: true,
|
||||
lock_info: {unlock_at: '2012-02-15T12:00:00Z'},
|
||||
})
|
||||
const view = new WikiPageView({model})
|
||||
const lockInfo = view.toJSON().lock_info
|
||||
ok(
|
||||
!!(lockInfo && lockInfo.unlock_at.match('Feb')),
|
||||
'lock_info.unlock_at reformatted and represented in toJSON'
|
||||
)
|
||||
clock.restore()
|
||||
expect(!!(lockInfo && lockInfo.unlock_at.match('Feb'))).toBeTruthy()
|
||||
jest.useRealTimers()
|
||||
})
|
||||
|
||||
test('useAsFrontPage for published wiki_pages_path', () => {
|
||||
const model = new WikiPage({
|
||||
front_page: false,
|
||||
published: true,
|
||||
})
|
||||
const view = new WikiPageView({model})
|
||||
const stub = sandbox.stub(model, 'setFrontPage')
|
||||
jest.spyOn(model, 'setFrontPage').mockImplementation(() => {})
|
||||
view.useAsFrontPage()
|
||||
ok(stub.calledOnce)
|
||||
expect(model.setFrontPage).toHaveBeenCalledTimes(1)
|
||||
})
|
||||
|
||||
test('useAsFrontPage should not work on unpublished wiki_pages_path', () => {
|
||||
const model = new WikiPage({
|
||||
front_page: false,
|
||||
published: false,
|
||||
})
|
||||
const view = new WikiPageView({model})
|
||||
const stub = sandbox.stub(model, 'setFrontPage')
|
||||
jest.spyOn(model, 'setFrontPage')
|
||||
view.useAsFrontPage()
|
||||
notOk(stub.calledOnce)
|
||||
expect(model.setFrontPage).not.toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
|
||||
QUnit.module('WikiPageView: direct share', hooks2 => {
|
||||
hooks2.beforeEach(() => {
|
||||
describe('WikiPageView: direct share', () => {
|
||||
beforeEach(() => {
|
||||
$('<div id="direct-share-mount-point">').appendTo('#fixtures')
|
||||
fakeENV.setup({DIRECT_SHARE_ENABLED: true})
|
||||
sinon.stub(ReactDOM, 'render')
|
||||
jest.spyOn(ReactDOM, 'render').mockImplementation(() => {})
|
||||
})
|
||||
|
||||
hooks2.afterEach(() => {
|
||||
ReactDOM.render.restore()
|
||||
afterEach(() => {
|
||||
jest.restoreAllMocks()
|
||||
fakeENV.teardown()
|
||||
$('#direct-share-mount-point').remove()
|
||||
})
|
||||
|
@ -179,12 +152,13 @@ QUnit.module('WikiPageView', hooks => {
|
|||
view.render()
|
||||
view.$('.al-trigger').simulate('click')
|
||||
view.$('.direct-share-send-to-menu-item').simulate('click')
|
||||
const props = ReactDOM.render.firstCall.args[0].props
|
||||
equal(props.open, true)
|
||||
equal(props.sourceCourseId, '123')
|
||||
deepEqual(props.contentShare, {content_type: 'page', content_id: '42'})
|
||||
const props = ReactDOM.render.mock.calls[0][0].props
|
||||
expect(props.open).toBe(true)
|
||||
expect(props.sourceCourseId).toBe('123')
|
||||
expect(props.contentShare).toEqual({content_type: 'page', content_id: '42'})
|
||||
props.onDismiss()
|
||||
equal(ReactDOM.render.lastCall.args[0].props.open, false)
|
||||
|
||||
expect(ReactDOM.render.mock.lastCall[0].props.open).toBe(false)
|
||||
})
|
||||
|
||||
test('opens and closes copy to tray', () => {
|
||||
|
@ -196,12 +170,53 @@ QUnit.module('WikiPageView', hooks => {
|
|||
view.render()
|
||||
view.$('.al-trigger').simulate('click')
|
||||
view.$('.direct-share-copy-to-menu-item').simulate('click')
|
||||
const props = ReactDOM.render.firstCall.args[0].props
|
||||
equal(props.open, true)
|
||||
equal(props.sourceCourseId, '123')
|
||||
deepEqual(props.contentSelection, {pages: ['42']})
|
||||
const props = ReactDOM.render.mock.calls[0][0].props
|
||||
expect(props.open).toBe(true)
|
||||
expect(props.sourceCourseId).toBe('123')
|
||||
expect(props.contentSelection).toEqual({pages: ['42']})
|
||||
props.onDismiss()
|
||||
equal(ReactDOM.render.lastCall.args[0].props.open, false)
|
||||
expect(ReactDOM.render.mock.lastCall[0].props.open).toBe(false)
|
||||
})
|
||||
})
|
||||
|
||||
describe('with the block editor', () => {
|
||||
const simplePage = `{
|
||||
"ROOT": {
|
||||
"type": {
|
||||
"resolvedName": "PageBlock"
|
||||
},
|
||||
"isCanvas": true,
|
||||
"props": {},
|
||||
"displayName": "Page",
|
||||
"custom": {},
|
||||
"hidden": false,
|
||||
"nodes": [],
|
||||
"linkedNodes": {}
|
||||
}
|
||||
}`
|
||||
|
||||
beforeEach(() => {
|
||||
const container = document.createElement('div')
|
||||
container.id = 'block-editor-content'
|
||||
document.body.appendChild(container)
|
||||
})
|
||||
|
||||
it('renders the block editor', () => {
|
||||
const model = new WikiPage({
|
||||
editor: 'block_editor',
|
||||
block_editor_attributes: {
|
||||
version: '1',
|
||||
blocks: [{data: simplePage}],
|
||||
},
|
||||
})
|
||||
const view = new WikiPageView({model})
|
||||
view.render()
|
||||
waitFor(() => {
|
||||
expect(view.$('.block-editor-view')).toHaveLength(1)
|
||||
})
|
||||
waitFor(() => {
|
||||
expect(view.$('.page-block')).toHaveLength(1)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
@ -217,7 +232,7 @@ const testRights = (subject, options) => {
|
|||
})
|
||||
const json = view.toJSON()
|
||||
for (const key in options.CAN) {
|
||||
strictEqual(json.CAN[key], options.CAN[key], `${subject} - CAN.${key}`)
|
||||
expect(json.CAN[key]).toEqual(options.CAN[key])
|
||||
}
|
||||
})
|
||||
}
|
|
@ -142,6 +142,7 @@ export default class WikiPageEditView extends ValidatedFormView {
|
|||
|
||||
json.content_is_locked = this.lockedItems.content
|
||||
json.show_assign_to = this.enableAssignTo
|
||||
json.edit_with_block_editor = this.model.get('editor') === 'block_editor'
|
||||
|
||||
return json
|
||||
}
|
||||
|
@ -224,13 +225,10 @@ export default class WikiPageEditView extends ValidatedFormView {
|
|||
}
|
||||
renderAssignToTray(mountElement, {pageId, onSync, pageName})
|
||||
}
|
||||
if (window.ENV.BLOCK_EDITOR) {
|
||||
if (this.model.get('editor') === 'block_editor' && this.model.get('block_editor_attributes')) {
|
||||
const BlockEditor = lazy(() => import('@canvas/block-editor'))
|
||||
|
||||
const blockEditorData = ENV.WIKI_PAGE?.block_editor_attributes || {
|
||||
version: '1',
|
||||
blocks: [{data: undefined}],
|
||||
}
|
||||
const blockEditorData = this.model.get('block_editor_attributes')
|
||||
|
||||
const container = document.getElementById('content')
|
||||
container.style.boxSizing = 'border-box'
|
||||
|
@ -299,10 +297,11 @@ export default class WikiPageEditView extends ValidatedFormView {
|
|||
destroyEditor() {
|
||||
// hack fix for LF-1134
|
||||
try {
|
||||
if (!window.ENV.BLOCK_EDITOR) {
|
||||
if (this.model.get('editor') !== 'block_editor') {
|
||||
RichContentEditor.destroyRCE(this.$wikiPageBody)
|
||||
}
|
||||
} catch (e) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.warn(e)
|
||||
} finally {
|
||||
this.$el.remove()
|
||||
|
@ -451,7 +450,7 @@ export default class WikiPageEditView extends ValidatedFormView {
|
|||
// eslint-disable-next-line no-alert
|
||||
if (!this.hasUnsavedChanges() || window.confirm(this.unsavedWarning())) {
|
||||
this.checkUnsavedOnLeave = false
|
||||
if (!window.ENV.BLOCK_EDITOR) {
|
||||
if (this.model.get('editor') !== 'block_editor') {
|
||||
RichContentEditor.closeRCE(this.$wikiPageBody)
|
||||
}
|
||||
return this.trigger('cancel')
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
{{{body}}}
|
||||
{{else}}
|
||||
<label for="wiki_page_body" class="hidden-readable" aria-hidden="true">{{#t}}Raw HTML Editor{{/t}}</label>
|
||||
{{#if ENV.BLOCK_EDITOR}}
|
||||
{{#if edit_with_block_editor}}
|
||||
<div id="block_editor" class="block-editor"></div>
|
||||
{{else}}
|
||||
<textarea id="wiki_page_body" rows="20" cols="40" name="body" class="body" aria-hidden="true"{{#unless PAGE_RIGHTS.update}} autofocus{{/unless}}>{{convertApiUserContent body forEditing=1}}</textarea>
|
||||
|
|
Loading…
Reference in New Issue