### Initializing Experiment Page Setup (JavaScript) Source: https://github.com/slaclab/explgbk/blob/master/templates/experiments.html This snippet imports the `setupExperimentsPage` function from `../static/experiments.js` and immediately calls it. This function is responsible for initializing the client-side logic and rendering for the experiment selection page, likely setting up event listeners, data fetching, and UI components. ```JavaScript import { setupExperimentsPage } from "../static/experiments.js"; setupExperimentsPage(); ``` -------------------------------- ### Setting Up Logbook UI on DOM Load - JavaScript Source: https://github.com/slaclab/explgbk/blob/master/templates/lgbk.html This snippet attaches an event listener to the `DOMContentLoaded` event, ensuring that the UI setup logic runs only after the HTML document has been fully loaded and parsed. It first loads site-specific tabs, then proceeds to set up the main logbook tabs using the `tabload` function, establishes a WebSocket connection, sets the current UI sample, and performs additional miscellaneous setup tasks. ```JavaScript document.addEventListener('DOMContentLoaded', () => { loadSiteSpecificTabs() .then(() => { lgbksetuptabs(tabload); WebSocketConnection.connect(); setCurrentUISample(); miscSetup(); }) }) ``` -------------------------------- ### Setting Up Dashboard on DOM Load - JavaScript Source: https://github.com/slaclab/explgbk/blob/master/templates/ops.html This snippet sets up the operator dashboard once the DOM content is fully loaded. It asynchronously loads site-specific tabs, initializes the main tab setup function (`lgbksetuptabs`), establishes a WebSocket connection, and performs miscellaneous setup tasks, ensuring the dashboard is fully functional upon user interaction. ```JavaScript document.addEventListener('DOMContentLoaded', () => { loadSiteSpecificTabs() .then(() => { lgbksetuptabs(tabload); WebSocketConnection.connect(); miscSetup(); }) }) ``` -------------------------------- ### Starting a New Run via cURL Source: https://github.com/slaclab/explgbk/blob/master/static/html/docs/devguides/external_previews.html This cURL command initiates a new run for the 'A_Test_Experiment'. This is the first step before adding any run-specific parameters. ```Shell curl -s "https://localhost/psdm/run_control/A_Test_Experiment/ws/start_run" ``` -------------------------------- ### Full Widget Initialization and Data Management - jQuery/Lodash/Mustache Source: https://github.com/slaclab/explgbk/blob/master/static/html/docs/devguides/pagination.html Demonstrates the complete setup and usage of the sorting/pagination widget. It initializes the widget, defines a Mustache template for rendering data rows, sets up infinite scrolling, populates the widget with a large dataset using `addObjects`, and then incrementally adds/updates individual records using `addObject`, including a delayed update example. ```JavaScript sortable_paginator($("#sorted_table"), "_id", "_id", true); var tb = $("#sorted_table").find("tbody"), rwtmpl = "{{_id}}{{first}}{{last}}"; Mustache.parse(rwtmpl); $(window).scroll(function () { if ($(window).scrollTop() >= $(document).height() - $(window).height() - 10) { $("#sorted_table").data("spgntr").pageDown(); } }); var rws = []; _.each(_.range(2, 9999), function(i) { var rw = {"_id": i, "first": "F_"+ i, "last": "L_"+i}; rw.render = function(){ return $(Mustache.render(rwtmpl, this)) }; rws.push(rw); }); $("#sorted_table").data("spgntr").addObjects(rws); _.each(_.range(10000, 10050), function(i) { var rw = {"_id": i, "first": "F_"+ i, "last": "L_"+i}; rw.render = function(){ return $(Mustache.render(rwtmpl, this)) }; $("#sorted_table").data("spgntr").addObject(rw); }); window.setTimeout(function(){ _.each([10038, 10052, 10051, 1000, 1], function(i){ console.log("Adding " + i); var rw = {"_id": i, "first": "FUpdated_"+ i, "last": "L_Updated"+i}; rw.render = function(){ return $(Mustache.render(rwtmpl, this)) }; $("#sorted_table").data("spgntr").addObject(rw); }); }, 1000*10); ``` -------------------------------- ### Defining API Endpoints and User Constants (JavaScript) Source: https://github.com/slaclab/explgbk/blob/master/templates/experiments.html This snippet defines various JavaScript constants for API endpoints used in the experiment logbook application, including URLs for fetching experiments, user groups, active experiments, and registering new experiments. It also initializes user-specific data like `logged_in_user`, `privileges`, and `logged_in_user_details`, likely populated from a server-side template. ```JavaScript const logbook_site = "{{ logbook_site }}"; const experiments_url = ( logbook_site == "LCLS" ? "ws/experiments?categorize=instrument_runperiod&sortby=runperiod" : "ws/experiments?categorize=instrument_lastrunyear&sortby=lastrunyear" ); const useridgroups_url = "ws/usergroups"; const active_experiments_url = "ws/activeexperiments"; const lookup_experiment_in_urawi = "ws/lookup_experiment_in_urawi"; const register_experiment_url = "ws/register_new_experiment"; const logged_in_user = "{{ logged_in_user }}"; const privileges = {{ privileges|safe }}; const logged_in_user_details = {{ logged_in_user_details|safe }}; let pagepath = "{{pagepath}}"; import "../static/html/components/all.js"; ``` -------------------------------- ### Handling Old Hash-Based URL Redirection - JavaScript Source: https://github.com/slaclab/explgbk/blob/master/templates/lgbk.html This code imports site-specific tab loading and miscellaneous setup functions. It then checks if the current URL uses an old hash-based navigation style. If so, it displays a redirection message to the user and automatically redirects them to the new path-based URL after a 2-second delay, ensuring compatibility with legacy links. ```JavaScript import { loadSiteSpecificTabs } from "../../static/html/tabs/lgbk/sitespecifictabs.js"; import { miscSetup } from "../../static/html/tabs/lgbk/miscsetup.js"; if(_.includes([ "#info", "#eLog", "#samples", "#runTables", "#fileManager", "#feedback", "#collaborators", "#lcls_wf_defs", "#lcls_wf_jobs", "#summaries" ], location.hash)) { document.querySelector("#lgbk_body").innerHTML = `

