Welcome to the UKRI Digital Research Skills Catalyst
A national hub for researcher and innovator development.
Boost your digital research skills, accelerate your research impact—discover 80+ learning resources, events, and expert-led training in one central hub with the UKRI Digital Research Skills Catalyst. Find out more here.
Code
# This cell loads the CSV data directly from the Google sheet via its published CSV-specific URL.# We need to load in Python, as OJS doesn't have a caching system.# Once loaded, we "publish" the variable globally to OJS.import pandas as pdcourse_data_cached = pd.read_csv("https://docs.google.com/spreadsheets/d/e/2PACX-1vRSrvsfFfVwokza_WP9JIzd4Wfg6OKPBJcwelLTqYn1SgigZXnfcU6_apN5gWTMF79n4CRQFNOJ5w6M/pub?gid=1012757406&single=true&output=csv")ojs_define(course_data_cached = course_data_cached)
Code
// This cell transposes the data presented from Python, as numpy & OJS expect data in opposite ordercourse_data =transpose(course_data_cached)
// This cell implements a show/hide button for extra filters.// This works via a JavaScript function that finds and toggles the div display style.{const toggleLink =document.createElement("a"); toggleLink.href="#"; toggleLink.textContent="show filters"; toggleLink.addEventListener("click", (event) => {event.preventDefault();const filter_div =document.getElementById("search-filters");if (filter_div.style.display==="none") { toggleLink.textContent="hide filters"; filter_div.style.display="block" } else { toggleLink.textContent="show filters"; filter_div.style.display="none" } });return toggleLink;}
Code
// Performs filtering of the complete (`course_data`) data into the filtered (`course_filtered`) set.// If there is no search, and nothing has been selected in the filters then we return everything.course_filtered = ( (!selected_audience) &&// (selected_educational_level ?? []).length === 0 && (selected_resource_type ?? []).length===0&& (selected_time ?? []).length===0&& (selected_provider ?? []).length===0&& (!search_query) )? course_data.filter(row => row.featured==="yes"): course_data.filter(row =>// audience (!selected_audience ||!row.audience|| row.audience.includes(selected_audience)) &&// educational level// ((selected_educational_level ?? []).length === 0 || (selected_educational_level ?? []).includes(row.educationalLevel)) &&// resource type ((selected_resource_type ?? []).length===0|| (selected_resource_type ?? []).includes(row.learningResourceType)) &&// time ((selected_time ?? []).length===0|| (selected_time ?? []).includes(row.approxTimeRequired)) &&// provider ((selected_provider ?? []).length===0|| (selected_provider ?? []).includes(row.provider)) &&// search (!search_query || row.headline.toLowerCase().includes(search_query) || (row.description&& row.description.includes(search_query)) || (row.projectFunding&& row.projectFunding.includes(search_query)) || (row.identifier&& row.identifier.includes(search_query)) ) )
Code
// This cell iterates through the the filtered course results, and builds the displayed output.// If there are no selected results, we show a placeholder <div>.// All filtered courses are displayed, sorted first by `featured` status then in the CSV file order.{const search_results =document.getElementById("primary-search-results");const empty_results =document.getElementById("empty-primary-search-results");if (course_filtered.length===0) {returnhtml` <div class="course-data-empty"> <p>No results to display</p> </div> ` } else {returnhtml`${course_filtered.slice().sort((a, b) => {if(a.featured==="yes"&& b.featured==="no") return-1;if(a.featured==="no"&& b.featured==="yes") return1;return0; }).map((row, row_index) =>html` <div class="${row.featured==="yes"?"course-data featured":"course-data"}" id="course_data_${row_index}"> <h3> <a href=${row.url}>${row.headline}</a> </h3> <p>${row.description}</p> <input type="checkbox" class="toggle-state" id="toggle-state-${row_index}"> <label for="toggle-state-${row_index}" class="toggle-button"></label> <div class="course-data-extras" id="course_data_extras_${row_index}"> <table> <tr> <th scope="row">Pre-requisites</th> <td class="pre-reqs">${row.competencyRequired?.split(/,(?=(?:(?:[^"]*"){2})*[^"]*$)/).map(prereq =>html`<p>${prereq.trim().replace(/^"|"$/g,"")}</p>`)}</td> </tr> <tr> <th scope="row">Teaches</th> <td class="teaches">${row.teaches?.split(/,(?=(?:(?:[^"]*"){2})*[^"]*$)/).map(teach_p =>html`<p>${teach_p.trim().replace(/^"|"$/g,"")}</p>`)}</td> </tr> <tr> <th scope="row">Time required</th> <td class="required">${row.TimeRequired}</td> </tr> <tr> <th scope="row">Credit</th> <td class="credit">${md`${row.creditText}`}</td> </tr> <tr> <th scope="row">Provider</th> <td>${row.projectFunding}</td> </tr> </table> </div> </div> `)}` }}
Code
// This cell fires whenever the "reset filters" button is pressed.{ reset_filters;// This updates whenever the reset button fires.functionresetInput(view, value) {const el = view.querySelector("select, input");if (!el) return; el.value= value; view.value= value; el.dispatchEvent(newEvent("input", { bubbles:true })); }resetInput(viewof selected_audience,null);// resetInput(viewof selected_educational_level, []);resetInput(viewof selected_resource_type,null);resetInput(viewof selected_time,null);resetInput(viewof selected_provider,null);}
Code
// This cell displays a table of all `course_data` for debugging only.Inputs.table(course_data)