master
Fabien Benetou 4 years ago
commit a479cb8abc
  1. 111
      flat.html
  2. 150
      index.html
  3. 187
      setup/index.html
  4. 18
      setup/upload/server/php/files/usersdb.js

@ -0,0 +1,111 @@
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css" integrity="sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M" crossorigin="anonymous">
<link href="https://getbootstrap.com/docs/4.0/examples/signin/signin.css" rel="stylesheet">
<script src="setup/upload/server/php/files/usersdb.js"></script>
<script src="https://aframe.io/releases/1.0.0/aframe.min.js"></script>
</head>
<style>
body { background-color: transparent; }
#email, #sms {
font-size: xx-large;
}
</style>
<body>
<img src="setup/productlogo.png">
<h3>flat viewer by category sorted by position</h3>
<div id="spacesholder">Your spaces:
<ul id="spaces"></ul>
</div>
<div>Already have an account? <span onclick="login()" style="text-decoration: underline;">Log-in</span>
<form>
<div id="login" style="display:none"><input id="useremail"/>
<button style="margin-top:2px;" type="button" onclick="loginViaEmail()" id="loginemail" class="btn btn-lg btn-primary btn-block">Login</button>
</div>
</form>
<div style="display:none" id="nouser">User not found. Double check your email address then contact fabien@iterative-explorations.com</a></div>
</div>
<script>
const urlParams = new URLSearchParams(window.location.search);
const email = urlParams.get('email');
if (email) loginViaEmail()
var uploadedURL = "setup/upload/server/php/files/";
var images = []
var url = "/"
var urlParameters = "?customimages="
var userspace
function login(){
document.querySelector("#login").style.display = "block"
}
function findCategory(image){
if (!userspace) return
console.log(image.filename)
var imagePos = new THREE.Vector3();
imagePos.copy ( AFRAME.utils.coordinates.parse(image.position) )
var closest
var smallestDistance = 1000
for (var category of userspace.categories){
var categoryPos = new THREE.Vector3();
categoryPos.copy ( AFRAME.utils.coordinates.parse(category.position) )
var distance = categoryPos.distanceTo( imagePos )
if (distance < smallestDistance){
smallestDistance = distance
closest = category.label
}
console.log(distance, category.label)
}
return closest
}
function loginViaEmail(){
var path = "setup/"
if (!email)
email = document.querySelector("#useremail").value
userspace = database[email]
if (!userspace){
document.querySelector("#nouser").style.display = "block"
return
}
document.querySelector("#spacesholder").style.display = "block"
var spaces = document.querySelector("#spaces")
var space = document.createElement("li")
var spacelink = document.createElement("a")
var images = userspace.files
spacelink.href = url + urlParameters
spacelink.target = "_blank"
spacelink.innerHTML = userspace.last_login
space.appendChild(spacelink)
for (var image of images){
urlParameters += image.filename + ","
space.innerHTML += path + image.filename + " " + findCategory( image )
}
console.log(space)
spaces.appendChild(space)
console.log("userspace", userspace)
}
</script>
<h3 style="position:absolute; bottom:0px; right:0px;">A product by <a href="https://iterative-explorations.com"><img width="200px" src="https://iterative-explorations.com/logo.svg"></a>.</h3>
</body>
</html>

