canvas-lms/lib/outcomes/learning_outcome_group_chil...

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

244 lines
9.8 KiB
Ruby
Raw Normal View History

# frozen_string_literal: true
#
# Copyright (C) 2021 - 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/>.
#
module Outcomes
Add cache to Outcomes::LearningOutcomeGroupChildren Updates Outcomes::LearningOutcomeGroupChildren by adding cache at the queries for getting the total subgroups and outcomes. closes OUT-4148 flag=improved_outcomes_management Test plan: - Create nested learning outcome groups - For each nested learning outcome group create learning outcomes > With FF improved_outcomes_management: OFF - On Rails console: calls to Outcomes::LearningOutcomeGroupChildren methods should return a default value - On web: when generating actions over ContentTag, LearningOutcome and LearningOutcomeGroup it should not lead to clear any cache > With FF improved_outcomes_management: ON - On Rails console: call Outcomes::LearningOutcomeGroupChildren methods for getting total subgroups and outcomes, queries to the DB should be made (it will need the root context) - Call again the same methods, it should return the values from cache - Create a new instance of the class and call the same methods, it should return the values from cache - Clear the cache with `Rails.cache.clear` - On web (or through GraphiQL) get the total subgroups and total outcomes multiple times; it should cache the data and should not run additional queries - On web: clear the cache by executing the following actions: - Add a Learning Outcome Group - Adopt a Learning Outcome Group - Copy a Learning Outcome Group from global - Remove a Learning Outcome Group - Add an Outcome - Remove an Outcome - Get the total subgroups and total outcomes, it should run new queries - Run the same tests for global context, it should generate and clear the cache in the same way Change-Id: I9b0bfc68b84b3e36869d69a926ef84d9989ea96d Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/257257 Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com> Reviewed-by: Augusto Callejas <acallejas@instructure.com> QA-Review: Chrystal Langston <chrystal.langston@instructure.com> Product-Review: Michael Brewer-Davis <mbd@instructure.com>
2021-01-23 09:03:53 +08:00
class LearningOutcomeGroupChildren
include OutcomesFeaturesHelper
attr_reader :context
SHORT_DESCRIPTION = "coalesce(learning_outcomes.short_description, '')"
# E'<[^>]+>' -> removes html tags
# E'&\\w+;' -> removes html entities
DESCRIPTION = "regexp_replace(regexp_replace(coalesce(learning_outcomes.description, ''), E'<[^>]+>', '', 'gi'), E'&\\w+;', ' ', 'gi')"
MAP_CANVAS_POSTGRES_LOCALES = {
"ar" => "arabic", # العربية
"ca" => "spanish", # Català
"da" => "danish", # Dansk
"da-x-k12" => "danish", # Dansk GR/GY
"de" => "german", # Deutsch
"en-AU" => "english", # English (Australia)
"en-CA" => "english", # English (Canada)
"en-GB" => "english", # English (United Kingdom)
"en" => "english", # English (US)
"es" => "spanish", # Español
"fr" => "french", # Français
"fr-CA" => "french", # Français (Canada)
"it" => "italian", # Italiano
"hu" => "hungarian", # Magyar
"nl" => "dutch", # Nederlands
"nb" => "norwegian", # Norsk (Bokmål)
"nb-x-k12" => "norwegian", # Norsk (Bokmål) GS/VGS
"pt" => "portuguese", # Português
"pt-BR" => "portuguese", # Português do Brasil
"ru" => "russian", # pу́сский
"fi" => "finnish", # Suomi
"sv" => "swedish", # Svenska
"sv-x-k12" => "swedish", # Svenska GR/GY
"tr" => "turkish" # Türkçe
}.freeze
def initialize(context = nil)
@context = context
end
def total_outcomes(learning_outcome_group_id, args = {})
if args == {} && improved_outcomes_management?
cache_key = total_outcomes_cache_key(learning_outcome_group_id)
Rails.cache.fetch(cache_key) do
total_outcomes_for(learning_outcome_group_id, args)
end
else
total_outcomes_for(learning_outcome_group_id, args)
Add cache to Outcomes::LearningOutcomeGroupChildren Updates Outcomes::LearningOutcomeGroupChildren by adding cache at the queries for getting the total subgroups and outcomes. closes OUT-4148 flag=improved_outcomes_management Test plan: - Create nested learning outcome groups - For each nested learning outcome group create learning outcomes > With FF improved_outcomes_management: OFF - On Rails console: calls to Outcomes::LearningOutcomeGroupChildren methods should return a default value - On web: when generating actions over ContentTag, LearningOutcome and LearningOutcomeGroup it should not lead to clear any cache > With FF improved_outcomes_management: ON - On Rails console: call Outcomes::LearningOutcomeGroupChildren methods for getting total subgroups and outcomes, queries to the DB should be made (it will need the root context) - Call again the same methods, it should return the values from cache - Create a new instance of the class and call the same methods, it should return the values from cache - Clear the cache with `Rails.cache.clear` - On web (or through GraphiQL) get the total subgroups and total outcomes multiple times; it should cache the data and should not run additional queries - On web: clear the cache by executing the following actions: - Add a Learning Outcome Group - Adopt a Learning Outcome Group - Copy a Learning Outcome Group from global - Remove a Learning Outcome Group - Add an Outcome - Remove an Outcome - Get the total subgroups and total outcomes, it should run new queries - Run the same tests for global context, it should generate and clear the cache in the same way Change-Id: I9b0bfc68b84b3e36869d69a926ef84d9989ea96d Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/257257 Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com> Reviewed-by: Augusto Callejas <acallejas@instructure.com> QA-Review: Chrystal Langston <chrystal.langston@instructure.com> Product-Review: Michael Brewer-Davis <mbd@instructure.com>
2021-01-23 09:03:53 +08:00
end
end
Add notImportedOutcomesCount field to LearningOutcomeGroup type closes OUT-4743 flag=improved_outcomes_management Test plan: - Import Academic Benchmarks - Go to Account > Settings > Feature Options and enable Improved Outcomes Management FF - Go to Account > Outcomes and open developer tools -> network - Select via TreeBrowser the root outcome group and use network tab to find the id of that group from the graphql response - Click on Find button select State Standards in the Find Modal; then find the id of that group using network tab - Open a new browser tab, go to canvas.docker/graphiql and paste the query below in the GraphiQL window: query GroupDetailWithSearchQuery($id: ID!, $targetGroupId: Int) { group: legacyNode(type: LearningOutcomeGroup, _id: $id) { ... on LearningOutcomeGroup { _id title contextType contextId outcomesCount notImportedOutcomesCount(targetGroupId: $targetGroupId) outcomes(first: 10) { edges { _id node { ... on LearningOutcome { _id description title } } } } } } } - In the query variables window paste the snippet below { "id": X, "targetGroupId": Y } - Replace X with the id of the State Standards group, Y with the id of the imported group and execute the query - Verify that there are no errors in the response - Verify that notImportedOutcomesCount is equal to the number of outcomes in State Standards - Import 10 outcomes from State Standards to the account - In the Manage View select the group where outcomes are imported and find its id from the network tab - Verify that notImportedOutcomesCount is equal to the number of State Standards minus 10 - Go to Course > Outcomes, and repeat the above tests importing from Account Standrds and verify that results are the same Change-Id: I20652b5ece5350c2df884c98defc11d8d092b8b0 Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/272768 Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com> Reviewed-by: Marcus Pompeu <marcus.pompeu@instructure.com> Reviewed-by: Chrystal Langston <chrystal.langston@instructure.com> Reviewed-by: Manoel Quirino <manoel.quirino@instructure.com> QA-Review: Chrystal Langston <chrystal.langston@instructure.com> Product-Review: Ben Friedman <ben.friedman@instructure.com>
2021-09-28 03:44:44 +08:00
def not_imported_outcomes(learning_outcome_group_id, args = {})
if group_exists?(args[:target_group_id])
target_group = LearningOutcomeGroup.find_by(id: args[:target_group_id])
source_group_outcome_ids = outcome_links(learning_outcome_group_id).distinct.pluck(:content_id)
target_group_outcome_ids = outcome_links(target_group.id).distinct.pluck(:content_id)
(source_group_outcome_ids - (source_group_outcome_ids & target_group_outcome_ids)).size
end
end
def suboutcomes_by_group_id(learning_outcome_group_id, args = {})
relation = outcome_links(learning_outcome_group_id)
relation = filter_outcomes(relation, args[:filter]) unless args[:filter].nil? || !outcome_alignment_summary_enabled?(@context)
relation = relation.joins(:learning_outcome_content)
.joins("INNER JOIN #{LearningOutcomeGroup.quoted_table_name} AS logs
ON logs.id = content_tags.associated_asset_id")
if args[:search_query]
relation = add_search_query(relation, args[:search_query])
add_search_order(relation, args[:search_query])
else
relation.order(
LearningOutcomeGroup.best_unicode_collation_key("logs.title"),
LearningOutcome.best_unicode_collation_key("short_description")
)
end
Fetch suboutcomes within a learning outcome group via graphql Add ability to fetch all sub-outcomes of a learning outcome group Ordered by parent group title then outcome short description. The Results should be paginated to accommodate for infinite scroll. closes OUT-4130 flag=improved_outcomes_management test plan - PreReq: Account/Course with outcomes and groups - Log into Canvas and navigate to graphiql - Run the below query - outcomes should be populated with all outcomes and suboutcomes For the root outcome group order by group title, outcome short description - Run the below query query GroupDetailQuery($id: ID!, $outcomesCursor: String) { group: legacyNode(type: LearningOutcomeGroup, _id: $id) { ... on LearningOutcomeGroup { _id description title outcomesCount outcomes(first: 10, after: $outcomesCursor) { pageInfo { hasNextPage startCursor endCursor } nodes { ... on LearningOutcome { _id description title } } } } } } { "id": 1, "outcomesCursor": "" } - All outcomes should be returned ordered by parent group name, then outcome name - Change the name of an outcome and/or group to force it to change the order. - Run the query again, and you should see the updated outcome or Parent group’s outcomes first before the remain outcomes Change-Id: Icdad82c0b57ca625924d9b0af7d7b3304b88c251 Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/257653 Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com> Product-Review: Michael Brewer-Davis <mbd@instructure.com> Reviewed-by: Pat Renner <prenner@instructure.com> Reviewed-by: Michael Brewer-Davis <mbd@instructure.com> QA-Review: Pat Renner <prenner@instructure.com>
2021-01-29 00:31:25 +08:00
end
Add cache to Outcomes::LearningOutcomeGroupChildren Updates Outcomes::LearningOutcomeGroupChildren by adding cache at the queries for getting the total subgroups and outcomes. closes OUT-4148 flag=improved_outcomes_management Test plan: - Create nested learning outcome groups - For each nested learning outcome group create learning outcomes > With FF improved_outcomes_management: OFF - On Rails console: calls to Outcomes::LearningOutcomeGroupChildren methods should return a default value - On web: when generating actions over ContentTag, LearningOutcome and LearningOutcomeGroup it should not lead to clear any cache > With FF improved_outcomes_management: ON - On Rails console: call Outcomes::LearningOutcomeGroupChildren methods for getting total subgroups and outcomes, queries to the DB should be made (it will need the root context) - Call again the same methods, it should return the values from cache - Create a new instance of the class and call the same methods, it should return the values from cache - Clear the cache with `Rails.cache.clear` - On web (or through GraphiQL) get the total subgroups and total outcomes multiple times; it should cache the data and should not run additional queries - On web: clear the cache by executing the following actions: - Add a Learning Outcome Group - Adopt a Learning Outcome Group - Copy a Learning Outcome Group from global - Remove a Learning Outcome Group - Add an Outcome - Remove an Outcome - Get the total subgroups and total outcomes, it should run new queries - Run the same tests for global context, it should generate and clear the cache in the same way Change-Id: I9b0bfc68b84b3e36869d69a926ef84d9989ea96d Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/257257 Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com> Reviewed-by: Augusto Callejas <acallejas@instructure.com> QA-Review: Chrystal Langston <chrystal.langston@instructure.com> Product-Review: Michael Brewer-Davis <mbd@instructure.com>
2021-01-23 09:03:53 +08:00
def clear_total_outcomes_cache
Rails.cache.delete(context_timestamp_cache_key) if improved_outcomes_management?
end
def self.supported_languages
# cache this in the class since this won't change so much
@supported_languages ||= ContentTag.connection.execute(
"SELECT cfgname FROM pg_ts_config"
).to_a.map { |r| r["cfgname"] }
end
private
Add notImportedOutcomesCount field to LearningOutcomeGroup type closes OUT-4743 flag=improved_outcomes_management Test plan: - Import Academic Benchmarks - Go to Account > Settings > Feature Options and enable Improved Outcomes Management FF - Go to Account > Outcomes and open developer tools -> network - Select via TreeBrowser the root outcome group and use network tab to find the id of that group from the graphql response - Click on Find button select State Standards in the Find Modal; then find the id of that group using network tab - Open a new browser tab, go to canvas.docker/graphiql and paste the query below in the GraphiQL window: query GroupDetailWithSearchQuery($id: ID!, $targetGroupId: Int) { group: legacyNode(type: LearningOutcomeGroup, _id: $id) { ... on LearningOutcomeGroup { _id title contextType contextId outcomesCount notImportedOutcomesCount(targetGroupId: $targetGroupId) outcomes(first: 10) { edges { _id node { ... on LearningOutcome { _id description title } } } } } } } - In the query variables window paste the snippet below { "id": X, "targetGroupId": Y } - Replace X with the id of the State Standards group, Y with the id of the imported group and execute the query - Verify that there are no errors in the response - Verify that notImportedOutcomesCount is equal to the number of outcomes in State Standards - Import 10 outcomes from State Standards to the account - In the Manage View select the group where outcomes are imported and find its id from the network tab - Verify that notImportedOutcomesCount is equal to the number of State Standards minus 10 - Go to Course > Outcomes, and repeat the above tests importing from Account Standrds and verify that results are the same Change-Id: I20652b5ece5350c2df884c98defc11d8d092b8b0 Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/272768 Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com> Reviewed-by: Marcus Pompeu <marcus.pompeu@instructure.com> Reviewed-by: Chrystal Langston <chrystal.langston@instructure.com> Reviewed-by: Manoel Quirino <manoel.quirino@instructure.com> QA-Review: Chrystal Langston <chrystal.langston@instructure.com> Product-Review: Ben Friedman <ben.friedman@instructure.com>
2021-09-28 03:44:44 +08:00
def outcome_links(learning_outcome_group_id)
group_ids = children_ids_with_self(learning_outcome_group_id)
Remove deleted outcomes linked to active ContentTags in IOM closes OUT-5175 flag=improved_outcomes_management Test plan: - Enable Improved Outcomes Management FF - Import from Academic Benchmarks state standards with large number of outcomes (> 10,000): "California State Board of Education", guid: "68B555A8-ACA0-11E9-8BB2-0A11CDE56ADE" and "New York State Education Department", guid: "9127D390-F1B9- 11E5-862E-0938DC287387" - Go to Account > Outcomes and create an outcome - Open rails console, find the created outcome, set its workflow_state to 'deleted' and clear Rails cache: o=LearningOutcome.last o.workflow_state = 'deleted' o.save! Rails.cache.clear - Refresh the Account > Outcomes page - Verify that the outcome is no longer displayed in Manage View and the outcome count for the outcome's parent group is correct - Open devtools -> network - Click on Find button to open Find Modal - Select "California State Board of Education" via TreeBrowser; in devtools select the second graphql query and click Timing tab - Wait for the query to finish and verify that its Waiting (TTFB) time is less than 3-4 sec - Repeat for the New York State standards Change-Id: I9b3c3d2de153b69ef12bcef38e8bc3a0f8f36b03 Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/295796 Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com> Product-Review: Kyle Rosenbaum <krosenbaum@instructure.com> Reviewed-by: Dave Wenzlick <david.wenzlick@instructure.com> Reviewed-by: Chrystal Langston <chrystal.langston@instructure.com> QA-Review: Chrystal Langston <chrystal.langston@instructure.com>
2022-07-09 00:39:14 +08:00
relation = ContentTag.active.learning_outcome_links.where(associated_asset_id: group_ids)
# Exclude tags for which the aligned outcome is deleted
valid_outcome_ids = relation
.select("content_tags.content_id")
.joins("LEFT OUTER JOIN #{LearningOutcome.quoted_table_name} AS outcomes ON content_tags.content_id = outcomes.id")
.where("outcomes.workflow_state<>'deleted'")
relation.where(content_id: valid_outcome_ids)
Add notImportedOutcomesCount field to LearningOutcomeGroup type closes OUT-4743 flag=improved_outcomes_management Test plan: - Import Academic Benchmarks - Go to Account > Settings > Feature Options and enable Improved Outcomes Management FF - Go to Account > Outcomes and open developer tools -> network - Select via TreeBrowser the root outcome group and use network tab to find the id of that group from the graphql response - Click on Find button select State Standards in the Find Modal; then find the id of that group using network tab - Open a new browser tab, go to canvas.docker/graphiql and paste the query below in the GraphiQL window: query GroupDetailWithSearchQuery($id: ID!, $targetGroupId: Int) { group: legacyNode(type: LearningOutcomeGroup, _id: $id) { ... on LearningOutcomeGroup { _id title contextType contextId outcomesCount notImportedOutcomesCount(targetGroupId: $targetGroupId) outcomes(first: 10) { edges { _id node { ... on LearningOutcome { _id description title } } } } } } } - In the query variables window paste the snippet below { "id": X, "targetGroupId": Y } - Replace X with the id of the State Standards group, Y with the id of the imported group and execute the query - Verify that there are no errors in the response - Verify that notImportedOutcomesCount is equal to the number of outcomes in State Standards - Import 10 outcomes from State Standards to the account - In the Manage View select the group where outcomes are imported and find its id from the network tab - Verify that notImportedOutcomesCount is equal to the number of State Standards minus 10 - Go to Course > Outcomes, and repeat the above tests importing from Account Standrds and verify that results are the same Change-Id: I20652b5ece5350c2df884c98defc11d8d092b8b0 Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/272768 Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com> Reviewed-by: Marcus Pompeu <marcus.pompeu@instructure.com> Reviewed-by: Chrystal Langston <chrystal.langston@instructure.com> Reviewed-by: Manoel Quirino <manoel.quirino@instructure.com> QA-Review: Chrystal Langston <chrystal.langston@instructure.com> Product-Review: Ben Friedman <ben.friedman@instructure.com>
2021-09-28 03:44:44 +08:00
end
def filter_outcomes(relation, filter)
outcomes = LearningOutcome.preload(:alignments).where(id: relation.map(&:content_id))
filtered_tag_ids = if filter == "WITH_ALIGNMENTS"
relation.reject { |tag| outcomes.find(tag.content_id).alignments.empty? }.map(&:id)
elsif filter == "NO_ALIGNMENTS"
relation.select { |tag| outcomes.find(tag.content_id).alignments.empty? }.map(&:id)
end
filtered_tag_ids.nil? ? relation : relation.where(id: filtered_tag_ids)
end
Add notImportedOutcomesCount field to LearningOutcomeGroup type closes OUT-4743 flag=improved_outcomes_management Test plan: - Import Academic Benchmarks - Go to Account > Settings > Feature Options and enable Improved Outcomes Management FF - Go to Account > Outcomes and open developer tools -> network - Select via TreeBrowser the root outcome group and use network tab to find the id of that group from the graphql response - Click on Find button select State Standards in the Find Modal; then find the id of that group using network tab - Open a new browser tab, go to canvas.docker/graphiql and paste the query below in the GraphiQL window: query GroupDetailWithSearchQuery($id: ID!, $targetGroupId: Int) { group: legacyNode(type: LearningOutcomeGroup, _id: $id) { ... on LearningOutcomeGroup { _id title contextType contextId outcomesCount notImportedOutcomesCount(targetGroupId: $targetGroupId) outcomes(first: 10) { edges { _id node { ... on LearningOutcome { _id description title } } } } } } } - In the query variables window paste the snippet below { "id": X, "targetGroupId": Y } - Replace X with the id of the State Standards group, Y with the id of the imported group and execute the query - Verify that there are no errors in the response - Verify that notImportedOutcomesCount is equal to the number of outcomes in State Standards - Import 10 outcomes from State Standards to the account - In the Manage View select the group where outcomes are imported and find its id from the network tab - Verify that notImportedOutcomesCount is equal to the number of State Standards minus 10 - Go to Course > Outcomes, and repeat the above tests importing from Account Standrds and verify that results are the same Change-Id: I20652b5ece5350c2df884c98defc11d8d092b8b0 Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/272768 Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com> Reviewed-by: Marcus Pompeu <marcus.pompeu@instructure.com> Reviewed-by: Chrystal Langston <chrystal.langston@instructure.com> Reviewed-by: Manoel Quirino <manoel.quirino@instructure.com> QA-Review: Chrystal Langston <chrystal.langston@instructure.com> Product-Review: Ben Friedman <ben.friedman@instructure.com>
2021-09-28 03:44:44 +08:00
def total_outcomes_for(learning_outcome_group_id, args = {})
relation = outcome_links(learning_outcome_group_id)
relation = filter_outcomes(relation, args[:filter]) unless args[:filter].nil? || !outcome_alignment_summary_enabled?(@context)
if args[:search_query]
relation = relation.joins(:learning_outcome_content)
relation = add_search_query(relation, args[:search_query])
end
relation.count
end
def add_search_query(relation, search_query)
# Tried to check if the lang is supported in the same query
# using a CASE WHEN but it wont work because it'll
# parse to_tsvector with the not supported lang, and it'll throw an error
sql = if self.class.supported_languages.include?(lang)
ContentTag.sanitize_sql_array([<<~SQL.squish, lang, search_query])
SELECT unnest(tsvector_to_array(to_tsvector(?, ?))) as token
SQL
else
ContentTag.sanitize_sql_array([<<~SQL.squish, search_query])
SELECT unnest(tsvector_to_array(to_tsvector(?))) as token
SQL
end
search_query_tokens = ContentTag.connection.execute(sql).to_a.map { |r| r["token"] }.uniq
short_description_query = ContentTag.sanitize_sql_array(["#{SHORT_DESCRIPTION} ~* ANY(array[?])",
search_query_tokens])
description_query = ContentTag.sanitize_sql_array(["#{DESCRIPTION} ~* ANY(array[?])", search_query_tokens])
relation.where("#{short_description_query} OR #{description_query}")
end
def add_search_order(relation, search_query)
select_query = ContentTag.sanitize_sql_array([<<~SQL.squish, search_query, search_query])
"content_tags".*,
GREATEST(public.word_similarity(?, #{SHORT_DESCRIPTION}), public.word_similarity(?, #{DESCRIPTION})) as sim
SQL
relation.select(select_query).order(
"sim DESC",
LearningOutcomeGroup.best_unicode_collation_key("logs.title"),
LearningOutcome.best_unicode_collation_key("short_description")
)
end
def children_ids_with_self(learning_outcome_group_id)
sql = <<~SQL.squish
Add cache to Outcomes::LearningOutcomeGroupChildren Updates Outcomes::LearningOutcomeGroupChildren by adding cache at the queries for getting the total subgroups and outcomes. closes OUT-4148 flag=improved_outcomes_management Test plan: - Create nested learning outcome groups - For each nested learning outcome group create learning outcomes > With FF improved_outcomes_management: OFF - On Rails console: calls to Outcomes::LearningOutcomeGroupChildren methods should return a default value - On web: when generating actions over ContentTag, LearningOutcome and LearningOutcomeGroup it should not lead to clear any cache > With FF improved_outcomes_management: ON - On Rails console: call Outcomes::LearningOutcomeGroupChildren methods for getting total subgroups and outcomes, queries to the DB should be made (it will need the root context) - Call again the same methods, it should return the values from cache - Create a new instance of the class and call the same methods, it should return the values from cache - Clear the cache with `Rails.cache.clear` - On web (or through GraphiQL) get the total subgroups and total outcomes multiple times; it should cache the data and should not run additional queries - On web: clear the cache by executing the following actions: - Add a Learning Outcome Group - Adopt a Learning Outcome Group - Copy a Learning Outcome Group from global - Remove a Learning Outcome Group - Add an Outcome - Remove an Outcome - Get the total subgroups and total outcomes, it should run new queries - Run the same tests for global context, it should generate and clear the cache in the same way Change-Id: I9b0bfc68b84b3e36869d69a926ef84d9989ea96d Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/257257 Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com> Reviewed-by: Augusto Callejas <acallejas@instructure.com> QA-Review: Chrystal Langston <chrystal.langston@instructure.com> Product-Review: Michael Brewer-Davis <mbd@instructure.com>
2021-01-23 09:03:53 +08:00
WITH RECURSIVE levels AS (
SELECT id, id AS parent_id
FROM (#{LearningOutcomeGroup.active.where(id: learning_outcome_group_id).to_sql}) AS data
Add cache to Outcomes::LearningOutcomeGroupChildren Updates Outcomes::LearningOutcomeGroupChildren by adding cache at the queries for getting the total subgroups and outcomes. closes OUT-4148 flag=improved_outcomes_management Test plan: - Create nested learning outcome groups - For each nested learning outcome group create learning outcomes > With FF improved_outcomes_management: OFF - On Rails console: calls to Outcomes::LearningOutcomeGroupChildren methods should return a default value - On web: when generating actions over ContentTag, LearningOutcome and LearningOutcomeGroup it should not lead to clear any cache > With FF improved_outcomes_management: ON - On Rails console: call Outcomes::LearningOutcomeGroupChildren methods for getting total subgroups and outcomes, queries to the DB should be made (it will need the root context) - Call again the same methods, it should return the values from cache - Create a new instance of the class and call the same methods, it should return the values from cache - Clear the cache with `Rails.cache.clear` - On web (or through GraphiQL) get the total subgroups and total outcomes multiple times; it should cache the data and should not run additional queries - On web: clear the cache by executing the following actions: - Add a Learning Outcome Group - Adopt a Learning Outcome Group - Copy a Learning Outcome Group from global - Remove a Learning Outcome Group - Add an Outcome - Remove an Outcome - Get the total subgroups and total outcomes, it should run new queries - Run the same tests for global context, it should generate and clear the cache in the same way Change-Id: I9b0bfc68b84b3e36869d69a926ef84d9989ea96d Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/257257 Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com> Reviewed-by: Augusto Callejas <acallejas@instructure.com> QA-Review: Chrystal Langston <chrystal.langston@instructure.com> Product-Review: Michael Brewer-Davis <mbd@instructure.com>
2021-01-23 09:03:53 +08:00
UNION ALL
SELECT child.id AS id, parent.parent_id AS parent_id
FROM #{LearningOutcomeGroup.quoted_table_name} child
INNER JOIN levels parent ON parent.id = child.learning_outcome_group_id
WHERE child.workflow_state <> 'deleted'
)
SELECT id FROM levels
Add cache to Outcomes::LearningOutcomeGroupChildren Updates Outcomes::LearningOutcomeGroupChildren by adding cache at the queries for getting the total subgroups and outcomes. closes OUT-4148 flag=improved_outcomes_management Test plan: - Create nested learning outcome groups - For each nested learning outcome group create learning outcomes > With FF improved_outcomes_management: OFF - On Rails console: calls to Outcomes::LearningOutcomeGroupChildren methods should return a default value - On web: when generating actions over ContentTag, LearningOutcome and LearningOutcomeGroup it should not lead to clear any cache > With FF improved_outcomes_management: ON - On Rails console: call Outcomes::LearningOutcomeGroupChildren methods for getting total subgroups and outcomes, queries to the DB should be made (it will need the root context) - Call again the same methods, it should return the values from cache - Create a new instance of the class and call the same methods, it should return the values from cache - Clear the cache with `Rails.cache.clear` - On web (or through GraphiQL) get the total subgroups and total outcomes multiple times; it should cache the data and should not run additional queries - On web: clear the cache by executing the following actions: - Add a Learning Outcome Group - Adopt a Learning Outcome Group - Copy a Learning Outcome Group from global - Remove a Learning Outcome Group - Add an Outcome - Remove an Outcome - Get the total subgroups and total outcomes, it should run new queries - Run the same tests for global context, it should generate and clear the cache in the same way Change-Id: I9b0bfc68b84b3e36869d69a926ef84d9989ea96d Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/257257 Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com> Reviewed-by: Augusto Callejas <acallejas@instructure.com> QA-Review: Chrystal Langston <chrystal.langston@instructure.com> Product-Review: Michael Brewer-Davis <mbd@instructure.com>
2021-01-23 09:03:53 +08:00
SQL
LearningOutcomeGroup.connection.execute(sql).as_json.map { |r| r["id"] }
Add cache to Outcomes::LearningOutcomeGroupChildren Updates Outcomes::LearningOutcomeGroupChildren by adding cache at the queries for getting the total subgroups and outcomes. closes OUT-4148 flag=improved_outcomes_management Test plan: - Create nested learning outcome groups - For each nested learning outcome group create learning outcomes > With FF improved_outcomes_management: OFF - On Rails console: calls to Outcomes::LearningOutcomeGroupChildren methods should return a default value - On web: when generating actions over ContentTag, LearningOutcome and LearningOutcomeGroup it should not lead to clear any cache > With FF improved_outcomes_management: ON - On Rails console: call Outcomes::LearningOutcomeGroupChildren methods for getting total subgroups and outcomes, queries to the DB should be made (it will need the root context) - Call again the same methods, it should return the values from cache - Create a new instance of the class and call the same methods, it should return the values from cache - Clear the cache with `Rails.cache.clear` - On web (or through GraphiQL) get the total subgroups and total outcomes multiple times; it should cache the data and should not run additional queries - On web: clear the cache by executing the following actions: - Add a Learning Outcome Group - Adopt a Learning Outcome Group - Copy a Learning Outcome Group from global - Remove a Learning Outcome Group - Add an Outcome - Remove an Outcome - Get the total subgroups and total outcomes, it should run new queries - Run the same tests for global context, it should generate and clear the cache in the same way Change-Id: I9b0bfc68b84b3e36869d69a926ef84d9989ea96d Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/257257 Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com> Reviewed-by: Augusto Callejas <acallejas@instructure.com> QA-Review: Chrystal Langston <chrystal.langston@instructure.com> Product-Review: Michael Brewer-Davis <mbd@instructure.com>
2021-01-23 09:03:53 +08:00
end
def context_timestamp_cache
Rails.cache.fetch(context_timestamp_cache_key) do
(Time.zone.now.to_f * 1000).to_i
end
end
def total_outcomes_cache_key(learning_outcome_group_id = nil)
["learning_outcome_group_total_outcomes",
context_asset_string,
context_timestamp_cache,
learning_outcome_group_id].cache_key
end
def context_timestamp_cache_key
["learning_outcome_group_context_timestamp", context_asset_string].cache_key
end
def context_asset_string
@context_asset_string ||= (context || LearningOutcomeGroup.global_root_outcome_group).global_asset_string
Add cache to Outcomes::LearningOutcomeGroupChildren Updates Outcomes::LearningOutcomeGroupChildren by adding cache at the queries for getting the total subgroups and outcomes. closes OUT-4148 flag=improved_outcomes_management Test plan: - Create nested learning outcome groups - For each nested learning outcome group create learning outcomes > With FF improved_outcomes_management: OFF - On Rails console: calls to Outcomes::LearningOutcomeGroupChildren methods should return a default value - On web: when generating actions over ContentTag, LearningOutcome and LearningOutcomeGroup it should not lead to clear any cache > With FF improved_outcomes_management: ON - On Rails console: call Outcomes::LearningOutcomeGroupChildren methods for getting total subgroups and outcomes, queries to the DB should be made (it will need the root context) - Call again the same methods, it should return the values from cache - Create a new instance of the class and call the same methods, it should return the values from cache - Clear the cache with `Rails.cache.clear` - On web (or through GraphiQL) get the total subgroups and total outcomes multiple times; it should cache the data and should not run additional queries - On web: clear the cache by executing the following actions: - Add a Learning Outcome Group - Adopt a Learning Outcome Group - Copy a Learning Outcome Group from global - Remove a Learning Outcome Group - Add an Outcome - Remove an Outcome - Get the total subgroups and total outcomes, it should run new queries - Run the same tests for global context, it should generate and clear the cache in the same way Change-Id: I9b0bfc68b84b3e36869d69a926ef84d9989ea96d Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/257257 Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com> Reviewed-by: Augusto Callejas <acallejas@instructure.com> QA-Review: Chrystal Langston <chrystal.langston@instructure.com> Product-Review: Michael Brewer-Davis <mbd@instructure.com>
2021-01-23 09:03:53 +08:00
end
def improved_outcomes_management?
@improved_outcomes_management ||= if context
context.root_account.feature_enabled?(:improved_outcomes_management)
else
Add cache to Outcomes::LearningOutcomeGroupChildren Updates Outcomes::LearningOutcomeGroupChildren by adding cache at the queries for getting the total subgroups and outcomes. closes OUT-4148 flag=improved_outcomes_management Test plan: - Create nested learning outcome groups - For each nested learning outcome group create learning outcomes > With FF improved_outcomes_management: OFF - On Rails console: calls to Outcomes::LearningOutcomeGroupChildren methods should return a default value - On web: when generating actions over ContentTag, LearningOutcome and LearningOutcomeGroup it should not lead to clear any cache > With FF improved_outcomes_management: ON - On Rails console: call Outcomes::LearningOutcomeGroupChildren methods for getting total subgroups and outcomes, queries to the DB should be made (it will need the root context) - Call again the same methods, it should return the values from cache - Create a new instance of the class and call the same methods, it should return the values from cache - Clear the cache with `Rails.cache.clear` - On web (or through GraphiQL) get the total subgroups and total outcomes multiple times; it should cache the data and should not run additional queries - On web: clear the cache by executing the following actions: - Add a Learning Outcome Group - Adopt a Learning Outcome Group - Copy a Learning Outcome Group from global - Remove a Learning Outcome Group - Add an Outcome - Remove an Outcome - Get the total subgroups and total outcomes, it should run new queries - Run the same tests for global context, it should generate and clear the cache in the same way Change-Id: I9b0bfc68b84b3e36869d69a926ef84d9989ea96d Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/257257 Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com> Reviewed-by: Augusto Callejas <acallejas@instructure.com> QA-Review: Chrystal Langston <chrystal.langston@instructure.com> Product-Review: Michael Brewer-Davis <mbd@instructure.com>
2021-01-23 09:03:53 +08:00
LoadAccount.default_domain_root_account.feature_enabled?(:improved_outcomes_management)
end
end
Add notImportedOutcomesCount field to LearningOutcomeGroup type closes OUT-4743 flag=improved_outcomes_management Test plan: - Import Academic Benchmarks - Go to Account > Settings > Feature Options and enable Improved Outcomes Management FF - Go to Account > Outcomes and open developer tools -> network - Select via TreeBrowser the root outcome group and use network tab to find the id of that group from the graphql response - Click on Find button select State Standards in the Find Modal; then find the id of that group using network tab - Open a new browser tab, go to canvas.docker/graphiql and paste the query below in the GraphiQL window: query GroupDetailWithSearchQuery($id: ID!, $targetGroupId: Int) { group: legacyNode(type: LearningOutcomeGroup, _id: $id) { ... on LearningOutcomeGroup { _id title contextType contextId outcomesCount notImportedOutcomesCount(targetGroupId: $targetGroupId) outcomes(first: 10) { edges { _id node { ... on LearningOutcome { _id description title } } } } } } } - In the query variables window paste the snippet below { "id": X, "targetGroupId": Y } - Replace X with the id of the State Standards group, Y with the id of the imported group and execute the query - Verify that there are no errors in the response - Verify that notImportedOutcomesCount is equal to the number of outcomes in State Standards - Import 10 outcomes from State Standards to the account - In the Manage View select the group where outcomes are imported and find its id from the network tab - Verify that notImportedOutcomesCount is equal to the number of State Standards minus 10 - Go to Course > Outcomes, and repeat the above tests importing from Account Standrds and verify that results are the same Change-Id: I20652b5ece5350c2df884c98defc11d8d092b8b0 Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/272768 Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com> Reviewed-by: Marcus Pompeu <marcus.pompeu@instructure.com> Reviewed-by: Chrystal Langston <chrystal.langston@instructure.com> Reviewed-by: Manoel Quirino <manoel.quirino@instructure.com> QA-Review: Chrystal Langston <chrystal.langston@instructure.com> Product-Review: Ben Friedman <ben.friedman@instructure.com>
2021-09-28 03:44:44 +08:00
def group_exists?(learning_outcome_group_id)
LearningOutcomeGroup.find_by(id: learning_outcome_group_id) != nil
end
def lang
# lang can be nil, so we check with instance_variable_defined? method
unless instance_variable_defined?("@lang")
account = context&.root_account || LoadAccount.default_domain_root_account
@lang = MAP_CANVAS_POSTGRES_LOCALES[account.default_locale || "en"]
end
@lang
end
end
end