Redirecting old style hash URL's (${location.hash}) to new style path based URL's. You should be redirected automatically in a few seconds.

`; setTimeout(() => { window.location.replace("./" + location.hash.substring(1)); }, 2000); } ``` -------------------------------- ### Creating Collections and Indices in MongoDB 'site' Database Source: https://github.com/slaclab/explgbk/blob/master/Install.md This snippet switches to the 'site' database and creates two collections, 'roles' and 'experiment_switch', along with their respective indices. The 'roles' collection index ensures uniqueness for 'app' and 'name' fields, while 'experiment_switch' index facilitates efficient querying based on experiment details and time. ```MongoDB Shell use site db['roles'].create_index( [("app", ASCENDING), ("name", ASCENDING)], unique=True) db['experiment_switch'].create_index( [("experiment_name", ASCENDING), ("instrument", ASCENDING), ("station", ASCENDING), ("switch_time", ASCENDING)]) ``` -------------------------------- ### Initializing Global Variables and Importing Components - JavaScript Source: https://github.com/slaclab/explgbk/blob/master/templates/lgbk.html This snippet initializes several global JavaScript variables with values dynamically injected from a server-side template. These variables provide essential context for the logbook application, such as experiment details, user information, and authentication status. It also imports a core JavaScript component file that likely contains shared UI elements or utilities. ```JavaScript const experiment_name = "{{ experiment_name }}"; const instrument_name = "{{ instrument_name }}"; const logged_in_user = "{{ logged_in_user }}"; const logbook_site = "{{ logbook_site }}"; const privileges = {{ privileges|safe }}; let auth_expiration_time = {{ auth_expiration_time }}; let current_sample_at_DAQ = {{current_sample_name|json|safe}}; let sample_showing_in_UI = current_sample_at_DAQ; let is_locked = {{ is_locked }}; let tabname = "{{tabname}}"; let pagepath = "{{pagepath}}"; import "../../static/html/components/all.js"; ``` -------------------------------- ### Creating MongoDB Users with Specific Roles Source: https://github.com/slaclab/explgbk/blob/master/Install.md This snippet demonstrates how to create 'admin', 'reader', and 'writer' users in MongoDB's 'admin' database. Each user is assigned specific roles to manage users, read any database, or read/write to any database, respectively. These users are intended for service access. ```MongoDB Shell use admin db.createUser( { user: "admin", pwd: "somepassword", roles: [ { role: "userAdminAnyDatabase", db: "admin" }, { role: "root", db: "admin" } ] } ) db.createUser( { user: "reader", pwd: "somepassword", roles: [ { role: "readAnyDatabase", db: "admin" } ] } ) db.createUser( { user: "writer", pwd: "somepassword", roles: [ { role: "readWriteAnyDatabase", db: "admin" } ] } ) ``` -------------------------------- ### Dynamically Loading and Displaying Tabs - JavaScript Source: https://github.com/slaclab/explgbk/blob/master/templates/lgbk.html This asynchronous function is responsible for dynamically loading a JavaScript module specified by `taburl`. It then extracts the `tabshow` function from the imported module and executes it, passing the `target` element. This pattern allows for on-demand loading of tab content, improving initial page load performance by only loading necessary code when a tab is activated. ```JavaScript async function tabload(taburl, target) { const { tabshow } = await import(taburl); tabshow(target); } ``` -------------------------------- ### Inserting Initial Logbook Roles into MongoDB 'site' Database Source: https://github.com/slaclab/explgbk/blob/master/Install.md This snippet populates the 'roles' collection within the 'site' database with initial data for LogBook application roles: Editor, Writer, and Reader. Each role defines specific privileges (e.g., read, post, edit, delete) and lists associated players (users or groups) who possess these roles, enabling access control for the logbook. ```MongoDB Shell use site db['roles'].insertMany([ { "app" : "LogBook", "name" : "Editor", "privileges" : [ "read", "post", "edit", "delete" ], "players" : [ "uid:editor" ] }, { "app" : "LogBook", "name" : "Writer", "privileges" : [ "post", "read" ], "players" : [ "group_containing_all_writers", "uid:writer" ] }, { "app" : "LogBook", "name" : "Reader", "privileges" : [ "read" ], "players" : [ "group_containing_all_readers", "uid:reader" ] } ]) ``` -------------------------------- ### Rendering POC Details using Mustache.js and jQuery Source: https://github.com/slaclab/explgbk/blob/master/static/html/ms/info_LCLS.html This JavaScript snippet defines a Mustache template named `poctmpl` to structure the display of Point of Contact (POC) information. It then uses `Mustache.render` to process this template with an `info` data object, generating HTML. Finally, this generated HTML is appended to the first element with the class `exp_details` found within the HTML element with the ID `info_tab`. This operation is typically performed when relevant setup information is available. ```JavaScript var poctmpl = `{{#latest_setup.general-poc1}}
POC 1:{{.}}
{{/latest_setup.general-poc1}}{{#latest_setup.general-poc2}}
POC 2:{{.}}
{{/latest_setup.general-poc2}}`; $("#info_tab").find(".exp_details").first().append(Mustache.render(poctmpl, info)); ``` -------------------------------- ### MongoDB Run Document Structure for LCLS DM Source: https://github.com/slaclab/explgbk/blob/master/static/html/docs/devguides/db_details.html This JSON snippet illustrates the structure of a document stored in the 'runs' collection. It captures essential metadata for a data acquisition run, including its unique ID, run number, type, start and end times, and various parameters. It also shows how editable user comments and sample associations are stored within the document. ```JSON { "_id" : ObjectId("5e5xxxx"), "num" : 8, "type" : "EPICS", "begin_time" : ISODate("2013-05-24T04:36:20Z"), "end_time" : ISODate("2013-05-24T04:36:25Z"), "params" : { "AT1L0:SOLID:MPA:01:POS_STATE_RBV" : "RETRACTED", "AT1L0:SOLID:MPA:02:POS_STATE_RBV" : "RETRACTED", "MFX:DIA:MMS:07:DF" : "1", "DAQ Detectors/BldEb-0|NoDevice-0" : true, "DAQ Detectors/EpicsArch-0|NoDevice-0" : true, "DAQ Detectors/MfxEndstation-0|Epix10ka2M-0" : true, "DAQ Detector Totals/Damaged" : 0, "DAQ Detector Totals/Events" : 1094, "DAQ Detector Totals/Size" : 4.824235104, ... }, "editable_params" : { "pauls_comment" : { "value" : "Reverted back to previous setting", "modified_by" : "pdirac", "modified_time" : ISODate("2021-12-06T18:33:14.778Z") } }, "sample" : ObjectId("5dexxx") } ``` -------------------------------- ### Initializing User and Site Variables - JavaScript Source: https://github.com/slaclab/explgbk/blob/master/templates/help.html This snippet initializes global JavaScript variables with user, site, and privilege details, likely populated by a server-side templating engine. These variables are crucial for client-side logic that adapts to the logged-in user's context and permissions. ```JavaScript var logged_in_user = "{{ logged_in_user }}"; var logbook_site = "{{ logbook_site }}"; var logged_in_user_details = {{ logged_in_user_details|safe }}; var privileges = {{ privileges|safe }}; const pagepath = "{{pagepath}}"; ``` -------------------------------- ### Loading Dynamic Help Content via AJAX - jQuery JavaScript Source: https://github.com/slaclab/explgbk/blob/master/templates/help.html This jQuery snippet loads help content from 'docs/help.html' into a specific div. It then dynamically shows/hides sections based on the current 'logbook_site' and the user's 'privileges', and scrolls to a specific hash if present in the URL. ```JavaScript $(function() { $(document).ready(function() { $.ajax ("docs/help.html") .done(function( hlp ) { $("#lgbk_help").find(".helptext").append(hlp); $("#lgbk_help").find("[class*='site_']").addClass("d-none"); $("#lgbk_help").find("[class*='priv_']").addClass("d-none"); $("#lgbk_help").find(".site_"+logbook_site).removeClass("d-none"); _.each(privileges, function(v, k){ if(v) { $("#lgbk_help").find(".priv_"+k).removeClass("d-none"); } }) let hash = window.location.hash; console.log(hash); if(!_.isNil(hash) && $("#lgbk_help").find(".helptext").find(hash).length > 0) { $("#lgbk_help").find(".helptext").find(hash)[0].scrollIntoView(); } }) .fail(function(jqXHR, textStatus, errorThrown) { alert("Server failure: " + _.get(jqXHR, "responseText", textStatus))}) }) }) ``` -------------------------------- ### Loading and Displaying CryoEM Sample Information with jQuery and Mustache Source: https://github.com/slaclab/explgbk/blob/master/static/html/ms/info_CryoEM.html This JavaScript snippet handles the asynchronous loading and rendering of CryoEM sample data. It fetches run and sample details from `ws/runs` and `ws/samples` endpoints, processes the data using Lodash to group runs by sample and determine earliest/latest run times, and then renders each sample's information into an HTML template using Mustache. The rendered content is appended to the `#cryo_info_samples` element. ```JavaScript $("#info_tab").on("info_loaded", function(ev, info){ $.when($.getJSON("ws/runs", {includeParams: false}), $.getJSON("ws/samples")) .done(function(d0, d1){ let sample2runs = _.groupBy(d0[0].value, "sample"), sample2earlieststarttime = _.sortBy(_.map(sample2runs, function(v, k){return {"sample": k, "earliest_run": _.min(_.map(v, function(x){ return moment(x["begin_time"]).toDate()}))}}), "earliest_run"), samples = d1[0].value; let sampletmpl = `
Sample Name:{{name}}Preprocessing runs completed:{{sampleruncount}}
Sample Description:{{description}}
Time Started:{{#FormatDate}}{{first_run}}{{/FormatDate}}Time Ended:{{#FormatDate}}{{last_run}}{{/FormatDate}}
`; Mustache.parse(sampletmpl); _.each(_.sortBy(samples, "name"), function(v,k){ let sampleObj = v; sampleObj.sampleruns = _.get(sample2runs, v["_id"], []); sampleObj.sampleruncount = sampleObj.sampleruns.length; sampleObj.first_run = _.min(_.map(sampleObj.sampleruns, function(r){return moment(r["begin_time"]).toDate()})); sampleObj.last_run = _.max(_.map(sampleObj.sampleruns, function(r){return moment(r["begin_time"]).toDate()})); sampleObj.FormatDate = elog_formatdatetime; let rendered = $(Mustache.render(sampletmpl, sampleObj)); $("#cryo_info_samples").append(rendered); }) }); }); ``` -------------------------------- ### Dynamically Loading Tab Content (JavaScript) Source: https://github.com/slaclab/explgbk/blob/master/templates/project.html This asynchronous JavaScript function `tabload` dynamically imports a module specified by `taburl` and calls its `tabshow` function, passing a `target` element. An event listener ensures that `lgbksetuptabs` is called with `tabload` as a callback once the DOM is fully loaded, enabling dynamic tab functionality. ```JavaScript async function tabload(taburl, target) { const { tabshow } = await import(taburl); tabshow(target); } document.addEventListener('DOMContentLoaded', () => { lgbksetuptabs(tabload); }) ``` -------------------------------- ### Initializing Project and User Variables (JavaScript) Source: https://github.com/slaclab/explgbk/blob/master/templates/project.html This JavaScript snippet initializes global variables with data passed from the server-side template, including user login details, privileges, project name, ID, current tab, and page path. It also imports a shared JavaScript component for UI elements. ```JavaScript var logged_in_user = "{{ logged_in_user }}"; var privileges = {{ privileges|safe }}; var logged_in_user_details = {{ logged_in_user_details|safe }} let project = "{{ project_name }}"; let prjid = "{{project_id}}"; let tabname = "{{tabname}}"; let pagepath = "{{pagepath}}"; import "../../../static/html/components/all.js"; ``` -------------------------------- ### Handling Old URL Redirects and Dynamic Tab Loading - JavaScript Source: https://github.com/slaclab/explgbk/blob/master/templates/ops.html This snippet handles redirection of old-style hash-based URLs to new path-based URLs, providing a smooth transition for users. It also defines an asynchronous function `tabload` for dynamically importing and displaying content for different tabs, improving application performance by lazy-loading modules. ```JavaScript // Module specifier are resolved using the current module's URL as base. This is the "current" module; so all dynamic imports from now on will use this as their base. // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import.meta/resolve import { loadSiteSpecificTabs } from "../../static/html/ops/sitespecifictabs.js"; import { miscSetup } from "../../static/html/ops/miscsetup.js"; if(_.includes([ "#switch", "#experiments", "#instruments", "#global_roles", "#inst_roles", "#summary", "#data_mov" ], location.hash)) { document.querySelector("#lgbk_body").innerHTML = `

Redirecting old style hash URL's (${location.hash}) to new style path based URL's. You should be redirected automatically in a few seconds.

`; setTimeout(() => { window.location.replace("./" + location.hash.substring(1)); }, 2000); } async function tabload(taburl, target) { const { tabshow } = await import(taburl); tabshow(target); } ``` -------------------------------- ### Dynamically Loading UI Tabs (JavaScript) Source: https://github.com/slaclab/explgbk/blob/master/templates/projects.html This JavaScript code imports a global UI component library and defines an asynchronous function to dynamically load and display tab content. It ensures that the project list tab is loaded and rendered into the '#projectlist' element once the DOM is fully loaded, using a module-based approach. ```JavaScript import "../../static/html/components/all.js"; async function tabload(taburl, target) { const { tabshow } = await import(taburl); tabshow(target); } document.addEventListener('DOMContentLoaded', () => { tabload(lgbkabspath("/static/html/tabs/project/prjlist/tab.js"), document.querySelector("#projectlist")); }) ``` -------------------------------- ### Initializing Logbook Entry Variables (JavaScript) Source: https://github.com/slaclab/explgbk/blob/master/templates/elog_entry.html This JavaScript snippet initializes several global variables with values dynamically injected from a server-side template. These variables provide essential context for the logbook entry, including experiment, instrument, entry ID, logged-in user, logbook site, and page path, enabling client-side scripts to access this information. ```JavaScript var experiment_name = "{{ experiment_name }}"; var instrument_name = "{{ instrument_name }}"; var entry_id = "{{ entry_id }}"; var logged_in_user = "{{ logged_in_user }}"; var logbook_site = "{{ logbook_site }}"; const pagepath = "{{pagepath}}"; ``` -------------------------------- ### Initializing User Session Variables (JavaScript) Source: https://github.com/slaclab/explgbk/blob/master/templates/projects.html This snippet initializes global JavaScript variables with user-specific session data and the current page path. It retrieves values from server-side templating, likely for displaying user information and controlling UI elements based on privileges. ```JavaScript var logged_in_user = "{{ logged_in_user }}"; var privileges = {{ privileges|safe }}; var logged_in_user_details = {{ logged_in_user_details|safe }}; const pagepath = "{{pagepath}}"; ``` -------------------------------- ### Dynamically Loading UI Tab on DOMContentLoaded (JavaScript) Source: https://github.com/slaclab/explgbk/blob/master/templates/elog_entry.html This JavaScript code defines an asynchronous function `tabload` to dynamically import and execute a module from a given URL, specifically designed to show a UI tab. It then attaches an event listener to the `DOMContentLoaded` event, ensuring that the `tabload` function is called with the path to the logbook entry tab script once the HTML document is fully loaded and parsed. ```JavaScript async function tabload(taburl) { const { tabshow } = await import(taburl); tabshow(); } document.addEventListener('DOMContentLoaded', () => { tabload("../../../static/html/tabs/lgbk/elogentry/tab.js"); }) ``` -------------------------------- ### Sample Grouping Data Model (JSON) Source: https://github.com/slaclab/explgbk/blob/master/static/html/docs/devguides/db_details.html This JSON snippet illustrates the data model for 'Samples', which are used to logically group experimental runs. Each sample has a name, a description, and a flexible 'params' object that can contain arbitrary key-value pairs. The system supports declarative constraints on these custom parameters. ```JSON { "_id" : ObjectId("5de9xxx"), "name" : "MmpL3", "description" : "CryoEM Time", "params" : { "imaging_method" : "single-particle", "imaging_software" : "SerialEM", "imaging_format" : ".tif", "apix" : "1.06", "fmdose" : "1.42", "preprocess/enable" : "1", "preprocess/convert_gainref" : "1", "preprocess/apply_gainref" : "1", "preprocess/align/motioncor2/throw" : "0", "preprocess/align/motioncor2/outstk" : "0" } } ``` -------------------------------- ### Fetching and Rendering Logbook API Endpoints - JavaScript Source: https://github.com/slaclab/explgbk/blob/master/static/html/docs/api.html This JavaScript snippet uses jQuery to fetch API endpoint data from `../../lgbk/ws/api_endpoints`. It then processes the data using Lodash to format methods and check for HTML content in docstrings. Finally, it uses Mustache.js to render the endpoint details into the `#api_endpoints` element, providing a dynamic display of the API documentation. It includes error handling for server failures. ```JavaScript $(function() { $(document).ready(function() { $.getJSON ("../../lgbk/ws/api_endpoints") .done(function( endpoints ) { let epl = _.map(endpoints, function(v){ v["methods"] = _.join(v["methods"].sort(), ","); v["fmt"] = v["docstring"].includes("
"); return v }); console.log(epl); let endpointtmpl = `{{#.}}
{{endpoint}}
{{methods}}
{{^fmt}}
{{docstring}}
{{/fmt}}{{#fmt}}{{{docstring}}}{{/fmt}}
{{/.}}`; Mustache.parse(endpointtmpl); $("#api_endpoints").append($(Mustache.render(endpointtmpl, epl))); }) .fail(function(jqXHR, textStatus, errorThrown) { alert("Server failure: " + _.get(jqXHR, "responseText", textStatus))}) }) }) ``` -------------------------------- ### Apache Configuration for Authorized External Previews Source: https://github.com/slaclab/explgbk/blob/master/static/html/docs/devguides/external_previews.html This Apache configuration block defines a `LocationMatch` rule to serve protected images. It aliases requests to a local file path, sets an environment variable from a cookie, and enforces authorization by comparing a hashed experiment name with the cookie value. ```Apache Configuration [^/]+)/(?.*)$"> Alias "/nfs/slac/dept/protected_images/%{env:MATCH_EXPNAME}/%{env:MATCH_FILENAME}" SetEnvIf Cookie "LGBK_EXT_PREVIEW=([^;]+)" HASHED_PREVIEW_COOKIE=$1 Require expr "%{{base64:%{md5:%{reqenv:MATCH_EXPNAME}SLACExpLgBk}} == %{unescape:%{reqenv:HASHED_PREVIEW_COOKIE}}" ``` -------------------------------- ### Adding Image Parameter Description to MongoDB Source: https://github.com/slaclab/explgbk/blob/master/static/html/docs/devguides/external_previews.html This MongoDB shell command adds a new run parameter description for 'preview' to the 'site' database. This defines 'preview' as an 'image/png' type, allowing it to be rendered as an image in run tables. ```MongoDB Shell use site db.run_param_descriptions.insertOne( { "param_name" : "preview", "category" : "Previews and other Images", "description" : "The main preview", "type": "image/png" }) ``` -------------------------------- ### Importing UI Components - JavaScript Source: https://github.com/slaclab/explgbk/blob/master/templates/ops.html This line imports a collection of shared UI components from a static JavaScript file. These components are likely used to build the interactive elements of the operator dashboard, ensuring a consistent user interface. ```JavaScript import "../../static/html/components/all.js"; ``` -------------------------------- ### Setting Up Shift Management Toolbar (JavaScript) Source: https://github.com/slaclab/explgbk/blob/master/static/html/tabs/shifts.html This function initializes and appends a 'new shift' button to the page's toolbar. Clicking this button triggers the `edit_shift` function, pre-populating the leader field with the currently logged-in user's information. ```JavaScript let setupToolBar = function() { var tab_toolbar = ``; var toolbar_rendered = $(tab_toolbar); $("#toolbar_for_tab").append(toolbar_rendered); $("#new_shift").on("click", function(e){ $("#shifts_tab").data("edit_shift")({leader: logged_in_user})}); }; setupToolBar(); ``` -------------------------------- ### MongoDB Run Parameter Description Document Source: https://github.com/slaclab/explgbk/blob/master/static/html/docs/devguides/db_details.html This JSON snippet shows the structure of a document in the `run_param_descriptions` collection. It maps a parameter name (typically an EPICS PV) to its human-readable description, providing context for the `params` field found in the 'runs' collection documents. ```JSON { "param_name" : "AT1L0:SOLID:MPA:01:POS_STATE_RBV", "description" : "at1l0_SolidAttenuator_1" } ``` -------------------------------- ### Inspecting MongoDB Collections for an LCLS Experiment Source: https://github.com/slaclab/explgbk/blob/master/static/html/docs/devguides/db_details.html This snippet demonstrates how to switch to an experiment-specific MongoDB database and list its collections. It shows the typical collections found within an LCLS experiment database, such as 'runs', 'file_catalog', and 'elog', which store various types of data and metadata related to the experiment. ```MongoDB Shell < use diadaq13 switched to db diadaq13 < db.getCollectionNames() [ "runs", "file_catalog", "roles", "samples", "run_tables", "workflow_definitions", "workflow_jobs", "elog", "info", "run_param_descriptions", "shifts" ] ``` -------------------------------- ### Adding Run Parameters with External Image URL via cURL Source: https://github.com/slaclab/explgbk/blob/master/static/html/docs/devguides/external_previews.html This cURL command adds multiple run parameters, including 'voltage', 'current', 'resistance', and 'preview'. The 'preview' parameter is set to a direct URL of an external image, which will be displayed in the run table. ```Shell curl -H "Content-Type: application/json" -XPOST "https://localhost/psdm/run_control/A_Test_Experiment/ws/add_run_params" -d '{ "voltage":120.0, "current":1.20, "resistance": 0.01, "preview": "https://www6.slac.stanford.edu/sites/www6.slac.stanford.edu/files/SLAC-lab-lowres.jpg" }' ``` -------------------------------- ### Experiment Information Document - MongoDB/JSON Source: https://github.com/slaclab/explgbk/blob/master/static/html/docs/devguides/db_details.html This snippet defines the structure of a single document containing information about an experiment. It includes details like experiment name, instrument, start/end times, leader account, contact information, POSIX group, and a flexible 'params' object for miscellaneous key-value pairs. ```JSON { "_id" : "experiment_name", "name" : "experiment_name", "instrument" : "XPP", "description" : "Description for the experiment", "start_time" : ISODate("2021-03-06T17:00:00Z"), "end_time" : ISODate("2021-03-11T05:00:00Z"), "leader_account" : "leader_unix_account", "contact_info" : "Principal Investigator (principal.investigator@gmail.com)", "posix_group" : "experiment_name", "params" : { "PNR" : "Proposal ID from the user portal", "zoom_meeting_id" : "917 1111 1111", "zoom_meeting_pwd" : "5555555", "zoom_meeting_url" : "https://zoom.us/j/9171111111?pwd=kerplunk", "dm_locations" : "SRCF_FFB" } } ``` -------------------------------- ### Managing Experiment Info and Questionnaire Display (JavaScript) Source: https://github.com/slaclab/explgbk/blob/master/static/html/ms/info_LCLS.html This JavaScript code block handles the 'info_loaded' event for the experiment information tab. It manages the display and editing of experiment parameters based on user privileges, dynamically fetching and rendering input forms. Additionally, it integrates and displays a URAWI questionnaire by embedding an iframe and fetching related proposal attributes (like Points of Contact) via AJAX, rendering them using Mustache. ```JavaScript $("#info_tab").on("info_loaded", function(ev, info){ if(!_.get(privileges, "feedback_write", false)) { $("#info_tab").find(".param_edit").addClass("d-none"); } $("#info_tab").find(".param_edit").on("click", function(){ let param_name = $(this).attr("data-param-name"), param_value = _.get(info, param_name), param_title = $(this).attr("data-param-title"), param_msg = $(this).attr("data-param-message"); $.ajax ("../../static/html/ms/gen_oneinput.html") .done(function(d0){ console.log(param_msg); let rendered = $(Mustache.render(d0, { title: param_title, message: param_msg, btnlbl: "Submit", curvalue: param_value })); rendered.find(".gen_input_submit").on("click", function(){ let update_param_value = rendered.find(".gen_input").val(), updated_params = _.set({}, _.replace(param_name, "params.", ""), update_param_value); $.post({url: "ws/add_update_experiment_params", data: JSON.stringify(updated_params), contentType: "application/json; charset=utf-8", dataType: "json"}) .done(function(data, textStatus, jqXHR) { if(data.success) { $("#glbl_modals_go_here").find(".modal").modal("hide"); window.location.reload(true); } else { error_message("Server side exception updating experiment parameter " + data.errormsg); } }) .fail( function(jqXHR, textStatus, errorThrown) { error_message("Server side HTTP updating experiment parameter " + textStatus); }) }) $("#glbl_modals_go_here").empty().append(rendered); $("#glbl_modals_go_here").find(".modal").on("hidden.bs.modal", function(){ $("#glbl_modals_go_here").empty(); }); $("#glbl_modals_go_here").find(".modal").modal("show"); }) }) if(_.has(info, "params.PNR") && !_.isEqual(_.get(info, "params.PNR"), "N/A")) { $("#info_tab").find(".ques_embed").prepend($("

Questionnaire

")); let run_period = "run"+_.get(info, "params.run_period", experiment_name.slice(experiment_name.length - 2)); let questionnaire_prefix = "../../../questionnaire_slac"; if(_.has(info, "instrument_info.params.questionnaire_prefix")) { questionnaire_prefix = _.get(info, "instrument_info.params.questionnaire_prefix"); console.log("Questionnaire prefix override", questionnaire_prefix); } $.getJSON(questionnaire_prefix + "/ws/questionnaire/urawidata/" + run_period + "/" + _.get(info, "params.PNR")) .done(function(ques_data){ let questionnaire_url = questionnaire_prefix + "/proposal_questionnaire/" + run_period + "/" + _.get(info, "params.PNR") + "/?hideHeader=true"; $("#info_tab").find(".ques_tabs").first().append(''); $(document).on("resize_embedded_iframe", function(ev, newh){ console.log("Changing embedded IFrame's height to " + newh); $("#info_tab").find(".sitespecific_iframe").height(newh); }) $.getJSON("../../../questionnaire_slac/ws/proposal/attribute/" + run_period + '/' + _.get(info, "params.PNR")) .done(function(ques_attr){ console.log(ques_attr); var pocs = _.fromPairs(_.filter(_.map(_.get(ques_attr, "personnel"), function(ps) { if(_.get(ps, "id") == "personnel-poc-sci1" || _.get(ps, "id") == "personnel-poc-sci2") return [_.get(ps, "id"), _.get(ps, "val")]; }))); var poctmpl = "{{#personnel-poc-sci1}}
POC 1:{{personnel-poc-sci1}}
{{/personnel-poc-sci1}}{{#personnel-poc-sci2}}
POC 2:{{personnel-poc-sci2}}
{{/personnel-poc-sci2}}"; $("#info_tab").find(".exp_details").first().append(Mustache.render(poctmpl, pocs, {})); }).fail(function(){ console.log("Cannot get personnel from the questionnaire."); }); }).fail(function() { $("#info_tab").find(".ques_tabs").append($('

Cannot load questionnaire for this proposal.

')); }); } ``` -------------------------------- ### Defining Workflow Definition Schema in JSON Source: https://github.com/slaclab/explgbk/blob/master/static/html/docs/devguides/db_details.html This JSON snippet illustrates the schema for a 'workflow definition' document, used by the ARP (Automated Run Processing) system. It includes fields such as the workflow name, the absolute path to the executable, additional parameters, the LCLS DM event trigger (e.g., 'START_OF_RUN'), the SLURM user ID for execution, and the DM location where the workflow is to be executed. ```JSON { "_id" : ObjectId("5f45xxx"), "name" : "#submit_offbyone", "executable" : "/reg/g/psdm/utils/arp/offbyone", "parameters" : "", "trigger" : "START_OF_RUN", "run_as_user" : "userid", "location" : "SLAC" } ``` -------------------------------- ### Adding Run Parameters with Authorized Image URL via cURL Source: https://github.com/slaclab/explgbk/blob/master/static/html/docs/devguides/external_previews.html This cURL command adds run parameters, using the 'ws/ext_preview' service for the 'preview' parameter. This approach is used when images require authorization, as the application will handle the redirect and cookie for secure access. ```Shell curl -H "Content-Type: application/json" -XPOST "https://localhost/psdm/run_control/A_Test_Experiment/ws/add_run_params" -d '{ "voltage":120.0, "current":1.20, "resistance": 0.01, "preview": "ws/ext_preview/protected_images/<**_experiment_name_**>/sample.png" }' ``` -------------------------------- ### Styling Body Element - CSS Source: https://github.com/slaclab/explgbk/blob/master/static/html/docs/roles.html This CSS snippet defines basic styling for the `body` element of an HTML document. It sets the width, height, and padding, likely for print-friendly or fixed-layout pages within the application. This ensures consistent page dimensions and spacing. ```CSS body { width: 8.5in; height: 11in; padding: 1.0em; } ``` -------------------------------- ### Defining Custom Parameters for Samples Modal (JSON) Source: https://github.com/slaclab/explgbk/blob/master/static/html/docs/devguides/custom_params.html This JSON configuration defines a set of custom parameters for the 'samples' modal. It specifies various fields like imaging_method, imaging_software, imaging_format, superres, phase_plate, pixel_density, and fmdose, along with their labels, types (enum, bool, int, float), required status, options for enums, and descriptions. This structure allows for flexible and validated input fields in the UI. ```JSON { "_id" : "samples", "params" : [ { "param_name" : "imaging_method", "label": "Imaging method", "required" : true, "param_type" : "enum", "options" : [ "single-particle", "tomography" ], "description": "Long description about the imaging method." }, { "param_name" : "imaging_software", "label": "Imaging software", "required" : true, "param_type" : "enum", "options" : [ "EPU", "SerialEM" ] }, { "param_name" : "imaging_format", "label": "Imaging Format", "required" : true, "param_type" : "enum", "options" : [ ".tif", ".mrc" ] }, { "param_name" : "superres", "required" : true, "param_type" : "enum", "options" : [ { "label" : "Yes", "value" : 1 }, { "label" : "No", "value" : 0 } ], "label" : "Super Resolution", "description" : "Are the frames saved as super resolution? Note that K3 frames are always saved as super resolution so please choose yes." }, { "param_name" : "phase_plate", "label": "Phase plate used?", "param_type" : "bool", "required" : true }, { "param_name" : "pixel_density", "label": "Pixel density (in dpi)", "param_type" : "int", "required" : true }, { "param_name" : "fmdose", "param_type" : "float" } ] } ``` -------------------------------- ### Terminating the Current Run via cURL Source: https://github.com/slaclab/explgbk/blob/master/static/html/docs/devguides/external_previews.html This cURL command concludes the active run for 'A_Test_Experiment'. It should be executed once all desired run parameters have been set. ```Shell curl -s "https://localhost/psdm/run_control/A_Test_Experiment/ws/end_run" ``` -------------------------------- ### Styling Body Element - CSS Source: https://github.com/slaclab/explgbk/blob/master/static/html/docs/devguides/pagination.html Applies basic styling to the HTML body element, setting its width, height, and padding. This is a general CSS rule, not directly part of the widget's core functionality but might be used in a page utilizing it. ```CSS body { width: 8.5in; height: 11in; padding: 1.0em; } ``` -------------------------------- ### Role-Based Access Control Data Model (JSON) Source: https://github.com/slaclab/explgbk/blob/master/static/html/docs/devguides/db_details.html This JSON snippet defines the structure for a role within the LCLS DM's role-based access control system. It specifies the application the role applies to (e.g., 'LogBook'), the role's name (e.g., 'Writer'), and a list of 'players' (groups or individual user IDs) assigned to that role. Privileges associated with the role are managed globally in the 'site' database. ```JSON { "_id" : ObjectId("602d9xxx"), "app" : "LogBook", "name" : "Writer", "players" : [ "experiment_specific_group", "uid:collaborator1", "uid:collaborator2" ] } ``` ```JSON "privileges" : [ "post", "read" ] ``` -------------------------------- ### Fetching and Rendering Shift List in jQuery Source: https://github.com/slaclab/explgbk/blob/master/static/html/tabs/shifts.html This code defines a Mustache template for rendering shift table rows. It then fetches shift data and the latest active shift from two different backend endpoints using `$.getJSON`. The fetched data is processed to mark the latest shift, formatted, and then rendered into the UI using the Mustache template. ```javascript var shift_tr_tmpl = "{{#value}}{{ name }}{{#FormatDate}}{{begin_time}}{{/FormatDate}}{{#FormatDate}}{{end_time}}{{/FormatDate}}{{ leader }}{{ description }}{{/value}}"; Mustache.parse(shift_tr_tmpl); $.when($.getJSON("ws/shifts"), $.getJSON("ws/get_latest_shift")) .done(function(d0, d1){ var shift_data = d0[0], latest_shift = d1[0], latest_shift_data = _.find(shift_data.value, function(o){ return o.name == _.get(latest_shift, 'value.name', ''); }); if(latest_shift_data){ latest_shift_data['latest'] = true; } shift_data.FormatDate = elog_formatdatetime; $("#shifts_tab").data("shifts", shift_data); var rendered = $(Mustache.render(shift_tr_tmpl, shift_data)); ``` -------------------------------- ### Defining Run Table Schema in JSON Source: https://github.com/slaclab/explgbk/blob/master/static/html/docs/devguides/db_details.html This JSON snippet defines the schema for a 'run table' document, used to represent tabular data and graphs of run parameters in the SLAC Lab Experiment Logbook. It specifies properties like name, description, editability, table type (e.g., 'table', 'histogram', 'scatter'), sort index, and column definitions (coldefs) including labels, data sources, types, and positions. The 'coldefs' array details how individual columns are structured and sourced from run documents. ```JSON { "_id" : ObjectId("619xxx"), "name" : "test table", "description" : "scan info", "is_editable" : true, "table_type" : "table", "sort_index" : 100, "coldefs" : [ { "label" : "scan motor", "type" : "EPICS/Scan Info", "source" : "params.XPP:SCAN:SCANVAR00", "is_editable" : false, "position" : 0 }, { "label" : "", "type" : "EPICS/Scan Info", "source" : "params.XPP:SCAN:MIN00", "is_editable" : false, "position" : 1 }, { "label" : "", "type" : "EPICS/Scan Info", "source" : "params.XPP:SCAN:MAX00", "is_editable" : false, "position" : 2 }, { "label" : "comments", "type" : "Editables", "source" : "editable_params.comments.value", "is_editable" : true, "position" : 3 } ] } ```