@ -0,0 +1,150 @@
<head>
<meta charset="UTF-8">
<title>Think + Relax space by Iterative Explorations</title>
<script src="https://aframe.io/releases/1.0.0/aframe.min.js"></script>
<script src="https://rawgit.com/feiss/aframe-environment-component/master/dist/aframe-environment-component.min.js"></script>
<script src="https://cdn.rawgit.com/donmccurdy/aframe-extras/v4.1.2/dist/aframe-extras.min.js"></script>
<script src="https://unpkg.com/super-hands@3.0.0/dist/super-hands.min.js"></script>
<script src="pimvrhelpers.js"></script>
</head>
<script>
// could add an in VR edit mode for the categories, to position them, name them, etc
// should be mostly for adjustments
var timer = AFRAME.utils.getUrlParameter('timer')
if (!timer) timer = 300 //5min
function saveNewItemsPosition(){
var selector = ".notes";
var pos = ""
document.querySelectorAll(selector).forEach(
e => pos += "\n" + AFRAME.utils.coordinates.stringify( e.getAttribute("position") )
)
pimvrSaveRemote("WeWorkTest", pos) // from pimvrhelpers.js
// should be saved by username by space
// could be pointed at from the database file (thus having multiple storages)
}
AFRAME.registerComponent("watch", {
init: function() {
document.querySelector("#timer").setAttribute("text","value:"+timer)
this.tick = AFRAME.utils.throttleTick(this.tick, 1000, this);
// details https://aframe.io/docs/1.0.0/core/utils.html#aframe-utils-throttle-function-minimuminterval-optionalcontext
},
tick: function (t, dt) {
var time = Number( document.querySelector("#timer").getAttribute("text").value )
time--
document.querySelector("#timer").setAttribute("text","value:"+(time))
},
})
AFRAME.registerComponent("relaxing-introduction", {
init: function() {
// get in flow state
// for now controlled just with AFrame animation
// cf https://aframe.io/docs/1.0.0/components/animation.html
setTimeout(function(){
for (var note of document.querySelectorAll(".notes")){ note.emit("fadein") }
}, 10 * 1000) // arbitrary 10s, should be instead after the introduction is finished
}
})
AFRAME.registerComponent("decompression-conclusion", {
init: function() {
// cf PoC at 2017 W3C web authoring workshop with Roland Dubois
setTimeout(function(){
var intructions = document.querySelector("#instructions")
instructions.setAttribute("position", "-1 1.5 -1") // assumes the user is roughtly centered... could force on camera instead
instructions.setAttribute("text", "value", "Your session will end soon\n\nVisit https://learnWebVR.xyz/flat.html\n\nto work outside of VR.")
instructions.setAttribute("opacity", "1") // could be animated instead
console.log("X min voice over and notes fade-out with contextual information (time, weather, etc)")
document.querySelector("[environment]").setAttribute("environment", "preset:checkerboard")
}, timer * 1000);
}
})
AFRAME.registerComponent("environment-by-url", {
schema: {},
init: function() {
var environment = AFRAME.utils.getUrlParameter('environment')
if (environment) document.querySelector("[environment]").setAttribute("environment", "preset:" + environment)
}
})
AFRAME.registerComponent("photo-importer", {
schema: {},
init: function() {
var baseURL = "setup/"
var images = AFRAME.utils.getUrlParameter('customimages').split(',');
if (images.length == 1) window.location = baseURL; // no images? must be configured first
// could also display a tutorial instead
var i=1
for (var image of images){
if (image){
var id = "placeholder"+i
var placeholder = document.querySelector("#"+id)
if (!placeholder){
// TODO somehow not interactable anymore?!
// had a similar silly issue before but can't recall how I fixed it :(
// something basic about entities or hierarchy...
placeholder = document.createElement("a-box")
placeholder.id = id
placeholder.setAttribute("material", "shader:flat")
placeholder.setAttribute("hoverable", "")
placeholder.setAttribute("grabbable", "")
placeholder.setAttribute("draggable", "")
placeholder.setAttribute("dropppable", "")
// somehow does appear visually correct but are NOT interactable!
placeholder.setAttribute("position", "" + i/1.5-1.5 + " 1.5 -0.7")
placeholder.setAttribute("scale", "0.5 0.3 0.01")
// assume 1 * 1.5 photo ratio (landscape)
AFRAME.scenes[0].appendChild(placeholder)
}
placeholder.className += "notes"
placeholder.setAttribute("opacity", "0")
placeholder.setAttribute("animation", "property: components.material.material.opacity; to: 1; dur: 1500; easing: linear; startEvents: fadein;")
placeholder.setAttribute("src", baseURL+image)
i++
}
}
}
})
</script>
<body>
<a-scene photo-importer environment-by-url relaxing-introduction decompression-conclusion>
<a-entity environment="preset: forest;"></a-entity>
<a-entity sphere-collider="objects: a-box" super-hands hand-controls="left"></a-entity>
<a-entity sphere-collider="objects: a-box" super-hands hand-controls="right"></a-entity>
<!-- could be wrist watch as I've done via Twitter years ago -->
<a-text watch id="timer" rotation="180 0 180" position="0 1 2" value="time"></a-text>
<a-text id="instructions" position="-1 1.5 -0.65" value="welcome to your\n\nthink+relax space" opacity="0"
animation__fadein="property: components.text.material.uniforms.opacity.value; to: 0.99; dur: 1500; easing: linear"
animation__fadeout="property: components.text.material.uniforms.opacity.value; to: 0.01; dur: 1500; easing: linear; startEvents: fadeout;"
animation__leave="property: object3D.position.z; to: -100; dur: 15000; easing: linear; delay: 2500;"
></a-text>
<a-text rotation="-20 20 0" position="-2 0.2 -2" scale="1 1 1" value="waiting"></a-text>
<a-box material="wireframe:true" color="orange" position="-2 1 -2" scale="2 2 2"></a-box>
<a-text rotation="-20 0 0" position=" 0 0.2 -2" scale="1 1 1" value="in progress"></a-text>
<a-box material="wireframe:true" color="red" position="0 1 -2" scale="2 2 2"></a-box>
<a-text rotation="-20 -20 0" position=" 2 0.2 -2" scale="1 1 1" value="completed"></a-text>
<a-box material="wireframe:true" color="green" position="2 1 -2" scale="2 2 2"></a-box>
<a-box material="shader:flat" id="placeholder1" hoverable grabbable stretchable draggable dropppable position="0.5 1.5 -0.5" scale="0.5 0.3 0.01"></a-box>
<a-box material="shader:flat" id="placeholder2" hoverable grabbable stretchable draggable dropppable position="0 1.9 -0.7" scale="0.5 0.3 0.01"></a-box>
<a-box material="shader:flat" id="placeholder3" hoverable grabbable stretchable draggable dropppable position="-0.5 1.5 -0.7" scale="0.5 0.3 0.01"></a-box>
<!-- somehow creating dynamically fails... even though it did (!) work at some point (but wasn't saved via git)-->
<!-- until then will rely on a pool of objects -->
</a-scene>
</body>

@ -0,0 +1,187 @@
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css" integrity="sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M" crossorigin="anonymous">
<link href="https://getbootstrap.com/docs/4.0/examples/signin/signin.css" rel="stylesheet">
<script src="clipboard.min.js"></script>
<script src="upload/server/php/files/usersdb.js"></script>
</head>
<style>
body { background-color: transparent; }
#email, #sms {
font-size: xx-large;
}
</style>
<body>
<img src="productlogo.png">
<script>
var tickMark = "&#10004;";
var uploadedURL = "upload/server/php/files/";
var images = []
var url = "/"
var urlParameters = "?customimages="
function generateURL(){
//var url = "https://learnwebvr.xyz/importer.html"
for (var image of images){
urlParameters += image + ","
}
console.log ("URL", urlParameters );
var encodedURL = url + urlParameters
encodedURL += "&environment=" + document.querySelector("#environment").value
document.querySelector("#link").href = encodedURL
document.querySelector("#copyBtn").setAttribute("data-clipboard-text", encodedURL)
document.querySelector("#generateURL").style.display = "block"
document.querySelector("#email").href = "mailto:?&subject=session&body=" + encodeURIComponent( encodedURL )
// tested on iPhone 6S and Pixel2 and desktop
if( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ) {
}
else {
document.querySelector("#copydiv").className = "cold-md-6"
document.querySelector("#emaildiv").className = "cold-md-6"
}
}
</script>
<div class="container">
<form class="form-signin">
Environment:
<select id="environment">
<option name="contact">contact</option>
<option name="egypt">egypt</option>
<option name="checkerboard">checkerboard</option>
<option name="forest" selected="selected">forest</option>
<option name="goaland">goaland</option>
<option name="yavapai">yavapai</option>
<option name="goldmine">goldmine</option>
<option name="threetowers">threetowers</option>
<option name="poison">poison</option>
<option name="arches">arches</option>
<option name="tron">tron</option>
<option name="japan">japan</option>
<option name="dream">dream</option>
<option name="volcano">volcano</option>
<option name="starry">starry</option>
<option name="osiris">osiris</option>
</select>
<button style="margin-top:2px;" type="button" onclick="unhide('#fileupload2');" class="btn btn-primary btn-block">Upload your office photos<br/>(post-its, white board, etc)</button>
No content available? Try <a target="_blank" href="https://learnwebvr.xyz/?customimages=upload/server/php/files/photo6035074301452988871.jpg,upload/server/php/files/photo6035074301452988870.jpg,upload/server/php/files/IMG_6496 (1).jpg"> this example instead</a>!
<input style="display:none;" id="fileupload2" type="file" name="files[]" data-url="upload/server/php/" multiple>
<div style="display:none;" id="fileuploaded2">Files uploaded: </div>
<div style="opacity:0.7;" id="uploadrate"></div>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="upload/js/vendor/jquery.ui.widget.js"></script>
<script src="upload/js/jquery.iframe-transport.js"></script>
<script src="upload/js/jquery.fileupload.js"></script>
<script>
function unhide( element ){
document.querySelector(element).style.display = "block";
}
$(function () {
$('#fileupload2').fileupload({
dataType: 'json',
done: function (e, data) {
$.each(data.result.files, function (index, file) {
var imageURL = uploadedURL + (file.name)
images.push(imageURL)
var uploaded = document.querySelector("#fileuploaded2");
uploaded.style.display = "block";
uploaded.innerHTML += tickMark;
});
}
});
});
</script>
<button style="margin-top:2px;" type="button" onclick="generateURL()" id="generate-simulation" class="btn btn-lg btn-primary btn-block">Generate your<br/>relax+think space</button>
</form>
</div>
<div id="generateURL" style="display:none; text-align:center;" class="container">
<div class="container">
<a id="link" target="_blank" href=""><button type="button" class="btn btn-lg btn-primary btn-block">Launch relax+think space</button></a>
</div>
<br/>
<div class="container">
<div class="row">
<div class="col-md-4" id="copydiv">
<button class="btn" data-clipboard-text="" id="copyBtn">Copy to clipboard</button>
<script>
new Clipboard('.btn');
</script>
</div>
<div class="col-md-4" id="emaildiv">
<a id="email" href="" target="_blank">email link</a>
</div>
</div>
</div>
</div>
<script>
function login(){
document.querySelector("#login").style.display = "block"
}
function loginViaEmail(){
var email = document.querySelector("#useremail").value
var userspace = database[email]
if (!userspace){
document.querySelector("#nouser").style.display = "block"
return
}
document.querySelector("#spacesholder").style.display = "block"
var spaces = document.querySelector("#spaces")
var space = document.createElement("li")
var spacelink = document.createElement("a")
var images = userspace.files
for (var image of images){
urlParameters += image.filename + ","
}
spacelink.href = url + urlParameters
spacelink.target = "_blank"
spacelink.innerHTML = userspace.last_login
space.appendChild(spacelink)
console.log(space)
spaces.appendChild(space)
console.log("userspace", userspace)
}
</script>
<div>Already have an account? <span onclick="login()" style="text-decoration: underline;">Log-in</span>
<form>
<div id="login" style="display:none"><input id="useremail"/>
<button style="margin-top:2px;" type="button" onclick="loginViaEmail()" id="loginemail" class="btn btn-lg btn-primary btn-block">Login</button>
</div>
</form>
<div style="display:none" id="nouser">User not found. Double check your email address then contact fabien@iterative-explorations.com</a></div>
<div style="display:none" id="spacesholder">Your spaces:
<ul id="spaces"></ul>
</div>
</div>
<h3 style="position:absolute; bottom:0px; right:0px;">A product by <a href="https://iterative-explorations.com"><img width="200px" src="https://iterative-explorations.com/logo.svg"></a>.</h3>
</body>
</html>

@ -0,0 +1,18 @@
var database = {
"fabien@benetou.fr" : {
"username": "fabien",
"password": "test",
"last_login": 1576749381516,
"environment": "forest",
"files" : [
{ "position": "-2 1 -2", "filename" : "upload/server/php/files/C1C4E2F7-865A-4DB4-9274-1EA69B6C4A7E.jpeg" },
{ "position": "0 1 -2", "filename" : "upload/server/php/files/4A21A76C-F375-4884-9040-BC51A24057A6.jpeg" },
{ "position": "2 1 -2", "filename" : "upload/server/php/files/2CD9932F-891C-4BA5-BDDA-A3B39B39CF09.jpeg" }
],
"categories" : [
{ "position": "-2 1 -2", "color" : "orange", "label" : "waiting" },
{ "position": "0 1 -2", "color" : "red", "label" : "in progress" },
{ "position": "2 1 -2", "color" : "green", "label" : "completed" }
]
}
}
Loading…
Cancel
Save