Initial commit
13
#migrate/#migrate.Rproj
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
Version: 1.0
|
||||
|
||||
RestoreWorkspace: Default
|
||||
SaveWorkspace: Default
|
||||
AlwaysSaveHistory: Default
|
||||
|
||||
EnableCodeIndexing: Yes
|
||||
UseSpacesForTab: Yes
|
||||
NumSpacesForTab: 2
|
||||
Encoding: UTF-8
|
||||
|
||||
RnwWeave: Sweave
|
||||
LaTeX: pdfLaTeX
|
||||
BIN
#migrate/.RData
Normal file
275
#migrate/migrate-runs.R
Normal file
|
|
@ -0,0 +1,275 @@
|
|||
#!/usr/bin/env Rscript
|
||||
# =============================================================================
|
||||
# migrate-runs.R
|
||||
#
|
||||
# Dupliziert alle Runs von Nutzer A auf Nutzer B über die formr-API v1.
|
||||
# Die in den Runs liegenden Surveys werden dabei serverseitig als eigene
|
||||
# Kopien unter Nutzer B neu angelegt (leere results_table). Surveys, die in
|
||||
# KEINEM Run hängen, werden bewusst nicht angefasst.
|
||||
#
|
||||
# Hintergrund und Gesamtplan: docs/zweiter-nutzer-einrichten.md (Teil A.2b, E)
|
||||
#
|
||||
# Ablauf:
|
||||
# Phase 1 (als Nutzer A, Scope run:read [+ file:read]):
|
||||
# GET /v1/runs/{name}/structure -> JSON pro Run nach WORKDIR/structures/
|
||||
# Phase 2 (als Nutzer B, Scope run:write [+ file:write]):
|
||||
# POST /v1/runs/{name-} -> leeren Run anlegen
|
||||
# PUT /v1/runs/{name-}/structure-> Struktur (inkl. Surveys) importieren
|
||||
#
|
||||
# Es kann immer nur EINE API-Session aktiv sein, daher die zwei Phasen.
|
||||
# Das Skript ist wiederholbar: bereits angelegte Ziel-Runs werden übersprungen.
|
||||
#
|
||||
# -----------------------------------------------------------------------------
|
||||
# EINMALIGE EINRICHTUNG (im R-Prompt, NICHT in dieser Datei):
|
||||
#
|
||||
# install.packages("keyring")
|
||||
# remotes::install_github("rubenarslan/formr") # formr ist nicht auf CRAN
|
||||
# library(formr)
|
||||
#
|
||||
# # client_id / client_secret aus dem formr-Panel (admin/account -> API
|
||||
# # credentials). Werte NUR hier interaktiv eingeben, nie in Dateien.
|
||||
# formr_store_keys(host = "https://diagnostik.karneboge.de/api",
|
||||
# client_id = "<CLIENT-ID-NUTZER-A>",
|
||||
# client_secret = "<SECRET-NUTZER-A>",
|
||||
# account = "mig_read")
|
||||
# formr_store_keys(host = "https://diagnostik.karneboge.de/api",
|
||||
# client_id = "<CLIENT-ID-NUTZER-B>",
|
||||
# client_secret = "<SECRET-NUTZER-B>",
|
||||
# account = "mig_write")
|
||||
#
|
||||
# Client A braucht Scope: run:read (optional zusätzlich file:read)
|
||||
# Client B braucht Scope: run:write (optional zusätzlich file:write)
|
||||
# Beide OHNE Run-Einschränkung. Nach der Migration beide Clients löschen.
|
||||
#
|
||||
# VPN muss verbunden sein (die /api ist auf die VPN-IP beschränkt).
|
||||
# =============================================================================
|
||||
|
||||
|
||||
# ==== 1. KONFIGURATION =======================================================
|
||||
|
||||
HOST <- "https://diagnostik.karneboge.de/api"
|
||||
ACC_READ <- "mig_read" # keyring-account Nutzer A (siehe Einrichtung oben)
|
||||
ACC_WRITE <- "mig_write" # keyring-account Nutzer B
|
||||
|
||||
SUFFIX <- "-" # Ziel-Run-Name = Quell-Name + SUFFIX (z. B. phq9 -> phq9-)
|
||||
|
||||
ONLY <- NULL # NULL = alle Runs. Für den Testlauf: c("phq9", "gad7")
|
||||
|
||||
DRY_RUN <- FALSE # TRUE: nichts schreiben, nur anzeigen was passieren würde.
|
||||
# Erst nach erfolgreichem Testlauf auf FALSE setzen.
|
||||
|
||||
DO_FILES <- TRUE # TRUE: in Runs hochgeladene Dateien (Bildmaterial in
|
||||
# Fragebögen) mitkopieren. Braucht file:read / file:write.
|
||||
|
||||
# Arbeitsverzeichnis (Export-JSONs + Log + ggf. Dateien). Standard: Unterordner
|
||||
# neben diesem Skript.
|
||||
WORKDIR <- NULL # NULL = <skriptordner>/run-migration ; sonst fester Pfad
|
||||
|
||||
|
||||
# ==== 2. VORBEREITUNG ========================================================
|
||||
|
||||
if (!requireNamespace("formr", quietly = TRUE)) {
|
||||
stop("Paket 'formr' fehlt: remotes::install_github('rubenarslan/formr')", call. = FALSE)
|
||||
}
|
||||
for (p in c("keyring", "jsonlite")) {
|
||||
if (!requireNamespace(p, quietly = TRUE)) {
|
||||
stop("Paket '", p, "' fehlt: install.packages('", p, "')", call. = FALSE)
|
||||
}
|
||||
}
|
||||
library(formr)
|
||||
|
||||
.script_dir <- tryCatch({
|
||||
cmd <- commandArgs(FALSE)
|
||||
f <- sub("^--file=", "", grep("^--file=", cmd, value = TRUE))
|
||||
if (length(f) == 1L) {
|
||||
dirname(normalizePath(f))
|
||||
} else if (requireNamespace("rstudioapi", quietly = TRUE) &&
|
||||
rstudioapi::isAvailable() &&
|
||||
nzchar(rstudioapi::getSourceEditorContext()$path)) {
|
||||
dirname(normalizePath(rstudioapi::getSourceEditorContext()$path))
|
||||
} else {
|
||||
getwd()
|
||||
}
|
||||
}, error = function(e) getwd())
|
||||
|
||||
if (is.null(WORKDIR)) WORKDIR <- file.path(.script_dir, "run-migration")
|
||||
dir.create(file.path(WORKDIR, "structures"), recursive = TRUE, showWarnings = FALSE)
|
||||
|
||||
message("Arbeitsverzeichnis: ", normalizePath(WORKDIR))
|
||||
message("Modus: ", if (DRY_RUN) "DRY-RUN (nichts wird geschrieben)" else ">>> SCHREIBEND <<<")
|
||||
if (!is.null(ONLY)) message("Nur diese Runs: ", paste(ONLY, collapse = ", "))
|
||||
message("")
|
||||
|
||||
# gültiger formr-Run-Name: Buchstabe vorn, dann a-z A-Z 0-9 - , Länge 3..256
|
||||
valid_run_name <- function(x) grepl("^[a-zA-Z][a-zA-Z0-9-]{2,255}$", x)
|
||||
|
||||
# Log-Sammler
|
||||
LOG <- new.env()
|
||||
LOG$rows <- list()
|
||||
log_add <- function(phase, src, dst = NA, status, units_src = NA, units_dst = NA, message = "") {
|
||||
LOG$rows[[length(LOG$rows) + 1L]] <- data.frame(
|
||||
ts = format(Sys.time(), "%Y-%m-%d %H:%M:%S"),
|
||||
phase = phase, src = src, dst = dst, status = status,
|
||||
units_src = units_src, units_dst = units_dst, message = message,
|
||||
stringsAsFactors = FALSE
|
||||
)
|
||||
}
|
||||
|
||||
# leere JSON-Objekte {} -> null (der Server verträgt {} in manchen Feldern nicht;
|
||||
# gleiche Korrektur wie in formr_api_push_project)
|
||||
clean_structure_json <- function(path) {
|
||||
txt <- paste(readLines(path, warn = FALSE), collapse = "\n")
|
||||
txt2 <- gsub('":[[:space:]]*\\{\\}', '": null', txt)
|
||||
if (!identical(txt, txt2)) writeLines(txt2, path)
|
||||
}
|
||||
|
||||
|
||||
# ==== 3. PHASE 0 – Run-Liste von Nutzer A ====================================
|
||||
|
||||
message("== Phase 0: Run-Liste abrufen (Nutzer A) ==")
|
||||
formr_api_authenticate(host = HOST, account = ACC_READ, verbose = FALSE)
|
||||
runs_a <- formr_api_runs()
|
||||
formr_api_logout(verbose = FALSE)
|
||||
|
||||
if (!nrow(runs_a)) stop("Nutzer A hat keine Runs (oder Client-Scope fehlt).", call. = FALSE)
|
||||
|
||||
src_names <- runs_a$name
|
||||
if (!is.null(ONLY)) {
|
||||
missing <- setdiff(ONLY, src_names)
|
||||
if (length(missing)) message(" Nicht bei Nutzer A gefunden: ", paste(missing, collapse = ", "))
|
||||
src_names <- intersect(src_names, ONLY)
|
||||
}
|
||||
if (!length(src_names)) stop("Keine Runs zur Migration ausgewählt.", call. = FALSE)
|
||||
message(" ", length(src_names), " Run(s) vorgemerkt.\n")
|
||||
|
||||
|
||||
# ==== 4. PHASE 1 – Struktur exportieren (Nutzer A) ==========================
|
||||
|
||||
message("== Phase 1: Struktur exportieren (Nutzer A) ==")
|
||||
formr_api_authenticate(host = HOST, account = ACC_READ, verbose = FALSE)
|
||||
|
||||
for (src in src_names) {
|
||||
jf <- file.path(WORKDIR, "structures", paste0(src, ".json"))
|
||||
tryCatch({
|
||||
st <- formr_api_run_structure(src)
|
||||
jsonlite::write_json(st, jf, pretty = TRUE, auto_unbox = TRUE)
|
||||
clean_structure_json(jf)
|
||||
n <- length(st$units)
|
||||
message(sprintf(" [export] %-42s %3d units", src, n))
|
||||
log_add("export", src, status = "ok", units_src = n)
|
||||
|
||||
if (DO_FILES) {
|
||||
fdf <- tryCatch(formr_api_files(src, verbose = FALSE),
|
||||
error = function(e) data.frame())
|
||||
if (nrow(fdf)) {
|
||||
fd <- file.path(WORKDIR, "files", src)
|
||||
dir.create(fd, recursive = TRUE, showWarnings = FALSE)
|
||||
for (i in seq_len(nrow(fdf))) {
|
||||
dest <- file.path(fd, basename(fdf$name[i]))
|
||||
tryCatch(
|
||||
utils::download.file(fdf$url[i], dest, mode = "wb", quiet = TRUE),
|
||||
error = function(e) message(" Datei-Download fehlgeschlagen: ", fdf$name[i])
|
||||
)
|
||||
}
|
||||
message(sprintf(" %d Datei(en) gesichert", nrow(fdf)))
|
||||
}
|
||||
}
|
||||
}, error = function(e) {
|
||||
message(sprintf(" [export] %-42s FEHLER: %s", src, conditionMessage(e)))
|
||||
log_add("export", src, status = "error", message = conditionMessage(e))
|
||||
})
|
||||
}
|
||||
|
||||
formr_api_logout(verbose = FALSE)
|
||||
message("")
|
||||
|
||||
|
||||
# ==== 5. PHASE 2 – Runs anlegen + Struktur importieren (Nutzer B) ===========
|
||||
|
||||
message("== Phase 2: Runs anlegen + importieren (Nutzer B) ==")
|
||||
formr_api_authenticate(host = HOST, account = ACC_WRITE, verbose = FALSE)
|
||||
|
||||
existing_b <- formr_api_runs()
|
||||
existing_b_names <- if (nrow(existing_b)) existing_b$name else character(0)
|
||||
|
||||
for (src in src_names) {
|
||||
jf <- file.path(WORKDIR, "structures", paste0(src, ".json"))
|
||||
dst <- paste0(src, SUFFIX)
|
||||
|
||||
if (!file.exists(jf)) {
|
||||
message(sprintf(" [skip] %-42s kein Export vorhanden", src))
|
||||
log_add("import", src, dst, status = "skipped", message = "kein Export-JSON")
|
||||
next
|
||||
}
|
||||
if (!valid_run_name(dst)) {
|
||||
message(sprintf(" [skip] %-42s Ziel-Name '%s' ungültig", src, dst))
|
||||
log_add("import", src, dst, status = "skipped", message = "Ziel-Name ungültig")
|
||||
next
|
||||
}
|
||||
if (dst %in% existing_b_names) {
|
||||
message(sprintf(" [skip] %-42s '%s' existiert schon", src, dst))
|
||||
log_add("import", src, dst, status = "skipped", message = "Ziel-Run existiert")
|
||||
next
|
||||
}
|
||||
|
||||
st_src <- jsonlite::read_json(jf)
|
||||
n_src <- length(st_src$units)
|
||||
|
||||
if (DRY_RUN) {
|
||||
message(sprintf(" [dry] %-42s -> %-44s (%d units)", src, dst, n_src))
|
||||
log_add("import", src, dst, status = "dry-run", units_src = n_src)
|
||||
next
|
||||
}
|
||||
|
||||
tryCatch({
|
||||
formr_api_create_run(dst, verbose = FALSE)
|
||||
formr_api_run_structure(dst, structure_json_path = jf, verbose = FALSE)
|
||||
|
||||
chk <- formr_api_run_structure(dst)
|
||||
n_dst <- length(chk$units)
|
||||
ok <- n_dst >= n_src
|
||||
message(sprintf(" [import] %-42s -> %-44s %d/%d units %s",
|
||||
src, dst, n_dst, n_src, if (ok) "OK" else "!! UNVOLLSTÄNDIG"))
|
||||
log_add("import", src, dst,
|
||||
status = if (ok) "ok" else "incomplete",
|
||||
units_src = n_src, units_dst = n_dst)
|
||||
|
||||
if (DO_FILES) {
|
||||
fd <- file.path(WORKDIR, "files", src)
|
||||
if (dir.exists(fd) && length(list.files(fd))) {
|
||||
tryCatch({
|
||||
formr_api_upload_file(dst, fd, verbose = FALSE)
|
||||
message(sprintf(" %d Datei(en) hochgeladen",
|
||||
length(list.files(fd))))
|
||||
}, error = function(e) message(" Datei-Upload: ", conditionMessage(e)))
|
||||
}
|
||||
}
|
||||
}, error = function(e) {
|
||||
message(sprintf(" [import] %-42s -> %-44s FEHLER: %s",
|
||||
src, dst, conditionMessage(e)))
|
||||
log_add("import", src, dst, status = "error",
|
||||
units_src = n_src, message = conditionMessage(e))
|
||||
})
|
||||
}
|
||||
|
||||
formr_api_logout(verbose = FALSE)
|
||||
message("")
|
||||
|
||||
|
||||
# ==== 6. LOG SCHREIBEN ======================================================
|
||||
|
||||
log_df <- do.call(rbind, LOG$rows)
|
||||
logf <- file.path(WORKDIR, sprintf("migration-log-%s.csv",
|
||||
format(Sys.time(), "%Y%m%d-%H%M%S")))
|
||||
utils::write.csv(log_df, logf, row.names = FALSE)
|
||||
|
||||
message("== Zusammenfassung ==")
|
||||
print(table(log_df$phase, log_df$status))
|
||||
message("\nLog: ", logf)
|
||||
|
||||
if (DRY_RUN) {
|
||||
message("\nDRY-RUN beendet. Kontrolliere die Liste oben, dann DRY_RUN <- FALSE.")
|
||||
} else {
|
||||
message("\nFertig. Nacharbeit (Footer, secrets, cron/public) siehe ",
|
||||
"docs/zweiter-nutzer-einrichten.md Teil E.7.")
|
||||
}
|
||||
6
#migrate/migrate_from_login.R
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
library(formr)
|
||||
formr_store_keys(host = "https://diagnostik.karneboge.de/api",
|
||||
client_id = "0934eacfc17353849a18ae2a25e0a926",
|
||||
client_secret = "07081cdea6c0095411c41cd77417b3b4ade12d16668ba3acd57121cf091319a2",
|
||||
account = "mig_read")
|
||||
formr_api_authenticate(host = "https://diagnostik.karneboge.de/api", account = "mig_read")
|
||||
6
#migrate/migrate_to_login.R
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
library(formr)
|
||||
formr_store_keys(host = "https://diagnostik.karneboge.de/api",
|
||||
client_id = "d49cf61350616e854d8e419c0a6511d8",
|
||||
client_secret = "9a3785aa33065f073fe1ca43c0c6955d8383838ba27dd8e03ee90044f3040c9a",
|
||||
account = "mig_write")
|
||||
formr_api_authenticate(host = "https://diagnostik.karneboge.de/api", account = "mig_write")
|
||||
BIN
#migrate/run-migration/files/IST-Screening/ist_a_41_a.png
Normal file
|
After Width: | Height: | Size: 2.6 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_41_b.png
Normal file
|
After Width: | Height: | Size: 4.1 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_41_c.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_41_d.png
Normal file
|
After Width: | Height: | Size: 2.6 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_41_e.png
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_41_stimulus.png
Normal file
|
After Width: | Height: | Size: 9.7 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_42_a.png
Normal file
|
After Width: | Height: | Size: 5.7 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_42_b.png
Normal file
|
After Width: | Height: | Size: 6.9 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_42_c.png
Normal file
|
After Width: | Height: | Size: 4.6 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_42_d.png
Normal file
|
After Width: | Height: | Size: 4.6 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_42_e.png
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_42_stimulus.png
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_43_a.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_43_b.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_43_c.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_43_d.png
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_43_e.png
Normal file
|
After Width: | Height: | Size: 2.6 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_43_stimulus.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_44_a.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_44_b.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_44_c.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_44_d.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_44_e.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_44_stimulus.png
Normal file
|
After Width: | Height: | Size: 8.3 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_45_a.png
Normal file
|
After Width: | Height: | Size: 5.9 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_45_b.png
Normal file
|
After Width: | Height: | Size: 7.2 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_45_c.png
Normal file
|
After Width: | Height: | Size: 6.1 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_45_d.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_45_e.png
Normal file
|
After Width: | Height: | Size: 2.6 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_45_stimulus.png
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_46_a.png
Normal file
|
After Width: | Height: | Size: 5.6 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_46_b.png
Normal file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_46_c.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_46_d.png
Normal file
|
After Width: | Height: | Size: 3.7 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_46_e.png
Normal file
|
After Width: | Height: | Size: 881 B |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_46_stimulus.png
Normal file
|
After Width: | Height: | Size: 8.2 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_47_a.png
Normal file
|
After Width: | Height: | Size: 920 B |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_47_b.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_47_c.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_47_d.png
Normal file
|
After Width: | Height: | Size: 4.6 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_47_e.png
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_47_stimulus.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_48_a.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_48_b.png
Normal file
|
After Width: | Height: | Size: 3.7 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_48_c.png
Normal file
|
After Width: | Height: | Size: 3.2 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_48_d.png
Normal file
|
After Width: | Height: | Size: 3.2 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_48_e.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_48_stimulus.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_49_a.png
Normal file
|
After Width: | Height: | Size: 7.7 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_49_b.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_49_c.png
Normal file
|
After Width: | Height: | Size: 8.1 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_49_d.png
Normal file
|
After Width: | Height: | Size: 7.2 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_49_e.png
Normal file
|
After Width: | Height: | Size: 7.2 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_49_stimulus.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_50_a.png
Normal file
|
After Width: | Height: | Size: 4.3 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_50_b.png
Normal file
|
After Width: | Height: | Size: 6.5 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_50_c.png
Normal file
|
After Width: | Height: | Size: 899 B |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_50_d.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_50_e.png
Normal file
|
After Width: | Height: | Size: 905 B |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_50_stimulus.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_51_a.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_51_b.png
Normal file
|
After Width: | Height: | Size: 926 B |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_51_c.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_51_d.png
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_51_e.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_51_stimulus.png
Normal file
|
After Width: | Height: | Size: 8.8 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_52_a.png
Normal file
|
After Width: | Height: | Size: 7.4 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_52_b.png
Normal file
|
After Width: | Height: | Size: 7 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_52_c.png
Normal file
|
After Width: | Height: | Size: 7.4 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_52_d.png
Normal file
|
After Width: | Height: | Size: 8 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_52_e.png
Normal file
|
After Width: | Height: | Size: 8.4 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_52_stimulus.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_53_a.png
Normal file
|
After Width: | Height: | Size: 7.9 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_53_b.png
Normal file
|
After Width: | Height: | Size: 2 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_53_c.png
Normal file
|
After Width: | Height: | Size: 9 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_53_d.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_53_e.png
Normal file
|
After Width: | Height: | Size: 9.2 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_53_stimulus.png
Normal file
|
After Width: | Height: | Size: 21 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_54_a.png
Normal file
|
After Width: | Height: | Size: 4.6 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_54_b.png
Normal file
|
After Width: | Height: | Size: 4.9 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_54_c.png
Normal file
|
After Width: | Height: | Size: 4 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_54_d.png
Normal file
|
After Width: | Height: | Size: 4.6 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_54_e.png
Normal file
|
After Width: | Height: | Size: 6.4 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_54_stimulus.png
Normal file
|
After Width: | Height: | Size: 9.9 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_55_a.png
Normal file
|
After Width: | Height: | Size: 6.4 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_55_b.png
Normal file
|
After Width: | Height: | Size: 8.2 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_55_c.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_55_d.png
Normal file
|
After Width: | Height: | Size: 7.9 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_55_e.png
Normal file
|
After Width: | Height: | Size: 9.5 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_55_e_v2.png
Normal file
|
After Width: | Height: | Size: 9.3 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_55_stimulus.png
Normal file
|
After Width: | Height: | Size: 27 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_56_a.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_56_b.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_56_c.png
Normal file
|
After Width: | Height: | Size: 3.2 KiB |
BIN
#migrate/run-migration/files/IST-Screening/ist_a_56_d.png
Normal file
|
After Width: | Height: | Size: 15 KiB |