Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Jspsych Surveys #24

Merged
merged 42 commits into from
May 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
deb22fb
Update readme
okaycj Mar 22, 2024
2ffde67
Update eslint package to fix warning message
okaycj Mar 22, 2024
9eb1b96
Add exit survey pacakge
okaycj Mar 22, 2024
43e507e
exit survey
okaycj Mar 22, 2024
cc98017
Use survey_function to format survey text
okaycj Mar 26, 2024
aebc86c
edit exit survey question titles and descriptions
becky-gilbert Mar 27, 2024
1d6edcb
change question names and MC values to match EFP names
becky-gilbert Mar 27, 2024
ec75dee
add withdrawal and feedback questions
becky-gilbert Mar 27, 2024
bf8878f
Change package name, exit survey parameters
okaycj Mar 27, 2024
2328104
Fixed typing
okaycj Mar 27, 2024
2e9b691
Added privacy and databrary params
okaycj Mar 27, 2024
1b78ea0
Update API to get a study
okaycj Mar 28, 2024
471b96b
Get study to add to withdraw copu
okaycj Mar 28, 2024
afe5d14
Add MD link
okaycj Mar 28, 2024
e2eba50
disable the video sharing questions if video withdrawal is true
becky-gilbert Mar 28, 2024
36be231
add support for private level only option for media use question
becky-gilbert Mar 28, 2024
90761bf
Merge branch 'jspsych-surveys' of https://github.com/lookit/lookit-js…
becky-gilbert Mar 28, 2024
3d999b8
fix private_level_only so that value is private in data
becky-gilbert Mar 28, 2024
1d428f2
Add global data store
okaycj Apr 1, 2024
a69de96
fix withdrawal question value in data and logic for enabling/disablin…
becky-gilbert Apr 1, 2024
c227f3f
add validation for child birthdate: cannot be a future date
becky-gilbert Apr 1, 2024
9e254a7
Combine helpers and api into new package called data
okaycj Apr 3, 2024
3f6fef9
Update root package
okaycj Apr 3, 2024
5ba5109
Update initjspych to use new data structure
okaycj Apr 3, 2024
2bfc2d7
Update survey to use new data structure
okaycj Apr 3, 2024
1aa1f98
Moved exit survey function to utils
okaycj Apr 3, 2024
111bf90
First pass at tests
okaycj Apr 9, 2024
c6017df
Add consent servey plugin
okaycj Apr 10, 2024
40adad1
These packages are needed when building in linux environment
okaycj Apr 10, 2024
eb9e31d
Add data finish function
okaycj Apr 10, 2024
9e36eeb
Remove unneeded comments
okaycj Apr 10, 2024
a7f0e08
Added text markdown to consent survey
okaycj Apr 10, 2024
5cb89d2
Update tests
okaycj Apr 11, 2024
51deb02
Update versions of deps
okaycj Apr 11, 2024
c4f2cf8
Update to getUuids
okaycj Apr 16, 2024
cf81bd4
freeze loaded data
okaycj Apr 18, 2024
ceb94d7
install jspsych/plugin-survey from npm and fix compatibility (pass ob…
becky-gilbert May 1, 2024
f9019f2
replace exit.json with exit_json.ts and fix import
becky-gilbert May 1, 2024
ae527c6
fix linting errors
becky-gilbert May 1, 2024
c620bae
fix failing data test due to syntax error in untranspiled deep-freeze…
becky-gilbert May 2, 2024
2048267
fix linting error
becky-gilbert May 2, 2024
111ac52
Needed to adjust ts config to build.
okaycj May 6, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ module.exports = {
},
plugins: ["@typescript-eslint"],
ignorePatterns: ["packages/**/dist/*"],
rules: { "require-await": "error" },
};
1 change: 1 addition & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{
"jsonRecursiveSort": true,
"plugins": [
"prettier-plugin-packagejson",
"prettier-plugin-sort-json",
Expand Down
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ Add build and test script to new package's `package.json`:
```json
"scripts": {
"test": "jest --coverage",
"dev": "rollup --config rollup.config.dev.mjs --watch",
"build": "rollup --config"
},
```
Expand Down Expand Up @@ -53,8 +54,8 @@ Edit `tsconfig.json`:
```json
{
"compilerOptions": {
"strict": true,
"baseUrl": "."
"baseUrl": ".",
"strict": true
},
"extends": "@jspsych/config/tsconfig.core.json",
"include": ["src"]
Expand Down
2,405 changes: 1,356 additions & 1,049 deletions package-lock.json

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,15 @@
"scripts": {
"build": "npm run build --workspaces",
"changeset": "changeset",
"fix": "eslint ./**/*.{ts,mjs} --fix && prettier . -l --write",
"fix": "prettier . -l --write && eslint ./**/*.{ts,mjs} --fix",
"format": "prettier . -c",
"lint": "eslint ./packages/**/src/**/*.ts --quiet",
"test": "npm test --workspaces"
},
"devDependencies": {
"@changesets/cli": "^2.27.1",
"@typescript-eslint/eslint-plugin": "^6.14.0",
"@typescript-eslint/parser": "^6.14.0",
"@typescript-eslint/eslint-plugin": "^7.3.1",
"@typescript-eslint/parser": "^7.3.1",
"eslint": "^8.55.0",
"eslint-config-prettier": "^9.1.0",
"jest-fetch-mock": "^3.0.3",
Expand Down
6 changes: 6 additions & 0 deletions packages/data/jest.config.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
const config = require("@jspsych/config/jest").makePackageConfig(__dirname);
module.exports = {
...config,
moduleNameMapper: {},
transformIgnorePatterns: ["node_modules/(?!deep-freeze-es6)"],
};
11 changes: 7 additions & 4 deletions packages/lookit-api/package.json → packages/data/package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "@lookit/lookit-api",
"name": "@lookit/data",
"version": "0.0.1",
"description": "This is a JS implementation of lookit's RESTful API.",
"homepage": "https://github.com/lookit/lookit-jspsych#readme",
Expand All @@ -9,7 +9,7 @@
"repository": {
"type": "git",
"url": "git+https://github.com/lookit/lookit-jspsych.git",
"directory": "packages/lookit-api"
"directory": "packages/data"
},
"license": "ISC",
"author": "Christopher J Green <[email protected]> (https://github.com/okaycj)",
Expand All @@ -20,9 +20,12 @@
"dev": "rollup --config rollup.config.dev.mjs --watch",
"test": "jest --coverage"
},
"dependencies": {},
"dependencies": {
"deep-freeze-es6": "^3.0.2"
},
"devDependencies": {
"@jspsych/config": "^2.0.0"
"@jspsych/config": "^2.0.0",
"jest-fetch-mock": "^3.0.3"
},
"peerDependencies": {
"jspsych": "^7.3.4"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
import { makeRollupConfig } from "@jspsych/config/rollup";

export default makeRollupConfig("lookitAPI");
export default makeRollupConfig("chsData");
45 changes: 45 additions & 0 deletions packages/data/src/api.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import {
finish,
retrieveChild,
retrievePastSessions,
retrieveResponse,
retrieveStudy,
updateResponse,
} from "./api";

jest.mock("./utils", () => ({
...jest.requireActual("./utils"),
getUuids: jest.fn(),
get: jest.fn().mockReturnValue("get response"),
patch: jest.fn().mockReturnValue("patch response"),
}));

test("Api call to get Child", async () => {
expect(await retrieveChild()).toStrictEqual("get response");
});

test("Api call to get Past Sessions", async () => {
expect(await retrievePastSessions("some uuid")).toStrictEqual("get response");
});

test("Api call to get Study", async () => {
expect(await retrieveStudy()).toStrictEqual("get response");
});

test("Api call to get Response", async () => {
expect(await retrieveResponse("some uuid")).toStrictEqual("get response");
});

test("Api call to patch Response", async () => {
expect(await updateResponse("some uuid", {})).toStrictEqual("patch response");
});

test("Check that all calls to API have finished", async () => {
expect(await finish()).toStrictEqual([
"get response",
"get response",
"get response",
"get response",
"patch response",
]);
});
48 changes: 48 additions & 0 deletions packages/data/src/api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import {
Child,
PastSession,
Promises,
Response,
ResponseAttrsUpdate,
ResponseUpdate,
Study,
} from "./types";
import { get, getUuids, patch } from "./utils";

const CONFIG = <const>{ ...getUuids() };
const promises: Promises[] = [];

function deposit<T extends Promises>(promise: T) {
promises.push(promise);
return promise;
}

export function finish() {
return Promise.all(promises);
}

export function retrieveChild() {
return deposit(get<Child>(`children/${CONFIG.child}/`));
}

export function retrievePastSessions(uuid: string) {
return deposit(get<PastSession[]>(`past-sessions/${uuid}/`));
}

export function retrieveStudy() {
return deposit(get<Study>(`studies/${CONFIG.study}/`));
}

export function retrieveResponse(uuid: string) {
return deposit(get<Response>(`responses/${uuid}/`));
}

export function updateResponse(uuid: string, data: ResponseAttrsUpdate) {
return deposit(
patch<ResponseUpdate, Response>(`responses/${uuid}/`, {
id: uuid,
type: "responses",
attributes: data,
}),
);
}
25 changes: 25 additions & 0 deletions packages/data/src/index.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import Api from "./index";

jest.mock("./utils", () => ({
...jest.requireActual("./utils"),
getUuids: jest.fn(),
}));

jest.mock("./api", () => ({
...jest.requireActual("./api"),
retrieveStudy: jest.fn().mockReturnValue("Study"),
retrieveChild: jest.fn().mockReturnValue("Child"),
retrievePastSessions: jest.fn().mockReturnValue("PastSessions"),
retrieveResponse: jest.fn().mockReturnValue("Response"),
}));

test("Load data for this study into window.chs", async () => {
expect(Object.hasOwn(window, "chs")).toBeFalsy();
await Api.load("response uuid");
expect(window.chs).toEqual({
study: "Study",
child: "Child",
pastSessions: "PastSessions",
response: "Response",
});
});
37 changes: 37 additions & 0 deletions packages/data/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import deepFreeze from "deep-freeze-es6";
import {
finish,
retrieveChild,
retrievePastSessions,
retrieveResponse,
retrieveStudy,
updateResponse,
} from "./api";
import { Child, PastSession, Response, Study } from "./types";

declare global {
interface Window {
chs: {
study: Study;
child: Child;
pastSessions: PastSession[];
response: Response;
};
}
}

async function load(response_uuid: string) {
if (!window.chs) {
Object.assign(window, {
chs: {
study: await retrieveStudy(),
child: await retrieveChild(),
pastSessions: await retrievePastSessions(response_uuid),
response: await retrieveResponse(response_uuid),
},
});
deepFreeze(window.chs);
}
}

export default { load, retrieveResponse, updateResponse, finish };
67 changes: 66 additions & 1 deletion packages/lookit-api/src/types.ts → packages/data/src/types.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
import { DataCollection } from "jspsych/dist/modules/data/DataCollection";

export type Promises = Promise<Data<Attributes> | Data<Attributes>[]>;

export type Relationship = {
links: {
related: string;
Expand All @@ -11,6 +15,36 @@ export type Attributes = {

export interface Relationships {}

export interface StudyAttrs extends Attributes {
name: string;
short_description: string;
purpose: string;
criteria: string;
duration: string;
contact_info: string;
/** Format: binary */
image?: string | null;
structure?: Record<string, never>;
generator?: string;
use_generator?: boolean;
display_full_screen?: boolean;
/** Format: uri */
exit_url?: string;
/** @enum {string} */
state?:
| "created"
| "submitted"
| "rejected"
| "retracted"
| "approved"
| "active"
| "paused"
| "deactivated"
| "archived";
public?: boolean;
responses: string[];
}

export interface ChildAttrs extends Attributes {
given_name: string;
birthday: string;
Expand All @@ -27,7 +61,7 @@ export interface ChildAttrs extends Attributes {
export interface PastSessionAttrs extends Attributes {
conditions?: Record<string, never>;
global_event_timings?: Record<string, never>;
exp_data?: Record<string, never>;
exp_data?: DataCollection[];
sequence?: string[];
completed?: boolean;
completed_consent_frame?: boolean;
Expand Down Expand Up @@ -59,12 +93,20 @@ export interface ApiResponse<Data> {
data: Data;
}

export interface Study extends Data<StudyAttrs> {
type: "studies";
relationships: {
responses: Relationship;
};
}

export interface Child extends Data<ChildAttrs> {
type: "children";
relationships: {
user: Relationship;
};
}

export interface PastSession extends Data<PastSessionAttrs> {
type: "past_sessions";
relationships: {
Expand All @@ -74,3 +116,26 @@ export interface PastSession extends Data<PastSessionAttrs> {
demographic_snapshot: Relationship;
};
}

export interface Response extends Data<PastSessionAttrs> {
type: "responses";
relationships: {
child: Relationship;
user: Relationship;
study: Relationship;
demographic_snapshot: Relationship;
};
}

export interface ResponseUpdate {
type: "responses";
id: string;
attributes: ResponseAttrsUpdate;
}

export interface ResponseAttrsUpdate {
exp_data?: DataCollection[];
completed?: boolean;
survey_consent?: boolean;
completed_consent_frame?: boolean;
}
Loading