Scaffold LTI Extensions page
This commit adds a scaffolded FE for the LTI extensions page in Canvas test plan: Go to Admin -> Extensions and click between Manage/Discover to make sure the routing works and reload pages to make sure the nested urls work. Turn the lti_registrations_discover_page feature flag off to make sure the page the discover page is not accessible, and then turn the lti_registrations_page off to make sure the whole extensions view is not accessible. fixes: INTEROP-8515 flag=lti_registrations_page Change-Id: I7d34b387d03a4bce66325a4791645c6502784b12 Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/341783 Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com> Reviewed-by: Steve Mcgee <steve.mcgee@instructure.com> QA-Review: Steve Mcgee <steve.mcgee@instructure.com> Product-Review: Paul Gray <paul.gray@instructure.com>
This commit is contained in:
parent
69b2162d67
commit
ef232ca5a9
|
@ -387,6 +387,7 @@ class ApplicationController < ActionController::Base
|
||||||
react_discussions_post
|
react_discussions_post
|
||||||
instui_nav
|
instui_nav
|
||||||
enhanced_developer_keys_tables
|
enhanced_developer_keys_tables
|
||||||
|
lti_registrations_discover_page
|
||||||
].freeze
|
].freeze
|
||||||
JS_ENV_BRAND_ACCOUNT_FEATURES = [
|
JS_ENV_BRAND_ACCOUNT_FEATURES = [
|
||||||
:embedded_release_notes
|
:embedded_release_notes
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
#
|
||||||
|
# Copyright (C) 2012 - 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/>.
|
||||||
|
#
|
||||||
|
|
||||||
|
class LtiRegistrationsController < ApplicationController
|
||||||
|
def index
|
||||||
|
require_account_context
|
||||||
|
|
||||||
|
if @context.feature_enabled?(:lti_registrations_page)
|
||||||
|
set_active_tab "extensions"
|
||||||
|
add_crumb t("#crumbs.apps", "Extensions")
|
||||||
|
|
||||||
|
render :index
|
||||||
|
else
|
||||||
|
render "shared/errors/404_message", status: :not_found, formats: [:html]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -1893,6 +1893,7 @@ class Account < ActiveRecord::Base
|
||||||
TAB_JOBS = 15
|
TAB_JOBS = 15
|
||||||
TAB_DEVELOPER_KEYS = 16
|
TAB_DEVELOPER_KEYS = 16
|
||||||
TAB_RELEASE_NOTES = 17
|
TAB_RELEASE_NOTES = 17
|
||||||
|
TAB_EXTENSIONS = 18
|
||||||
|
|
||||||
def external_tool_tabs(opts, user)
|
def external_tool_tabs(opts, user)
|
||||||
tools = Lti::ContextToolFinder
|
tools = Lti::ContextToolFinder
|
||||||
|
@ -1956,6 +1957,11 @@ class Account < ActiveRecord::Base
|
||||||
tabs << { id: TAB_DEVELOPER_KEYS, label: t("#account.tab_developer_keys", "Developer Keys"), css_class: "developer_keys", href: :account_developer_keys_path, account_id: root_account.id }
|
tabs << { id: TAB_DEVELOPER_KEYS, label: t("#account.tab_developer_keys", "Developer Keys"), css_class: "developer_keys", href: :account_developer_keys_path, account_id: root_account.id }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if root_account? && grants_right?(user, :manage_developer_keys) && root_account.feature_enabled?(:lti_registrations_page)
|
||||||
|
registrations_path = root_account.feature_enabled?(:lti_registrations_discover_page) ? :account_lti_registrations_path : :account_lti_manage_registrations_path
|
||||||
|
tabs << { id: TAB_EXTENSIONS, label: t("#account.tab_extensions", "Extensions"), css_class: "extensions", href: registrations_path, account_id: root_account.id }
|
||||||
|
end
|
||||||
|
|
||||||
tabs += external_tool_tabs(opts, user)
|
tabs += external_tool_tabs(opts, user)
|
||||||
tabs += Lti::MessageHandler.lti_apps_tabs(self, [Lti::ResourcePlacement::ACCOUNT_NAVIGATION], opts)
|
tabs += Lti::MessageHandler.lti_apps_tabs(self, [Lti::ResourcePlacement::ACCOUNT_NAVIGATION], opts)
|
||||||
Lti::ResourcePlacement.update_tabs_and_return_item_banks_tab(tabs)
|
Lti::ResourcePlacement.update_tabs_and_return_item_banks_tab(tabs)
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
<%
|
||||||
|
# Copyright (C) 2012 - 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/>.
|
||||||
|
%>
|
||||||
|
|
||||||
|
<%
|
||||||
|
@show_left_side = true
|
||||||
|
%>
|
||||||
|
|
||||||
|
<% provide :page_title do %><%= t :title, "Extensions" %><% end %>
|
||||||
|
|
||||||
|
<% js_bundle :lti_registrations %>
|
||||||
|
|
||||||
|
<div id="reactContent"></div>
|
|
@ -261,3 +261,22 @@ lti_placement_restrictions:
|
||||||
state: allowed_on
|
state: allowed_on
|
||||||
ci:
|
ci:
|
||||||
state: allowed_on
|
state: allowed_on
|
||||||
|
lti_registrations_page:
|
||||||
|
state: hidden
|
||||||
|
applies_to: RootAccount
|
||||||
|
display_name: LTI Extensions Page
|
||||||
|
description: |-
|
||||||
|
When enabled, the LTI Extensions page will be available in the Account navigation.
|
||||||
|
environments:
|
||||||
|
development:
|
||||||
|
state: hidden
|
||||||
|
lti_registrations_discover_page:
|
||||||
|
state: hidden
|
||||||
|
applies_to: RootAccount
|
||||||
|
display_name: LTI Extensions Discover Page
|
||||||
|
description: |-
|
||||||
|
When enabled, the LTI Extensions Discover page will be available in the Extensions view.
|
||||||
|
environments:
|
||||||
|
development:
|
||||||
|
state: hidden
|
||||||
|
custom_transition_proc: lti_registrations_discover_page_hook
|
||||||
|
|
|
@ -786,6 +786,10 @@ CanvasRails::Application.routes.draw do
|
||||||
resources :developer_keys, only: :index
|
resources :developer_keys, only: :index
|
||||||
get "/developer_keys/:key_id", controller: :developer_keys, action: :index, as: "account_developer_key_view"
|
get "/developer_keys/:key_id", controller: :developer_keys, action: :index, as: "account_developer_key_view"
|
||||||
|
|
||||||
|
get "extensions", controller: :lti_registrations, action: :index, as: "lti_registrations"
|
||||||
|
get "extensions/*path", controller: :lti_registrations, action: :index
|
||||||
|
get "extensions/manage", controller: :lti_registrations, action: :index, as: "lti_manage_registrations"
|
||||||
|
|
||||||
get "release_notes" => "release_notes#manage", :as => :release_notes_manage
|
get "release_notes" => "release_notes#manage", :as => :release_notes_manage
|
||||||
|
|
||||||
get "blackout_dates" => "blackout_dates#index"
|
get "blackout_dates" => "blackout_dates#index"
|
||||||
|
|
|
@ -143,5 +143,12 @@ module FeatureFlags
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def self.lti_registrations_discover_page_hook(_user, context, _from_state, transitions)
|
||||||
|
unless context.feature_enabled?(:lti_registrations_page)
|
||||||
|
transitions["on"] ||= {}
|
||||||
|
transitions["on"]["message"] = I18n.t("The LTI Extensions Discover page won't be accessible unless the LTI Registrations page is enabled")
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -84,6 +84,7 @@ const featureBundles: {
|
||||||
dashboard: () => import('./features/dashboard/index'),
|
dashboard: () => import('./features/dashboard/index'),
|
||||||
deep_linking_response: () => import('./features/deep_linking_response/index'),
|
deep_linking_response: () => import('./features/deep_linking_response/index'),
|
||||||
developer_keys_v2: () => import('./features/developer_keys_v2/index'),
|
developer_keys_v2: () => import('./features/developer_keys_v2/index'),
|
||||||
|
lti_registrations: () => import('./features/lti_registrations/index'),
|
||||||
discussion_topic_edit_v2: () => import('./features/discussion_topic_edit_v2/index'),
|
discussion_topic_edit_v2: () => import('./features/discussion_topic_edit_v2/index'),
|
||||||
discussion_topic_edit: () => import('./features/discussion_topic_edit/index'),
|
discussion_topic_edit: () => import('./features/discussion_topic_edit/index'),
|
||||||
discussion_topic: () => import('./features/discussion_topic/index'),
|
discussion_topic: () => import('./features/discussion_topic/index'),
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
/*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
export const Discover = () => {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<h1>This is the Discover page</h1>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
/*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from 'react'
|
||||||
|
import type {RouteObject} from 'react-router-dom'
|
||||||
|
import {Discover} from './Discover'
|
||||||
|
|
||||||
|
export const DiscoverRoute: RouteObject = {
|
||||||
|
path: '/',
|
||||||
|
element: <Discover />,
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
/*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from 'react'
|
||||||
|
import ReactDOM from 'react-dom'
|
||||||
|
import {createBrowserRouter, RouterProvider, Link} from 'react-router-dom'
|
||||||
|
import {Discover} from './discover/Discover'
|
||||||
|
import {Manage} from './manage/Manage'
|
||||||
|
import {LtiAppsLayout} from './layout/LtiAppsLayout'
|
||||||
|
import {DiscoverRoute} from './discover'
|
||||||
|
import {ManageRoute} from './manage'
|
||||||
|
|
||||||
|
const getBasename = () => {
|
||||||
|
const path = window.location.pathname
|
||||||
|
const parts = path.split('/')
|
||||||
|
return parts.slice(0, parts.indexOf('extensions') + 1).join('/')
|
||||||
|
}
|
||||||
|
|
||||||
|
// window.ENV.lti_registrations_discover_page
|
||||||
|
|
||||||
|
const router = createBrowserRouter(
|
||||||
|
[
|
||||||
|
{
|
||||||
|
path: '/',
|
||||||
|
element: <LtiAppsLayout />,
|
||||||
|
children: window.ENV.FEATURES.lti_registrations_discover_page
|
||||||
|
? [DiscoverRoute, ManageRoute]
|
||||||
|
: [ManageRoute],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
{
|
||||||
|
basename: getBasename(),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
ReactDOM.render(<RouterProvider router={router} />, document.getElementById('reactContent'))
|
|
@ -0,0 +1,71 @@
|
||||||
|
/*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from 'react'
|
||||||
|
import ReactDOM from 'react-dom'
|
||||||
|
import {createBrowserRouter, RouterProvider, Link, Outlet, useMatch} from 'react-router-dom'
|
||||||
|
import {useScope as useI18nScope} from '@canvas/i18n'
|
||||||
|
import {Heading} from '@instructure/ui-heading'
|
||||||
|
import {Spinner} from '@instructure/ui-spinner'
|
||||||
|
import {Tabs} from '@instructure/ui-tabs'
|
||||||
|
import {View} from '@instructure/ui-view'
|
||||||
|
import {Text} from '@instructure/ui-text'
|
||||||
|
|
||||||
|
const I18n = useI18nScope('lti_registrations')
|
||||||
|
|
||||||
|
export const LtiAppsLayout = () => {
|
||||||
|
const isManage = useMatch('/manage/*')
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<View as="div" margin="0 0 small 0" padding="none">
|
||||||
|
<Heading level="h1">{I18n.t('Extensions')}</Heading>
|
||||||
|
</View>
|
||||||
|
<Text size="large">{I18n.t('Discover Something new or manage existing LTI extensions')}</Text>
|
||||||
|
<Tabs margin="medium auto" padding="medium" onRequestTabChange={() => {}}>
|
||||||
|
{window.ENV.FEATURES.lti_registrations_discover_page && (
|
||||||
|
<Tabs.Panel
|
||||||
|
isSelected={!isManage}
|
||||||
|
id="tabB"
|
||||||
|
href="/"
|
||||||
|
renderTitle={
|
||||||
|
<Link style={{color: 'initial', textDecoration: 'initial'}} to="/">
|
||||||
|
{I18n.t('Discover')}
|
||||||
|
</Link>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Outlet />
|
||||||
|
</Tabs.Panel>
|
||||||
|
)}
|
||||||
|
<Tabs.Panel
|
||||||
|
renderTitle={
|
||||||
|
<Link style={{color: 'initial', textDecoration: 'initial'}} to="/manage">
|
||||||
|
{I18n.t('Manage')}
|
||||||
|
</Link>
|
||||||
|
}
|
||||||
|
id="tabA"
|
||||||
|
padding="large"
|
||||||
|
isSelected={!!isManage}
|
||||||
|
active={true}
|
||||||
|
>
|
||||||
|
<Outlet />
|
||||||
|
</Tabs.Panel>
|
||||||
|
</Tabs>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
/*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from 'react'
|
||||||
|
import {Outlet} from 'react-router-dom'
|
||||||
|
|
||||||
|
export const Manage = () => {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<h1>This is the Manage page</h1>
|
||||||
|
<Outlet />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from 'react'
|
||||||
|
import type {RouteObject} from 'react-router-dom'
|
||||||
|
import {Manage} from './Manage'
|
||||||
|
|
||||||
|
export const ManageRoute: RouteObject = {
|
||||||
|
path: 'manage',
|
||||||
|
element: <Manage />,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: 'foo',
|
||||||
|
element: <div>Foo</div>,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'bar',
|
||||||
|
element: <div>Bar</div>,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"name": "@canvas-features/lti_registrations",
|
||||||
|
"private": true,
|
||||||
|
"version": "1.0.0",
|
||||||
|
"owner": "INTEROP"
|
||||||
|
}
|
|
@ -216,6 +216,7 @@ export type SiteAdminFeatureId =
|
||||||
| 'platform_service_speedgrader'
|
| 'platform_service_speedgrader'
|
||||||
| 'render_both_to_do_lists'
|
| 'render_both_to_do_lists'
|
||||||
| 'instui_header'
|
| 'instui_header'
|
||||||
|
| 'lti_registrations_discover_page'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* From ApplicationController#JS_ENV_ROOT_ACCOUNT_FEATURES
|
* From ApplicationController#JS_ENV_ROOT_ACCOUNT_FEATURES
|
||||||
|
|
Loading…
Reference in New Issue