diff --git a/README.md b/README.md index dfc0829f..5b41ccc4 100644 --- a/README.md +++ b/README.md @@ -9,8 +9,12 @@ The Engaging Computing Group develops new technologies to enable learners—yout ## Status [![CircleCI](https://circleci.com/gh/engaging-computing/MYR.svg?style=shield)](https://circleci.com/gh/engaging-computing/MYR) -## Change Log - 2.0.0 -> 2.0.1 -- Fixed bug where tokens expired after one hour and weren't refreshed +## Change Log - 2.0.1 -> 2.1.0 +- Added object transparency +- Page titles are not all Myr.js +- Fixed bug where save prompt would not appear +- Added missing defauly argument to setRotation +- Track UID in Analytics ## Acknowledgments MYR uses [Aframe](https://aframe.io), a fantastic open source project, to render objects and effects in the three dimensional space. diff --git a/package.json b/package.json index 2b4af10b..7aca4b24 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "myr", - "version": "2.0.1", + "version": "2.1.0", "private": false, "engines": { "node": "12.18.2" diff --git a/public/index.html b/public/index.html index 0f4848ec..2f9c09e8 100644 --- a/public/index.html +++ b/public/index.html @@ -23,7 +23,7 @@ - Myr.js + MYR diff --git a/src/actions/collectionActions.js b/src/actions/collectionActions.js index c2dcf2ce..1b91b3b4 100644 --- a/src/actions/collectionActions.js +++ b/src/actions/collectionActions.js @@ -33,6 +33,7 @@ export function asyncCollection(collectionID, uid) { .then((resp) => { switch(resp.status){ case 200: + document.title = collectionID + " Collection | MYR"; resp.json().then((data) => { data.forEach((doc) => { collectionProjects.push(doc); diff --git a/src/actions/courseActions.js b/src/actions/courseActions.js index a238246f..4e301d04 100644 --- a/src/actions/courseActions.js +++ b/src/actions/courseActions.js @@ -50,11 +50,12 @@ export function fetchCourse(courseId) { .then(response => { response.json() .then(json => { + document.title = json.name + " Course | MYR"; dispatch(loadCourse(json)); //Make sure that the course is not empty if(json.lessons.length <= 0){ - noLessons.name = json.name; + noLessons.name = json.name; dispatch(loadLesson(noLessons)); return; } @@ -66,7 +67,7 @@ export function fetchCourse(courseId) { { name: json.lessons[0].name, desc: "This scene was saved from the course: " + json.name - })); + })); }) .catch(err => { console.error(err); diff --git a/src/actions/editorActions.js b/src/actions/editorActions.js index 564ee8f5..b9646aaa 100644 --- a/src/actions/editorActions.js +++ b/src/actions/editorActions.js @@ -60,6 +60,10 @@ export function fetchScene(id, uid = "anon") { response.json().then((json) =>{ if(json.code){ + //don't change the title when fetching scene in collection + if(!document.title.includes("Collection")) { + document.title = json.name + " | MYR"; + } dispatch(render(json.code, uid || "anon")); dispatch(updateSavedText(json.code)); let settings = DEF_SETTINGS; diff --git a/src/actions/referenceExampleActions.js b/src/actions/referenceExampleActions.js index 5440f7a4..ef09d827 100644 --- a/src/actions/referenceExampleActions.js +++ b/src/actions/referenceExampleActions.js @@ -32,6 +32,11 @@ export function fetchReferenceExample(funcName) { response.json() .then(json => { dispatch(loadReferenceExample(response.status === 200 ? json : notFound)); + if(response.status === 200) { + document.title = json.functionName + " Reference | MYR"; + } else { + document.title = "Reference | MYR"; + } dispatch(render(json.code || "")); dispatch(sceneActions.setNameDesc( { diff --git a/src/components/layouts/Ide.js b/src/components/layouts/Ide.js index c21c2e92..a3a01542 100644 --- a/src/components/layouts/Ide.js +++ b/src/components/layouts/Ide.js @@ -44,7 +44,7 @@ export const Ide = ({ editor, editorActions, user, authActions, scene, sceneActi : <>
- /> +
diff --git a/src/components/reference/ReferencePage.js b/src/components/reference/ReferencePage.js index 1e93b38d..3cb497bb 100644 --- a/src/components/reference/ReferencePage.js +++ b/src/components/reference/ReferencePage.js @@ -95,6 +95,7 @@ export default class Reference extends React.Component { }; render() { + document.title = "Reference | MYR"; return (
{ let editor = window.ace.edit("ace-editor"); - if(editor.getSession().getValue() === this.props.text || window.confirm("A new version of the scene is available, would you like to load it?")){ + if(editor.getSession().getValue() === this.props.scene.code || window.confirm("A new version of the scene is available, would you like to load it?")){ this.props.actions.fetchScene(this.props.projectId); } }); @@ -206,6 +206,9 @@ class Header extends Component { this.props.projectActions.asyncUserProj(this.props.user.uid); this.props.collectionActions.asyncCollections(this.props.user.uid); this.setRefreshTime(googleAuth.tokenObj.expires_at); + + //send uid to google analyrica + window.gtag("config", "UA-122925714-1", {"user_id": this.props.user.googleId}); } setRefreshTime = (time) => { diff --git a/src/myr/Myr.js b/src/myr/Myr.js index 86a8cb6a..0a15a8e0 100644 --- a/src/myr/Myr.js +++ b/src/myr/Myr.js @@ -13,6 +13,7 @@ class Myr { this.sceneEl = document.querySelector("a-scene"); this.cursor = { color: "red", + transparency: 0, position: { x: 0, y: 0, @@ -80,6 +81,7 @@ class Myr { this.id = 0; this.cursor = { color: "red", + transparency: 0, position: { x: 0, y: 0, @@ -123,6 +125,7 @@ class Myr { resetCursor = () => { this.cursor = { color: "red", + transparency: 0, position: { x: 0, y: 0, @@ -154,6 +157,16 @@ class Myr { return this.counter++; }; + setTransparency = (transparency = 0) => { + if(typeof transparency === "number" && transparency <= 100 && transparency >= 0) { + this.cursor.transparency = transparency / 100; + } else { + console.error("setTransparency() either recieved a non numeric value or a value out of range (0-100)"); + } + + return this.cursor.opacity; + } + setPosition = (x = 0, y = 1, z = 0) => { if (typeof x === "number" && typeof y === "number" && typeof z === "number") { this.cursor.position = { @@ -288,7 +301,7 @@ class Myr { return this.cursor.scale.z; }; - setRotation = (x, y = 0, z = 0) => { + setRotation = (x = 0, y = 0, z = 0) => { if (typeof x === "number" && typeof y === "number" && typeof z === "number") { this.cursor.rotation = { x: x, @@ -334,6 +347,9 @@ class Myr { case "magnitude": this.setMagnitude(value); break; + case "transparency": + this.setTransparency(value); + break; default: this.cursor[key] = value; } @@ -514,7 +530,7 @@ class Myr { let base = { geometry: "primitive: box;", id: "box" + this.genNewId(), - material: `color: ${this.cursor.color}; side: double`, + material: `color: ${this.cursor.color}; side: double; opacity: ${1 - this.cursor.transparency};`, position: { ...this.cursor.position }, rotation: this.cursor.rotation, scale: this.cursor.scale, @@ -530,7 +546,7 @@ class Myr { position: this.cursor.position, scale: this.cursor.scale, rotation: this.cursor.rotation, - material: `color: ${this.cursor.color}; side: double;`, + material: `color: ${this.cursor.color}; side: double; opacity: ${1 - this.cursor.transparency};`, }; return this.mergeProps(base, params); } @@ -539,7 +555,7 @@ class Myr { cone = (params) => { let base = { id: "cone" + this.genNewId(), - geometry: `primitive: cone; radiusBottom: ${this.cursor.radius}; radiusTop: 0.1;`, + geometry: `primitive: cone; radiusBottom: ${this.cursor.radius}; radiusTop: 0.1; opacity: ${1 - this.cursor.transparency};`, position: this.cursor.position, scale: this.cursor.scale, rotation: this.cursor.rotation, @@ -552,7 +568,7 @@ class Myr { cylinder = (params) => { let base = { id: "cyl" + this.genNewId(), - geometry: `primitive: cylinder; radius: ${this.cursor.radius}; theta-length: ${this.cursor.phiLength};`, + geometry: `primitive: cylinder; radius: ${this.cursor.radius}; theta-length: ${this.cursor.phiLength}; opacity: ${1 - this.cursor.transparency};`, position: this.cursor.position, scale: this.cursor.scale, rotation: this.cursor.rotation, @@ -570,7 +586,7 @@ class Myr { position: this.cursor.position, scale: this.cursor.scale, rotation: this.cursor.rotation, - material: `color: ${this.cursor.color}; side: double;`, + material: `color: ${this.cursor.color}; side: double; opacity: ${1 - this.cursor.transparency};`, }; return this.mergeProps(base, params); } @@ -583,7 +599,7 @@ class Myr { position: this.cursor.position, scale: this.cursor.scale, rotation: this.cursor.rotation, - material: `color: ${this.cursor.color}; side: double;`, + material: `color: ${this.cursor.color}; side: double; opacity: ${1 - this.cursor.transparency};`, }; return this.mergeProps(base, params); } @@ -596,7 +612,7 @@ class Myr { position: this.cursor.position, scale: this.cursor.scale, rotation: this.cursor.rotation, - material: `color: ${this.cursor.color}; side: double;`, + material: `color: ${this.cursor.color}; side: double; opacity: ${1 - this.cursor.transparency};`, }; return this.mergeProps(base, params); } @@ -618,7 +634,7 @@ class Myr { plane = (params) => { let base = { id: "plane" + this.genNewId(), - geometry: `primitive: plane; height: 1; width: 1; phi-length: ${this.cursor.phiLength};`, + geometry: `primitive: plane; height: 1; width: 1; phi-length: ${this.cursor.phiLength}; opacity: ${1 - this.cursor.transparency};`, position: this.cursor.position, scale: this.cursor.scale, rotation: this.cursor.rotation, @@ -631,7 +647,7 @@ class Myr { polyhedron = (params) => { let base = { id: "poly" + this.genNewId(), - geometry: `primitive: sphere; segmentsWidth: 2; segmentsHeight: 8; phi-length: ${this.cursor.phiLength};`, + geometry: `primitive: sphere; segmentsWidth: 2; segmentsHeight: 8; phi-length: ${this.cursor.phiLength}; opacity: ${1 - this.cursor.transparency};`, position: this.cursor.position, scale: this.cursor.scale, rotation: this.cursor.rotation, @@ -643,7 +659,7 @@ class Myr { ring = (params) => { let base = { id: "ring" + this.genNewId(), - geometry: `primitive: ring; radiusInner: 0.5; radiusOuter: 1; theta-length: ${this.cursor.phiLength};`, + geometry: `primitive: ring; radiusInner: 0.5; radiusOuter: 1; theta-length: ${this.cursor.phiLength}; opacity: ${1 - this.cursor.transparency};`, position: this.cursor.position, scale: this.cursor.scale, rotation: this.cursor.rotation, @@ -660,7 +676,7 @@ class Myr { position: this.cursor.position, scale: this.cursor.scale, rotation: this.cursor.rotation, - material: `color: ${this.cursor.color}; side: double;`, + material: `color: ${this.cursor.color}; side: double; opacity: ${1 - this.cursor.transparency};`, }; return this.mergeProps(base, params); } @@ -672,7 +688,7 @@ class Myr { position: this.cursor.position, scale: this.cursor.scale, rotation: this.cursor.rotation, - material: `color: ${this.cursor.color}; side: double;`, + material: `color: ${this.cursor.color}; side: double; opacity: ${1 - this.cursor.transparency};`, }; return this.mergeProps(base, params); } @@ -711,7 +727,7 @@ class Myr { position: this.cursor.position, scale: this.cursor.scale, rotation: this.cursor.rotation, - material: `color: ${this.cursor.color}; side: double;`, + material: `color: ${this.cursor.color}; side: double; opacity: ${1 - this.cursor.transparency};`, }; return this.mergeProps(base, params); } @@ -723,7 +739,7 @@ class Myr { position: this.cursor.position, scale: this.cursor.scale, rotation: this.cursor.rotation, - material: `color: ${this.cursor.color}; side: double`, + material: `color: ${this.cursor.color}; side: double; opacity: ${1 - this.cursor.transparency};`, p: 2, q: 3, }; @@ -737,7 +753,7 @@ class Myr { position: this.cursor.position, scale: this.cursor.scale, rotation: this.cursor.rotation, - material: `color: ${this.cursor.color}; side: double;`, + material: `color: ${this.cursor.color}; side: double; opacity: ${1 - this.cursor.transparency};`, }; return this.mergeProps(base, params); } @@ -751,7 +767,7 @@ class Myr { position: this.cursor.position, scale: this.cursor.scale, rotation: this.cursor.rotation, - material: `color: ${this.cursor.color}; side: double;`, + material: `color: ${this.cursor.color}; side: double; opacity: ${1 - this.cursor.transparency};`, }; return this.mergeProps(base, params); } diff --git a/src/myr/reference.js b/src/myr/reference.js index 854bca81..3334452d 100644 --- a/src/myr/reference.js +++ b/src/myr/reference.js @@ -283,6 +283,12 @@ let transformations = [ description: The setZPos function changes the z component of the position in the cursor. The default z position is 0., example: "setZPos" }, + { + name: "setTransparency", + parameters: [{type: "number", name: "transparency"}], + description: The setTransparency function changes the opacity of the element. The range of transparency is from 0% (solid) to 100% (invisible). The default is 0%., + example: "setTransparency" + }, { name: "increasePosition", parameters: [{ type: "number", name: "x" }, { type: "number", name: "y" }, { type: "number", name: "z" }], diff --git a/src/tests/Myr.test.js b/src/tests/Myr.test.js index 5477f200..80af38ab 100644 --- a/src/tests/Myr.test.js +++ b/src/tests/Myr.test.js @@ -6,6 +6,7 @@ let colorRegEx = new RegExp("#([0-9]|[A-F]|[a-f]){6}"); const defaultCursor = { color: "red", + transparency: 0, position: { x: 0, y: 0, @@ -880,4 +881,44 @@ describe("Other Myr functionality", () => { expect(myr.cursor.color).toEqual("red"); }); + + it("setTransparency should set the appropriate cursor attribute correctly", () => { + myr.setTransparency(0); + expect(myr.cursor.transparency).toEqual(0); + + myr.setTransparency(100); + expect(myr.cursor.transparency).toEqual(1); + + myr.setTransparency(50); + expect(myr.cursor.transparency).toEqual(0.5); + + myr.setTransparency(40); + expect(myr.cursor.transparency).toEqual(0.4); + }); + + it("setTransparency should not change opacity if it received an invalid argument", () => { + myr.reset(); + + myr.setTransparency(-100); + expect(myr.cursor.transparency).toEqual(0); + myr.setTransparency(-50); + expect(myr.cursor.transparency).toEqual(0); + myr.setTransparency(-1); + expect(myr.cursor.transparency).toEqual(0); + + myr.setTransparency("50"); + expect(myr.cursor.transparency).toEqual(0); + myr.setTransparency("1"); + expect(myr.cursor.transparency).toEqual(0); + + myr.setTransparency([1, 2, 3]); + expect(myr.cursor.transparency).toEqual(0); + + myr.setTransparency({ + test: true, + valid: "false", + value: 1 + }); + expect(myr.cursor.transparency).toEqual(0); + }); });