pr360-questionnaire 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,64 @@
1
+ // NOTE: The contents of this file will only be executed if
2
+ // you uncomment its entry in "assets/js/app.js".
3
+
4
+ // Bring in Phoenix channels client library:
5
+ import {Socket} from "phoenix"
6
+
7
+ // And connect to the path in "lib/patient_reach_360_web/endpoint.ex". We pass the
8
+ // token for authentication. Read below how it should be used.
9
+ let socket = new Socket("/socket", {params: {token: window.userToken}})
10
+
11
+ // When you connect, you'll often need to authenticate the client.
12
+ // For example, imagine you have an authentication plug, `MyAuth`,
13
+ // which authenticates the session and assigns a `:current_user`.
14
+ // If the current user exists you can assign the user's token in
15
+ // the connection for use in the layout.
16
+ //
17
+ // In your "lib/patient_reach_360_web/router.ex":
18
+ //
19
+ // pipeline :browser do
20
+ // ...
21
+ // plug MyAuth
22
+ // plug :put_user_token
23
+ // end
24
+ //
25
+ // defp put_user_token(conn, _) do
26
+ // if current_user = conn.assigns[:current_user] do
27
+ // token = Phoenix.Token.sign(conn, "user socket", current_user.id)
28
+ // assign(conn, :user_token, token)
29
+ // else
30
+ // conn
31
+ // end
32
+ // end
33
+ //
34
+ // Now you need to pass this token to JavaScript. You can do so
35
+ // inside a script tag in "lib/patient_reach_360_web/templates/layout/app.html.heex":
36
+ //
37
+ // <script>window.userToken = "<%= assigns[:user_token] %>";</script>
38
+ //
39
+ // You will need to verify the user token in the "connect/3" function
40
+ // in "lib/patient_reach_360_web/channels/user_socket.ex":
41
+ //
42
+ // def connect(%{"token" => token}, socket, _connect_info) do
43
+ // # max_age: 1209600 is equivalent to two weeks in seconds
44
+ // case Phoenix.Token.verify(socket, "user socket", token, max_age: 1_209_600) do
45
+ // {:ok, user_id} ->
46
+ // {:ok, assign(socket, :user, user_id)}
47
+ //
48
+ // {:error, reason} ->
49
+ // :error
50
+ // end
51
+ // end
52
+ //
53
+ // Finally, connect to the socket:
54
+ socket.connect()
55
+
56
+ // Now that you are connected, you can join channels with a topic.
57
+ // Let's assume you have a channel with a topic named `room` and the
58
+ // subtopic is its id - in this case 42:
59
+ let channel = socket.channel("room:42", {})
60
+ channel.join()
61
+ .receive("ok", resp => { console.log("Joined successfully", resp) })
62
+ .receive("error", resp => { console.log("Unable to join", resp) })
63
+
64
+ export default socket
package/package.json ADDED
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "pr360-questionnaire",
3
+ "description": "An element to render a questionnaire for PatientReach 360.",
4
+ "version": "0.0.1",
5
+ "main": "dist/index.js",
6
+ "author": {
7
+ "email": "chris@launchscout.com",
8
+ "name": "Chris Nelson",
9
+ "url": "http://launchscout.com"
10
+ },
11
+ "repository": {
12
+ "type": "github",
13
+ "url": "https://github.com/PatientReach360/patient_reach_360"
14
+ },
15
+
16
+ "scripts": {
17
+ "build": "node build.mjs",
18
+ "test": "web-test-runner \"build/questionnaire-test.js\" --node-resolve",
19
+ "pretest": "node build.mjs",
20
+ "prepublish": "node build.mjs"
21
+ },
22
+ "dependencies": {
23
+ "esbuild": "^0.18.11",
24
+ "esbuild-sass-plugin": "^2.10.0",
25
+ "lit": "^2.7.6",
26
+ "phoenix": "file:../deps/phoenix",
27
+ "phoenix_html": "file:../deps/phoenix_html",
28
+ "phoenix_live_view": "file:../deps/phoenix_live_view",
29
+ "phx-live-state": "^0.9.2",
30
+ "vimeo-video-element": "^1.0.1"
31
+ },
32
+ "devDependencies": {
33
+ "@open-wc/testing": "^3.2.0",
34
+ "@web/test-runner": "^0.17.0",
35
+ "sinon": "^15.2.0",
36
+ "typescript": "^5.1.6"
37
+ }
38
+ }
@@ -0,0 +1,45 @@
1
+ import '../js/questionnaire';
2
+ import { expect } from "@esm-bundle/chai";
3
+ import { QuestionnaireElement} from '../js/questionnaire';
4
+ import { fixture } from '@open-wc/testing';
5
+ import LiveState from 'phx-live-state';
6
+ import sinon from 'sinon';
7
+
8
+ describe('questionnaire test', async () => {
9
+ beforeEach(async () => {
10
+ window['questionnaireState'] = sinon.createStubInstance(LiveState);
11
+ });
12
+ it('renders a question', async () => {
13
+ const questionnaireElement: QuestionnaireElement = await fixture(`
14
+ <pr360-questionnaire url="wss://foo.bar">
15
+ <button>Click me</button>
16
+ </pr360-questionnaire>
17
+ `);
18
+ questionnaireElement.currentStep = {
19
+ id: "1",
20
+ type: "Question",
21
+ text: "What is your favorite color?",
22
+ url: "https://foo.bar",
23
+ answers: [
24
+ {
25
+ id: "1",
26
+ text: "Blue"
27
+ }
28
+ ],
29
+ }
30
+ questionnaireElement.questionnaireName = "foo";
31
+ const button = questionnaireElement.querySelector('button');
32
+ button?.click();
33
+ await questionnaireElement.updateComplete;
34
+ expect(questionnaireElement.shadowRoot?.textContent).to.contain("What is your favorite color?");
35
+ });
36
+ it('adds hubspot tracking code', async () => {
37
+ const questionnaireElement: QuestionnaireElement = await fixture(`
38
+ <pr360-questionnaire url="wss://foo.bar">
39
+ <button>Click me</button>
40
+ </pr360-questionnaire>
41
+ `);
42
+ const script = document.querySelector('script#hs-script-loader');
43
+ expect(script).to.not.be.null;
44
+ });
45
+ });
package/tsconfig.json ADDED
@@ -0,0 +1,11 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2020",
4
+ "outDir": "build",
5
+ "moduleResolution": "node",
6
+ "declaration": true,
7
+ "allowSyntheticDefaultImports": true,
8
+ "experimentalDecorators": true
9
+ },
10
+ "include": ["./**/*.ts"]
11
+ }
@@ -0,0 +1,165 @@
1
+ /**
2
+ * @license MIT
3
+ * topbar 2.0.0, 2023-02-04
4
+ * https://buunguyen.github.io/topbar
5
+ * Copyright (c) 2021 Buu Nguyen
6
+ */
7
+ (function (window, document) {
8
+ "use strict";
9
+
10
+ // https://gist.github.com/paulirish/1579671
11
+ (function () {
12
+ var lastTime = 0;
13
+ var vendors = ["ms", "moz", "webkit", "o"];
14
+ for (var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
15
+ window.requestAnimationFrame =
16
+ window[vendors[x] + "RequestAnimationFrame"];
17
+ window.cancelAnimationFrame =
18
+ window[vendors[x] + "CancelAnimationFrame"] ||
19
+ window[vendors[x] + "CancelRequestAnimationFrame"];
20
+ }
21
+ if (!window.requestAnimationFrame)
22
+ window.requestAnimationFrame = function (callback, element) {
23
+ var currTime = new Date().getTime();
24
+ var timeToCall = Math.max(0, 16 - (currTime - lastTime));
25
+ var id = window.setTimeout(function () {
26
+ callback(currTime + timeToCall);
27
+ }, timeToCall);
28
+ lastTime = currTime + timeToCall;
29
+ return id;
30
+ };
31
+ if (!window.cancelAnimationFrame)
32
+ window.cancelAnimationFrame = function (id) {
33
+ clearTimeout(id);
34
+ };
35
+ })();
36
+
37
+ var canvas,
38
+ currentProgress,
39
+ showing,
40
+ progressTimerId = null,
41
+ fadeTimerId = null,
42
+ delayTimerId = null,
43
+ addEvent = function (elem, type, handler) {
44
+ if (elem.addEventListener) elem.addEventListener(type, handler, false);
45
+ else if (elem.attachEvent) elem.attachEvent("on" + type, handler);
46
+ else elem["on" + type] = handler;
47
+ },
48
+ options = {
49
+ autoRun: true,
50
+ barThickness: 3,
51
+ barColors: {
52
+ 0: "rgba(26, 188, 156, .9)",
53
+ ".25": "rgba(52, 152, 219, .9)",
54
+ ".50": "rgba(241, 196, 15, .9)",
55
+ ".75": "rgba(230, 126, 34, .9)",
56
+ "1.0": "rgba(211, 84, 0, .9)",
57
+ },
58
+ shadowBlur: 10,
59
+ shadowColor: "rgba(0, 0, 0, .6)",
60
+ className: null,
61
+ },
62
+ repaint = function () {
63
+ canvas.width = window.innerWidth;
64
+ canvas.height = options.barThickness * 5; // need space for shadow
65
+
66
+ var ctx = canvas.getContext("2d");
67
+ ctx.shadowBlur = options.shadowBlur;
68
+ ctx.shadowColor = options.shadowColor;
69
+
70
+ var lineGradient = ctx.createLinearGradient(0, 0, canvas.width, 0);
71
+ for (var stop in options.barColors)
72
+ lineGradient.addColorStop(stop, options.barColors[stop]);
73
+ ctx.lineWidth = options.barThickness;
74
+ ctx.beginPath();
75
+ ctx.moveTo(0, options.barThickness / 2);
76
+ ctx.lineTo(
77
+ Math.ceil(currentProgress * canvas.width),
78
+ options.barThickness / 2
79
+ );
80
+ ctx.strokeStyle = lineGradient;
81
+ ctx.stroke();
82
+ },
83
+ createCanvas = function () {
84
+ canvas = document.createElement("canvas");
85
+ var style = canvas.style;
86
+ style.position = "fixed";
87
+ style.top = style.left = style.right = style.margin = style.padding = 0;
88
+ style.zIndex = 100001;
89
+ style.display = "none";
90
+ if (options.className) canvas.classList.add(options.className);
91
+ document.body.appendChild(canvas);
92
+ addEvent(window, "resize", repaint);
93
+ },
94
+ topbar = {
95
+ config: function (opts) {
96
+ for (var key in opts)
97
+ if (options.hasOwnProperty(key)) options[key] = opts[key];
98
+ },
99
+ show: function (delay) {
100
+ if (showing) return;
101
+ if (delay) {
102
+ if (delayTimerId) return;
103
+ delayTimerId = setTimeout(() => topbar.show(), delay);
104
+ } else {
105
+ showing = true;
106
+ if (fadeTimerId !== null) window.cancelAnimationFrame(fadeTimerId);
107
+ if (!canvas) createCanvas();
108
+ canvas.style.opacity = 1;
109
+ canvas.style.display = "block";
110
+ topbar.progress(0);
111
+ if (options.autoRun) {
112
+ (function loop() {
113
+ progressTimerId = window.requestAnimationFrame(loop);
114
+ topbar.progress(
115
+ "+" + 0.05 * Math.pow(1 - Math.sqrt(currentProgress), 2)
116
+ );
117
+ })();
118
+ }
119
+ }
120
+ },
121
+ progress: function (to) {
122
+ if (typeof to === "undefined") return currentProgress;
123
+ if (typeof to === "string") {
124
+ to =
125
+ (to.indexOf("+") >= 0 || to.indexOf("-") >= 0
126
+ ? currentProgress
127
+ : 0) + parseFloat(to);
128
+ }
129
+ currentProgress = to > 1 ? 1 : to;
130
+ repaint();
131
+ return currentProgress;
132
+ },
133
+ hide: function () {
134
+ clearTimeout(delayTimerId);
135
+ delayTimerId = null;
136
+ if (!showing) return;
137
+ showing = false;
138
+ if (progressTimerId != null) {
139
+ window.cancelAnimationFrame(progressTimerId);
140
+ progressTimerId = null;
141
+ }
142
+ (function loop() {
143
+ if (topbar.progress("+.1") >= 1) {
144
+ canvas.style.opacity -= 0.05;
145
+ if (canvas.style.opacity <= 0.05) {
146
+ canvas.style.display = "none";
147
+ fadeTimerId = null;
148
+ return;
149
+ }
150
+ }
151
+ fadeTimerId = window.requestAnimationFrame(loop);
152
+ })();
153
+ },
154
+ };
155
+
156
+ if (typeof module === "object" && typeof module.exports === "object") {
157
+ module.exports = topbar;
158
+ } else if (typeof define === "function" && define.amd) {
159
+ define(function () {
160
+ return topbar;
161
+ });
162
+ } else {
163
+ this.topbar = topbar;
164
+ }
165
+ }.call(this, window, document));