From 5cb129f30f206679dce5959cecc32ec4d1fff83f Mon Sep 17 00:00:00 2001 From: valentinMachado Date: Tue, 1 Jun 2021 10:23:05 +0200 Subject: [PATCH 01/68] data nudefined => null --- src/Game/Shared/Command.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Game/Shared/Command.js b/src/Game/Shared/Command.js index 1d95f67bb..1253e1b81 100644 --- a/src/Game/Shared/Command.js +++ b/src/Game/Shared/Command.js @@ -10,7 +10,7 @@ const CommandModule = class Command { this.type = json.type; this.userID = json.userID; this.avatarID = json.avatarID; - this.data = json.data; + this.data = json.data || null; } getData() { @@ -38,7 +38,6 @@ const CommandModule = class Command { } toJSON() { - return { type: this.type, avatarID: this.avatarID, From c8545da0178221d806a1cf4f2496cd2145d7e41b Mon Sep 17 00:00:00 2001 From: valentinMachado Date: Thu, 3 Jun 2021 10:48:23 +0200 Subject: [PATCH 02/68] add getter gameview --- src/Game/GameView/GameView.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/Game/GameView/GameView.js b/src/Game/GameView/GameView.js index a0f89cf7d..d6968417b 100644 --- a/src/Game/GameView/GameView.js +++ b/src/Game/GameView/GameView.js @@ -314,6 +314,18 @@ export class GameView { cameraShadow.updateProjectionMatrix(); } + getWorldStateInterpolator() { + return this.worldStateInterpolator; + } + + getLastState() { + return this.lastState; + } + + getInputManager() { + return this.inputManager; + } + updateViewServer(dt) { //TODO itowns BUG if (!isNaN(dt)) { From a5606dc5a8e13a1f166cd4563077f12b87f59840 Mon Sep 17 00:00:00 2001 From: valentinMachado Date: Thu, 3 Jun 2021 10:56:03 +0200 Subject: [PATCH 03/68] remove debug --- src/Game/GameView/GameView.js | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/Game/GameView/GameView.js b/src/Game/GameView/GameView.js index d6968417b..ab750e29f 100644 --- a/src/Game/GameView/GameView.js +++ b/src/Game/GameView/GameView.js @@ -21,15 +21,9 @@ import { isFunction } from 'jquery'; const udvShared = require('../Shared/Shared'); const Command = udvShared.Command; const WorldState = udvShared.WorldState; -const Data = udvShared.Data; - -//DEBUG -let id = 0; export class GameView { constructor(params) { - this.id = id; - id++; params.htmlParent = params.htmlParent || document.body; From 6c9c44a6e1523053fe7bb26922b4b6df1ae7802c Mon Sep 17 00:00:00 2001 From: valentinMachado Date: Thu, 3 Jun 2021 16:49:31 +0200 Subject: [PATCH 04/68] rename quat parse --- src/Game/Components/AssetsManager.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Game/Components/AssetsManager.js b/src/Game/Components/AssetsManager.js index e9a3fc3af..1b174cf70 100644 --- a/src/Game/Components/AssetsManager.js +++ b/src/Game/Components/AssetsManager.js @@ -260,10 +260,10 @@ export class AssetsManager { const noShadow = modelData.noShadow || false; //rotation - const quatTHREE2UDV = new THREE.Quaternion().setFromEuler( + const quatYUP2ZUP = new THREE.Quaternion().setFromEuler( new THREE.Euler(-Math.PI * 0.5, 0, Math.PI) ); - obj.applyQuaternion(quatTHREE2UDV); + obj.applyQuaternion(quatYUP2ZUP); const bbox = new THREE.Box3().setFromObject(obj); const parent = new THREE.Object3D(); @@ -277,6 +277,7 @@ export class AssetsManager { break; case 'min': obj.position.sub(bbox.min); + console.log(id, bbox.min); break; case 'center_min': let centerMin = bbox.min.clone().lerp(bbox.max, 0.5); @@ -284,7 +285,6 @@ export class AssetsManager { obj.position.sub(centerMin); break; default: - throw new Error('no anchor'); } //scale From 876c117db838d73154dc4052037478b7036b55ba Mon Sep 17 00:00:00 2001 From: valentinMachado Date: Thu, 3 Jun 2021 18:10:11 +0200 Subject: [PATCH 05/68] remove log --- src/Game/Components/AssetsManager.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Game/Components/AssetsManager.js b/src/Game/Components/AssetsManager.js index 1b174cf70..86ef40dd1 100644 --- a/src/Game/Components/AssetsManager.js +++ b/src/Game/Components/AssetsManager.js @@ -277,7 +277,6 @@ export class AssetsManager { break; case 'min': obj.position.sub(bbox.min); - console.log(id, bbox.min); break; case 'center_min': let centerMin = bbox.min.clone().lerp(bbox.max, 0.5); From 935c576d8f82933e73c14a1f34ffc258ca458de5 Mon Sep 17 00:00:00 2001 From: valentinMachado Date: Fri, 4 Jun 2021 10:59:13 +0200 Subject: [PATCH 06/68] add outdated setter --- src/Game/Shared/GameObject/GameObject.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Game/Shared/GameObject/GameObject.js b/src/Game/Shared/GameObject/GameObject.js index 598744107..b99191bed 100644 --- a/src/Game/Shared/GameObject/GameObject.js +++ b/src/Game/Shared/GameObject/GameObject.js @@ -58,8 +58,6 @@ const GameObjectModule = class GameObject { //assets has been initialized this.initialized = false; - - //TODO remove me //default object3d this.object3D = new THREE.Object3D(); this.object3D.name = this.name + '_object3D'; @@ -207,6 +205,10 @@ const GameObjectModule = class GameObject { return this.outdated; } + setOutdated(value) { + this.outdated = value; + } + executeScripts(event, params) { const script = this.getComponent(WorldScriptComponent.TYPE); if (!script) return null; From 93573e1f3b741e06286dd981ad075eb7cc185647 Mon Sep 17 00:00:00 2001 From: valentinMachado Date: Fri, 4 Jun 2021 12:25:19 +0200 Subject: [PATCH 07/68] refacto --- src/Game/{ => Shared}/Components/THREEUtils.js | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/Game/{ => Shared}/Components/THREEUtils.js (100%) diff --git a/src/Game/Components/THREEUtils.js b/src/Game/Shared/Components/THREEUtils.js similarity index 100% rename from src/Game/Components/THREEUtils.js rename to src/Game/Shared/Components/THREEUtils.js From 01b3621db02acf49231c0bcac44e7ab869423acb Mon Sep 17 00:00:00 2001 From: valentinMachado Date: Fri, 4 Jun 2021 12:25:29 +0200 Subject: [PATCH 08/68] refacto bis --- src/Game/Components/AssetsManager.js | 2 +- src/Game/Components/Components.js | 2 +- src/Game/GameView/GameView.js | 5 +---- src/Game/Shared/Components/Components.js | 2 ++ src/Game/Shared/Components/THREEUtils.js | 12 ++++++++---- src/Game/Shared/GameObject/GameObject.js | 25 +++++++++++++----------- 6 files changed, 27 insertions(+), 21 deletions(-) diff --git a/src/Game/Components/AssetsManager.js b/src/Game/Components/AssetsManager.js index 86ef40dd1..34e2b632d 100644 --- a/src/Game/Components/AssetsManager.js +++ b/src/Game/Components/AssetsManager.js @@ -4,7 +4,7 @@ import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'; import * as THREE from 'three'; import * as jquery from 'jquery'; import GameObjectModule from '../Shared/GameObject/GameObject'; -import { THREEUtils } from '../Components/THREEUtils'; +const THREEUtils = require('../Shared/Components/THREEUtils'); const DEFAULT_MATERIAL = new THREE.MeshLambertMaterial({ color: 0x00ff00 }); diff --git a/src/Game/Components/Components.js b/src/Game/Components/Components.js index 1abd65a66..d65691aab 100644 --- a/src/Game/Components/Components.js +++ b/src/Game/Components/Components.js @@ -4,4 +4,4 @@ export { WebSocketService } from './WebSocketService'; export { WorldStateInterpolator } from './WorldStateInterpolator'; export { AssetsManager } from './AssetsManager'; export { InputManager } from './InputManager'; -export { THREEUtils } from './THREEUtils'; + diff --git a/src/Game/GameView/GameView.js b/src/Game/GameView/GameView.js index ab750e29f..5d8c41a7b 100644 --- a/src/Game/GameView/GameView.js +++ b/src/Game/GameView/GameView.js @@ -7,8 +7,6 @@ import { AssetsManager } from '../Components/AssetsManager'; import { InputManager } from '../Components/InputManager'; import { Cameraman, Routine } from '../Components/Cameraman'; -import { THREEUtils } from '../Components/THREEUtils'; - import * as THREE from 'three'; import * as proj4 from 'proj4'; import * as itowns from 'itowns'; @@ -16,15 +14,14 @@ import * as itowns from 'itowns'; import './GameView.css'; import LocalScript from '../Shared/GameObject/Components/LocalScript'; import Render from '../Shared/GameObject/Components/Render'; -import { isFunction } from 'jquery'; const udvShared = require('../Shared/Shared'); const Command = udvShared.Command; const WorldState = udvShared.WorldState; +const THREEUtils = udvShared.Components.THREEUtils; export class GameView { constructor(params) { - params.htmlParent = params.htmlParent || document.body; //html diff --git a/src/Game/Shared/Components/Components.js b/src/Game/Shared/Components/Components.js index 919edc2bd..c4d0d74e4 100644 --- a/src/Game/Shared/Components/Components.js +++ b/src/Game/Shared/Components/Components.js @@ -2,8 +2,10 @@ const commonJsData = require('./Data'); const commonJsPrefabUtils = require('./PrefabUtils'); +const commonJsTHREEUtils = require('./THREEUtils'); module.exports = { Data: commonJsData, PrefabUtils: commonJsPrefabUtils, + THREEUtils: commonJsTHREEUtils, }; diff --git a/src/Game/Shared/Components/THREEUtils.js b/src/Game/Shared/Components/THREEUtils.js index 8ed2f06b0..759049a1c 100644 --- a/src/Game/Shared/Components/THREEUtils.js +++ b/src/Game/Shared/Components/THREEUtils.js @@ -1,10 +1,10 @@ /** @format */ -import * as THREE from 'three'; +const THREE = require('three'); //TODO create an object Transform with a clone method -const THREEUtils = { +module.exports = { textureEncoding: THREE.RGBDEncoding, addLights(scene) { @@ -37,6 +37,10 @@ const THREEUtils = { // renderer.toneMapping = THREE.ReinhardToneMapping; // renderer.toneMappingExposure = 1; }, -}; -export { THREEUtils }; + Transform: class { + constructor() { + console.log('new transform'); + } + }, +}; diff --git a/src/Game/Shared/GameObject/GameObject.js b/src/Game/Shared/GameObject/GameObject.js index b99191bed..f337c1131 100644 --- a/src/Game/Shared/GameObject/GameObject.js +++ b/src/Game/Shared/GameObject/GameObject.js @@ -12,6 +12,7 @@ const ColliderComponent = require('./Components/Collider'); const WorldScriptComponent = require('./Components/WorldScript'); const JSONUtils = require('../../../Components/SystemUtils/JSONUtils'); const LocalScriptModule = require('./Components/LocalScript'); +const THREEUtils = require('../Components/THREEUtils'); const GameObjectModule = class GameObject { constructor(json, parent) { @@ -29,6 +30,7 @@ const GameObjectModule = class GameObject { //name this.name = json.name || 'none'; + //TODO remove me //prefabId this.prefabId = json.prefabId || null; @@ -61,6 +63,9 @@ const GameObjectModule = class GameObject { //default object3d this.object3D = new THREE.Object3D(); this.object3D.name = this.name + '_object3D'; + + //buffer + this.eulerBuffer = new THREE.Euler(0, 0, 0, 'ZXY'); //to avoid new THREE.Euler on fetchObject3D } updateNoStaticFromGO(go, assetsManager) { @@ -279,20 +284,18 @@ const GameObjectModule = class GameObject { if (!obj) obj = this.object3D; } - //transform + //position obj.position.copy(this.getPosition()); - //TODO rotation n'est plus un THREE VEctor3 mais un euler - obj.rotation.copy( - new THREE.Euler( - this.transform.rotation.x, - this.transform.rotation.y, - this.transform.rotation.z, - 'ZXY' - ) - ); + //rot + const rot = this.getRotation(); + this.eulerBuffer.x = rot.x; + this.eulerBuffer.y = rot.y; + this.eulerBuffer.z = rot.z; + obj.rotation.copy(this.eulerBuffer); + //scale obj.scale.copy(this.getScale()); - //reset + //add children if recursive if (recursive) { this.children.forEach(function (child) { const childObj = child.fetchObject3D(); From f1688b3839b570f3c1f3005fe40b012b4c00ffef Mon Sep 17 00:00:00 2001 From: valentinMachado Date: Fri, 4 Jun 2021 13:17:37 +0200 Subject: [PATCH 09/68] rename --- src/Game/Shared/GameObject/Components/Render.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Game/Shared/GameObject/Components/Render.js b/src/Game/Shared/GameObject/Components/Render.js index d3eee94fb..aea94fcd0 100644 --- a/src/Game/Shared/GameObject/Components/Render.js +++ b/src/Game/Shared/GameObject/Components/Render.js @@ -92,7 +92,7 @@ const RenderModule = class Render { //stock data in userData this.object3D.userData = { - uuid: this.parent.getUUID(), + gameObjectUUID: this.parent.getUUID(), }; //get the 3D model From a741fbc43f07a62f1da083a1434bdf3b5d3e48ee Mon Sep 17 00:00:00 2001 From: valentinMachado Date: Fri, 4 Jun 2021 14:19:05 +0200 Subject: [PATCH 10/68] transform class --- src/Game/Shared/Components/THREEUtils.js | 62 ++++++++++++++++++++++-- 1 file changed, 59 insertions(+), 3 deletions(-) diff --git a/src/Game/Shared/Components/THREEUtils.js b/src/Game/Shared/Components/THREEUtils.js index 759049a1c..992b9ac27 100644 --- a/src/Game/Shared/Components/THREEUtils.js +++ b/src/Game/Shared/Components/THREEUtils.js @@ -38,9 +38,65 @@ module.exports = { // renderer.toneMappingExposure = 1; }, - Transform: class { - constructor() { - console.log('new transform'); + Transform: class Transform { + constructor(position, rotation, scale) { + this.position = position || new THREE.Vector3(); + this.rotation = rotation || new THREE.Vector3(); + this.scale = scale || new THREE.Vector3(1, 1, 1); + } + + getPosition() { + return this.position; + } + + setPosition(position) { + this.position = position; + } + + getRotation() { + return this.rotation; + } + + setRotation(rotation) { + this.rotation = rotation; + } + + getScale() { + return this.scale; + } + + setScale(scale) { + this.scale = scale; + } + + clone() { + return new Transform( + this.position.clone(), + this.rotation.clone(), + this.scale.clone() + ); + } + + setFromJSON(json) { + if (json) { + if (json.position) { + this.position.x = json.position.x; + this.position.y = json.position.y; + this.position.z = json.position.z; + } + + if (json.rotation) { + this.rotation.x = json.rotation.x; + this.rotation.y = json.rotation.y; + this.rotation.z = json.rotation.z; + } + + if (json.scale) { + this.scale.x = json.scale.x; + this.scale.y = json.scale.y; + this.scale.z = json.scale.z; + } + } } }, }; From 28bbe15df0fa168702af227d8ac20f4379c877dd Mon Sep 17 00:00:00 2001 From: valentinMachado Date: Fri, 4 Jun 2021 15:27:06 +0200 Subject: [PATCH 11/68] transform refacto --- src/Game/Components/Cameraman.js | 1 + src/Game/Shared/Components/THREEUtils.js | 28 +++-- .../Shared/GameObject/Components/Collider.js | 11 +- src/Game/Shared/GameObject/GameObject.js | 103 +++++------------- src/Game/UDVDebugger/UDVDebugger.js | 4 +- 5 files changed, 53 insertions(+), 94 deletions(-) diff --git a/src/Game/Components/Cameraman.js b/src/Game/Components/Cameraman.js index 327beed0a..76cc75bd3 100644 --- a/src/Game/Components/Cameraman.js +++ b/src/Game/Components/Cameraman.js @@ -111,6 +111,7 @@ export class Cameraman { quaternion.multiply(quaternionCam); quaternion.multiply(quaternionAngle); + //this is not a transform of THREEUtils.Transform return { position: position, quaternion: quaternion }; } diff --git a/src/Game/Shared/Components/THREEUtils.js b/src/Game/Shared/Components/THREEUtils.js index 992b9ac27..520ec4d96 100644 --- a/src/Game/Shared/Components/THREEUtils.js +++ b/src/Game/Shared/Components/THREEUtils.js @@ -2,8 +2,6 @@ const THREE = require('three'); -//TODO create an object Transform with a clone method - module.exports = { textureEncoding: THREE.RGBDEncoding, @@ -77,24 +75,32 @@ module.exports = { ); } + lerp(transform, ratio) { + this.position.lerp(transform.getPosition(), ratio); + this.rotation.lerp(transform.getRotation(), ratio); + this.scale.lerp(transform.getScale(), ratio); + } + + toJSON() { + return { + position: this.position.toArray(), + rotation: this.rotation.toArray(), + scale: this.scale.toArray(), + }; + } + setFromJSON(json) { if (json) { if (json.position) { - this.position.x = json.position.x; - this.position.y = json.position.y; - this.position.z = json.position.z; + this.position.fromArray(json.position); } if (json.rotation) { - this.rotation.x = json.rotation.x; - this.rotation.y = json.rotation.y; - this.rotation.z = json.rotation.z; + this.rotation.fromArray(json.rotation); } if (json.scale) { - this.scale.x = json.scale.x; - this.scale.y = json.scale.y; - this.scale.z = json.scale.z; + this.scale.fromArray(json.scale); } } } diff --git a/src/Game/Shared/GameObject/Components/Collider.js b/src/Game/Shared/GameObject/Components/Collider.js index 585a0f87a..2f15cda5b 100644 --- a/src/Game/Shared/GameObject/Components/Collider.js +++ b/src/Game/Shared/GameObject/Components/Collider.js @@ -96,8 +96,9 @@ class ShapeWrapper { const circle = new Circle(json.center.x, json.center.y, json.radius); this.update = function (worldtransform) { - circle.x = json.center.x + worldtransform.position.x; - circle.y = json.center.y + worldtransform.position.y; + const wp = worldtransform.getPosition(); + circle.x = json.center.x + wp.x; + circle.y = json.center.y + wp.y; }; this.shape = circle; @@ -114,10 +115,8 @@ class ShapeWrapper { this.update = function (worldtransform) { const points = []; json.points.forEach(function (p) { - const point = [ - p.x + worldtransform.position.x, - p.y + worldtransform.position.y, - ]; + const wp = worldtransform.getPosition(); + const point = [p.x + wp.x, p.y + wp.y]; points.push(point); //TODO handle rotation }); diff --git a/src/Game/Shared/GameObject/GameObject.js b/src/Game/Shared/GameObject/GameObject.js index f337c1131..a75d20fec 100644 --- a/src/Game/Shared/GameObject/GameObject.js +++ b/src/Game/Shared/GameObject/GameObject.js @@ -35,7 +35,8 @@ const GameObjectModule = class GameObject { this.prefabId = json.prefabId || null; //transform - this.setTransformFromJSON(json.transform); + this.transform = new THREEUtils.Transform(); + this.transform.setFromJSON(json.transform); //static this.static = json.static || false; @@ -84,7 +85,7 @@ const GameObjectModule = class GameObject { setFromJSON(json) { this.components = {}; //clear this.setComponentsFromJSON(json); - this.setTransformFromJSON(json.transform); + this.transform.setFromJSON(json.transform); this.name = json.name; this.static = json.static; @@ -112,17 +113,13 @@ const GameObjectModule = class GameObject { } computeWorldTransform() { - const result = { - position: new THREE.Vector3(), - rotation: new THREE.Vector3(), - scale: new THREE.Vector3(1, 1, 1), - }; + const result = new THREEUtils.Transform(); let current = this; do { - result.position.add(current.getPosition()); - result.rotation.add(current.getRotation()); - result.scale.multiply(current.getScale()); + result.getPosition().add(current.getPosition()); + result.getRotation().add(current.getRotation()); + result.getScale().multiply(current.getScale()); current = current.parent; } while (current); @@ -131,21 +128,19 @@ const GameObjectModule = class GameObject { } move(vector) { - this.transform.position.add(vector); + this.transform.getPosition().add(vector); this.outdated = true; } clampRotation() { - this.transform.rotation.x = - (Math.PI * 2 + this.transform.rotation.x) % (Math.PI * 2); - this.transform.rotation.y = - (Math.PI * 2 + this.transform.rotation.y) % (Math.PI * 2); - this.transform.rotation.z = - (Math.PI * 2 + this.transform.rotation.z) % (Math.PI * 2); + const r = this.transform.getRotation(); + r.x = (Math.PI * 2 + r.x) % (Math.PI * 2); + r.y = (Math.PI * 2 + r.y) % (Math.PI * 2); + r.z = (Math.PI * 2 + r.z) % (Math.PI * 2); } rotate(vector) { - this.transform.rotation.add(vector); + this.transform.getRotation().add(vector); this.clampRotation(); this.outdated = true; } @@ -166,12 +161,9 @@ const GameObjectModule = class GameObject { } computeForwardVector() { + const r = this.transform.getRotation(); const quaternion = new THREE.Quaternion().setFromEuler( - new THREE.Euler( - this.transform.rotation.x, - this.transform.rotation.y, - this.transform.rotation.z - ) + new THREE.Euler(r.x, r.y, r.z) ); const result = this.getDefaultForward().applyQuaternion(quaternion); return result; @@ -306,35 +298,12 @@ const GameObjectModule = class GameObject { return obj; } - setTransformFromJSON(json) { - if (!this.transform) { - const defaultTransform = { - position: new THREE.Vector3(), - rotation: new THREE.Vector3(), - scale: new THREE.Vector3(1, 1, 1), - }; - this.transform = defaultTransform; - } - - if (json) { - if (json.position) { - this.transform.position.x = json.position.x; - this.transform.position.y = json.position.y; - this.transform.position.z = json.position.z; - } - - if (json.rotation) { - this.transform.rotation.x = json.rotation.x; - this.transform.rotation.y = json.rotation.y; - this.transform.rotation.z = json.rotation.z; - } + getTransform() { + return this.transform; + } - if (json.scale) { - this.transform.scale.x = json.scale.x; - this.transform.scale.y = json.scale.y; - this.transform.scale.z = json.scale.z; - } - } + setTransform(transform) { + this.transform = transform; } clone() { @@ -406,31 +375,31 @@ const GameObjectModule = class GameObject { } getRotation() { - return this.transform.rotation; + return this.transform.getRotation(); } setRotation(vector) { - this.transform.rotation.set(vector.x, vector.y, vector.z); + this.transform.getRotation().set(vector.x, vector.y, vector.z); this.clampRotation(); this.outdated = true; } setPosition(vector) { - this.transform.position.set(vector.x, vector.y, vector.z); + this.transform.getPosition().set(vector.x, vector.y, vector.z); this.outdated = true; } getPosition() { - return this.transform.position; + return this.transform.getPosition(); } setScale(vector) { - this.transform.scale.set(vector.x, vector.y, vector.z); + this.transform.getScale().set(vector.x, vector.y, vector.z); this.outdated = true; } getScale() { - return this.transform.scale; + return this.transform.getScale(); } getName() { @@ -453,10 +422,6 @@ const GameObjectModule = class GameObject { children.push(child.toJSON(withServerComponent)); }); - const position = this.transform.position; - const rot = this.transform.rotation; - const scale = this.transform.scale; - const components = {}; for (let type in this.components) { const c = this.components[type]; @@ -465,11 +430,6 @@ const GameObjectModule = class GameObject { } } - //TODO not declare here or use THREE.Vector3.toJSON - const V2JSON = function (vector) { - return { x: vector.x, y: vector.y, z: vector.z }; - }; - return { name: this.name, type: GameObjectModule.TYPE, @@ -479,11 +439,7 @@ const GameObjectModule = class GameObject { parentUUID: this.parentUUID, components: components, children: children, - transform: { - position: V2JSON(position), - rotation: V2JSON(rot), - scale: V2JSON(scale), - }, + transform: this.transform.toJSON(), }; } }; @@ -492,10 +448,7 @@ GameObjectModule.TYPE = 'GameObject'; GameObjectModule.interpolateInPlace = function (g1, g2, ratio) { //modify g1 transform - g1.transform.position.lerp(g2.transform.position, ratio); - g1.transform.rotation.lerp(g2.transform.rotation, ratio); - g1.transform.scale.lerp(g2.transform.scale, ratio); - + g1.getTransform().lerp(g2.getTransform(), ratio); return g1; }; diff --git a/src/Game/UDVDebugger/UDVDebugger.js b/src/Game/UDVDebugger/UDVDebugger.js index e2b195daa..f3a731399 100644 --- a/src/Game/UDVDebugger/UDVDebugger.js +++ b/src/Game/UDVDebugger/UDVDebugger.js @@ -102,8 +102,8 @@ export class UDVDebugger { }; const loc = { - x: avatarGO.transform.position.x / pixelWorldUnit.width, - y: avatarGO.transform.position.y / pixelWorldUnit.height, + x: avatarGO.getPosition().x / pixelWorldUnit.width, + y: avatarGO.getPosition().y / pixelWorldUnit.height, }; // console.log(loc); From f1a88e9130b8b9973af6e3c47e64acdd2d8fa0dd Mon Sep 17 00:00:00 2001 From: valentinMachado Date: Mon, 7 Jun 2021 09:07:30 +0200 Subject: [PATCH 12/68] remove prefabId --- src/Game/Shared/Components/Components.js | 2 -- src/Game/Shared/Components/Data.js | 2 +- src/Game/Shared/Components/PrefabUtils.js | 28 ----------------------- src/Game/Shared/GameObject/GameObject.js | 10 +------- 4 files changed, 2 insertions(+), 40 deletions(-) delete mode 100644 src/Game/Shared/Components/PrefabUtils.js diff --git a/src/Game/Shared/Components/Components.js b/src/Game/Shared/Components/Components.js index c4d0d74e4..94608c1f0 100644 --- a/src/Game/Shared/Components/Components.js +++ b/src/Game/Shared/Components/Components.js @@ -1,11 +1,9 @@ /** @format */ const commonJsData = require('./Data'); -const commonJsPrefabUtils = require('./PrefabUtils'); const commonJsTHREEUtils = require('./THREEUtils'); module.exports = { Data: commonJsData, - PrefabUtils: commonJsPrefabUtils, THREEUtils: commonJsTHREEUtils, }; diff --git a/src/Game/Shared/Components/Data.js b/src/Game/Shared/Components/Data.js index 3b4343102..373abdc4c 100644 --- a/src/Game/Shared/Components/Data.js +++ b/src/Game/Shared/Components/Data.js @@ -17,7 +17,7 @@ module.exports = Object.freeze({ }, }, - //THREAD + //THREAD TODO move this to worldthread and rename this file Constants pack(obj) { let OString = JSON.stringify(obj); diff --git a/src/Game/Shared/Components/PrefabUtils.js b/src/Game/Shared/Components/PrefabUtils.js deleted file mode 100644 index 2c6352b77..000000000 --- a/src/Game/Shared/Components/PrefabUtils.js +++ /dev/null @@ -1,28 +0,0 @@ -/** @format */ - -const JSONUtils = require('../../../Components/SystemUtils/JSONUtils'); - -module.exports = { - parsePrefab(goJSON, manager) { - console.warn('deprecated ?'); - const parse = function (json, cb) { - if (json.children instanceof Object) { - for (let key in json.children) { - cb(json.children, key); - } - } - }; - - parse(goJSON, function (json, key) { - const value = json[key]; - - if (value.prefabId != undefined) { - const prefabJSON = manager.fetchPrefabJSON(value.prefabId); - JSONUtils.overWrite(prefabJSON, json); - json[key] = prefabJSON; - } - }); - - return goJSON; - }, -}; diff --git a/src/Game/Shared/GameObject/GameObject.js b/src/Game/Shared/GameObject/GameObject.js index a75d20fec..0285a6e2c 100644 --- a/src/Game/Shared/GameObject/GameObject.js +++ b/src/Game/Shared/GameObject/GameObject.js @@ -30,10 +30,6 @@ const GameObjectModule = class GameObject { //name this.name = json.name || 'none'; - //TODO remove me - //prefabId - this.prefabId = json.prefabId || null; - //transform this.transform = new THREEUtils.Transform(); this.transform.setFromJSON(json.transform); @@ -90,14 +86,10 @@ const GameObjectModule = class GameObject { this.static = json.static; //TODO recursive call for children + if (this.children.length) console.warn('children not set from ', json); } initAssetsComponents(manager, udvShared, isServerSide = false) { - if (this.prefabId) { - const json = manager.fetchPrefabJSON(this.prefabId); - JSONUtils.overWrite(json, this.json); - this.setFromJSON(json); - } if (!this.initialized) { this.initialized = true; From 0a7f170bfc8e8bb983dfe41860fbf6db34f7f1d3 Mon Sep 17 00:00:00 2001 From: valentinMachado Date: Mon, 7 Jun 2021 09:29:47 +0200 Subject: [PATCH 13/68] move function in utils --- src/Components/SystemUtils/File.js | 16 +++++++++++++++ src/Components/SystemUtils/JSONUtils.js | 27 +++++++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/src/Components/SystemUtils/File.js b/src/Components/SystemUtils/File.js index 43afe413f..2e076ba55 100644 --- a/src/Components/SystemUtils/File.js +++ b/src/Components/SystemUtils/File.js @@ -14,6 +14,7 @@ module.exports = { downloadAnchorNode.click(); downloadAnchorNode.remove(); }, + loadJSON(filePath) { return new Promise((resolve, reject) => { jquery.ajax({ @@ -30,4 +31,19 @@ module.exports = { }); }); }, + + readSingleFile(e, onLoad) { + try { + const file = e.target.files[0]; + if (!file) { + return; + } + const _this = this; + const reader = new FileReader(); + reader.onload = onLoad; + reader.readAsText(file); + } catch (e) { + throw new Error(e); + } + }, }; diff --git a/src/Components/SystemUtils/JSONUtils.js b/src/Components/SystemUtils/JSONUtils.js index 918af82a0..cddb0cd94 100644 --- a/src/Components/SystemUtils/JSONUtils.js +++ b/src/Components/SystemUtils/JSONUtils.js @@ -38,4 +38,31 @@ module.exports = { } }); }, + + separator: '&', + + pack(jsonArray) { + let result = ''; + for (let key in jsonArray) { + result += JSON.stringify(jsonArray[key]); + result += this.separator; + } + + //remove seprator at the end + if (result.endsWith(this.separator)) { + result = result.slice(0, result.length - this.separator.length); + } + return result; + }, + + unpack(string) { + const prefabs = string.split(this.separator); + const result = {}; + prefabs.forEach(function (p) { + const json = JSON.parse(p); + result[json.name] = json; + }); + + return result; + }, }; From b8bd580ac0b52a46505aa4f9435d270105805708 Mon Sep 17 00:00:00 2001 From: valentinMachado Date: Mon, 7 Jun 2021 09:43:09 +0200 Subject: [PATCH 14/68] static func bind --- src/Game/Shared/GameObject/Components/Render.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/Game/Shared/GameObject/Components/Render.js b/src/Game/Shared/GameObject/Components/Render.js index aea94fcd0..3ccd4e19a 100644 --- a/src/Game/Shared/GameObject/Components/Render.js +++ b/src/Game/Shared/GameObject/Components/Render.js @@ -155,4 +155,20 @@ const RenderModule = class Render { RenderModule.TYPE = 'Render'; +RenderModule.bindName = function (goJSON, name) { + try { + goJSON.components.Render.name = name; + } catch (e) { + throw new Error(e); + } +}; + +RenderModule.bindColor = function (goJSON, color) { + try { + goJSON.components.Render.color = color; + } catch (e) { + throw new Error(e); + } +}; + module.exports = RenderModule; From a728a9d85d6ca678b089fe141fb472cd2471bc50 Mon Sep 17 00:00:00 2001 From: valentinMachado Date: Mon, 7 Jun 2021 10:57:21 +0200 Subject: [PATCH 15/68] add TODO --- src/Game/Components/AssetsManager.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Game/Components/AssetsManager.js b/src/Game/Components/AssetsManager.js index 34e2b632d..b60062e6b 100644 --- a/src/Game/Components/AssetsManager.js +++ b/src/Game/Components/AssetsManager.js @@ -201,6 +201,7 @@ export class AssetsManager { return frame; } + //TODO assetManager load video with config a return video with id createVideo(path, w = 1, h = 1, size) { const video = document.createElement('video'); video.src = path; From d0fc1088e8f3263aa0876fe5642776ebf27b351f Mon Sep 17 00:00:00 2001 From: valentinMachado Date: Mon, 7 Jun 2021 13:58:16 +0200 Subject: [PATCH 16/68] video are now localscript --- src/Game/Components/AssetsManager.js | 9 +++++++++ src/Game/GameView/GameView.js | 8 +++----- src/Game/Shared/GameObject/Components/Render.js | 16 +++++----------- 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/src/Game/Components/AssetsManager.js b/src/Game/Components/AssetsManager.js index b60062e6b..73901e897 100644 --- a/src/Game/Components/AssetsManager.js +++ b/src/Game/Components/AssetsManager.js @@ -10,6 +10,8 @@ const DEFAULT_MATERIAL = new THREE.MeshLambertMaterial({ color: 0x00ff00 }); export class AssetsManager { constructor() { + this.conf = null; + //manager to load scripts this.prefabs = {}; this.worldScripts = {}; @@ -47,6 +49,11 @@ export class AssetsManager { return new GameObjectModule(this.prefabs[idprefab]); } + fetchVideoPath(idVideo) { + if (!this.conf.videos[idVideo]) console.error('no video with id ', idVideo); + return this.conf.videos[idVideo].path; + } + fetchPrefabJSON(idprefab) { if (!this.prefabs[idprefab]) console.error('no prefab with id ', idprefab); return JSON.parse(JSON.stringify(this.prefabs[idprefab])); @@ -323,6 +330,8 @@ export class AssetsManager { } loadFromConfig(config) { + this.conf = config; + //load config file const _this = this; const loader = new GLTFLoader(); diff --git a/src/Game/GameView/GameView.js b/src/Game/GameView/GameView.js index 5d8c41a7b..4a440d0d1 100644 --- a/src/Game/GameView/GameView.js +++ b/src/Game/GameView/GameView.js @@ -404,11 +404,9 @@ export class GameView { if (!_this.isLocal) g.initAssetsComponents(_this.assetsManager, udvShared); - g.traverse(function (child) { - const scriptComponent = child.getComponent(LocalScript.TYPE); - if (scriptComponent) - scriptComponent.execute(LocalScript.EVENT.INIT, [ctx]); - }); + const scriptComponent = g.getComponent(LocalScript.TYPE); + if (scriptComponent) + scriptComponent.execute(LocalScript.EVENT.INIT, [ctx]); //add static object to obstacle if (g.isStatic()) { diff --git a/src/Game/Shared/GameObject/Components/Render.js b/src/Game/Shared/GameObject/Components/Render.js index 3ccd4e19a..3f5440965 100644 --- a/src/Game/Shared/GameObject/Components/Render.js +++ b/src/Game/Shared/GameObject/Components/Render.js @@ -86,6 +86,11 @@ const RenderModule = class Render { } } + addObject3D(obj) { + this.object3D.add(obj); + this.originalObject3D = this.object3D.clone(); + } + initAssets(assetsManager) { this.object3D = new THREE.Object3D(); this.object3D.name = 'Render Object3D ' + this.parent.getName(); @@ -129,17 +134,6 @@ const RenderModule = class Render { ); this.object3D.add(mediaImg); } - - if (this.media.video) { - const result = assetsManager.createVideo( - this.media.video.path, - this.media.video.width, - this.media.video.height, - this.media.video.size - ); - this.tickCb.push(result.tick); - this.object3D.add(result.frame); - } } const color = this.color; From 427bd03905370707b8ceaaa030387f7de088ade7 Mon Sep 17 00:00:00 2001 From: valentinMachado Date: Mon, 7 Jun 2021 16:13:39 +0200 Subject: [PATCH 17/68] export transform control --- src/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/index.js b/src/index.js index 1f076ff5e..c396989d3 100644 --- a/src/index.js +++ b/src/index.js @@ -27,8 +27,8 @@ export { jquery }; //three import * as THREE from 'three'; import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'; -import { PointerLockControls } from 'three/examples/jsm/controls/PointerLockControls'; -export { THREE, OrbitControls, PointerLockControls }; +import { TransformControls } from 'three/examples/jsm/controls/TransformControls'; +export { THREE, OrbitControls, TransformControls }; //proj4 import * as proj4 from 'proj4'; From 74ca5da96b991b552c48ec211577e4be04e10ef7 Mon Sep 17 00:00:00 2001 From: valentinMachado Date: Tue, 8 Jun 2021 10:35:59 +0200 Subject: [PATCH 18/68] format with prettier widgets sources --- .eslintrc.js | 23 + package.json | 2 + .../3DTiles/3DTilesBuildingUtils.js | 17 +- .../View/CameraPositionerView.js | 15 +- src/Widgets/CityObjects/CityObjectModule.js | 24 +- .../View/AttributeFilterSelector.js | 20 +- .../View/CityObjectFilterSelector.js | 27 +- .../View/CityObjectFilterWindow.js | 35 +- .../CityObjects/View/CityObjectWindow.css | 6 +- .../CityObjects/View/CityObjectWindow.js | 84 ++-- .../CityObjects/ViewModel/AttributeFilter.js | 22 +- .../CityObjects/ViewModel/CityObjectFilter.js | 16 +- .../CityObjects/ViewModel/CityObjectLayer.js | 14 +- .../ViewModel/CityObjectProvider.js | 61 ++- .../View/DocumentVisualizer.css | 6 +- .../View/DocumentVisualizerWindow.js | 73 +-- src/Widgets/Documents/DocumentModule.js | 12 +- src/Widgets/Documents/Model/Document.js | 25 +- .../Documents/Model/DocumentService.js | 86 ++-- .../Documents/View/AbstractDocumentWindow.js | 37 +- .../Documents/View/DocumentInspectorWindow.js | 38 +- .../Documents/View/DocumentNavigatorWindow.js | 80 ++-- src/Widgets/Documents/View/DocumentView.js | 47 +- src/Widgets/Documents/View/DocumentWindow.css | 10 +- .../Documents/ViewModel/DocumentFilter.js | 14 +- .../Documents/ViewModel/DocumentProvider.js | 97 ++-- .../ViewModel/DocumentSearchFilter.js | 46 +- .../3DTilesDebug/views/3DTilesDebugWindow.js | 68 ++- .../services/AuthenticationService.js | 291 ++++++------ .../views/AuthenticationView.css | 182 ++++---- .../views/AuthenticationView.js | 263 +++++------ .../Extensions/Contribute/ContributeModule.js | 48 +- .../Contribute/Service/ContributeService.js | 16 +- .../Extensions/Contribute/View/Contribute.css | 14 +- .../Contribute/View/DocumentCreationWindow.js | 95 ++-- .../View/DocumentDeletionInterface.js | 20 +- .../Contribute/View/DocumentUpdateWindow.js | 40 +- .../DocumentCommentsModule.js | 20 +- .../services/DocumentCommentsService.js | 97 ++-- .../views/DocumentCommentsStyle.css | 132 +++--- .../views/DocumentCommentsWindow.js | 139 +++--- .../DocumentValidationModule.js | 23 +- .../Service/DocumentsInValidationSource.js | 8 +- .../Service/ValidationService.js | 16 +- .../DocumentValidation/View/ValidationView.js | 105 +++-- src/Widgets/Extensions/Extensions.js | 2 - .../Geocoding/services/GeocodingService.js | 40 +- .../Geocoding/views/GeocodingStyle.css | 18 +- .../Geocoding/views/GeocodingView.js | 43 +- src/Widgets/GuidedTour/GuidedTour.css | 370 +++++++-------- src/Widgets/GuidedTour/GuidedTour.js | 176 +++---- .../GuidedTour/GuidedTourController.js | 82 ++-- src/Widgets/LayerChoice/views/LayerChoice.js | 95 ++-- src/Widgets/Links/LinkModule.js | 54 ++- src/Widgets/Links/Model/Link.js | 17 +- src/Widgets/Links/Model/LinkService.js | 32 +- .../Links/View/CityObjectLinkInterface.js | 36 +- .../Links/View/DocumentLinkInterface.js | 79 ++-- src/Widgets/Links/View/LinkView.js | 59 ++- .../Links/ViewModel/CityObjectLinkFilters.js | 48 +- src/Widgets/Links/ViewModel/LinkProvider.js | 155 ++++--- src/Widgets/Others/About.css | 45 +- src/Widgets/Others/About.js | 54 ++- src/Widgets/Others/Help.css | 54 +-- src/Widgets/Others/Help.js | 25 +- .../Temporal/Model/3DTemporalBatchTable.js | 142 +++--- .../Model/3DTemporalBoundingVolume.js | 43 +- .../Temporal/Model/3DTemporalExtension.js | 244 +++++----- .../Model/3DTemporalPrimaryTransaction.js | 18 +- .../Temporal/Model/3DTemporalTileset.js | 82 ++-- .../Temporal/Model/3DTemporalTransaction.js | 21 +- .../Model/3DTemporalTransactionAggregate.js | 18 +- .../Temporal/Model/3DTemporalVersion.js | 27 +- .../3DTILES_temporal.batchTable.schema.json | 2 +- .../3DTILES_temporal.primaryTransaction.json | 21 +- .../3DTILES_temporal.tileset.schema.json | 14 +- .../3DTILES_temporal.transaction.schema.json | 6 +- ..._temporal.transactionAggregate.schema.json | 23 +- ...DTILES_temporal.version.schema.schema.json | 4 +- ...LES_temporal.versionTransition.schema.json | 2 +- src/Widgets/Temporal/TemporalModule.js | 24 +- src/Widgets/Temporal/View/EnumWindows.js | 16 +- src/Widgets/Temporal/View/NetworkManager.js | 133 +++--- .../Temporal/View/TemporalGraphWindow.js | 85 ++-- .../Temporal/View/TemporalSliderWindow.js | 112 ++--- src/Widgets/Temporal/View/TemporalView.js | 46 +- src/Widgets/Temporal/View/TemporalWindow.css | 68 +-- .../Temporal/ViewModel/TemporalProvider.js | 428 ++++++++++-------- 88 files changed, 3115 insertions(+), 2462 deletions(-) create mode 100644 .eslintrc.js diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 000000000..00b804fc4 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,23 @@ +/** @format */ + +module.exports = { + env: { + browser: true, + es2021: true, + node: true, + }, + extends: 'eslint:recommended', + parserOptions: { + ecmaVersion: 2020, + sourceType: 'module', + ecmaFeatures: { + jsx: true, + }, + }, + rules: { + indent: [2, 2, { SwitchCase: 1 }], + 'linebreak-style': ['error', 'unix'], + quotes: ['error', 'single'], + semi: ['error', 'always'], + }, +}; diff --git a/package.json b/package.json index 3b689cd3b..28ac51c2e 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,7 @@ "description": "A collection of itowns plugins", "main": "src", "scripts": { + "eslint": "./node_modules/.bin/eslint ./src", "test": "npm run build", "build": "cross-env NODE_ENV=production webpack", "build-debug": "cross-env NODE_ENV=development webpack", @@ -36,6 +37,7 @@ "child-process-promise": "^2.2.1", "cross-env": "^7.0.3", "css-loader": "^0.28.10", + "eslint": "^7.28.0", "nodemon": "^2.0.7", "style-loader": "^0.20.3", "url-loader": "^1.0.1", diff --git a/src/Components/3DTiles/3DTilesBuildingUtils.js b/src/Components/3DTiles/3DTilesBuildingUtils.js index fdc61ab5f..086c003b0 100644 --- a/src/Components/3DTiles/3DTilesBuildingUtils.js +++ b/src/Components/3DTiles/3DTilesBuildingUtils.js @@ -1,11 +1,16 @@ -import { setTileVerticesColor, getBatchIdFromIntersection, - getBatchTableFromTile, - getTileInLayer} from "./3DTilesUtils"; +/** @format */ + +import { + setTileVerticesColor, + getBatchIdFromIntersection, + getBatchTableFromTile, + getTileInLayer, +} from './3DTilesUtils'; /** * Gets a building ID from an intersection. The intersecting object must * be a "Mesh" object with a batch id. - * + * * @param {*} inter An intersection */ export function getBuildingIdFromIntersection(inter) { @@ -28,7 +33,7 @@ export function getBuildingInfoFromBuildingId(tilesInfo, buildingId) { /** * Sets the color of one building in the scene. - * + * * @param {*} layer The 3DTiles layer. * @param {*} buildingInfo The building info. * @param {Array} color The color. @@ -39,4 +44,4 @@ export function colorBuilding(layer, buildingInfo, color) { throw 'Building not in the view - tile is not loaded'; } setTileVerticesColor(tile, color, buildingInfo.arrayIndexes); -} \ No newline at end of file +} diff --git a/src/Widgets/CameraPositioner/View/CameraPositionerView.js b/src/Widgets/CameraPositioner/View/CameraPositionerView.js index 095105b5c..7dd3ff773 100644 --- a/src/Widgets/CameraPositioner/View/CameraPositionerView.js +++ b/src/Widgets/CameraPositioner/View/CameraPositionerView.js @@ -1,7 +1,9 @@ +/** @format */ + //Components -import { ModuleView } from "../../../Components/ModuleView/ModuleView"; -import { PositionerWindow } from "../../../Components/Camera/PositionerWindow"; -import { Window } from "../../../Components/GUI/js/Window"; +import { ModuleView } from '../../../Components/ModuleView/ModuleView'; +import { PositionerWindow } from '../../../Components/Camera/PositionerWindow'; +import { Window } from '../../../Components/GUI/js/Window'; export class CameraPositionerView extends ModuleView { constructor(itownsView, cameraControls) { @@ -9,8 +11,9 @@ export class CameraPositionerView extends ModuleView { this.positionerWindow = new PositionerWindow(itownsView, cameraControls); - this.positionerWindow.addEventListener(Window.EVENT_DISABLED, - () => this.disable()); + this.positionerWindow.addEventListener(Window.EVENT_DISABLED, () => + this.disable() + ); } enableView() { @@ -20,4 +23,4 @@ export class CameraPositionerView extends ModuleView { disableView() { this.positionerWindow.dispose(); } -} \ No newline at end of file +} diff --git a/src/Widgets/CityObjects/CityObjectModule.js b/src/Widgets/CityObjects/CityObjectModule.js index e32169f93..678b45085 100644 --- a/src/Widgets/CityObjects/CityObjectModule.js +++ b/src/Widgets/CityObjects/CityObjectModule.js @@ -1,8 +1,10 @@ +/** @format */ + //Components -import { CityObjectStyle } from "../../Components/3DTiles/Model/CityObjectStyle"; +import { CityObjectStyle } from '../../Components/3DTiles/Model/CityObjectStyle'; -import { CityObjectProvider } from "./ViewModel/CityObjectProvider"; -import { CityObjectWindow } from "./View/CityObjectWindow"; +import { CityObjectProvider } from './ViewModel/CityObjectProvider'; +import { CityObjectWindow } from './View/CityObjectWindow'; /** * Manages the city objects and allows the user to visualize them with @@ -14,7 +16,7 @@ export class CityObjectModule { * Manages the city objects and allows the user to visualize them with * filters. Other modules can extend the functionnalities of the city object * module by adding filters. - * + * * @param {LayerManager} layerManager The layer manager. * @param {object} config The UDV configuration. * @param {object} config.cityObjects The city objects config. @@ -43,7 +45,7 @@ export class CityObjectModule { /** * Adds an event listener to the city object provider. - * + * * @param {string} event The event of the city object provider. * @param {(data: any) => any} action The listener method. */ @@ -53,7 +55,7 @@ export class CityObjectModule { /** * Removes the event listener from the city object provider. - * + * * @param {(data: any) => any} action The listener to remove. */ removeEventListener(action) { @@ -61,9 +63,9 @@ export class CityObjectModule { } /** - * Creates a new extension for the city object window. An extension is + * Creates a new extension for the city object window. An extension is * a piece of HTML identified by a label. - * + * * @param {string} label The extension label. * @param {object} options The options for the extension. * @param {string} options.type The type of the extension. Can either be @@ -83,7 +85,7 @@ export class CityObjectModule { /** * Removes an existing extension in the city object window. - * + * * @param {string} label The extension label. */ removeExtension(label) { @@ -92,11 +94,11 @@ export class CityObjectModule { /** * Adds a filter selector in the city object filter window. - * + * * @param {CityObjectFilterSelector} filterSelector The filter selector to * add. */ addFilterSelector(filterSelector) { this.view.addFilterSelector(filterSelector); } -} \ No newline at end of file +} diff --git a/src/Widgets/CityObjects/View/AttributeFilterSelector.js b/src/Widgets/CityObjects/View/AttributeFilterSelector.js index 90064ea1f..1a8757afe 100644 --- a/src/Widgets/CityObjects/View/AttributeFilterSelector.js +++ b/src/Widgets/CityObjects/View/AttributeFilterSelector.js @@ -1,6 +1,8 @@ -import { CityObjectFilterSelector } from "./CityObjectFilterSelector"; -import { CityObjectProvider } from "../ViewModel/CityObjectProvider"; -import { AttributeFilter } from "../ViewModel/AttributeFilter"; +/** @format */ + +import { CityObjectFilterSelector } from './CityObjectFilterSelector'; +import { CityObjectProvider } from '../ViewModel/CityObjectProvider'; +import { AttributeFilter } from '../ViewModel/AttributeFilter'; /** * A filter selector for the `AttributeFilter` filter. It allows the user to @@ -11,7 +13,7 @@ import { AttributeFilter } from "../ViewModel/AttributeFilter"; export class AttributeFilterSelector extends CityObjectFilterSelector { /** * Constructs the attribute filter selector from the provider. - * + * * @param {CityObjectProvider} provider The city object provider. */ constructor(provider) { @@ -19,7 +21,7 @@ export class AttributeFilterSelector extends CityObjectFilterSelector { /** * The associated attribute filter. - * + * * @type {AttributeFilter} */ this.filter = new AttributeFilter(); @@ -29,7 +31,7 @@ export class AttributeFilterSelector extends CityObjectFilterSelector { } get html() { - return /*html*/` + return /*html*/ ` @@ -42,9 +44,9 @@ export class AttributeFilterSelector extends CityObjectFilterSelector { /** * Sets the `tileId`, `batchId` and `props` attributes of the attribut filter * from the given form data. - * + * * @override - * + * * @param {FormData} formData */ onSubmit(formData) { @@ -56,4 +58,4 @@ export class AttributeFilterSelector extends CityObjectFilterSelector { } } } -} \ No newline at end of file +} diff --git a/src/Widgets/CityObjects/View/CityObjectFilterSelector.js b/src/Widgets/CityObjects/View/CityObjectFilterSelector.js index 34dd96dde..1ba6f26eb 100644 --- a/src/Widgets/CityObjects/View/CityObjectFilterSelector.js +++ b/src/Widgets/CityObjects/View/CityObjectFilterSelector.js @@ -2,26 +2,29 @@ * Represents an option in the list of filters the user can select. It also * stores additional HTML that can be put in a form if the filter accepts * parameters. + * + * @format */ + export class CityObjectFilterSelector { /** * Constructs a filter selector from the associated filter label and a * display name. - * + * * @param {string} filterLabel The associated filter. * @param {string} displayName The displayed name in the `select` tag. */ - constructor(filterLabel, displayName) { + constructor(filterLabel, displayName) { /** * The label of the corresponding filter. - * + * * @type {string} */ this.filterLabel = filterLabel; /** * The displayed name of the filter. - * + * * @type {string} */ this.displayName = displayName; @@ -29,7 +32,7 @@ export class CityObjectFilterSelector { /** * The HTML that will be put in the filter form. - * + * * @returns {string} */ get html() { @@ -40,29 +43,25 @@ export class CityObjectFilterSelector { /** * Triggers when the HTML elements are created. */ - onCreated() { - - } + onCreated() {} /** * Triggers when the form is submitted. - * + * * @param {FormData} formData The form data corresponding to the filter * selector form. */ - onSubmit(formData) { - - } + onSubmit(formData) {} /** * Adds the HTML content of the filter selector in the given HTLM element. * This element should be a form, or part of a form. Calls the `onCreated` * hook. - * + * * @param {HTMLElement} parentElement The parent element to add the fields. */ appendFormFieldsTo(parentElement) { parentElement.innerHTML = this.html; this.onCreated(); } -} \ No newline at end of file +} diff --git a/src/Widgets/CityObjects/View/CityObjectFilterWindow.js b/src/Widgets/CityObjects/View/CityObjectFilterWindow.js index 7de85fa85..e9b018a86 100644 --- a/src/Widgets/CityObjects/View/CityObjectFilterWindow.js +++ b/src/Widgets/CityObjects/View/CityObjectFilterWindow.js @@ -1,7 +1,9 @@ +/** @format */ + //Components -import { Window } from "../../../Components/GUI/js/Window"; +import { Window } from '../../../Components/GUI/js/Window'; -import { CityObjectFilterSelector } from "./CityObjectFilterSelector"; +import { CityObjectFilterSelector } from './CityObjectFilterSelector'; /** * The filter selection window. This window allows the user to pick a filter @@ -17,7 +19,7 @@ export class CityObjectFilterWindow extends Window { /** * The list of filter selectors. - * + * * @type {Array} */ this.filterSelectors = []; @@ -27,7 +29,7 @@ export class CityObjectFilterWindow extends Window { } get innerContentHtml() { - return /*html*/` + return /*html*/ `

Filter selection

@@ -55,19 +57,21 @@ export class CityObjectFilterWindow extends Window { this.filterFormElement.onsubmit = () => { this._onSubmit(); return false; - } + }; } /** * Adds a filter selector in the filter selectos list. - * + * * @param {CityObjectFilterSelector} filterSelector The filter selector to * add. */ addFilterSelector(filterSelector) { if (!!this.getFilterSelector(filterSelector.filterLabel)) { - throw 'A filter selector with the same filter label already exist: ' - + filterSelector.filterLabel; + throw ( + 'A filter selector with the same filter label already exist: ' + + filterSelector.filterLabel + ); } this.filterSelectors.push(filterSelector); this._createFilterSelect(); @@ -75,7 +79,7 @@ export class CityObjectFilterWindow extends Window { /** * Returns the filter selector corresponding to the given filter label. - * + * * @param {string} filterLabel The label of the filter. */ getFilterSelector(filterLabel) { @@ -125,12 +129,14 @@ export class CityObjectFilterWindow extends Window { * selected the 'No filter' option. */ _getCurrentSelector() { - let selected = this.filterSelectElement.options[this.filterSelectElement.selectedIndex].label; + let selected = + this.filterSelectElement.options[this.filterSelectElement.selectedIndex] + .label; if (selected === 'no-filter') { return undefined; } - + let selector = this.getFilterSelector(selected); if (selector === undefined) { @@ -154,7 +160,10 @@ export class CityObjectFilterWindow extends Window { let formData = new FormData(this.filterFormElement); selector.onSubmit(formData); - this.sendEvent(CityObjectFilterWindow.EVENT_FILTER_SELECTED, selector.filterLabel); + this.sendEvent( + CityObjectFilterWindow.EVENT_FILTER_SELECTED, + selector.filterLabel + ); this.disable(); } @@ -191,4 +200,4 @@ export class CityObjectFilterWindow extends Window { static get EVENT_FILTER_SELECTED() { return 'EVENT_FILTER_SELECTED'; } -} \ No newline at end of file +} diff --git a/src/Widgets/CityObjects/View/CityObjectWindow.css b/src/Widgets/CityObjects/View/CityObjectWindow.css index a5d4c1d4a..9f403a2a0 100644 --- a/src/Widgets/CityObjects/View/CityObjectWindow.css +++ b/src/Widgets/CityObjects/View/CityObjectWindow.css @@ -1,3 +1,5 @@ +/** @format */ + .city-object-title { margin: 5px 0 5px 0; font-weight: bold; @@ -13,7 +15,7 @@ margin: 10px; } -.city-object-filter-section input[type="text"] { +.city-object-filter-section input[type='text'] { width: 100%; box-sizing: border-box; } @@ -27,4 +29,4 @@ border: 1px solid #f2f2f2; margin: 2px; margin-left: 10px; -} \ No newline at end of file +} diff --git a/src/Widgets/CityObjects/View/CityObjectWindow.js b/src/Widgets/CityObjects/View/CityObjectWindow.js index d9940dbae..5359230a6 100644 --- a/src/Widgets/CityObjects/View/CityObjectWindow.js +++ b/src/Widgets/CityObjects/View/CityObjectWindow.js @@ -1,11 +1,13 @@ +/** @format */ + //Components -import { Window } from "../../../Components/GUI/js/Window"; -import { CityObjectStyle } from "../../../Components/3DTiles/Model/CityObjectStyle"; +import { Window } from '../../../Components/GUI/js/Window'; +import { CityObjectStyle } from '../../../Components/3DTiles/Model/CityObjectStyle'; -import { CityObjectProvider } from "../ViewModel/CityObjectProvider"; -import { CityObjectFilterSelector } from "./CityObjectFilterSelector"; -import { CityObjectFilterWindow } from "./CityObjectFilterWindow"; -import { AttributeFilterSelector } from "./AttributeFilterSelector"; +import { CityObjectProvider } from '../ViewModel/CityObjectProvider'; +import { CityObjectFilterSelector } from './CityObjectFilterSelector'; +import { CityObjectFilterWindow } from './CityObjectFilterWindow'; +import { AttributeFilterSelector } from './AttributeFilterSelector'; import './CityObjectWindow.css'; @@ -17,7 +19,7 @@ import './CityObjectWindow.css'; export class CityObjectWindow extends Window { /** * Constructs the window from the provider. - * + * * @param {CityObjectProvider} provider The city object provider. */ constructor(provider) { @@ -25,35 +27,35 @@ export class CityObjectWindow extends Window { /** * The city object provider. - * + * * @type {CityObjectProvider} */ this.provider = provider; /** * The window for selected filters. - * + * * @type {CityObjectFilterWindow} */ this.filterWindow = new CityObjectFilterWindow(); /** * The style for the layer chosen by the user, through the filter window. - * + * * @type {CityObjectStyle | string} */ - this.defaultLayerStyle = {materialProps: {color: 0xffa14f}}; + this.defaultLayerStyle = { materialProps: { color: 0xffa14f } }; /** * Wether the use is currently selecting a city object. - * + * * @type {boolean} */ this.isSelectingCityObject = false; /** * The list of extensions - * + * * @type {Array<{html: string, label: string, id: string}>} */ this.extensions = []; @@ -61,7 +63,7 @@ export class CityObjectWindow extends Window { let viewerDiv = document.getElementById('viewerDiv'); /** * The event listener for mouse clicks. - * + * * @type {(event: MouseEvent) => any} */ this.mouseClickListener = (event) => { @@ -77,29 +79,34 @@ export class CityObjectWindow extends Window { viewerDiv.removeEventListener('mousedown', this.mouseClickListener); }); - // Adding a filter selector for the attribute filter - this.filterWindow.addFilterSelector(new AttributeFilterSelector(this.provider)); + this.filterWindow.addFilterSelector( + new AttributeFilterSelector(this.provider) + ); // The event listener for filter selection (in the filter window). Updates // the layer in the provider. this.filterWindow.addEventListener( CityObjectFilterWindow.EVENT_FILTER_SELECTED, - (filterLabel) => this._onFilterSelected(filterLabel)); + (filterLabel) => this._onFilterSelected(filterLabel) + ); // The event listener for the layer change. Updates the layer description. - this.provider.addEventListener(CityObjectProvider.EVENT_LAYER_CHANGED, - () => this._updateLayerDescription()); + this.provider.addEventListener(CityObjectProvider.EVENT_LAYER_CHANGED, () => + this._updateLayerDescription() + ); // Event listener for city object selection - this.provider.addEventListener(CityObjectProvider.EVENT_CITY_OBJECT_SELECTED, - (cityObject) => this._updateSelectedCityObjectDescription(cityObject)); + this.provider.addEventListener( + CityObjectProvider.EVENT_CITY_OBJECT_SELECTED, + (cityObject) => this._updateSelectedCityObjectDescription(cityObject) + ); this._updateLayerDescription(); this._updateSelectedCityObjectDescription(); } get innerContentHtml() { - return /*html*/` + return /*html*/ `

Filter

@@ -140,14 +147,12 @@ export class CityObjectWindow extends Window { this._createExtensionElement(extension); } - this.selectFilterButtonElement.onclick = - () => this.filterWindow.enable(); + this.selectFilterButtonElement.onclick = () => this.filterWindow.enable(); - this.clearFilterButtonElement.onclick = - () => this.provider.removeLayer(); + this.clearFilterButtonElement.onclick = () => this.provider.removeLayer(); - this.clearSelectionButtonElement.onclick = - () => this._clearCityObjectSelection(); + this.clearSelectionButtonElement.onclick = () => + this._clearCityObjectSelection(); this.clearSelectionButtonElement.disabled = true; @@ -167,7 +172,7 @@ export class CityObjectWindow extends Window { this.selectedFilterElement.innerText = layer.filter.toString(); this.layerColorIndicatorElement.style.display = ''; this.layerColorIndicatorElement.style.background = - '#' + (new THREE.Color(layer.style.materialProps.color)).getHexString(); + '#' + new THREE.Color(layer.style.materialProps.color).getHexString(); } else { this.selectedFilterElement.innerText = ''; this.layerColorIndicatorElement.style.display = 'none'; @@ -180,7 +185,7 @@ export class CityObjectWindow extends Window { /** * Adds a filter selector in the city object filter window. - * + * * @param {CityObjectFilterSelector} filterSelector The filter selector to * add. */ @@ -191,7 +196,7 @@ export class CityObjectWindow extends Window { /** * Triggered when the user selects a filter in the filter selection window. * Sets the correct layer in the provider. - * + * * @param {string} filterLabel The selected filter label. */ _onFilterSelected(filterLabel) { @@ -205,7 +210,7 @@ export class CityObjectWindow extends Window { /** * Sets the default style for the layer defined by the user (through the * filter selection window). - * + * * @param {CityObjectStyle | string} style The default style for the layer. */ setDefaultLayerStyle(style) { @@ -225,7 +230,7 @@ export class CityObjectWindow extends Window { /** * Updates the description for the selected city object. - * + * * @param {CityObject} cityObject The selected city object. */ _updateSelectedCityObjectDescription(cityObject) { @@ -233,8 +238,11 @@ export class CityObjectWindow extends Window { return; } - this.selectionColorIndicatorElement.style.background = '#' + - (new THREE.Color(this.provider.defaultSelectionStyle.materialProps.color)).getHexString(); + this.selectionColorIndicatorElement.style.background = + '#' + + new THREE.Color( + this.provider.defaultSelectionStyle.materialProps.color + ).getHexString(); if (!cityObject) { this.selectedCityObjectElement.innerHTML = ''; @@ -244,7 +252,7 @@ export class CityObjectWindow extends Window { this.clearSelectionButtonElement.disabled = false; - let html = /*html*/` + let html = /*html*/ `

Attributes

Tile ID : ${cityObject.tile.tileId}
@@ -252,7 +260,7 @@ export class CityObjectWindow extends Window { Layer : ${cityObject.tile.layer.name} `; for (let prop of Object.entries(cityObject.props)) { - html += /*html*/` + html += /*html*/ `
${prop[0]} : ${prop[1]} `; } @@ -318,4 +326,4 @@ export class CityObjectWindow extends Window { get selectionColorIndicatorElement() { return document.getElementById(this.selectionColorIndicatorId); } -} \ No newline at end of file +} diff --git a/src/Widgets/CityObjects/ViewModel/AttributeFilter.js b/src/Widgets/CityObjects/ViewModel/AttributeFilter.js index a429f4ec9..3b8a3c056 100644 --- a/src/Widgets/CityObjects/ViewModel/AttributeFilter.js +++ b/src/Widgets/CityObjects/ViewModel/AttributeFilter.js @@ -1,7 +1,9 @@ +/** @format */ + //Components -import { CityObject } from "../../../Components/3DTiles/Model/CityObject"; +import { CityObject } from '../../../Components/3DTiles/Model/CityObject'; -import { CityObjectFilter } from "./CityObjectFilter"; +import { CityObjectFilter } from './CityObjectFilter'; /** * A specialization of `CityObjectFilter` to filter the city objects from @@ -37,9 +39,9 @@ export class AttributeFilter extends CityObjectFilter { * Accepts city objects according to their attributes. For each attribute in * this filter that evaluates to `true` (ie. neither undefined, null nor an * empty string), equality is tested with the city object. - * + * * @param {CityObject} cityObject The city object to evaluate. - * + * * @returns {boolean} Wether the city object is acceptable. */ accepts(cityObject) { @@ -52,8 +54,10 @@ export class AttributeFilter extends CityObjectFilter { } for (let key of Object.keys(this.props)) { - if (!cityObject.props[key] || - (!!this.props[key] && this.props[key] != cityObject.props[key])) { + if ( + !cityObject.props[key] || + (!!this.props[key] && this.props[key] != cityObject.props[key]) + ) { return false; } } @@ -92,11 +96,11 @@ export class AttributeFilter extends CityObjectFilter { result += ', '; } } - result += ')' + result += ')'; } else { - result += 'All city objects' + result += 'All city objects'; } return result; } -} \ No newline at end of file +} diff --git a/src/Widgets/CityObjects/ViewModel/CityObjectFilter.js b/src/Widgets/CityObjects/ViewModel/CityObjectFilter.js index a10f47931..aebddc3a5 100644 --- a/src/Widgets/CityObjects/ViewModel/CityObjectFilter.js +++ b/src/Widgets/CityObjects/ViewModel/CityObjectFilter.js @@ -1,5 +1,7 @@ +/** @format */ + //Components -import { CityObject } from "../../../Components/3DTiles/Model/CityObject"; +import { CityObject } from '../../../Components/3DTiles/Model/CityObject'; /** * Represents a filter for city objects. It is basically a function that takes @@ -9,7 +11,7 @@ export class CityObjectFilter { /** * Constructs a new city object filter, from an acceptation function. If no * acceptation function was provided, the filter accepts all city objects. - * + * * @param {string} label The unique label identifying the filter. * @param {(CityObject) => boolean} [accepts] The function responsible to * filter the city objects. It must evaluate wether a city object is @@ -18,12 +20,12 @@ export class CityObjectFilter { constructor(label, accepts) { /** * The unique identifier of the filter. - * + * * @type {string} */ this.label = label; - if (typeof(accepts) === 'function') { + if (typeof accepts === 'function') { this.accepts = accepts; } else { // Necessary if inheritance is used, I'm not sure why though @@ -34,9 +36,9 @@ export class CityObjectFilter { /** * The function responsible to filter the city objects. It evaluates wether * a city object is acceptable according to the filter. - * + * * @param {CityObject} cityObject The city object to evaluate. - * + * * @returns {boolean} Wether the city object is acceptable. */ accepts(cityObject) { @@ -50,4 +52,4 @@ export class CityObjectFilter { toString() { return this.label; } -} \ No newline at end of file +} diff --git a/src/Widgets/CityObjects/ViewModel/CityObjectLayer.js b/src/Widgets/CityObjects/ViewModel/CityObjectLayer.js index fd258568c..9d2a59f63 100644 --- a/src/Widgets/CityObjects/ViewModel/CityObjectLayer.js +++ b/src/Widgets/CityObjects/ViewModel/CityObjectLayer.js @@ -1,7 +1,9 @@ +/** @format */ + //Components -import { CityObjectStyle } from "../../../Components/3DTiles/Model/CityObjectStyle"; +import { CityObjectStyle } from '../../../Components/3DTiles/Model/CityObjectStyle'; -import { CityObjectFilter } from "./CityObjectFilter"; +import { CityObjectFilter } from './CityObjectFilter'; /** * A layer represents an association between a set of city objects and a style. @@ -10,7 +12,7 @@ import { CityObjectFilter } from "./CityObjectFilter"; export class CityObjectLayer { /** * Constructs a layer from a filter and a style. - * + * * @param {CityObjectFilter} filter The filter associated with the layer. * @param {CityObjectStyle | string} style The style associated with the * layer. @@ -22,16 +24,16 @@ export class CityObjectLayer { /** * The filter associated with the layer. - * + * * @type {CityObjectFilter} */ this.filter = filter; /** * The style associated with the layer. - * + * * @type {CityObjectStyle | string} */ this.style = style; } -} \ No newline at end of file +} diff --git a/src/Widgets/CityObjects/ViewModel/CityObjectProvider.js b/src/Widgets/CityObjects/ViewModel/CityObjectProvider.js index e130e6dd4..99b40e6a5 100644 --- a/src/Widgets/CityObjects/ViewModel/CityObjectProvider.js +++ b/src/Widgets/CityObjects/ViewModel/CityObjectProvider.js @@ -1,11 +1,16 @@ +/** @format */ + //Components -import { CityObjectStyle } from "../../../Components/3DTiles/Model/CityObjectStyle"; -import { CityObjectID, CityObject } from "../../../Components/3DTiles/Model/CityObject"; -import { EventSender } from "../../../Components/Events/EventSender"; -import { LayerManager } from "../../../Components/LayerManager/LayerManager"; +import { CityObjectStyle } from '../../../Components/3DTiles/Model/CityObjectStyle'; +import { + CityObjectID, + CityObject, +} from '../../../Components/3DTiles/Model/CityObject'; +import { EventSender } from '../../../Components/Events/EventSender'; +import { LayerManager } from '../../../Components/LayerManager/LayerManager'; -import { CityObjectFilter } from "./CityObjectFilter"; -import { CityObjectLayer } from "./CityObjectLayer"; +import { CityObjectFilter } from './CityObjectFilter'; +import { CityObjectLayer } from './CityObjectLayer'; /** * The city object provider manages the city object by organizing them in two @@ -16,49 +21,49 @@ import { CityObjectLayer } from "./CityObjectLayer"; export class CityObjectProvider extends EventSender { /** * Constructs a city object provider, using a layer manager. - * + * * @param {LayerManager} layerManager The layer manager. */ constructor(layerManager) { super(); /** * The tiles manager. - * + * * @type {LayerManager} */ this.layerManager = layerManager; /** * The available filters. - * + * * @type {Object.} */ this.filters = {}; /** * The current highlighted layer. - * + * * @type {CityObjectLayer} */ this.cityOjectLayer = undefined; /** * The array of city objects in the layer. - * + * * @type {Array} */ this.layerCityObjectIds = []; /** * The selected city object. - * + * * @type {CityObject} */ this.selectedCityObject = undefined; /** * The style applied to the selected city object. - * + * * @type {CityObjectStyle | string} */ this.defaultSelectionStyle = { materialProps: { color: 0x13ddef } }; @@ -75,7 +80,7 @@ export class CityObjectProvider extends EventSender { /** * Selects a city object from a mouse event. If a city object is actually * under the mouse, the `EVENT_CITY_OBJECT_SELECTED` event is sent. - * + * * @param {MouseEvent} mouseEvent The mouse click event. */ selectCityObject(mouseEvent) { @@ -101,7 +106,7 @@ export class CityObjectProvider extends EventSender { /** * Sets the style for the selected city object. - * + * * @param {CityObjectStyle | string} style The style. */ setSelectionStyle(style) { @@ -115,7 +120,7 @@ export class CityObjectProvider extends EventSender { * Adds a filter to the dictionnary of available filters. The key shall be * the `label` attribute of the filter. After that, the * `EVENT_FILTERS_UPDATED` event is sent. - * + * * @param {CityObjectFilter} cityObjectFilter The filter to add. */ addFilter(cityObjectFilter) { @@ -132,7 +137,7 @@ export class CityObjectProvider extends EventSender { /** * Returns the currently available filters. - * + * * @return {Array} The currently available filters. */ getFilters() { @@ -145,7 +150,7 @@ export class CityObjectProvider extends EventSender { /** * Sets the current layer. The layer is defined by a filter (ie. a set * of city objects) and a style. Sends the `EVENT_LAYER_CHANGED` event. - * + * * @param {string} filterLabel Label of the filter that defines the layer. * The filter must first be registered using `addFilter`. * @param {CityObjectStyle | string} style The style to associate to the @@ -169,7 +174,7 @@ export class CityObjectProvider extends EventSender { /** * Returns the current layer. - * + * * @returns {CityObjectLayer} The current layer. */ getLayer() { @@ -188,13 +193,15 @@ export class CityObjectProvider extends EventSender { /** * Updates the tiles manager so that it has the correct styles associated with * the right city objects. - * + * * @private */ _updateTilesManager() { this.layerManager.removeAll3DTilesStyles(); if (!!this.selectedCityObject) { - let tileManager = this.layerManager.getTilesManagerByLayerID(this.selectedCityObject.tile.layer.id); + let tileManager = this.layerManager.getTilesManagerByLayerID( + this.selectedCityObject.tile.layer.id + ); if (this.cityOjectLayer === undefined) { this.layerCityObjectIds = []; @@ -203,10 +210,16 @@ export class CityObjectProvider extends EventSender { .findAllCityObjects(this.cityOjectLayer.filter.accepts) .map((co) => co.cityObjectId); - tileManager.setStyle(this.layerCityObjectIds, this.cityOjectLayer.style); + tileManager.setStyle( + this.layerCityObjectIds, + this.cityOjectLayer.style + ); } - tileManager.setStyle(this.selectedCityObject.cityObjectId, this.defaultSelectionStyle); + tileManager.setStyle( + this.selectedCityObject.cityObjectId, + this.defaultSelectionStyle + ); } } @@ -234,4 +247,4 @@ export class CityObjectProvider extends EventSender { static get EVENT_CITY_OBJECT_SELECTED() { return 'EVENT_CITY_OBJECT_SELECTED'; } -} \ No newline at end of file +} diff --git a/src/Widgets/DocumentVisualizer/View/DocumentVisualizer.css b/src/Widgets/DocumentVisualizer/View/DocumentVisualizer.css index 54c94e584..5318063d5 100644 --- a/src/Widgets/DocumentVisualizer/View/DocumentVisualizer.css +++ b/src/Widgets/DocumentVisualizer/View/DocumentVisualizer.css @@ -1,3 +1,5 @@ +/** @format */ + .orienter-box { width: 55%; height: 55%; @@ -18,7 +20,7 @@ .orienter-box .controls-panel { width: 80%; max-width: 500px; - background: rgba(30,30,30,.6); + background: rgba(30, 30, 30, 0.6); border: 1px solid #000; padding: 5px; color: white; @@ -41,4 +43,4 @@ .orienter-box .controls-panel .slider-container input { width: 100%; -} \ No newline at end of file +} diff --git a/src/Widgets/DocumentVisualizer/View/DocumentVisualizerWindow.js b/src/Widgets/DocumentVisualizer/View/DocumentVisualizerWindow.js index 1eba8039d..0f6018ca0 100644 --- a/src/Widgets/DocumentVisualizer/View/DocumentVisualizerWindow.js +++ b/src/Widgets/DocumentVisualizer/View/DocumentVisualizerWindow.js @@ -1,9 +1,11 @@ -import { AbstractDocumentWindow } from "../../Documents/View/AbstractDocumentWindow"; -import * as THREE from "three"; +/** @format */ + +import { AbstractDocumentWindow } from '../../Documents/View/AbstractDocumentWindow'; +import * as THREE from 'three'; import './DocumentVisualizer.css'; -import { DocumentProvider } from "../../Documents/ViewModel/DocumentProvider"; -import { DocumentModule } from "../../Documents/DocumentModule"; +import { DocumentProvider } from '../../Documents/ViewModel/DocumentProvider'; +import { DocumentModule } from '../../Documents/DocumentModule'; /** * Represents the document visualizer, under the form of an oriented image. It @@ -13,7 +15,7 @@ import { DocumentModule } from "../../Documents/DocumentModule"; export class DocumentVisualizerWindow extends AbstractDocumentWindow { /** * Creates a new document image orienter. - * + * * @param {DocumentModule} documentModule The document module. * @param {*} itownsView The iTowns view. * @param {*} cameraControls The planar camera controls. @@ -34,40 +36,40 @@ export class DocumentVisualizerWindow extends AbstractDocumentWindow { this.disable(); await this.startTravelToDisplayedDocument(); this.requestDisplay(); - } + }, }); /** * The iTowns view. - * + * * @type {any} */ this.itownsView = itownsView; /** * The camera controls. - * + * * @type {any} */ this.cameraControls = cameraControls; /** * The visualization camera position. - * + * * @type {THREE.Vector3} */ this.position = undefined; /** * The visualization camera orientation. - * + * * @type {THREE.Quaternion} */ this.quaternion = undefined; } get html() { - return /*html*/` + return /*html*/ `

@@ -84,7 +86,7 @@ export class DocumentVisualizerWindow extends AbstractDocumentWindow { windowCreated() { this.hide(); - this.window.classList.add("orienter-box"); + this.window.classList.add('orienter-box'); this.window.style.position = 'absolute'; this.closeButtonElement.onclick = () => { @@ -98,8 +100,10 @@ export class DocumentVisualizerWindow extends AbstractDocumentWindow { documentWindowReady() { // Dispose the window when the displayed document change - this.provider.addEventListener(DocumentProvider.EVENT_DISPLAYED_DOC_CHANGED, - () => this.disable()); + this.provider.addEventListener( + DocumentProvider.EVENT_DISPLAYED_DOC_CHANGED, + () => this.disable() + ); } ////////////////////// @@ -108,7 +112,7 @@ export class DocumentVisualizerWindow extends AbstractDocumentWindow { /** * Triggered when the opacity of the slider changes. This method apply the * change on the image and the output element. - * + * * @private */ _onOpacityChange() { @@ -120,7 +124,7 @@ export class DocumentVisualizerWindow extends AbstractDocumentWindow { /** * Sets the orientation for the camera. `startTravel` should be called after * this method to apply the new position. - * + * * @param {THREE.Vector3} position The visualization camera position. */ setTargetPosition(position) { @@ -130,7 +134,7 @@ export class DocumentVisualizerWindow extends AbstractDocumentWindow { /** * Sets the orientation for the camera. `startTravel` should be called after * this method to apply the new orientation. - * + * * @param {THREE.Quaternion} position The visualization camera orientation. */ setTargetQuaternion(quaternion) { @@ -139,7 +143,7 @@ export class DocumentVisualizerWindow extends AbstractDocumentWindow { /** * Sets the image source. - * + * * @param {string} newSrc The image source. */ setImageSrc(newSrc) { @@ -149,7 +153,7 @@ export class DocumentVisualizerWindow extends AbstractDocumentWindow { /** * Retrieve the displayed document and start a travel to its visualization * location. - * + * * @async */ async startTravelToDisplayedDocument() { @@ -161,9 +165,11 @@ export class DocumentVisualizerWindow extends AbstractDocumentWindow { let imageSrc = await this.provider.getDisplayedDocumentImage(); - if (isNaN(currentDoc.visualization.positionX) || - isNaN(currentDoc.visualization.quaternionX)) { - return; + if ( + isNaN(currentDoc.visualization.positionX) || + isNaN(currentDoc.visualization.quaternionX) + ) { + return; } var docViewPos = new THREE.Vector3(); @@ -187,10 +193,10 @@ export class DocumentVisualizerWindow extends AbstractDocumentWindow { /** * Starts the document orientation. The processes first assign the correct src * to the image, then sets the opacity to 0. After the travel is finished, - * the opacity is gradually restored. + * the opacity is gradually restored. * To call this function, the `position`, `quaternion` and `imageSrc` * attributes must all have been set beforehand. - * + * * @async */ startTravel() { @@ -198,8 +204,7 @@ export class DocumentVisualizerWindow extends AbstractDocumentWindow { this.opacitySliderElement.value = 0; this.opacityElement.value = 0; - this.cameraControls.initiateTravel(this.position, 2, - this.quaternion, true); + this.cameraControls.initiateTravel(this.position, 2, this.quaternion, true); this.itownsView.notifyChange(); return new Promise((resolve, reject) => { @@ -212,14 +217,14 @@ export class DocumentVisualizerWindow extends AbstractDocumentWindow { this._onOpacityChange(); if (nextValue >= 1) { nextValue = 1; - clearInterval(intervalHandle) + clearInterval(intervalHandle); } }; intervalHandle = setInterval(increaseOpacity, 15); resolve(); }, 2000); } catch (e) { - reject(e); + reject(e); } }); } @@ -228,7 +233,7 @@ export class DocumentVisualizerWindow extends AbstractDocumentWindow { ///// GETTERS get closeButtonId() { - return `${this.windowId}_close_button` + return `${this.windowId}_close_button`; } get closeButtonElement() { @@ -236,15 +241,15 @@ export class DocumentVisualizerWindow extends AbstractDocumentWindow { } get opacitySliderId() { - return `${this.windowId}_opacity_slider` + return `${this.windowId}_opacity_slider`; } get opacitySliderElement() { return document.getElementById(this.opacitySliderId); } - + get opacityId() { - return `${this.windowId}_opacity` + return `${this.windowId}_opacity`; } get opacityElement() { @@ -252,10 +257,10 @@ export class DocumentVisualizerWindow extends AbstractDocumentWindow { } get imageId() { - return `${this.windowId}_image` + return `${this.windowId}_image`; } get imageElement() { return document.getElementById(this.imageId); } -} \ No newline at end of file +} diff --git a/src/Widgets/Documents/DocumentModule.js b/src/Widgets/Documents/DocumentModule.js index 5dc2fe8a5..1ef144c04 100644 --- a/src/Widgets/Documents/DocumentModule.js +++ b/src/Widgets/Documents/DocumentModule.js @@ -1,9 +1,11 @@ +/** @format */ + //Components -import { RequestService } from "../../Components/Request/RequestService"; +import { RequestService } from '../../Components/Request/RequestService'; -import { DocumentService, DocumentSource } from "./Model/DocumentService"; -import { DocumentProvider } from "./ViewModel/DocumentProvider"; -import { DocumentView } from "./View/DocumentView"; +import { DocumentService, DocumentSource } from './Model/DocumentService'; +import { DocumentProvider } from './ViewModel/DocumentProvider'; +import { DocumentView } from './View/DocumentView'; /** * The entry point of the documents module. @@ -74,7 +76,7 @@ export class DocumentModule { * for a button. */ addInspectorExtension(label, options) { - this.view.inspectorWindow.addExtension(label, options) + this.view.inspectorWindow.addExtension(label, options); } /** diff --git a/src/Widgets/Documents/Model/Document.js b/src/Widgets/Documents/Model/Document.js index 3b0d85a86..73931814e 100644 --- a/src/Widgets/Documents/Model/Document.js +++ b/src/Widgets/Documents/Model/Document.js @@ -1,6 +1,9 @@ /** * Represents a document. + * + * @format */ + export class Document { /** * Creates a new document. @@ -8,70 +11,70 @@ export class Document { constructor() { /** * The ID of the document. - * + * * @type {number} */ this.id; /** * The title of the document. - * + * * @type {string} */ this.title; /** * The source of the document. - * + * * @type {string} */ this.source; /** * The holder of the rights for the document. - * + * * @type {string} */ this.rightsHolder; /** * The description of the document. - * + * * @type {string} */ this.description; /** * The reference data, in an ISO 8601 format. - * + * * @type {string} */ this.refDate; /** * The publication data, in an ISO 8601 format. - * + * * @type {string} */ this.publicationDate; /** * The creator id. - * + * * @type {number} */ this.user_id; /** * The validation status information. - * + * * @type {{status: string}} */ this.validationStatus; /** * Visualization information. - * + * * @type {{ * positionX: number, * positionY: number, @@ -84,4 +87,4 @@ export class Document { */ this.visualization; } -} \ No newline at end of file +} diff --git a/src/Widgets/Documents/Model/DocumentService.js b/src/Widgets/Documents/Model/DocumentService.js index 780dcccf2..1c6b3f05f 100644 --- a/src/Widgets/Documents/Model/DocumentService.js +++ b/src/Widgets/Documents/Model/DocumentService.js @@ -1,8 +1,10 @@ +/** @format */ + //Components -import { RequestService } from "../../../Components/Request/RequestService"; -import { imageToDataURI } from "../../../Components/DataProcessing/DataProcessing"; +import { RequestService } from '../../../Components/Request/RequestService'; +import { imageToDataURI } from '../../../Components/DataProcessing/DataProcessing'; -import { Document } from "./Document"; +import { Document } from './Document'; /** * This class is responsible of fetching the documents from the server. It is @@ -11,7 +13,7 @@ import { Document } from "./Document"; export class DocumentService { /** * Constructs a new document service. - * + * * @param {RequestService} requestService The request service. * @param {object} config The configuration of UD-Viz. * @param {object} config.server The server configuration. @@ -24,14 +26,14 @@ export class DocumentService { constructor(requestService, config) { /** * The request service. - * + * * @type {RequestService} */ this.requestService = requestService; - + /** * If authentication should be used for the request. - * + * * @type {boolean} */ this.authenticate = false; @@ -41,14 +43,14 @@ export class DocumentService { /** * The object that defines the server URLs to fetch documents. - * + * * @type {DocumentSource} */ this.source = new DefaultDocumentSource(config); /** * The list of documents. - * + * * @type {Array} */ this.documents = []; @@ -56,15 +58,15 @@ export class DocumentService { /** * Sets the source of documents. - * + * * @param {DocumentSource} docSource The document source. * @param {boolean} [authenticate] Specifies if authentication should be used * to fetch documents. - * + * * @returns {DocumentSource} The previous source. */ setSource(docSource, authenticate = false) { - if (! (docSource instanceof DocumentSource)) { + if (!(docSource instanceof DocumentSource)) { throw 'The document source must be an instance of DocumentSource'; } @@ -77,14 +79,17 @@ export class DocumentService { /** * Fetches the documents from the server and return them in an array. - * + * * @async - * + * * @returns {Promise>} */ async fetchDocuments() { - let req = await this.requestService.request('GET', - this.source.getDocumentUrl(), { authenticate: this.authenticate }); + let req = await this.requestService.request( + 'GET', + this.source.getDocumentUrl(), + { authenticate: this.authenticate } + ); if (req.status !== 200) { throw 'Could not fetch the documents: ' + req.statusText; @@ -97,20 +102,22 @@ export class DocumentService { /** * Fetches the image corresponding to the given document. - * + * * @param {Document} doc The document to fetch the image. - * + * * @returns {string} The data string of the image. */ async fetchDocumentImage(doc) { let imgUrl = this.source.getImageUrl(doc); let req = await this.requestService.request('GET', imgUrl, { responseType: 'arraybuffer', - authenticate: this.authenticate + authenticate: this.authenticate, }); if (req.status >= 200 && req.status < 300) { - return imageToDataURI(req.response, - req.getResponseHeader('Content-Type')); + return imageToDataURI( + req.response, + req.getResponseHeader('Content-Type') + ); } throw 'Could not get the file'; } @@ -120,15 +127,13 @@ export class DocumentService { * An object that holds and returns the URLs for documents. */ export class DocumentSource { - constructor() { - - } + constructor() {} /** * Returns the URL to retrieve the documents. - * + * * @abstract - * + * * @returns {string} */ getDocumentUrl() { @@ -137,11 +142,11 @@ export class DocumentSource { /** * Returns the URL to retrieve the image of the document. - * + * * @param {Document} doc The document. - * + * * @abstract - * + * * @returns {string} */ getImageUrl(doc) { @@ -154,7 +159,7 @@ export class DocumentSource { */ class DefaultDocumentSource extends DocumentSource { /** - * + * * @param {object} config The configuration of UD-Viz. * @param {object} config.server The server configuration. * @param {string} config.server.url The server url. @@ -166,23 +171,28 @@ class DefaultDocumentSource extends DocumentSource { /** * The URL to fetch the documents. - * + * * @type {string} */ this.documentUrl; /** * The route to fetch the document images. - * + * * @type {string} */ this.fileRoute; - if (!!config && !!config.server && !!config.server.url && - !!config.server.document && !!config.server.file) { + if ( + !!config && + !!config.server && + !!config.server.url && + !!config.server.document && + !!config.server.file + ) { this.documentUrl = config.server.url; - if (this.documentUrl.slice(-1) !== "/") { - this.documentUrl += "/"; + if (this.documentUrl.slice(-1) !== '/') { + this.documentUrl += '/'; } this.documentUrl += config.server.document; this.fileRoute = config.server.file; @@ -197,10 +207,10 @@ class DefaultDocumentSource extends DocumentSource { /** * @override - * + * * @param {Document} doc The document. */ getImageUrl(doc) { return this.documentUrl + '/' + doc.id + '/' + this.fileRoute; } -} \ No newline at end of file +} diff --git a/src/Widgets/Documents/View/AbstractDocumentWindow.js b/src/Widgets/Documents/View/AbstractDocumentWindow.js index a6187e726..971eb235e 100644 --- a/src/Widgets/Documents/View/AbstractDocumentWindow.js +++ b/src/Widgets/Documents/View/AbstractDocumentWindow.js @@ -1,51 +1,54 @@ +/** @format */ + //Components -import { Window } from "../../../Components/GUI/js/Window"; +import { Window } from '../../../Components/GUI/js/Window'; -import { DocumentProvider } from "../ViewModel/DocumentProvider"; -import { DocumentView } from "./DocumentView"; +import { DocumentProvider } from '../ViewModel/DocumentProvider'; +import { DocumentView } from './DocumentView'; -import './DocumentWindow.css' +import './DocumentWindow.css'; export class AbstractDocumentWindow extends Window { /** * Constructs an abstract document window from a name. - * + * * @param {string} name The name of the window. */ constructor(name) { - super(`document2-${name.replace(/ +/, "-").toLowerCase()}`, - `Document - ${name}`, true); + super( + `document2-${name.replace(/ +/, '-').toLowerCase()}`, + `Document - ${name}`, + true + ); /** * The document provider. - * + * * @type {DocumentProvider} */ this.provider = undefined; /** * The document view. - * + * * @type {DocumentView} */ this.view = undefined; } - + /** * Function called when the document provider and the view have been set up. * Operations that depends on them can be performed in this function. - * + * * @override */ - documentWindowReady() { - - } + documentWindowReady() {} /** * Sets the provider and the view. Should be called by `DocumentView`. Once * this is done, the window is actually usable ; this triggers the * `documentWindowReady` method. - * + * * @param {DocumentView} view The document view. * @param {DocumentProvider} provider The document provider. */ @@ -58,11 +61,11 @@ export class AbstractDocumentWindow extends Window { /** * Request to show a this document window. - * + * * @param {boolean} [hideOtherWindows] Set to `true` to hide other document * windows. */ requestDisplay(hideOtherWindows = false) { this.view.requestWindowDisplay(this, hideOtherWindows); } -} \ No newline at end of file +} diff --git a/src/Widgets/Documents/View/DocumentInspectorWindow.js b/src/Widgets/Documents/View/DocumentInspectorWindow.js index 49a1fd4a3..030fcc07a 100644 --- a/src/Widgets/Documents/View/DocumentInspectorWindow.js +++ b/src/Widgets/Documents/View/DocumentInspectorWindow.js @@ -1,6 +1,8 @@ -import { DocumentProvider } from "../ViewModel/DocumentProvider"; -import { Document } from "../Model/Document"; -import { AbstractDocumentWindow } from "./AbstractDocumentWindow"; +/** @format */ + +import { DocumentProvider } from '../ViewModel/DocumentProvider'; +import { Document } from '../Model/Document'; +import { AbstractDocumentWindow } from './AbstractDocumentWindow'; /** * The window responsible for displaying the currently displayed document, as @@ -31,7 +33,7 @@ export class DocumentInspectorWindow extends AbstractDocumentWindow { } get innerContentHtml() { - return /*html*/` + return /*html*/ `

Title:

@@ -86,8 +88,10 @@ export class DocumentInspectorWindow extends AbstractDocumentWindow { } documentWindowReady() { - this.provider.addEventListener(DocumentProvider.EVENT_DISPLAYED_DOC_CHANGED, - (doc) => this.onDisplayedDocumentChange(doc)); + this.provider.addEventListener( + DocumentProvider.EVENT_DISPLAYED_DOC_CHANGED, + (doc) => this.onDisplayedDocumentChange(doc) + ); } /////////////////////// @@ -133,10 +137,12 @@ export class DocumentInspectorWindow extends AbstractDocumentWindow { this.docDescriptionElement.innerText = newDocument.description; this.docSourceElement.innerText = newDocument.source; this.docRightsHolderElement.innerText = newDocument.rightsHolder; - this.docPubDateElement.innerText = - (new Date(newDocument.publicationDate)).toLocaleDateString(); - this.docRefDateElement.innerText = - (new Date(newDocument.refDate)).toLocaleDateString(); + this.docPubDateElement.innerText = new Date( + newDocument.publicationDate + ).toLocaleDateString(); + this.docRefDateElement.innerText = new Date( + newDocument.refDate + ).toLocaleDateString(); this.docImageElement.src = await this.provider.getDisplayedDocumentImage(); } @@ -144,7 +150,7 @@ export class DocumentInspectorWindow extends AbstractDocumentWindow { ///// GETTERS get docTitleId() { - return `${this.windowId}_title` + return `${this.windowId}_title`; } get docTitleElement() { @@ -152,7 +158,7 @@ export class DocumentInspectorWindow extends AbstractDocumentWindow { } get docDescriptionId() { - return `${this.windowId}_desc` + return `${this.windowId}_desc`; } get docDescriptionElement() { @@ -160,7 +166,7 @@ export class DocumentInspectorWindow extends AbstractDocumentWindow { } get docSourceId() { - return `${this.windowId}_source` + return `${this.windowId}_source`; } get docSourceElement() { @@ -168,7 +174,7 @@ export class DocumentInspectorWindow extends AbstractDocumentWindow { } get docRightsHolderId() { - return `${this.windowId}_rights_holder` + return `${this.windowId}_rights_holder`; } get docRightsHolderElement() { @@ -176,7 +182,7 @@ export class DocumentInspectorWindow extends AbstractDocumentWindow { } get docPubDateId() { - return `${this.windowId}_pub_date` + return `${this.windowId}_pub_date`; } get docPubDateElement() { @@ -184,7 +190,7 @@ export class DocumentInspectorWindow extends AbstractDocumentWindow { } get docRefDateId() { - return `${this.windowId}_ref_date` + return `${this.windowId}_ref_date`; } get docRefDateElement() { diff --git a/src/Widgets/Documents/View/DocumentNavigatorWindow.js b/src/Widgets/Documents/View/DocumentNavigatorWindow.js index c73d11943..12897b158 100644 --- a/src/Widgets/Documents/View/DocumentNavigatorWindow.js +++ b/src/Widgets/Documents/View/DocumentNavigatorWindow.js @@ -1,7 +1,9 @@ -import { DocumentProvider } from "../ViewModel/DocumentProvider"; -import { Document } from "../Model/Document"; -import { DocumentSearchFilter } from "../ViewModel/DocumentSearchFilter"; -import { AbstractDocumentWindow } from "./AbstractDocumentWindow"; +/** @format */ + +import { DocumentProvider } from '../ViewModel/DocumentProvider'; +import { Document } from '../Model/Document'; +import { DocumentSearchFilter } from '../ViewModel/DocumentSearchFilter'; +import { AbstractDocumentWindow } from './AbstractDocumentWindow'; /** * Represents the navigator window for the documents. It contains the filters on @@ -26,18 +28,18 @@ export class DocumentNavigatorWindow extends AbstractDocumentWindow { * a panel. * * @type {Object. any, - * html: string - * }>} - */ - this.extensions = {}; + * type: 'button' | 'panel', + * label: string, + * id: string, + * callback?: (doc: Document[]) => any, + * html: string + * }>} + */ + this.extensions = {}; } get innerContentHtml() { - return /*html*/` + return /*html*/ `

Document(s) @@ -111,10 +113,14 @@ export class DocumentNavigatorWindow extends AbstractDocumentWindow { documentWindowReady() { this.provider.addFilter(this.searchFilter); - this.provider.addEventListener(DocumentProvider.EVENT_FILTERED_DOCS_UPDATED, - (documents) => this._onFilteredDocumentsUpdate(documents)); - this.provider.addEventListener(DocumentProvider.EVENT_DISPLAYED_DOC_CHANGED, - (doc) => this._onDisplayedDocumentChange(doc)); + this.provider.addEventListener( + DocumentProvider.EVENT_FILTERED_DOCS_UPDATED, + (documents) => this._onFilteredDocumentsUpdate(documents) + ); + this.provider.addEventListener( + DocumentProvider.EVENT_DISPLAYED_DOC_CHANGED, + (doc) => this._onDisplayedDocumentChange(doc) + ); } ////////////////////////////// @@ -136,11 +142,13 @@ export class DocumentNavigatorWindow extends AbstractDocumentWindow { list.innerHTML = ''; for (let doc of documents) { let item = document.createElement('li'); - item.innerHTML = /*html*/` + item.innerHTML = /*html*/ `
${doc.title}
-
Refering ${(new Date(doc.refDate)).toLocaleDateString()}
+
Refering ${new Date( + doc.refDate + ).toLocaleDateString()}
`; - item.classList.add('navigator-result-doc') + item.classList.add('navigator-result-doc'); item.onclick = () => { this.provider.setDisplayedDocument(doc); }; @@ -167,13 +175,13 @@ export class DocumentNavigatorWindow extends AbstractDocumentWindow { } if (!!document) { let newIndex = this.provider.getDisplayedDocumentIndex(); - let newSelected = this.documentListElement - .querySelector(`li:nth-child(${newIndex + 1})`); + let newSelected = this.documentListElement.querySelector( + `li:nth-child(${newIndex + 1})` + ); newSelected.classList.add('document-selected'); } } - //////////////////////// ///// SEARCH AND FILTERS @@ -181,31 +189,37 @@ export class DocumentNavigatorWindow extends AbstractDocumentWindow { * Event on the 'search' button click. */ async search() { - let keywords = this.inputKeywordsElement.value.split(/[ ,;]/) - .filter((k) => k !== "").map((k) => k.toLowerCase()); + let keywords = this.inputKeywordsElement.value + .split(/[ ,;]/) + .filter((k) => k !== '') + .map((k) => k.toLowerCase()); this.searchFilter.keywords = keywords; let source = this.inputSourceElement.value.toLowerCase(); - this.searchFilter.source = (source !== "") ? source : undefined; + this.searchFilter.source = source !== '' ? source : undefined; let rightsHolder = this.inputRightsHolderElement.value.toLowerCase(); - this.searchFilter.rightsHolder = (rightsHolder !== "") ? rightsHolder - : undefined; + this.searchFilter.rightsHolder = + rightsHolder !== '' ? rightsHolder : undefined; let pubStartDate = this.inputPubDateStartElement.value; - this.searchFilter.pubStartDate = (!!pubStartDate) ? new Date(pubStartDate) + this.searchFilter.pubStartDate = !!pubStartDate + ? new Date(pubStartDate) : undefined; let pubEndDate = this.inputPubDateEndElement.value; - this.searchFilter.pubEndDate = (!!pubEndDate) ? new Date(pubEndDate) + this.searchFilter.pubEndDate = !!pubEndDate + ? new Date(pubEndDate) : undefined; let refStartDate = this.inputRefDateStartElement.value; - this.searchFilter.refStartDate = (!!refStartDate) ? new Date(refStartDate) + this.searchFilter.refStartDate = !!refStartDate + ? new Date(refStartDate) : undefined; let refEndDate = this.inputRefDateEndElement.value; - this.searchFilter.refEndDate = (!!refEndDate) ? new Date(refEndDate) + this.searchFilter.refEndDate = !!refEndDate + ? new Date(refEndDate) : undefined; this.provider.refreshDocumentList(); @@ -269,7 +283,7 @@ export class DocumentNavigatorWindow extends AbstractDocumentWindow { } get inputRightsHolderId() { - return `${this.windowId}_rights_holder` + return `${this.windowId}_rights_holder`; } get inputRightsHolderElement() { diff --git a/src/Widgets/Documents/View/DocumentView.js b/src/Widgets/Documents/View/DocumentView.js index 2083334e3..cd1b66b86 100644 --- a/src/Widgets/Documents/View/DocumentView.js +++ b/src/Widgets/Documents/View/DocumentView.js @@ -1,11 +1,13 @@ +/** @format */ + //Components -import { ModuleView } from "../../../Components/ModuleView/ModuleView"; -import { Window } from "../../../Components/GUI/js/Window"; +import { ModuleView } from '../../../Components/ModuleView/ModuleView'; +import { Window } from '../../../Components/GUI/js/Window'; -import { DocumentProvider } from "../ViewModel/DocumentProvider"; -import { DocumentNavigatorWindow } from "./DocumentNavigatorWindow"; -import { DocumentInspectorWindow } from "./DocumentInspectorWindow"; -import { AbstractDocumentWindow } from "./AbstractDocumentWindow"; +import { DocumentProvider } from '../ViewModel/DocumentProvider'; +import { DocumentNavigatorWindow } from './DocumentNavigatorWindow'; +import { DocumentInspectorWindow } from './DocumentInspectorWindow'; +import { AbstractDocumentWindow } from './AbstractDocumentWindow'; /** * The entry point of the document view. It holds the two main windows, inspector @@ -15,7 +17,7 @@ import { AbstractDocumentWindow } from "./AbstractDocumentWindow"; export class DocumentView extends ModuleView { /** * Creates a document view. - * + * * @param {DocumentProvider} provider The document provider. */ constructor(provider) { @@ -23,35 +25,35 @@ export class DocumentView extends ModuleView { /** * The document provider. - * + * * @type {DocumentProvider} */ this.provider = provider; /** * The search window. - * + * * @type {DocumentNavigatorWindow} */ this.navigatorWindow = new DocumentNavigatorWindow(); /** * The inspector window. - * + * * @type {DocumentInspectorWindow} */ this.inspectorWindow = new DocumentInspectorWindow(); /** * The different windows of the view. - * + * * @type {Array} */ - this.windows = [] + this.windows = []; /** * The windows that have been temporarily hidden. - * + * * @type {Array} */ this.hiddenWindows = []; @@ -70,13 +72,15 @@ export class DocumentView extends ModuleView { /** * Adds a new window to display information about documents. The document * provider is passed as parameter in this function. - * + * * @param {AbstractDocumentWindow} newWindow The window to add. */ addDocumentWindow(newWindow) { - if (! (newWindow instanceof AbstractDocumentWindow)) { - throw 'Only instances of AbstractDocumentWindow can be added to the ' + - 'document view'; + if (!(newWindow instanceof AbstractDocumentWindow)) { + throw ( + 'Only instances of AbstractDocumentWindow can be added to the ' + + 'document view' + ); } this.windows.push(newWindow); @@ -85,14 +89,15 @@ export class DocumentView extends ModuleView { /** * Request to show a specific document window. - * + * * @param {AbstractDocumentWindow} windowToDisplay The window to show. * @param {boolean} [hideOtherWindows] Set to `true` to hide other document * windows. */ requestWindowDisplay(windowToDisplay, hideOtherWindows = false) { - let found = this.windows - .findIndex(w => w.windowId === windowToDisplay.windowId) >= 0; + let found = + this.windows.findIndex((w) => w.windowId === windowToDisplay.windowId) >= + 0; if (!found) { throw 'Window must be registered first'; } @@ -135,4 +140,4 @@ export class DocumentView extends ModuleView { window.dispose(); } } -} \ No newline at end of file +} diff --git a/src/Widgets/Documents/View/DocumentWindow.css b/src/Widgets/Documents/View/DocumentWindow.css index 44b9f6c50..9c73225e9 100644 --- a/src/Widgets/Documents/View/DocumentWindow.css +++ b/src/Widgets/Documents/View/DocumentWindow.css @@ -1,6 +1,8 @@ -/* Generic for document windows */ - - +/** + * /* Generic for document windows + * + * @format + */ /* Search window */ @@ -9,7 +11,7 @@ margin-top: 5px; } -.search-form input[type="text"], +.search-form input[type='text'], .search-form select { box-sizing: border-box; width: 100%; diff --git a/src/Widgets/Documents/ViewModel/DocumentFilter.js b/src/Widgets/Documents/ViewModel/DocumentFilter.js index 71e5fdaf8..c7d60f9e6 100644 --- a/src/Widgets/Documents/ViewModel/DocumentFilter.js +++ b/src/Widgets/Documents/ViewModel/DocumentFilter.js @@ -1,4 +1,6 @@ -import { Document } from "../Model/Document"; +/** @format */ + +import { Document } from '../Model/Document'; /** * A filter for documents. It is essentially a function that determines if a @@ -7,7 +9,7 @@ import { Document } from "../Model/Document"; export class DocumentFilter { /** * Constructs a new document filter, from an acceptation function. - * + * * @param {(Document) => boolean} accepts The function responsible to filter * the documents. It must evaluate wether a document is acceptable according * to the filter. @@ -16,7 +18,7 @@ export class DocumentFilter { /** * The function responsible to filter the documents. It must evaluate wether * a document is acceptable according to the filter. - * + * * @type {(Document) => boolean} */ this.accepts = accepts; @@ -24,13 +26,13 @@ export class DocumentFilter { /** * Applies the filter to the documents. - * + * * @param {Array} documents The documents to filter. - * + * * @returns {Array} */ apply(documents) { let filtered = documents.filter(this.accepts); return filtered; } -} \ No newline at end of file +} diff --git a/src/Widgets/Documents/ViewModel/DocumentProvider.js b/src/Widgets/Documents/ViewModel/DocumentProvider.js index addd47825..41f171072 100644 --- a/src/Widgets/Documents/ViewModel/DocumentProvider.js +++ b/src/Widgets/Documents/ViewModel/DocumentProvider.js @@ -1,9 +1,11 @@ +/** @format */ + //Components -import { EventSender } from "../../../Components/Events/EventSender"; +import { EventSender } from '../../../Components/Events/EventSender'; -import { DocumentService } from "../Model/DocumentService"; -import { Document } from "../Model/Document"; -import { DocumentFilter } from "./DocumentFilter"; +import { DocumentService } from '../Model/DocumentService'; +import { Document } from '../Model/Document'; +import { DocumentFilter } from './DocumentFilter'; /** * Represents the set of documents that is displayed in the view. This includes @@ -15,7 +17,7 @@ import { DocumentFilter } from "./DocumentFilter"; export class DocumentProvider extends EventSender { /** * Constructs a new documents provider. - * + * * @param {DocumentService} service The document service. */ constructor(service) { @@ -23,35 +25,35 @@ export class DocumentProvider extends EventSender { /** * The document service. - * + * * @type {DocumentService} */ this.service = service; /** * The list of filters. - * + * * @type {Array} */ this.filters = []; /** * The list of all documents. - * + * * @type {Array} */ this.allDocuments = []; /** * The list of filtered documents. - * + * * @type {Array} */ this.filteredDocuments = []; /** * The currently displayed document. - * + * * @type {number} */ this.displayedDocumentIndex = undefined; @@ -77,28 +79,33 @@ export class DocumentProvider extends EventSender { if (this.filteredDocuments.length > 0) { if (previousDocument) { let previousDisplayedId = previousDocument.id; - let newIndex = this.filteredDocuments.findIndex(doc => - doc.id === previousDisplayedId); - this.displayedDocumentIndex = (newIndex >= 0) ? newIndex : 0; + let newIndex = this.filteredDocuments.findIndex( + (doc) => doc.id === previousDisplayedId + ); + this.displayedDocumentIndex = newIndex >= 0 ? newIndex : 0; } else { this.displayedDocumentIndex = 0; } } else { this.displayedDocumentIndex = undefined; } - await this.sendEvent(DocumentProvider.EVENT_FILTERED_DOCS_UPDATED, - this.getFilteredDocuments()); - await this.sendEvent(DocumentProvider.EVENT_DISPLAYED_DOC_CHANGED, - this.getDisplayedDocument()); + await this.sendEvent( + DocumentProvider.EVENT_FILTERED_DOCS_UPDATED, + this.getFilteredDocuments() + ); + await this.sendEvent( + DocumentProvider.EVENT_DISPLAYED_DOC_CHANGED, + this.getDisplayedDocument() + ); } /** * Adds a filter to the filtering pipeline. - * + * * @param {DocumentFilter} newFilter The new filter to add. */ addFilter(newFilter) { - if (! (newFilter instanceof DocumentFilter)) { + if (!(newFilter instanceof DocumentFilter)) { throw 'addFilter() expects a DocumentFilter parameter'; } this.filters.push(newFilter); @@ -106,12 +113,13 @@ export class DocumentProvider extends EventSender { /** * Sets the given document as the displayed one. - * + * * @param {Document} doc The document. */ setDisplayedDocument(doc) { - let index = this.filteredDocuments.findIndex((filteredDoc) => - doc.id === filteredDoc.id); + let index = this.filteredDocuments.findIndex( + (filteredDoc) => doc.id === filteredDoc.id + ); if (index < 0) { throw 'Document not found.'; @@ -123,12 +131,14 @@ export class DocumentProvider extends EventSender { /** * Change the displayed document index. Sends a `DISPLAYED_DOCUMENT_CHANGED` * event. - * + * * @param {number} index The new document index. */ setDisplayedDocumentIndex(index) { if (this.displayedDocumentIndex === undefined) { - console.warn('Cannot change displayed document if no document is present'); + console.warn( + 'Cannot change displayed document if no document is present' + ); return; } @@ -137,34 +147,41 @@ export class DocumentProvider extends EventSender { } this.displayedDocumentIndex = index; - this.sendEvent(DocumentProvider.EVENT_DISPLAYED_DOC_CHANGED, - this.getDisplayedDocument()); + this.sendEvent( + DocumentProvider.EVENT_DISPLAYED_DOC_CHANGED, + this.getDisplayedDocument() + ); } /** * Shift the displayed document index. The filtered array is treated as * cyclical. Sends a `DISPLAYED_DOCUMENT_CHANGED` event. - * + * * @param {number} offset The offset that will be applied to the current * index. */ shiftDisplayedDocumentIndex(offset) { if (this.displayedDocumentIndex === undefined) { - console.warn('Cannot change displayed document if no document is present'); + console.warn( + 'Cannot change displayed document if no document is present' + ); return; } offset = offset % this.filteredDocuments.length; - this.displayedDocumentIndex = (this.filteredDocuments.length + - this.displayedDocumentIndex + offset) % this.filteredDocuments.length; - - this.sendEvent(DocumentProvider.EVENT_DISPLAYED_DOC_CHANGED, - this.getDisplayedDocument()); + this.displayedDocumentIndex = + (this.filteredDocuments.length + this.displayedDocumentIndex + offset) % + this.filteredDocuments.length; + + this.sendEvent( + DocumentProvider.EVENT_DISPLAYED_DOC_CHANGED, + this.getDisplayedDocument() + ); } /** * Returns the list of all documents. - * + * * @returns {Array} */ getAllDocuments() { @@ -173,7 +190,7 @@ export class DocumentProvider extends EventSender { /** * Returns the filtered list of documents. - * + * * @returns {Array} */ getFilteredDocuments() { @@ -182,7 +199,7 @@ export class DocumentProvider extends EventSender { /** * Returns the currently displayed document. - * + * * @returns {Document | undefined} */ getDisplayedDocument() { @@ -195,7 +212,7 @@ export class DocumentProvider extends EventSender { /** * Returns the displayed document index. - * + * * @returns {number | undefined} */ getDisplayedDocumentIndex() { @@ -206,9 +223,9 @@ export class DocumentProvider extends EventSender { * Returns the image corresponding to the displayed document. It is a string * that can be put into the `src` attribute of an `img` tag (so either an * URL or a base64 encoded file). - * + * * @async - * + * * @returns {Promise} */ async getDisplayedDocumentImage() { @@ -229,4 +246,4 @@ export class DocumentProvider extends EventSender { static get EVENT_DISPLAYED_DOC_CHANGED() { return 'EVENT_DISPLAYED_DOC_CHANGED'; } -} \ No newline at end of file +} diff --git a/src/Widgets/Documents/ViewModel/DocumentSearchFilter.js b/src/Widgets/Documents/ViewModel/DocumentSearchFilter.js index 2c6444523..9d9087262 100644 --- a/src/Widgets/Documents/ViewModel/DocumentSearchFilter.js +++ b/src/Widgets/Documents/ViewModel/DocumentSearchFilter.js @@ -1,5 +1,7 @@ -import { DocumentFilter } from "./DocumentFilter"; -import { Document } from "../Model/Document"; +/** @format */ + +import { DocumentFilter } from './DocumentFilter'; +import { Document } from '../Model/Document'; /** * A document filter to use with the search window. It filters the documents @@ -17,14 +19,14 @@ export class DocumentSearchFilter extends DocumentFilter { /** * A list of keywords to search in the title or the description of the * document. These keywords should be in lowercase. - * + * * @type {Array} */ this.keywords = []; /** * A string representing the source. Should be in lowercase. - * + * * @type {string} */ this.source = undefined; @@ -36,28 +38,28 @@ export class DocumentSearchFilter extends DocumentFilter { /** * The lower bound of the publication date. - * + * * @type {Date} */ this.pubStartDate = undefined; /** * The upper bound of the publication date. - * + * * @type {Date} */ this.pubEndDate = undefined; /** * The lower bound of the refering date. - * + * * @type {Date} */ this.refStartDate = undefined; /** * The upper bound of the refering date. - * + * * @type {Date} */ this.refEndDate = undefined; @@ -65,14 +67,16 @@ export class DocumentSearchFilter extends DocumentFilter { /** * The function to filter the documents. - * + * * @param {Document} doc The document to filter. */ filterDocument(doc) { if (this.keywords.length > 0) { for (let keyword of this.keywords) { - if (!doc.title.toLowerCase().includes(keyword) && - !doc.description.toLowerCase().includes(keyword)) { + if ( + !doc.title.toLowerCase().includes(keyword) && + !doc.description.toLowerCase().includes(keyword) + ) { return false; } } @@ -82,16 +86,24 @@ export class DocumentSearchFilter extends DocumentFilter { return false; } - if (!!this.rightsHolder && - !doc.rightsHolder.toLowerCase().includes(this.rightsHolder)) { + if ( + !!this.rightsHolder && + !doc.rightsHolder.toLowerCase().includes(this.rightsHolder) + ) { return false; } - if (!!this.pubStartDate && !(this.pubStartDate <= new Date(doc.publicationDate))) { + if ( + !!this.pubStartDate && + !(this.pubStartDate <= new Date(doc.publicationDate)) + ) { return false; } - if (!!this.pubEndDate && !(this.pubEndDate >= new Date(doc.publicationDate))) { + if ( + !!this.pubEndDate && + !(this.pubEndDate >= new Date(doc.publicationDate)) + ) { return false; } @@ -102,7 +114,7 @@ export class DocumentSearchFilter extends DocumentFilter { if (!!this.refEndDate && !(this.refEndDate >= new Date(doc.refDate))) { return false; } - + return true; } @@ -118,4 +130,4 @@ export class DocumentSearchFilter extends DocumentFilter { this.refStartDate = undefined; this.refEndDate = undefined; } -} \ No newline at end of file +} diff --git a/src/Widgets/Extensions/3DTilesDebug/views/3DTilesDebugWindow.js b/src/Widgets/Extensions/3DTilesDebug/views/3DTilesDebugWindow.js index e9b59eb72..0fac2b999 100644 --- a/src/Widgets/Extensions/3DTilesDebug/views/3DTilesDebugWindow.js +++ b/src/Widgets/Extensions/3DTilesDebug/views/3DTilesDebugWindow.js @@ -1,13 +1,15 @@ +/** @format */ + //Components -import { Window } from "../../../../Components/GUI/js/Window"; -import { CityObjectStyle } from "../../../../Components/3DTiles/Model/CityObjectStyle"; -import { CityObjectID } from "../../../../Components/3DTiles/Model/CityObject"; -import { TilesManager } from "../../../../Components/3DTiles/TilesManager"; +import { Window } from '../../../../Components/GUI/js/Window'; +import { CityObjectStyle } from '../../../../Components/3DTiles/Model/CityObjectStyle'; +import { CityObjectID } from '../../../../Components/3DTiles/Model/CityObject'; +import { TilesManager } from '../../../../Components/3DTiles/TilesManager'; export class Debug3DTilesWindow extends Window { /** * Creates the debug window. - * + * * @param {layer} layerManager The tiles manager. */ constructor(layerManager) { @@ -15,17 +17,20 @@ export class Debug3DTilesWindow extends Window { /** * The tiles manager. - * + * * @type {layerManager} */ this.layerManager = layerManager; // Selection - this.layerManager.registerStyle('selected', new CityObjectStyle({ - materialProps: { color: 0x00ff00 } - })); + this.layerManager.registerStyle( + 'selected', + new CityObjectStyle({ + materialProps: { color: 0x00ff00 }, + }) + ); this.selectedCityObject = undefined; this.selectedTilesManager = undefined; - + let viewerDiv = document.getElementById('viewerDiv'); let clickListener = (event) => { this.onMouseClick(event); @@ -50,7 +55,7 @@ export class Debug3DTilesWindow extends Window { } get innerContentHtml() { - return /*html*/` + return /*html*/ `

0 / ? tiles loaded.

0 tiles visible.

@@ -94,7 +99,10 @@ export class Debug3DTilesWindow extends Window { // Sets the number of loaded tiles and add an event for dynamic change of this value. this.updateTBIInfoParagraphElement(); for (let i = 0; i < this.layerManager.tilesManagers.length; i++) { - this.layerManager.tilesManagers[i].addEventListener(TilesManager.EVENT_TILE_LOADED, (tile) => this.updateTBIInfoParagraphElement(tile)); + this.layerManager.tilesManagers[i].addEventListener( + TilesManager.EVENT_TILE_LOADED, + (tile) => this.updateTBIInfoParagraphElement(tile) + ); } this.groupColorOpacityInputElement.oninput = () => { this.groupColorOpacitySpanElement.innerText = @@ -127,7 +135,8 @@ export class Debug3DTilesWindow extends Window { */ onMouseMove(event) { // Update the current visible tile count - let visibleTileCount = this.layerManager.getVisible3DTilesTileCountFromLayers(); + let visibleTileCount = + this.layerManager.getVisible3DTilesTileCountFromLayers(); this.visibleTilesParagraphElement.innerText = `${visibleTileCount} tiles visible.`; } @@ -135,30 +144,37 @@ export class Debug3DTilesWindow extends Window { * If the user is currently hovering a building, fetches the building info * and colors the building. If a building was already selected, it returns to * its original coloring. - * + * * @param {MouseEvent} event The mouse event. */ onMouseClick(event) { let cityObject = this.layerManager.pickCityObject(event); if (cityObject !== undefined) { - for (let [key, value] of Object.entries(cityObject.props)) { this.clickDivElement.innerHTML += `
${key} : ${value}`; } if (!!this.selectedCityObject) { - this.selectedTilesManager.removeStyle(this.selectedCityObject.cityObjectId); + this.selectedTilesManager.removeStyle( + this.selectedCityObject.cityObjectId + ); this.selectedTilesManager.applyStyles(); } this.selectedCityObject = cityObject; - this.selectedTilesManager = this.layerManager.getTilesManagerByLayerID(this.selectedCityObject.tile.layer.id); - this.selectedTilesManager.setStyle(this.selectedCityObject.cityObjectId, 'selected'); + this.selectedTilesManager = this.layerManager.getTilesManagerByLayerID( + this.selectedCityObject.tile.layer.id + ); + this.selectedTilesManager.setStyle( + this.selectedCityObject.cityObjectId, + 'selected' + ); this.selectedTilesManager.applyStyles({ - updateFunction: - this.selectedTilesManager.view.notifyChange.bind(this.selectedTilesManager.view) + updateFunction: this.selectedTilesManager.view.notifyChange.bind( + this.selectedTilesManager.view + ), }); - this.clickDivElement.innerHTML = /*html*/` + this.clickDivElement.innerHTML = /*html*/ ` 3D Tiles : ${this.selectedTilesManager.layer.name}
Vertex indexes : ${cityObject.indexStart} to ${cityObject.indexEnd} (${cityObject.indexCount})
@@ -174,11 +190,15 @@ export class Debug3DTilesWindow extends Window { submitStyleForm() { try { let tileId = Number.parseInt(this.groupColorTileInputElement.value); - let batchIds = JSON.parse('[' + this.groupColorBatchInputElement.value + ']'); + let batchIds = JSON.parse( + '[' + this.groupColorBatchInputElement.value + ']' + ); let color = new THREE.Color(this.groupColorColorInputElement.value); let opacity = Number.parseFloat(this.groupColorOpacityInputElement.value); - this.layerManager.tilesManagers[0].setStyle(new CityObjectID(tileId, batchIds), - { materialProps: { color, opacity } }); + this.layerManager.tilesManagers[0].setStyle( + new CityObjectID(tileId, batchIds), + { materialProps: { color, opacity } } + ); this.layerManager.tilesManagers[0].applyStyles(); } catch (e) { alert(e); diff --git a/src/Widgets/Extensions/Authentication/services/AuthenticationService.js b/src/Widgets/Extensions/Authentication/services/AuthenticationService.js index ea5ba7c1c..bb912024e 100644 --- a/src/Widgets/Extensions/Authentication/services/AuthenticationService.js +++ b/src/Widgets/Extensions/Authentication/services/AuthenticationService.js @@ -1,148 +1,161 @@ -import {RequestService} from "../../../../Components/Request/RequestService" +/** @format */ + +import { RequestService } from '../../../../Components/Request/RequestService'; export function AuthenticationService(requestService, config) { - this.observers = []; - this.config = config; - this.loginUrl = `${config.server.url}${config.server.login}`; - //route to manage users (register) - this.userUrl = `${config.server.url}${config.server.user}`; - //route to get personal information - this.userMeUrl = `${config.server.url}${config.server.userMe}`; - this.requestService = new RequestService(); - this.loginRequiredKeys = ['username', 'password']; - this.registerRequiredKeys = ['username', 'firstName', 'lastName', 'password', 'email']; - this.storageKeys = { - token: 'user.token', - firstname: 'user.firstname', - lastname: 'user.lastname', - username: 'user.username', - email: 'user.email' - }; - - this.requestService = requestService; - - this.initialize = function initialize() { - this.requestService.setAuthenticationService(this); - }; - - this.login = async function login(formData) { - if (!this.formCheck(formData, this.loginRequiredKeys)) { - throw 'Invalid form'; - } - - if (this.isUserLoggedIn()) { - throw 'Already logged in'; - } - - const result = (await this.requestService.send('POST', this.loginUrl, formData, false)).response; - const resultJson = JSON.parse(result); - if (!resultJson) { - throw 'Username or password is incorrect' - } - const jwt = resultJson.token; - if (jwt !== undefined && jwt !== null) { - this.storeToken(jwt); - let response = JSON.parse((await this.requestService.send('GET', this.userMeUrl)).response); - const user = { - firstname: response.firstName, - lastname: response.lastName, - username: response.username, - email: response.email - }; - - this.storeUser(user); - - this.notifyObservers(); - } else { - throw 'Username or password is incorrect'; - } - }; - - this.logout = function logout() { - if (!this.isUserLoggedIn()) { - throw 'Not logged in'; - } - this.removeUserFromSession(); - - this.notifyObservers(); - }; - - this.register = async function register(formData) { - if (!this.formCheck(formData, this.registerRequiredKeys)) { - throw 'Invalid form'; - } - if (this.isUserLoggedIn()) { - throw 'Already logged in'; - } - const result = (await this.requestService.send('POST', this.userUrl, formData, false)).response; - const obj = JSON.parse(result); - - this.notifyObservers(); - }; - - this.formCheck = function formCheck(formData, requiredKeys) { - for (var key of requiredKeys) { - if (formData.get(key) === null) { - console.error(`Missing key in form : ${key}`) - return false; - } - } - return true; - }; - - this.removeUserFromSession = function removeUserFromSession() { - window.sessionStorage.removeItem(this.storageKeys.token); - window.sessionStorage.removeItem(this.storageKeys.firstname); - window.sessionStorage.removeItem(this.storageKeys.lastname); - window.sessionStorage.removeItem(this.storageKeys.username); - window.sessionStorage.removeItem(this.storageKeys.email); - }; - - this.storeToken = function (token) { - window.sessionStorage.setItem(this.storageKeys.token, token); + this.observers = []; + this.config = config; + this.loginUrl = `${config.server.url}${config.server.login}`; + //route to manage users (register) + this.userUrl = `${config.server.url}${config.server.user}`; + //route to get personal information + this.userMeUrl = `${config.server.url}${config.server.userMe}`; + this.requestService = new RequestService(); + this.loginRequiredKeys = ['username', 'password']; + this.registerRequiredKeys = [ + 'username', + 'firstName', + 'lastName', + 'password', + 'email', + ]; + this.storageKeys = { + token: 'user.token', + firstname: 'user.firstname', + lastname: 'user.lastname', + username: 'user.username', + email: 'user.email', + }; + + this.requestService = requestService; + + this.initialize = function initialize() { + this.requestService.setAuthenticationService(this); + }; + + this.login = async function login(formData) { + if (!this.formCheck(formData, this.loginRequiredKeys)) { + throw 'Invalid form'; + } + + if (this.isUserLoggedIn()) { + throw 'Already logged in'; } - this.storeUser = function storeUser(user) { - window.sessionStorage.setItem(this.storageKeys.firstname, user.firstname); - window.sessionStorage.setItem(this.storageKeys.lastname, user.lastname); - window.sessionStorage.setItem(this.storageKeys.username, user.username); - window.sessionStorage.setItem(this.storageKeys.email, user.email); - }; - - this.getUser = function getUser() { - let user = {}; - user.token = window.sessionStorage.getItem(this.storageKeys.token); - if (user.token === null || user.token === undefined) { - return null; - } - user.firstname = window.sessionStorage.getItem(this.storageKeys.firstname); - user.lastname = window.sessionStorage.getItem(this.storageKeys.lastname); - user.username = window.sessionStorage.getItem(this.storageKeys.username); - user.email = window.sessionStorage.getItem(this.storageKeys.email); - return user; - }; - - this.isUserLoggedIn = function isUserLoggedIn() { - try { - let user = this.getUser(); - return user !== null && user !== undefined; - } catch (e) { - console.error(e); - return false; - } - }; - - // Observers - this.addObserver = function (observerFunction) { - this.observers.push(observerFunction); + const result = ( + await this.requestService.send('POST', this.loginUrl, formData, false) + ).response; + const resultJson = JSON.parse(result); + if (!resultJson) { + throw 'Username or password is incorrect'; + } + const jwt = resultJson.token; + if (jwt !== undefined && jwt !== null) { + this.storeToken(jwt); + let response = JSON.parse( + (await this.requestService.send('GET', this.userMeUrl)).response + ); + const user = { + firstname: response.firstName, + lastname: response.lastName, + username: response.username, + email: response.email, + }; + + this.storeUser(user); + + this.notifyObservers(); + } else { + throw 'Username or password is incorrect'; } + }; - this.notifyObservers = function () { - for (let observer of this.observers) { - observer(); - } + this.logout = function logout() { + if (!this.isUserLoggedIn()) { + throw 'Not logged in'; } + this.removeUserFromSession(); + this.notifyObservers(); + }; + + this.register = async function register(formData) { + if (!this.formCheck(formData, this.registerRequiredKeys)) { + throw 'Invalid form'; + } + if (this.isUserLoggedIn()) { + throw 'Already logged in'; + } + const result = ( + await this.requestService.send('POST', this.userUrl, formData, false) + ).response; + const obj = JSON.parse(result); + + this.notifyObservers(); + }; + + this.formCheck = function formCheck(formData, requiredKeys) { + for (var key of requiredKeys) { + if (formData.get(key) === null) { + console.error(`Missing key in form : ${key}`); + return false; + } + } + return true; + }; + + this.removeUserFromSession = function removeUserFromSession() { + window.sessionStorage.removeItem(this.storageKeys.token); + window.sessionStorage.removeItem(this.storageKeys.firstname); + window.sessionStorage.removeItem(this.storageKeys.lastname); + window.sessionStorage.removeItem(this.storageKeys.username); + window.sessionStorage.removeItem(this.storageKeys.email); + }; + + this.storeToken = function (token) { + window.sessionStorage.setItem(this.storageKeys.token, token); + }; + + this.storeUser = function storeUser(user) { + window.sessionStorage.setItem(this.storageKeys.firstname, user.firstname); + window.sessionStorage.setItem(this.storageKeys.lastname, user.lastname); + window.sessionStorage.setItem(this.storageKeys.username, user.username); + window.sessionStorage.setItem(this.storageKeys.email, user.email); + }; + + this.getUser = function getUser() { + let user = {}; + user.token = window.sessionStorage.getItem(this.storageKeys.token); + if (user.token === null || user.token === undefined) { + return null; + } + user.firstname = window.sessionStorage.getItem(this.storageKeys.firstname); + user.lastname = window.sessionStorage.getItem(this.storageKeys.lastname); + user.username = window.sessionStorage.getItem(this.storageKeys.username); + user.email = window.sessionStorage.getItem(this.storageKeys.email); + return user; + }; + + this.isUserLoggedIn = function isUserLoggedIn() { + try { + let user = this.getUser(); + return user !== null && user !== undefined; + } catch (e) { + console.error(e); + return false; + } + }; + + // Observers + this.addObserver = function (observerFunction) { + this.observers.push(observerFunction); + }; + + this.notifyObservers = function () { + for (let observer of this.observers) { + observer(); + } + }; - this.initialize(); -} \ No newline at end of file + this.initialize(); +} diff --git a/src/Widgets/Extensions/Authentication/views/AuthenticationView.css b/src/Widgets/Extensions/Authentication/views/AuthenticationView.css index 7730f89eb..519e1b38b 100644 --- a/src/Widgets/Extensions/Authentication/views/AuthenticationView.css +++ b/src/Widgets/Extensions/Authentication/views/AuthenticationView.css @@ -1,147 +1,149 @@ +/** @format */ + #loginRegistrationWindow * { - box-sizing: border-box; + box-sizing: border-box; } #loginRegistrationWindow { - grid-template-columns: 1fr 1fr; - box-sizing: border-box; - position: absolute; - top: 0; - height: 100%; - width: 100%; - color: black; - font-size: 75%; - background-color: rgba(30, 30, 30, 0.3); - border: 1px solid rgb(90, 90, 90); - pointer-events: auto; - display: grid; - z-index: 50000; + grid-template-columns: 1fr 1fr; + box-sizing: border-box; + position: absolute; + top: 0; + height: 100%; + width: 100%; + color: black; + font-size: 75%; + background-color: rgba(30, 30, 30, 0.3); + border: 1px solid rgb(90, 90, 90); + pointer-events: auto; + display: grid; + z-index: 50000; } #loginRegistrationWindow > div > ul { - padding-left: 5px; + padding-left: 5px; } #loginRegistrationCloseButton { - margin-top: 2.2vw; - margin-left: 24.8vw; - grid-column: 2; - grid-row: 1; - height: 2vw; - width: 5vw; + margin-top: 2.2vw; + margin-left: 24.8vw; + grid-column: 2; + grid-row: 1; + height: 2vw; + width: 5vw; } #RegistrationForm { - margin: 2vw 0 auto auto; - display: grid; - grid-row: 1; - grid-column: 1; - width: 30vw; - height: 42vw; - padding: 1.5vw 6%; - color: white; - background-color: rgba(45, 52, 54, 0.9); - border: 0.15vw solid #2c2c2c; + margin: 2vw 0 auto auto; + display: grid; + grid-row: 1; + grid-column: 1; + width: 30vw; + height: 42vw; + padding: 1.5vw 6%; + color: white; + background-color: rgba(45, 52, 54, 0.9); + border: 0.15vw solid #2c2c2c; } #LoginForm { - margin: 2vw auto auto 0; - width: 30vw; - height: 42vw; - display: grid; - grid-row: 1; - grid-column: 2; - padding: 1.5vw 6%; - grid-template-rows: 5vw 2.5vw repeat(2, 5vw 3.5vw) 7vw 1fr; - color: white; - background-color: rgba(45, 52, 54, 0.9); - border: 0.15vw solid #2c2c2c; + margin: 2vw auto auto 0; + width: 30vw; + height: 42vw; + display: grid; + grid-row: 1; + grid-column: 2; + padding: 1.5vw 6%; + grid-template-rows: 5vw 2.5vw repeat(2, 5vw 3.5vw) 7vw 1fr; + color: white; + background-color: rgba(45, 52, 54, 0.9); + border: 0.15vw solid #2c2c2c; } #loginRegistrationWindow h2 { - text-align: center; - font-size: 3vw; - margin: 0; - font-weight: 700; + text-align: center; + font-size: 3vw; + margin: 0; + font-weight: 700; } -#LoginButton, #RegisterButton { - font-size: 2vw; - height: 4vw; - padding: 0 20%; - border-radius: 0.5vw; - color: white; - background-color: #1aaa55; - border: 0.2vw solid #168f48; +#LoginButton, +#RegisterButton { + font-size: 2vw; + height: 4vw; + padding: 0 20%; + border-radius: 0.5vw; + color: white; + background-color: #1aaa55; + border: 0.2vw solid #168f48; } -#LoginButton:hover, #RegisterButton:hover { - background-color: #168f48; +#LoginButton:hover, +#RegisterButton:hover { + background-color: #168f48; } #RegistrationForm label { - font-size: 1vw; - margin: auto 0 1% 1% ; + font-size: 1vw; + margin: auto 0 1% 1%; } #RegistrationForm label::after { - content: "*"; - color: red; - margin-left: 0.2vw; + content: '*'; + color: red; + margin-left: 0.2vw; } #RegistrationForm input { - font-size: 1.5vw; - padding: 2%; - background-color: #eeeeef; - border: 0.05vw solid black; + font-size: 1.5vw; + padding: 2%; + background-color: #eeeeef; + border: 0.05vw solid black; } #RegistrationForm button { - margin: 1.5vw auto auto; + margin: 1.5vw auto auto; } #LoginForm label { - font-size: 2.5vw; - margin: auto 0 1% 1% ; + font-size: 2.5vw; + margin: auto 0 1% 1%; } #LoginForm input { - font-size: 1.5vw; - padding: 2%; - background-color: #eeeeef; - border: 0.05vw solid black; + font-size: 1.5vw; + padding: 2%; + background-color: #eeeeef; + border: 0.05vw solid black; } #LoginForm div { - font-size: 2vw; - margin: 2vw auto; + font-size: 2vw; + margin: 2vw auto; } #LoginForm button { - margin: 3vw auto auto; + margin: 3vw auto auto; } .ErrorBox { - color: red; - font-weight: bold; - text-align: center; + color: red; + font-weight: bold; + text-align: center; } - -#loginRegistrationWindow label -{ - display: block; - width: 200px; - float: left; +#loginRegistrationWindow label { + display: block; + width: 200px; + float: left; } #profileMenu label { - display: block; - float: left; + display: block; + float: left; } -.SuccessBox{ - color: green; - text-align: center; -} \ No newline at end of file +.SuccessBox { + color: green; + text-align: center; +} diff --git a/src/Widgets/Extensions/Authentication/views/AuthenticationView.js b/src/Widgets/Extensions/Authentication/views/AuthenticationView.js index 31a5f4177..f423710f1 100644 --- a/src/Widgets/Extensions/Authentication/views/AuthenticationView.js +++ b/src/Widgets/Extensions/Authentication/views/AuthenticationView.js @@ -1,17 +1,18 @@ +/** @format */ + //Components import { ModuleView } from '../../../../Components/ModuleView/ModuleView'; import './AuthenticationView.css'; export class AuthenticationView extends ModuleView { + constructor(authenticationService) { + super(); + this.authenticationService = authenticationService; + } - constructor(authenticationService) { - super(); - this.authenticationService = authenticationService; - } - - html() { - return ` + html() { + return ` \

Registration

\

@@ -43,139 +44,139 @@ export class AuthenticationView extends ModuleView { \ \ `; - } - - appendToElement(htmlElement) { - let div = document.createElement('div'); - div.innerHTML = this.html(); - div.id = "loginRegistrationWindow"; - htmlElement.appendChild(div); - document.getElementById('loginRegistrationCloseButton').onclick = () => { - this.disable() - }; - document.getElementById('LoginButton').onclick = () => { - this.logInFunction() - }; - document.getElementById('RegisterButton').onclick = () => { - this.registerFunction() - }; - document.getElementById('PasswordRegistration').onkeypress = () => { - if ((event.key) == "Enter") this.registerFunction() - }; - document.getElementById('PasswordLogin').onkeypress = () => { - if ((event.key) == "Enter") this.logInFunction() - }; - } - - - dispose() { - let div = document.getElementById('loginRegistrationWindow'); - return div.parentNode.removeChild(div); - } - - displayRegisterError(msg) { - let errorField = document.getElementById('RegisterInfo'); - errorField.className = "ErrorBox" - errorField.innerHTML = msg; + } + + appendToElement(htmlElement) { + let div = document.createElement('div'); + div.innerHTML = this.html(); + div.id = 'loginRegistrationWindow'; + htmlElement.appendChild(div); + document.getElementById('loginRegistrationCloseButton').onclick = () => { + this.disable(); }; - - displayLoginError(msg) { - let errorField = document.getElementById('LoginInfo'); - errorField.innerHTML = msg; + document.getElementById('LoginButton').onclick = () => { + this.logInFunction(); }; - - displayRegisterSuccess(msg) { - let successField = document.getElementById('RegisterInfo'); - successField.className = "SuccessBox"; - successField.innerHTML = msg; - } - - isVisible() { - let div = document.getElementById('loginRegistrationWindow'); - return div !== undefined && div !== null; + document.getElementById('RegisterButton').onclick = () => { + this.registerFunction(); + }; + document.getElementById('PasswordRegistration').onkeypress = () => { + if (event.key == 'Enter') this.registerFunction(); + }; + document.getElementById('PasswordLogin').onkeypress = () => { + if (event.key == 'Enter') this.logInFunction(); + }; + } + + dispose() { + let div = document.getElementById('loginRegistrationWindow'); + return div.parentNode.removeChild(div); + } + + displayRegisterError(msg) { + let errorField = document.getElementById('RegisterInfo'); + errorField.className = 'ErrorBox'; + errorField.innerHTML = msg; + } + + displayLoginError(msg) { + let errorField = document.getElementById('LoginInfo'); + errorField.innerHTML = msg; + } + + displayRegisterSuccess(msg) { + let successField = document.getElementById('RegisterInfo'); + successField.className = 'SuccessBox'; + successField.innerHTML = msg; + } + + isVisible() { + let div = document.getElementById('loginRegistrationWindow'); + return div !== undefined && div !== null; + } + verifyNotEmptyValuesForm(formIds) { + var validate = true; + for (var id in formIds) { + let element = document.getElementById(formIds[id]); + element.setAttribute('style', ''); + if (element.value == '') { + element.setAttribute('style', ' border: 3px solid red'); + validate = false; + } } - verifyNotEmptyValuesForm(formIds) { - var validate = true; - for (var id in formIds) { - let element = document.getElementById(formIds[id]); - element.setAttribute("style", ""); - if (element.value == "") { - element.setAttribute("style", " border: 3px solid red"); - validate = false; - } - } - return validate; + return validate; + } + deleteValuesForm(formIds) { + for (var id in formIds) { + let element = document.getElementById(formIds[id]); + element.value = ''; } - deleteValuesForm(formIds) { - for (var id in formIds) { - let element = document.getElementById(formIds[id]); - element.value = ""; - } + } + verifymail() { + // This regular expression checks an email in the form of 'name@example.com' + let RegularExpression = + /^(([^<>()[]\.,;:s@]+(.[^<>()[]\.,;:s@]+)*)|(.+))@(([[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}])|(([a-zA-Z-0-9]+.)+[a-zA-Z]{2,}))$/; + let element = document.getElementById('Email'); + if (RegularExpression.test(element.value)) { + element.setAttribute('style', ''); + this.displayRegisterError(''); + return true; + } else { + element.setAttribute('style', ' border: 3px solid red'); + this.displayRegisterError('Please insert a valid mail'); + return false; } - verifymail() { - // This regular expression checks an email in the form of 'name@example.com' - let RegularExpression = /^(([^<>()[]\.,;:s@]+(.[^<>()[]\.,;:s@]+)*)|(.+))@(([[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}])|(([a-zA-Z-0-9]+.)+[a-zA-Z]{2,}))$/; - let element = document.getElementById("Email"); - if (RegularExpression.test(element.value)) { - element.setAttribute("style", ""); - this.displayRegisterError(""); - return true; - } - else { - element.setAttribute("style", " border: 3px solid red"); - this.displayRegisterError("Please insert a valid mail"); - return false; + } + + async logInFunction() { + this.displayLoginError(''); + const loginForm = document.getElementById('LoginForm'); + const formData = new FormData(loginForm); + var formIds = ['login', 'PasswordLogin']; + if (this.verifyNotEmptyValuesForm(formIds)) { + try { + await this.authenticationService.login(formData); + this.disable(); + } catch (e) { + if (e.status === 401) { + this.displayLoginError('Login or password invalid'); } + } } - - async logInFunction() { - this.displayLoginError(''); - const loginForm = document.getElementById('LoginForm'); - const formData = new FormData(loginForm); - var formIds = ['login', 'PasswordLogin']; - if (this.verifyNotEmptyValuesForm(formIds)) { - try { - await this.authenticationService.login(formData); - this.disable(); - } catch (e) { - if (e.status === 401) { - this.displayLoginError("Login or password invalid"); - } - - } + } + + async registerFunction() { + this.displayRegisterError(''); + const registerForm = document.getElementById('RegistrationForm'); + const formData = new FormData(registerForm); + var formIds = [ + 'Firstname', + 'Lastname', + 'Username', + 'Email', + 'PasswordRegistration', + ]; + if (this.verifyNotEmptyValuesForm(formIds) & this.verifymail()) { + try { + await this.authenticationService.register(formData); + this.deleteValuesForm(formIds); + this.displayRegisterSuccess('Your registration succeed'); + } catch (e) { + if (e.status == '422') { + this.displayRegisterError('The user already exist'); + } else { + this.displayRegisterError(e.response); } + } } + } + /////// MODULE MANAGEMENT FOR BASE DEMO - async registerFunction() { - this.displayRegisterError(''); - const registerForm = document.getElementById('RegistrationForm'); - const formData = new FormData(registerForm); - var formIds = ['Firstname', 'Lastname', 'Username', 'Email', 'PasswordRegistration']; - if (this.verifyNotEmptyValuesForm(formIds) & this.verifymail()) { - try { - await this.authenticationService.register(formData); - this.deleteValuesForm(formIds); - this.displayRegisterSuccess("Your registration succeed"); + enableView() { + this.appendToElement(this.parentElement); + } - } catch (e) { - if (e.status == '422') { - this.displayRegisterError('The user already exist'); - } - else { - this.displayRegisterError(e.response); - } - } - } - - - }; - /////// MODULE MANAGEMENT FOR BASE DEMO - - enableView() { - this.appendToElement(this.parentElement); - } - - disableView() { - this.dispose(); - } + disableView() { + this.dispose(); + } } diff --git a/src/Widgets/Extensions/Contribute/ContributeModule.js b/src/Widgets/Extensions/Contribute/ContributeModule.js index 49a80d6c2..9f9e7a963 100644 --- a/src/Widgets/Extensions/Contribute/ContributeModule.js +++ b/src/Widgets/Extensions/Contribute/ContributeModule.js @@ -1,13 +1,15 @@ +/** @format */ + //Widgets -import { DocumentModule } from "../../Documents/DocumentModule"; +import { DocumentModule } from '../../Documents/DocumentModule'; //Components -import { RequestService } from "../../../Components/Request/RequestService"; +import { RequestService } from '../../../Components/Request/RequestService'; -import { DocumentCreationWindow } from "./View/DocumentCreationWindow"; -import { DocumentUpdateWindow } from "./View/DocumentUpdateWindow"; -import { ContributeService } from "./Service/ContributeService"; -import { DocumentDeletionInterface } from "./View/DocumentDeletionInterface"; +import { DocumentCreationWindow } from './View/DocumentCreationWindow'; +import { DocumentUpdateWindow } from './View/DocumentUpdateWindow'; +import { ContributeService } from './Service/ContributeService'; +import { DocumentDeletionInterface } from './View/DocumentDeletionInterface'; /** * This module is used to manage the update, deletion and creation of documents. @@ -17,7 +19,7 @@ import { DocumentDeletionInterface } from "./View/DocumentDeletionInterface"; export class ContributeModule { /** * Constructs a new contribute module. - * + * * @param {DocumentModule} documentModule The document module. * @param {DocumentImageOrienter} documentImageOrienter The document image * orienter module. @@ -29,17 +31,33 @@ export class ContributeModule { * @param {string} config.server.url The server url. * @param {string} config.server.document The base route for documents. */ - constructor(documentModule, documentImageOrienter, requestService, itownsView, cameraControls, config) { - this.contributeService = new ContributeService(requestService, - documentModule.provider, config) + constructor( + documentModule, + documentImageOrienter, + requestService, + itownsView, + cameraControls, + config + ) { + this.contributeService = new ContributeService( + requestService, + documentModule.provider, + config + ); - this.creationWindow = new DocumentCreationWindow(this.contributeService, - itownsView, cameraControls, documentImageOrienter); - this.updateWindow = new DocumentUpdateWindow(this.contributeService, - documentModule); + this.creationWindow = new DocumentCreationWindow( + this.contributeService, + itownsView, + cameraControls, + documentImageOrienter + ); + this.updateWindow = new DocumentUpdateWindow( + this.contributeService, + documentModule + ); new DocumentDeletionInterface(documentModule, this.contributeService); documentModule.addDocumentWindow(this.creationWindow); documentModule.addDocumentWindow(this.updateWindow); } -} \ No newline at end of file +} diff --git a/src/Widgets/Extensions/Contribute/Service/ContributeService.js b/src/Widgets/Extensions/Contribute/Service/ContributeService.js index 14703380a..22e1a28f0 100644 --- a/src/Widgets/Extensions/Contribute/Service/ContributeService.js +++ b/src/Widgets/Extensions/Contribute/Service/ContributeService.js @@ -1,9 +1,11 @@ +/** @format */ + //Widgets -import { DocumentProvider } from "../../../Documents/ViewModel/DocumentProvider"; -import { Document } from "../../../Documents/Model/Document"; +import { DocumentProvider } from '../../../Documents/ViewModel/DocumentProvider'; +import { Document } from '../../../Documents/Model/Document'; //Components -import { RequestService } from "../../../../Components/Request/RequestService"; +import { RequestService } from '../../../../Components/Request/RequestService'; /** * This class performs the requests on the server to update and create @@ -74,7 +76,7 @@ export class ContributeService { let url = this.documentUrl + '/' + id; let response = await this.requestService.request('PUT', url, { - body: updatedData + body: updatedData, }); if (response.status >= 200 && response.status < 300) { @@ -95,9 +97,9 @@ export class ContributeService { * @returns {Document} The created document. */ async createDocument(creationData) { - let response = await (this.requestService.request('POST', this.documentUrl, { - body: creationData - })); + let response = await this.requestService.request('POST', this.documentUrl, { + body: creationData, + }); if (response.status >= 200 && response.status < 300) { let created = JSON.parse(response.responseText); diff --git a/src/Widgets/Extensions/Contribute/View/Contribute.css b/src/Widgets/Extensions/Contribute/View/Contribute.css index e46ed1231..1def77c2b 100644 --- a/src/Widgets/Extensions/Contribute/View/Contribute.css +++ b/src/Widgets/Extensions/Contribute/View/Contribute.css @@ -1,12 +1,16 @@ -/* forms */ +/** + * /* forms + * + * @format + */ -.doc-update-creation-form input[type="date"], -.doc-update-creation-form input[type="text"], -.doc-update-creation-form input[type="file"], +.doc-update-creation-form input[type='date'], +.doc-update-creation-form input[type='text'], +.doc-update-creation-form input[type='file'], .doc-update-creation-form textarea, .doc-update-creation-form select { display: block; width: 100%; max-width: 100%; box-sizing: border-box; -} \ No newline at end of file +} diff --git a/src/Widgets/Extensions/Contribute/View/DocumentCreationWindow.js b/src/Widgets/Extensions/Contribute/View/DocumentCreationWindow.js index dadf8b750..4b06675d8 100644 --- a/src/Widgets/Extensions/Contribute/View/DocumentCreationWindow.js +++ b/src/Widgets/Extensions/Contribute/View/DocumentCreationWindow.js @@ -1,71 +1,80 @@ +/** @format */ + import * as THREE from 'three'; //Widgets -import { DocumentVisualizerWindow } from "../../../DocumentVisualizer/View/DocumentVisualizerWindow"; -import { AbstractDocumentWindow } from "../../../Documents/View/AbstractDocumentWindow"; +import { DocumentVisualizerWindow } from '../../../DocumentVisualizer/View/DocumentVisualizerWindow'; +import { AbstractDocumentWindow } from '../../../Documents/View/AbstractDocumentWindow'; //Components -import { Window } from "../../../../Components/GUI/js/Window"; -import { PositionerWindow } from "../../../../Components/Camera/PositionerWindow"; +import { Window } from '../../../../Components/GUI/js/Window'; +import { PositionerWindow } from '../../../../Components/Camera/PositionerWindow'; -import { ContributeService } from "../Service/ContributeService"; +import { ContributeService } from '../Service/ContributeService'; export class DocumentCreationWindow extends AbstractDocumentWindow { /** * Creates a new document creation window. - * + * * @param {ContributeService} contributeService The contribute service to * perform requests. * @param {*} itownsView The iTowns view. * @param {*} cameraControls The planar camera controls. * @param {DocumentVisualizerWindow} documentImageOrienter The document image orienter module. */ - constructor(contributeService, itownsView, cameraControls, documentImageOrienter) { + constructor( + contributeService, + itownsView, + cameraControls, + documentImageOrienter + ) { super('Creation'); - /** * The contribute service to perform requests. - * + * * @type {ContributeService} */ this.contributeService = contributeService; /** * The camera positioner utility tool. - * + * * @type {PositionerWindow} */ this.positioner = new PositionerWindow(itownsView, cameraControls); - this.positioner.addEventListener(PositionerWindow.EVENT_POSITION_SUBMITTED, - (data) => this._registerPositionAndQuaternion(data)); - this.addEventListener(Window.EVENT_DISABLED, - () => this.positioner.disable()); + this.positioner.addEventListener( + PositionerWindow.EVENT_POSITION_SUBMITTED, + (data) => this._registerPositionAndQuaternion(data) + ); + this.addEventListener(Window.EVENT_DISABLED, () => + this.positioner.disable() + ); /** * The camera controls - * + * * @type {*} */ this.controls = cameraControls; /** * The registered camera position for the document visualization. - * + * * @type {THREE.Vector3} */ this.cameraPosition = undefined; /** * The registered camera orientation for the document visualization. - * + * * @type {THREE.Quaternion} */ this.cameraQuaternion = undefined; /** * The document image orienter module. - * + * * @type {DocumentVisualizerWindow} */ this.documentImageOrienter = documentImageOrienter; @@ -73,18 +82,20 @@ export class DocumentCreationWindow extends AbstractDocumentWindow { // same time. this.documentImageOrienter.addEventListener(Window.EVENT_DISABLED, () => { if (this.positioner.isVisible) { - this.positioner.disable() - }}); + this.positioner.disable(); + } + }); this.positioner.addEventListener(Window.EVENT_DISABLED, () => { this._exitEditMode(); if (this.documentImageOrienter.isVisible) { - this.documentImageOrienter.disable() - }}); + this.documentImageOrienter.disable(); + } + }); /** * The settings for an accurate movement of the camera. These settings * should be used in the `PlanarControls` class. - * + * * @type {{rotateSpeed: number, zoomInFactor: number, zoomOutFactor: number, * maxPanSpeed: number, minPanSpeed: number}} */ @@ -93,16 +104,16 @@ export class DocumentCreationWindow extends AbstractDocumentWindow { zoomInFactor: 0.04, zoomOutFactor: 0.04, maxPanSpeed: 5.0, - minPanSpeed: 0.01 + minPanSpeed: 0.01, }; /** * The saved state of the planar controls settings. This is used to restore * the default settings when needed. - * + * * @type {{rotateSpeed: number, zoomInFactor: number, zoomOutFactor: number, - * maxPanSpeed: number, minPanSpeed: number}} - */ + * maxPanSpeed: number, minPanSpeed: number}} + */ this.savedControlsSettings = {}; for (let key of Object.keys(this.accurateControlsSettings)) { this.savedControlsSettings[key] = this.controls[key]; @@ -110,7 +121,7 @@ export class DocumentCreationWindow extends AbstractDocumentWindow { } get innerContentHtml() { - return /*html*/` + return /*html*/ `

Document data

@@ -161,7 +172,7 @@ export class DocumentCreationWindow extends AbstractDocumentWindow { this.view.navigatorWindow.addExtension('Create', { type: 'button', html: 'Create a new document', - callback: () => this.view.requestWindowDisplay(this, true) + callback: () => this.view.requestWindowDisplay(this, true), }); } @@ -171,7 +182,7 @@ export class DocumentCreationWindow extends AbstractDocumentWindow { /** * Displays the document positioning interfaces : the window positioner and * the document image orienter. - * + * * @private */ _startPositioningDocument() { @@ -214,7 +225,7 @@ export class DocumentCreationWindow extends AbstractDocumentWindow { /** * Sets the initial values for the form. - * + * * @private */ _initForm() { @@ -231,13 +242,13 @@ export class DocumentCreationWindow extends AbstractDocumentWindow { /** * Checks if the form is ready to be validated. Every entry must have a * non-empty value, and the camera position / orientation must have been set. - * + * * @private */ _formValidation() { let data = new FormData(this.formElement); for (let entry of data.entries()) { - if (!entry[1] || entry[1] === "") { + if (!entry[1] || entry[1] === '') { return false; } } @@ -251,7 +262,7 @@ export class DocumentCreationWindow extends AbstractDocumentWindow { * Update the form buttons depending on the current form state. If the * document have been chosen, we can position it. If the form is valid, * we can create the document. - * + * * @private */ _updateFormButtons() { @@ -270,11 +281,11 @@ export class DocumentCreationWindow extends AbstractDocumentWindow { /** * Registers the camera position and orientation. - * + * * @param {{ * position: THREE.Vector3, * quaternion: THREE.Quaternion - * }} cameraState Position and orientation of the camera. + * }} cameraState Position and orientation of the camera. */ _registerPositionAndQuaternion(cameraState) { this.cameraPosition = cameraState.position; @@ -284,7 +295,7 @@ export class DocumentCreationWindow extends AbstractDocumentWindow { /** * Proceeds to create the document from the form data. - * + * * @private */ async _submitCreation() { @@ -300,7 +311,7 @@ export class DocumentCreationWindow extends AbstractDocumentWindow { data.append('quaternionY', this.cameraQuaternion.y); data.append('quaternionZ', this.cameraQuaternion.z); data.append('quaternionW', this.cameraQuaternion.w); - + try { await this.contributeService.createDocument(data); this.disable(); @@ -343,11 +354,11 @@ export class DocumentCreationWindow extends AbstractDocumentWindow { get docTitleElement() { return document.getElementById(this.docTitleId); } - + get docImageId() { return `${this.windowId}_image`; } - + get docImageElement() { return document.getElementById(this.docImageId); } @@ -361,7 +372,7 @@ export class DocumentCreationWindow extends AbstractDocumentWindow { } get docRightsHolderId() { - return `${this.windowId}_rights_holder` + return `${this.windowId}_rights_holder`; } get docRightsHolderElement() { @@ -391,4 +402,4 @@ export class DocumentCreationWindow extends AbstractDocumentWindow { get refDateElement() { return document.getElementById(this.refDateId); } -} \ No newline at end of file +} diff --git a/src/Widgets/Extensions/Contribute/View/DocumentDeletionInterface.js b/src/Widgets/Extensions/Contribute/View/DocumentDeletionInterface.js index 0740599a7..4f3a9f135 100644 --- a/src/Widgets/Extensions/Contribute/View/DocumentDeletionInterface.js +++ b/src/Widgets/Extensions/Contribute/View/DocumentDeletionInterface.js @@ -1,7 +1,9 @@ +/** @format */ + //Widgets -import { DocumentModule } from "../../../Documents/DocumentModule"; +import { DocumentModule } from '../../../Documents/DocumentModule'; -import { ContributeService } from "../Service/ContributeService"; +import { ContributeService } from '../Service/ContributeService'; /** * Represents a really simple interface to delete a document. It is just a @@ -11,7 +13,7 @@ import { ContributeService } from "../Service/ContributeService"; export class DocumentDeletionInterface { /** * Creates a button in the document browser to perform the deletion. - * + * * @param {DocumentModule} documentModule The document module. * @param {ContributeService} contributeService The contribute service. */ @@ -21,8 +23,12 @@ export class DocumentDeletionInterface { container: 'right', html: 'Delete', callback: async () => { - if (!confirm('You are going to delete the document. This operation ' + - 'is irreversible. Do you want to continue ?')) { + if ( + !confirm( + 'You are going to delete the document. This operation ' + + 'is irreversible. Do you want to continue ?' + ) + ) { return; } try { @@ -30,7 +36,7 @@ export class DocumentDeletionInterface { } catch (e) { alert(e); } - } + }, }); } -} \ No newline at end of file +} diff --git a/src/Widgets/Extensions/Contribute/View/DocumentUpdateWindow.js b/src/Widgets/Extensions/Contribute/View/DocumentUpdateWindow.js index 97635bdb4..0d87516b5 100644 --- a/src/Widgets/Extensions/Contribute/View/DocumentUpdateWindow.js +++ b/src/Widgets/Extensions/Contribute/View/DocumentUpdateWindow.js @@ -1,12 +1,13 @@ -//Widgets -import { AbstractDocumentWindow } from "../../../Documents/View/AbstractDocumentWindow"; -import { DocumentProvider } from "../../../Documents/ViewModel/DocumentProvider"; -import { DocumentModule } from "../../../Documents/DocumentModule"; +/** @format */ -import { ContributeService } from "../Service/ContributeService"; +//Widgets +import { AbstractDocumentWindow } from '../../../Documents/View/AbstractDocumentWindow'; +import { DocumentProvider } from '../../../Documents/ViewModel/DocumentProvider'; +import { DocumentModule } from '../../../Documents/DocumentModule'; -import "./Contribute.css"; +import { ContributeService } from '../Service/ContributeService'; +import './Contribute.css'; /** * This window is used to update a document. It contains a form that allows to @@ -34,12 +35,12 @@ export class DocumentUpdateWindow extends AbstractDocumentWindow { type: 'button', container: 'right', html: 'Update', - callback: () => this._initWindow() + callback: () => this._initWindow(), }); } get innerContentHtml() { - return /*html*/` + return /*html*/ `

@@ -75,12 +76,14 @@ export class DocumentUpdateWindow extends AbstractDocumentWindow { this.cancelButtonElement.onclick = () => { this.disable(); - } + }; } documentWindowReady() { - this.provider.addEventListener(DocumentProvider.EVENT_DISPLAYED_DOC_CHANGED, - () => this.disable()); + this.provider.addEventListener( + DocumentProvider.EVENT_DISPLAYED_DOC_CHANGED, + () => this.disable() + ); } /////////////////////// @@ -114,15 +117,16 @@ export class DocumentUpdateWindow extends AbstractDocumentWindow { } this.docTitleElement.innerText = doc.title; - this.docImageElement.src = - await this.provider.getDisplayedDocumentImage(); + this.docImageElement.src = await this.provider.getDisplayedDocumentImage(); this.sourceElement.value = doc.source; this.docRightsHolderElement.value = doc.rightsHolder; this.descriptionElement.value = doc.description; - this.pubDateElement.value = (new Date(doc.publicationDate)) - .toISOString().substring(0, 10); - this.refDateElement.value = (new Date(doc.refDate)) - .toISOString().substring(0, 10); + this.pubDateElement.value = new Date(doc.publicationDate) + .toISOString() + .substring(0, 10); + this.refDateElement.value = new Date(doc.refDate) + .toISOString() + .substring(0, 10); } ///////////////// @@ -186,7 +190,7 @@ export class DocumentUpdateWindow extends AbstractDocumentWindow { } get docRightsHolderId() { - return `${this.windowId}_rights_holder` + return `${this.windowId}_rights_holder`; } get docRightsHolderElement() { diff --git a/src/Widgets/Extensions/DocumentComments/DocumentCommentsModule.js b/src/Widgets/Extensions/DocumentComments/DocumentCommentsModule.js index 5a59342d3..5d578b5fb 100644 --- a/src/Widgets/Extensions/DocumentComments/DocumentCommentsModule.js +++ b/src/Widgets/Extensions/DocumentComments/DocumentCommentsModule.js @@ -1,10 +1,12 @@ -import { DocumentModule } from "../../Documents/DocumentModule"; +/** @format */ + +import { DocumentModule } from '../../Documents/DocumentModule'; //Components -import { RequestService } from "../../../Components/Request/RequestService"; +import { RequestService } from '../../../Components/Request/RequestService'; -import { DocumentCommentsService } from "./services/DocumentCommentsService"; -import { DocumentCommentsWindow } from "./views/DocumentCommentsWindow"; +import { DocumentCommentsService } from './services/DocumentCommentsService'; +import { DocumentCommentsWindow } from './views/DocumentCommentsWindow'; /** * The class that represents the document comments module. It contains a @@ -15,7 +17,7 @@ export class DocumentCommentsModule { /** * Creates the document comments module. Creates a service and a comments * window. - * + * * @param {DocumentModule} documentModule The document module. * @param {RequestService} requestService The request service. * @param {object} config The UDV config. @@ -26,10 +28,14 @@ export class DocumentCommentsModule { * @param {string} config.server.user The route for users. */ constructor(documentModule, requestService, config) { - this.service = new DocumentCommentsService(documentModule.provider, requestService, config); + this.service = new DocumentCommentsService( + documentModule.provider, + requestService, + config + ); this.commentsWindow = new DocumentCommentsWindow(this.service); documentModule.addDocumentWindow(this.commentsWindow); } -} \ No newline at end of file +} diff --git a/src/Widgets/Extensions/DocumentComments/services/DocumentCommentsService.js b/src/Widgets/Extensions/DocumentComments/services/DocumentCommentsService.js index acb130033..809919ab9 100644 --- a/src/Widgets/Extensions/DocumentComments/services/DocumentCommentsService.js +++ b/src/Widgets/Extensions/DocumentComments/services/DocumentCommentsService.js @@ -1,56 +1,67 @@ +/** @format */ + //Components -import { RequestService } from "../../../../Components/Request/RequestService"; +import { RequestService } from '../../../../Components/Request/RequestService'; -import { DocumentProvider } from "../../../Documents/ViewModel/DocumentProvider"; +import { DocumentProvider } from '../../../Documents/ViewModel/DocumentProvider'; /** * The service that performs the requests for document comments. This include * retrieve and create operations. */ export class DocumentCommentsService { - /** - * Creates a document comments service. - * - * @param {DocumentProvider} documentProvider The document provider. - * @param {RequestService} requestService The request service. - * @param {object} config The UD-Viz config. - * @param {object} config.server The server access config. - * @param {string} config.server.url The server URL. - * @param {string} config.server.document The route for documents. - * @param {string} config.server.comment The route for comments. - * @param {string} config.server.user The route for users. - */ - constructor (documentProvider, requestService, config) { - this.documentProvider = documentProvider; + /** + * Creates a document comments service. + * + * @param {DocumentProvider} documentProvider The document provider. + * @param {RequestService} requestService The request service. + * @param {object} config The UD-Viz config. + * @param {object} config.server The server access config. + * @param {string} config.server.url The server URL. + * @param {string} config.server.document The route for documents. + * @param {string} config.server.comment The route for comments. + * @param {string} config.server.user The route for users. + */ + constructor(documentProvider, requestService, config) { + this.documentProvider = documentProvider; - this.requestService = requestService; - - this.documentUrl = `${config.server.url}${config.server.document}`; - this.commentRoute = config.server.comment; - this.authorUrl = `${config.server.url}${config.server.user}`; - } + this.requestService = requestService; + + this.documentUrl = `${config.server.url}${config.server.document}`; + this.commentRoute = config.server.comment; + this.authorUrl = `${config.server.url}${config.server.user}`; + } - async getComments() { - let currentDocument = this.documentProvider.getDisplayedDocument(); - if (currentDocument !== null && currentDocument !== undefined) { - let url = this.documentUrl + "/" + currentDocument.id + "/" + this.commentRoute; - let response = (await this.requestService.request('GET', url, {authenticate: 'auto'})).response; - let jsonResponse = JSON.parse(response); - for (let element of jsonResponse) { - let url = this.authorUrl + "/" + element.user_id; - let responseAuthor = (await this.requestService.request('GET', url, {authenticate: 'auto'})).response; - element.author = JSON.parse(responseAuthor); - } - return jsonResponse; - } - return []; + async getComments() { + let currentDocument = this.documentProvider.getDisplayedDocument(); + if (currentDocument !== null && currentDocument !== undefined) { + let url = + this.documentUrl + '/' + currentDocument.id + '/' + this.commentRoute; + let response = ( + await this.requestService.request('GET', url, { authenticate: 'auto' }) + ).response; + let jsonResponse = JSON.parse(response); + for (let element of jsonResponse) { + let url = this.authorUrl + '/' + element.user_id; + let responseAuthor = ( + await this.requestService.request('GET', url, { + authenticate: 'auto', + }) + ).response; + element.author = JSON.parse(responseAuthor); + } + return jsonResponse; } + return []; + } - async publishComment(formData) { - let currentDocument = this.documentProvider.getDisplayedDocument(); - if (currentDocument !== null && currentDocument !== undefined) { - let url = this.documentUrl + "/" + currentDocument.id + "/" + this.commentRoute; - let response = (await this.requestService.send('POST', url, formData)).response; - } + async publishComment(formData) { + let currentDocument = this.documentProvider.getDisplayedDocument(); + if (currentDocument !== null && currentDocument !== undefined) { + let url = + this.documentUrl + '/' + currentDocument.id + '/' + this.commentRoute; + let response = (await this.requestService.send('POST', url, formData)) + .response; } -} \ No newline at end of file + } +} diff --git a/src/Widgets/Extensions/DocumentComments/views/DocumentCommentsStyle.css b/src/Widgets/Extensions/DocumentComments/views/DocumentCommentsStyle.css index 549729463..2e3d8cd59 100644 --- a/src/Widgets/Extensions/DocumentComments/views/DocumentCommentsStyle.css +++ b/src/Widgets/Extensions/DocumentComments/views/DocumentCommentsStyle.css @@ -1,76 +1,78 @@ +/** @format */ + #documentComments_innerWindow { - width: 100%; - height: 100%; - padding : 0; - margin: 0; - vertical-align:top; - display: grid; - grid-template-columns: 55% 45%; - } + width: 100%; + height: 100%; + padding: 0; + margin: 0; + vertical-align: top; + display: grid; + grid-template-columns: 55% 45%; +} - #documentComments_left{ - vertical-align:top; - overflow-y: auto; - } +#documentComments_left { + vertical-align: top; + overflow-y: auto; +} - #documentComments_right{ - vertical-align:top; - } +#documentComments_right { + vertical-align: top; +} - #documentComments_inputComment{ - height: 150px; - width: 90%; - margin: auto; - border-radius: 3px; - resize: none; - margin-top: 5px; - font-size: 10pt; - } +#documentComments_inputComment { + height: 150px; + width: 90%; + margin: auto; + border-radius: 3px; + resize: none; + margin-top: 5px; + font-size: 10pt; +} - #documentComments_inputButton{ - margin: 10%; - width: 70%; - } +#documentComments_inputButton { + margin: 10%; + width: 70%; +} - .commentRow { - width: 100%; - text-align: center; - } +.commentRow { + width: 100%; + text-align: center; +} - .talk-bubble { - margin: 3%; - position: relative; - width: 95%; - background-color: #e3dfff; - border-radius: 5px; - margin: 5px; - } +.talk-bubble { + margin: 3%; + position: relative; + width: 95%; + background-color: #e3dfff; + border-radius: 5px; + margin: 5px; +} - .talktext{ - padding: 0.3em; - text-align: left; - line-height: 0.9em; - } +.talktext { + padding: 0.3em; + text-align: left; + line-height: 0.9em; +} - .talktext-comment { - /* remove webkit p margins */ - color: #2f2d2e; - padding-left: 10px; - padding-right: 10px; - font-size: 100%; - } +.talktext-comment { + /* remove webkit p margins */ + color: #2f2d2e; + padding-left: 10px; + padding-right: 10px; + font-size: 100%; +} - .talktext-author { - border-bottom: 1px solid rgba(0, 0, 0, 0.3); - margin-top: 0; - padding: 5px; - font-weight: bold; - color: #41292c; - } +.talktext-author { + border-bottom: 1px solid rgba(0, 0, 0, 0.3); + margin-top: 0; + padding: 5px; + font-weight: bold; + color: #41292c; +} - .talktext-date { - color: #7d7d7d; - margin-bottom: 0; - text-align: right; - font-size: 90%; - } +.talktext-date { + color: #7d7d7d; + margin-bottom: 0; + text-align: right; + font-size: 90%; +} diff --git a/src/Widgets/Extensions/DocumentComments/views/DocumentCommentsWindow.js b/src/Widgets/Extensions/DocumentComments/views/DocumentCommentsWindow.js index 9ec060ff7..8b4f957a3 100644 --- a/src/Widgets/Extensions/DocumentComments/views/DocumentCommentsWindow.js +++ b/src/Widgets/Extensions/DocumentComments/views/DocumentCommentsWindow.js @@ -1,3 +1,5 @@ +/** @format */ + import { AbstractDocumentWindow } from '../../../Documents/View/AbstractDocumentWindow'; import { DocumentCommentsService } from '../services/DocumentCommentsService'; @@ -8,20 +10,19 @@ import './DocumentCommentsStyle.css'; * a comments creation interface. */ export class DocumentCommentsWindow extends AbstractDocumentWindow { + /** + * Creates a document comments window to add in the document browser. + * + * @param {DocumentCommentsService} documentCommentsService The document comments + * service. + */ + constructor(documentCommentsService) { + super('Comments'); + this.documentCommentsService = documentCommentsService; + } - /** - * Creates a document comments window to add in the document browser. - * - * @param {DocumentCommentsService} documentCommentsService The document comments - * service. - */ - constructor(documentCommentsService) { - super('Comments'); - this.documentCommentsService = documentCommentsService; - } - - get innerContentHtml() { - return /*html*/` + get innerContentHtml() { + return /*html*/ `
@@ -38,65 +39,75 @@ export class DocumentCommentsWindow extends AbstractDocumentWindow {
`; - } + } - windowCreated() { - this.hide(); + windowCreated() { + this.hide(); - this.window.style.width = '500px'; - this.window.style.height = '500px'; - this.window.style.left = '290px'; - this.window.style.top = '10px'; - this.innerContent.style.height = '100%'; - document.getElementById('documentComments_inputButton').onclick = this.publishComment.bind(this); - this.getComments(); - } + this.window.style.width = '500px'; + this.window.style.height = '500px'; + this.window.style.left = '290px'; + this.window.style.top = '10px'; + this.innerContent.style.height = '100%'; + document.getElementById('documentComments_inputButton').onclick = + this.publishComment.bind(this); + this.getComments(); + } - documentWindowReady() { - this.view.inspectorWindow.addExtension('Comments', { - type: 'button', - container: 'left', - html: 'Comments', - callback: () => { - this.view.requestWindowDisplay(this); - this.getComments(); - } - }); - } + documentWindowReady() { + this.view.inspectorWindow.addExtension('Comments', { + type: 'button', + container: 'left', + html: 'Comments', + callback: () => { + this.view.requestWindowDisplay(this); + this.getComments(); + }, + }); + } - getComments() { - this.documentCommentsService.getComments().then((comments) => { - document.getElementById('documentComments_left').innerHTML = ''; - for (let comment of comments) { - let text = (typeof comment.description === 'string') ? comment.description.replace(/(?:\r\n|\r|\n)/g, '
') : ''; - let div = document.createElement('div'); - div.className = 'talk-bubble'; - div.innerHTML = ` + getComments() { + this.documentCommentsService.getComments().then( + (comments) => { + document.getElementById('documentComments_left').innerHTML = ''; + for (let comment of comments) { + let text = + typeof comment.description === 'string' + ? comment.description.replace(/(?:\r\n|\r|\n)/g, '
') + : ''; + let div = document.createElement('div'); + div.className = 'talk-bubble'; + div.innerHTML = `
-

${comment.author.firstName} ${comment.author.lastName}

+

${comment.author.firstName} ${ + comment.author.lastName + }

${text}

-

${(new Date(comment.date)).toLocaleString()}

+

${new Date( + comment.date + ).toLocaleString()}

`; - document.getElementById('documentComments_left').appendChild(div); - } - }, (reason) => { - alert(reason); - this.disable(); - }); - } - - - async publishComment() { - let form = document.getElementById('documentComments_inputForm'); - let form_data = new FormData(form); - try { - await this.documentCommentsService.publishComment(form_data).then(() => { - document.getElementById('documentComments_inputComment').value = ''; - this.getComments(); - }); - } catch (e) { - alert(e); + document.getElementById('documentComments_left').appendChild(div); } + }, + (reason) => { + alert(reason); + this.disable(); + } + ); + } + + async publishComment() { + let form = document.getElementById('documentComments_inputForm'); + let form_data = new FormData(form); + try { + await this.documentCommentsService.publishComment(form_data).then(() => { + document.getElementById('documentComments_inputComment').value = ''; + this.getComments(); + }); + } catch (e) { + alert(e); } + } } diff --git a/src/Widgets/Extensions/DocumentValidation/DocumentValidationModule.js b/src/Widgets/Extensions/DocumentValidation/DocumentValidationModule.js index 613856240..c2b78f986 100644 --- a/src/Widgets/Extensions/DocumentValidation/DocumentValidationModule.js +++ b/src/Widgets/Extensions/DocumentValidation/DocumentValidationModule.js @@ -1,9 +1,11 @@ +/** @format */ + //Widgets -import { DocumentModule } from "../../Documents/DocumentModule"; +import { DocumentModule } from '../../Documents/DocumentModule'; -import { ValidationService } from "./Service/ValidationService"; -import { DocumentsInValidationDocumentSource } from "./Service/DocumentsInValidationSource"; -import { ValidationView } from "./View/ValidationView"; +import { ValidationService } from './Service/ValidationService'; +import { DocumentsInValidationDocumentSource } from './Service/DocumentsInValidationSource'; +import { ValidationView } from './View/ValidationView'; /** * The document extension to manage documents validation. It allows the user to @@ -16,15 +18,18 @@ export class DocumentValidationModule { * Creates the document validation module. Creates a validation service to * manage HTTP requests, a validation source to change the retrieving URL * and finally the view elements. - * - * @param {DocumentModule} documentModule The documents module. + * + * @param {DocumentModule} documentModule The documents module. */ constructor(documentModule, requestService, config) { this.validationService = new ValidationService(requestService, config); this.validationSource = new DocumentsInValidationDocumentSource(config); - new ValidationView(documentModule, this.validationService, - this.validationSource); + new ValidationView( + documentModule, + this.validationService, + this.validationSource + ); } -} \ No newline at end of file +} diff --git a/src/Widgets/Extensions/DocumentValidation/Service/DocumentsInValidationSource.js b/src/Widgets/Extensions/DocumentValidation/Service/DocumentsInValidationSource.js index 41331cd21..7f4469ec6 100644 --- a/src/Widgets/Extensions/DocumentValidation/Service/DocumentsInValidationSource.js +++ b/src/Widgets/Extensions/DocumentValidation/Service/DocumentsInValidationSource.js @@ -1,4 +1,6 @@ -import { DocumentSource } from "../../../Documents/Model/DocumentService"; +/** @format */ + +import { DocumentSource } from '../../../Documents/Model/DocumentService'; /** * The document source for documents in validation. @@ -6,7 +8,7 @@ import { DocumentSource } from "../../../Documents/Model/DocumentService"; export class DocumentsInValidationDocumentSource extends DocumentSource { /** * Creates the document source. - * + * * @param {object} config The UD-Viz configuration. * @param {object} config.server The configuration for the server. * @param {string} config.server.url The base URL of the server. @@ -29,4 +31,4 @@ export class DocumentsInValidationDocumentSource extends DocumentSource { getImageUrl(doc) { return this.documentUrl + '/' + doc.id + '/' + this.fileRoute; } -} \ No newline at end of file +} diff --git a/src/Widgets/Extensions/DocumentValidation/Service/ValidationService.js b/src/Widgets/Extensions/DocumentValidation/Service/ValidationService.js index 056388c79..173f352fe 100644 --- a/src/Widgets/Extensions/DocumentValidation/Service/ValidationService.js +++ b/src/Widgets/Extensions/DocumentValidation/Service/ValidationService.js @@ -1,7 +1,9 @@ +/** @format */ + //Components -import { RequestService } from "../../../../Components/Request/RequestService"; +import { RequestService } from '../../../../Components/Request/RequestService'; -import { Document } from "../../../Documents/Model/Document"; +import { Document } from '../../../Documents/Model/Document'; /** * This class is responsible for the validation requests. @@ -9,7 +11,7 @@ import { Document } from "../../../Documents/Model/Document"; export class ValidationService { /** * Constructs a validation service. - * + * * @param {RequestService} requestService The request service. * @param {object} config The UD-Viz configuration. * @param {object} config.server The configuration for the server. @@ -23,14 +25,14 @@ export class ValidationService { /** * Sends the request to validate the document. - * + * * @param {Document} doc The document to validate. */ async validate(doc) { let formData = new FormData(); formData.append('id', doc.id); let response = await this.requestService.request('POST', this.validateUrl, { - body: formData + body: formData, }); - }; -} \ No newline at end of file + } +} diff --git a/src/Widgets/Extensions/DocumentValidation/View/ValidationView.js b/src/Widgets/Extensions/DocumentValidation/View/ValidationView.js index e919a8efd..542e89866 100644 --- a/src/Widgets/Extensions/DocumentValidation/View/ValidationView.js +++ b/src/Widgets/Extensions/DocumentValidation/View/ValidationView.js @@ -1,17 +1,19 @@ -import { DocumentModule } from "../../../Documents/DocumentModule"; -import { DocumentSource } from "../../../Documents/Model/DocumentService"; -import { Document } from "../../../Documents/Model/Document"; +/** @format */ + +import { DocumentModule } from '../../../Documents/DocumentModule'; +import { DocumentSource } from '../../../Documents/Model/DocumentService'; +import { Document } from '../../../Documents/Model/Document'; //Components -import { Window } from "../../../../Components/GUI/js/Window"; +import { Window } from '../../../../Components/GUI/js/Window'; -import { ValidationService } from "../Service/ValidationService"; -import { DocumentsInValidationDocumentSource } from "../Service/DocumentsInValidationSource"; +import { ValidationService } from '../Service/ValidationService'; +import { DocumentsInValidationDocumentSource } from '../Service/DocumentsInValidationSource'; /** * This class represents the visual elements and their logic for the * validation module : - * + * * - Button "See documents in validation" to change the document source * - Panel "Currently seing ..." to inform the user that he/she is consulting * documents in validation or validated documents @@ -20,7 +22,7 @@ import { DocumentsInValidationDocumentSource } from "../Service/DocumentsInValid export class ValidationView { /** * Creates the view. - * + * * @param {DocumentModule} documentModule The document module. * @param {ValidationService} validationService The validation service. * @param {DocumentsInValidationDocumentSource} validationSource The source @@ -33,7 +35,7 @@ export class ValidationView { /** * Defines wether the interface displays documents to validate (`true`) or * validated documents (`false`). - * + * * @type {boolean} */ this.displayingDocumentsToValidate = false; @@ -41,14 +43,14 @@ export class ValidationView { /** * Stores the previous document source to restore it (the source for * validated documents). - * + * * @type {DocumentSource} */ this.previousDocumentSource = undefined; /** * The validation source. - * + * * @type {DocumentsInValidationDocumentSource} */ this.validationSource = validationSource; @@ -58,17 +60,19 @@ export class ValidationView { documentModule.addNavigatorExtension('Validation Filter', { type: 'div', container: 'filter', - html: /*html*/` + html: /*html*/ ` - ` + `, }); - documentModule.view.navigatorWindow.addEventListener(Window.EVENT_CREATED, - () => this._initView()); + documentModule.view.navigatorWindow.addEventListener( + Window.EVENT_CREATED, + () => this._initView() + ); } _initView() { @@ -76,7 +80,7 @@ export class ValidationView { this._toggleValidation(); this.switchElement.onchange = () => { this._toggleValidation(); - } + }; } /////////////////////////////////////// @@ -86,7 +90,7 @@ export class ValidationView { * Toggles the visualization of documents in validation, then refreshes the * document list with the new source. If the refresh fails (probably because * the user isn't logged in), reverts back to displaying validated documents. - * + * * @private */ _toggleValidation() { @@ -95,42 +99,46 @@ export class ValidationView { if (this.displayingDocumentsToValidate) { this._showDocumentsInValidation(); } else { - this._showValidatedDocuments() + this._showValidatedDocuments(); } - this.documentModule.refreshDocumentList().then(() => { - }, (reason) => { - this._showValidatedDocuments(); - this.displayingDocumentsToValidate = false; - this.switchElement.value = "validated"; - alert(reason); - }); + this.documentModule.refreshDocumentList().then( + () => {}, + (reason) => { + this._showValidatedDocuments(); + this.displayingDocumentsToValidate = false; + this.switchElement.value = 'validated'; + alert(reason); + } + ); } /** * Sets the document source to be documents in validation, and adds a * 'Validate' button in the browser. - * + * * @private */ _showDocumentsInValidation() { // Change the document source - this.previousDocumentSource = this.documentModule - .changeDocumentSource(this.validationSource, true); - + this.previousDocumentSource = this.documentModule.changeDocumentSource( + this.validationSource, + true + ); + // Adds the validate button this.documentModule.addInspectorExtension('Validate', { type: 'button', container: 'right', html: 'Validate', - callback: (doc) => this._validateDocument(doc) + callback: (doc) => this._validateDocument(doc), }); } /** * Sets to document source to validated documents, and removes the 'Validate' * button in the browser. - * + * * @private */ _showValidatedDocuments() { @@ -138,8 +146,10 @@ export class ValidationView { return; } - this.documentModule.changeDocumentSource(this.previousDocumentSource, - false); + this.documentModule.changeDocumentSource( + this.previousDocumentSource, + false + ); try { this.documentModule.removeBrowserExtension('Validate'); @@ -150,21 +160,28 @@ export class ValidationView { /** * Validates the document. - * + * * @private - * + * * @param {Document} doc The document to validate. */ _validateDocument(doc) { - if (!confirm('Are you sure do validate this document ? ' + - 'This operation is irreversible.')) { + if ( + !confirm( + 'Are you sure do validate this document ? ' + + 'This operation is irreversible.' + ) + ) { return; } - this.validationService.validate(this.documentModule.provider.getDisplayedDocument()).catch((reason) => { - alert(reason.statusText); - }).then(() => { - this.documentModule.refreshDocumentList(); - }); + this.validationService + .validate(this.documentModule.provider.getDisplayedDocument()) + .catch((reason) => { + alert(reason.statusText); + }) + .then(() => { + this.documentModule.refreshDocumentList(); + }); } ///////////// @@ -173,8 +190,8 @@ export class ValidationView { get switchId() { return 'document-validation-view-switch'; } - + get switchElement() { return document.getElementById(this.switchId); } -} \ No newline at end of file +} diff --git a/src/Widgets/Extensions/Extensions.js b/src/Widgets/Extensions/Extensions.js index d3f3f2a77..eca6b8968 100644 --- a/src/Widgets/Extensions/Extensions.js +++ b/src/Widgets/Extensions/Extensions.js @@ -15,5 +15,3 @@ export { Debug3DTilesWindow } from './3DTilesDebug/views/3DTilesDebugWindow'; export { ContributeModule } from './Contribute/ContributeModule'; export { DocumentValidationModule } from './DocumentValidation/DocumentValidationModule'; - - diff --git a/src/Widgets/Extensions/Geocoding/services/GeocodingService.js b/src/Widgets/Extensions/Geocoding/services/GeocodingService.js index 567047265..1e25f87d4 100644 --- a/src/Widgets/Extensions/Geocoding/services/GeocodingService.js +++ b/src/Widgets/Extensions/Geocoding/services/GeocodingService.js @@ -1,6 +1,8 @@ +/** @format */ + //Components -import { RequestService } from "../../../../Components/Request/RequestService"; -import { getAttributeByPath } from "../../../../Components/DataProcessing/DataProcessing"; +import { RequestService } from '../../../../Components/Request/RequestService'; +import { getAttributeByPath } from '../../../../Components/DataProcessing/DataProcessing'; export class GeocodingService { /** @@ -29,7 +31,7 @@ export class GeocodingService { * @param {String} searchString Either an address or the name of a place. */ async getCoordinates(searchString) { - if ((!!this.requestTimeIntervalMs) && !this.canDoRequest) { + if (!!this.requestTimeIntervalMs && !this.canDoRequest) { throw 'Cannot perform a request for now.'; } @@ -39,32 +41,36 @@ export class GeocodingService { //build the URL according to parameter description (in config file) let url = this.geocodingUrl + '?'; for (let [paramName, param] of Object.entries(this.parameters)) { - if (param.fill === "value") { + if (param.fill === 'value') { url += `${paramName}=${param.value}`; - } else if (param.fill === "query") { + } else if (param.fill === 'query') { url += `${paramName}=${queryString}`; - } else if (param.fill === "extent") { - url += paramName + '=' + param.format - .replace('SOUTH', this.extent.south) - .replace('WEST', this.extent.west) - .replace('NORTH', this.extent.north) - .replace('EAST', this.extent.east); + } else if (param.fill === 'extent') { + url += + paramName + + '=' + + param.format + .replace('SOUTH', this.extent.south) + .replace('WEST', this.extent.west) + .replace('NORTH', this.extent.north) + .replace('EAST', this.extent.east); } - url += "&"; + url += '&'; } //make the request const req = await this.requestService.request('GET', url, { - authenticate: false + authenticate: false, }); const response = JSON.parse(req.response); - const results = ((!!this.basePath) ? response[this.basePath] : response) - .map(res => { + const results = (!!this.basePath ? response[this.basePath] : response).map( + (res) => { return { lat: Number(getAttributeByPath(res, this.latPath)), - lng: Number(getAttributeByPath(res, this.lngPath)) + lng: Number(getAttributeByPath(res, this.lngPath)), }; - }); + } + ); if (!!this.requestTimeIntervalMs) { this.canDoRequest = false; diff --git a/src/Widgets/Extensions/Geocoding/views/GeocodingStyle.css b/src/Widgets/Extensions/Geocoding/views/GeocodingStyle.css index 32b53ef05..b627d18dc 100644 --- a/src/Widgets/Extensions/Geocoding/views/GeocodingStyle.css +++ b/src/Widgets/Extensions/Geocoding/views/GeocodingStyle.css @@ -1,3 +1,5 @@ +/** @format */ + #_geocoding_view { position: absolute; z-index: 200; @@ -32,9 +34,17 @@ } @keyframes open { - 0% { width: 0; opacity: 0; } - 20% { width: 0; opacity: 1; } - 100% { width: 300px; } + 0% { + width: 0; + opacity: 0; + } + 20% { + width: 0; + opacity: 1; + } + 100% { + width: 300px; + } } #_geocoding_view_centered { @@ -54,4 +64,4 @@ background-color: rgba(255, 255, 255, 0.5); padding: 5px 10px 5px 10px; border-radius: 10px; -} \ No newline at end of file +} diff --git a/src/Widgets/Extensions/Geocoding/views/GeocodingView.js b/src/Widgets/Extensions/Geocoding/views/GeocodingView.js index e51f5635d..dec63944f 100644 --- a/src/Widgets/Extensions/Geocoding/views/GeocodingView.js +++ b/src/Widgets/Extensions/Geocoding/views/GeocodingView.js @@ -1,13 +1,15 @@ +/** @format */ + import * as THREE from 'three'; import * as itowns from 'itowns'; -import Coordinates from "itowns/lib/Core/Geographic/Coordinates"; +import Coordinates from 'itowns/lib/Core/Geographic/Coordinates'; import proj4 from 'proj4'; //Components -import { ModuleView } from "../../../../Components/ModuleView/ModuleView"; -import { focusCameraOn } from "../../../../Components/Camera/CameraUtils"; +import { ModuleView } from '../../../../Components/ModuleView/ModuleView'; +import { focusCameraOn } from '../../../../Components/Camera/CameraUtils'; -import { GeocodingService } from "../services/GeocodingService"; +import { GeocodingService } from '../services/GeocodingService'; import './GeocodingStyle.css'; export class GeocodingView extends ModuleView { @@ -28,12 +30,15 @@ export class GeocodingView extends ModuleView { // (planarView of iTowns). It is indeed needed in getWorldCoordinates() // to convert the coordinates received from the geocoding service (WGS84) // to this coordinate system. - proj4.defs('EPSG:3946', '+proj=lcc +lat_1=45.25 +lat_2=46.75' + - ' +lat_0=46 +lon_0=3 +x_0=1700000 +y_0=5200000 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs'); + proj4.defs( + 'EPSG:3946', + '+proj=lcc +lat_1=45.25 +lat_2=46.75' + + ' +lat_0=46 +lon_0=3 +x_0=1700000 +y_0=5200000 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs' + ); } get html() { - return /*html*/` + return /*html*/ `
{ this.doGeocoding(); return false; - } + }; } } @@ -73,16 +78,16 @@ export class GeocodingView extends ModuleView { if (this.isCreated) { let div = this.viewElement; let input = this.searchInputElement; - input.style.transition = 'width 0.3s ease-out, opacity 0.4s ease-out' + input.style.transition = 'width 0.3s ease-out, opacity 0.4s ease-out'; input.style.width = '0'; input.style.opacity = '0'; input.ontransitionend = (event) => { - if (event.propertyName === "opacity") { + if (event.propertyName === 'opacity') { div.parentElement.removeChild(div); this.removePins(); resolve(); } - } + }; } else { resolve(); } @@ -100,8 +105,8 @@ export class GeocodingView extends ModuleView { try { let coords = await this.geocodingService.getCoordinates(searchString); - coords.forEach(c => { - let {lat, lng} = c; + coords.forEach((c) => { + let { lat, lng } = c; let i = 0; //step 1 : convert the lat/lng to coordinates used by itowns let targetPos = this.getWorldCoordinates(lat, lng); @@ -132,8 +137,11 @@ export class GeocodingView extends ModuleView { getWorldCoordinates(lat, lng) { const [targetX, targetY] = proj4('EPSG:3946').forward([lng, lat]); const coords = new Coordinates('EPSG:3946', targetX, targetY, 0); - const elevation = itowns.DEMUtils.getElevationValueAt(this.planarView.tileLayer, coords); - const targetZ = (!!elevation) ? elevation : undefined; + const elevation = itowns.DEMUtils.getElevationValueAt( + this.planarView.tileLayer, + coords + ); + const targetZ = !!elevation ? elevation : undefined; return new THREE.Vector3(targetX, targetY, targetZ); } @@ -146,12 +154,12 @@ export class GeocodingView extends ModuleView { async addPin(position) { const pinHeight = 50; const cylGeom = new THREE.CylinderGeometry(1, 8, pinHeight, 8); - const cylMat = new THREE.MeshToonMaterial({color: 0xff0000}); + const cylMat = new THREE.MeshToonMaterial({ color: 0xff0000 }); const cylMesh = new THREE.Mesh(cylGeom, cylMat); position.z += pinHeight / 2; this.addMeshToScene(cylMesh, position); const sphereGeom = new THREE.SphereGeometry(10, 16, 16); - const sphereMat = new THREE.MeshToonMaterial({color: 0xff00000}); + const sphereMat = new THREE.MeshToonMaterial({ color: 0xff00000 }); const sphereMesh = new THREE.Mesh(sphereGeom, sphereMat); position.z += pinHeight / 2; this.addMeshToScene(sphereMesh, position); @@ -277,7 +285,6 @@ export class GeocodingView extends ModuleView { * @override */ async disableView() { - await this.dispose(); } } diff --git a/src/Widgets/GuidedTour/GuidedTour.css b/src/Widgets/GuidedTour/GuidedTour.css index 8e0c4ca70..7939dd539 100644 --- a/src/Widgets/GuidedTour/GuidedTour.css +++ b/src/Widgets/GuidedTour/GuidedTour.css @@ -1,187 +1,187 @@ -#guidedTourTab{ - position: absolute; - margin : 3px; - border: 1px solid black; - background-color: white; - color: black; - height: 30px; - top: 0; - left: 5%; - pointer-events: auto; -} - -#guidedTourWindow{ - position: relative; - text-align: center; - color : black; - height: 100%; - font-size: 14; - pointer-events: none; -} - -#guidedTourTitle{ - display:inline-block; - margin-top: 10px; - color: black; - background-color: ivory; - text-align: center; - font-size: 16px; - font-weight: bold; - overflow: hidden; -} - -#guidedTourStepTitle{ - display:inline-block; - margin-top: 10px; - color: white; - text-align: center; - font-weight: bold; - overflow: hidden; -} - -#guidedTourText1{ - display:inline-block; - margin: 10px; - padding: 5px; - padding-left: 10px; - padding-right: 10px; - line-height: 130%; - /* height adjusted in GuidedTour.js, 45% or 60% */ - height: 45%; - color : black; - background-color: ivory ; - border : 1px solid rgb(90,90,90); - text-align: justify; - overflow: scroll; - pointer-events: auto; -} - -#guidedTourText2{ - display: none; - margin-top: 20px; - margin: 10px; - padding: 5px; - padding-left: 10px; - padding-right: 10px; - line-height: 130%; - height: 20%; - color : black; - background-color: ivory ; - border : 1px solid rgb(90,90,90); - text-align: justify; - overflow: scroll; - pointer-events: auto; -} - -#guidedTourDocTitle{ - display:inline-block; - margin-top: 10px; - color: white; - text-align: center; - font-weight: bold; - overflow: hidden; -} - -#guidedTourDocPreview{ - height: 25%; - display:inline-block; - margin: 5% ; -} - -#guidedTourDocPreviewImg{ - width: 100%; /* or any custom size */ - height: 100%; - object-fit: contain; -} - -#guidedTourStartButton{ - position: absolute; - bottom : 5px; - left: 0; - right: 0; - margin: auto; - border: 1px solid black; - background-color: white; - color: black; - height: 30px; - pointer-events: auto; -} - - -#guidedTourNextTourButton{ - position: absolute; - bottom : 5px; - right: 5px; - margin: auto; - font-size: 30px; - border: 1px solid black; - background-color: white; - color: black; - height: 40px; - pointer-events: auto; -} - -#guidedTourPreviousTourButton{ - position: absolute; - bottom : 5px; - left : 5px; - margin : auto; - font-size: 30px; - border: 1px solid black; - background-color: white; - color: black; - height: 40px; - pointer-events: auto; -} - -#guidedTourNextStepButton{ - position: absolute; - bottom : 5px; - right: 5px; - margin: auto; - font-size: 30px; - border: 1px solid black; - background-color: white; - color: black; - height: 40px; - pointer-events: auto; -} - -#guidedTourPreviousStepButton{ - position: absolute; - bottom : 5px; - left : 5px; - margin : auto; - font-size: 30px; - border: 1px solid black; - background-color: white; - color: black; - height: 40px; - pointer-events: auto; -} - -#guidedTourExitButton{ - position: absolute; - display:none; - bottom : 5px; - left: 0; - right: 0; - margin: auto; - border: 1px solid black; - background-color: white; - color: black; - height: 30px; - pointer-events: auto; -} - -#tourCpt{ - position: absolute; - margin-top: 10px; - color: white; - left : 15px; - bottom : 100px; - font-size: 14px; - font-weight: bold; - overflow: hidden; +/** @format */ +#guidedTourTab { + position: absolute; + margin: 3px; + border: 1px solid black; + background-color: white; + color: black; + height: 30px; + top: 0; + left: 5%; + pointer-events: auto; +} + +#guidedTourWindow { + position: relative; + text-align: center; + color: black; + height: 100%; + font-size: 14; + pointer-events: none; +} + +#guidedTourTitle { + display: inline-block; + margin-top: 10px; + color: black; + background-color: ivory; + text-align: center; + font-size: 16px; + font-weight: bold; + overflow: hidden; +} + +#guidedTourStepTitle { + display: inline-block; + margin-top: 10px; + color: white; + text-align: center; + font-weight: bold; + overflow: hidden; +} + +#guidedTourText1 { + display: inline-block; + margin: 10px; + padding: 5px; + padding-left: 10px; + padding-right: 10px; + line-height: 130%; + /* height adjusted in GuidedTour.js, 45% or 60% */ + height: 45%; + color: black; + background-color: ivory; + border: 1px solid rgb(90, 90, 90); + text-align: justify; + overflow: scroll; + pointer-events: auto; +} + +#guidedTourText2 { + display: none; + margin-top: 20px; + margin: 10px; + padding: 5px; + padding-left: 10px; + padding-right: 10px; + line-height: 130%; + height: 20%; + color: black; + background-color: ivory; + border: 1px solid rgb(90, 90, 90); + text-align: justify; + overflow: scroll; + pointer-events: auto; +} + +#guidedTourDocTitle { + display: inline-block; + margin-top: 10px; + color: white; + text-align: center; + font-weight: bold; + overflow: hidden; +} + +#guidedTourDocPreview { + height: 25%; + display: inline-block; + margin: 5%; +} + +#guidedTourDocPreviewImg { + width: 100%; /* or any custom size */ + height: 100%; + object-fit: contain; +} + +#guidedTourStartButton { + position: absolute; + bottom: 5px; + left: 0; + right: 0; + margin: auto; + border: 1px solid black; + background-color: white; + color: black; + height: 30px; + pointer-events: auto; +} + +#guidedTourNextTourButton { + position: absolute; + bottom: 5px; + right: 5px; + margin: auto; + font-size: 30px; + border: 1px solid black; + background-color: white; + color: black; + height: 40px; + pointer-events: auto; +} + +#guidedTourPreviousTourButton { + position: absolute; + bottom: 5px; + left: 5px; + margin: auto; + font-size: 30px; + border: 1px solid black; + background-color: white; + color: black; + height: 40px; + pointer-events: auto; +} + +#guidedTourNextStepButton { + position: absolute; + bottom: 5px; + right: 5px; + margin: auto; + font-size: 30px; + border: 1px solid black; + background-color: white; + color: black; + height: 40px; + pointer-events: auto; +} + +#guidedTourPreviousStepButton { + position: absolute; + bottom: 5px; + left: 5px; + margin: auto; + font-size: 30px; + border: 1px solid black; + background-color: white; + color: black; + height: 40px; + pointer-events: auto; +} + +#guidedTourExitButton { + position: absolute; + display: none; + bottom: 5px; + left: 0; + right: 0; + margin: auto; + border: 1px solid black; + background-color: white; + color: black; + height: 30px; + pointer-events: auto; +} + +#tourCpt { + position: absolute; + margin-top: 10px; + color: white; + left: 15px; + bottom: 100px; + font-size: 14px; + font-weight: bold; + overflow: hidden; } diff --git a/src/Widgets/GuidedTour/GuidedTour.js b/src/Widgets/GuidedTour/GuidedTour.js index 4698a9f09..de7c14d8b 100644 --- a/src/Widgets/GuidedTour/GuidedTour.js +++ b/src/Widgets/GuidedTour/GuidedTour.js @@ -1,8 +1,10 @@ +/** @format */ + //Components import { Window } from '../../Components/GUI/js/Window'; import '../../Components/GUI/css/window.css'; -import './GuidedTour.css' +import './GuidedTour.css'; /** * Class: GuidedTour @@ -15,9 +17,8 @@ import './GuidedTour.css' * //=============================================================================*/ export class GuidedTour extends Window { - constructor(guidedTourController) { - super('guidedTour', 'Guided Tour', false) + super('guidedTour', 'Guided Tour', false); this.guidedTourController = guidedTourController; this.tourIndex = 1; //current guided tour. Default is 1 (start) @@ -71,13 +72,16 @@ export class GuidedTour extends Window { // hide or show the guided tour window //============================================================================= - toggleGuidedTourWindow(){ - - document.getElementById('guidedTourWindow').style.display = - this.guidedTourWindowIsActive ? "block" : "none"; - this.guidedTourWindowIsActive = this.guidedTourWindowIsActive ? false : true; - - if(this.isStart){ + toggleGuidedTourWindow() { + document.getElementById('guidedTourWindow').style.display = this + .guidedTourWindowIsActive + ? 'block' + : 'none'; + this.guidedTourWindowIsActive = this.guidedTourWindowIsActive + ? false + : true; + + if (this.isStart) { this.startGuidedTourMode(); this.isStart = false; this.guidedTourController.toggleGuidedTourButtons(true); @@ -85,7 +89,7 @@ export class GuidedTour extends Window { } //get all available guided tour from the database - startGuidedTourMode(){ + startGuidedTourMode() { this.guidedTourController.getGuidedTours().then(() => { this.previewTour(); }); @@ -95,85 +99,90 @@ export class GuidedTour extends Window { * Initialize the preview of the guided tour */ //============================================================================= - previewTour(){ - document.getElementById('tourCpt').innerHTML = "Tour: " - + this.tourIndex + " out of " + this.guidedTourController.guidedTours.length; - document.getElementById("guidedTourPreviousTourButton").style.display = "block"; - document.getElementById("guidedTourNextTourButton").style.display = "block"; + previewTour() { + document.getElementById('tourCpt').innerHTML = + 'Tour: ' + + this.tourIndex + + ' out of ' + + this.guidedTourController.guidedTours.length; + document.getElementById('guidedTourPreviousTourButton').style.display = + 'block'; + document.getElementById('guidedTourNextTourButton').style.display = 'block'; // for the demo, until we have more than one finished guided tour // we can prevent user from changing tour by hiding the buttons - if(this.guidedTourController.preventUserFromChangingTour){ - document.getElementById("guidedTourPreviousTourButton").style.display = "none"; - document.getElementById("guidedTourNextTourButton").style.display = "none"; + if (this.guidedTourController.preventUserFromChangingTour) { + document.getElementById('guidedTourPreviousTourButton').style.display = + 'none'; + document.getElementById('guidedTourNextTourButton').style.display = + 'none'; } - document.getElementById("guidedTourPreviousStepButton").style.display = "none"; - document.getElementById("guidedTourNextStepButton").style.display = "none"; - document.getElementById("guidedTourExitButton").style.display = "none"; + document.getElementById('guidedTourPreviousStepButton').style.display = + 'none'; + document.getElementById('guidedTourNextStepButton').style.display = 'none'; + document.getElementById('guidedTourExitButton').style.display = 'none'; //document.getElementById("guidedTourText2").style.display = "none"; - document.getElementById("guidedTourStartButton").style.display = "block"; + document.getElementById('guidedTourStartButton').style.display = 'block'; let currentTour = this.guidedTourController.getCurrentTour(); - document.getElementById('guidedTourTitle').innerHTML = - currentTour ? currentTour.name - : 'No guided tour'; - document.getElementById('guidedTourText1').innerHTML = - currentTour ? currentTour.description - : 'Please add guided tours'; - document.getElementById("guidedTourText1").style.height = "45%"; - document.getElementById("guidedTourStepTitle").innerHTML = null; - + document.getElementById('guidedTourTitle').innerHTML = currentTour + ? currentTour.name + : 'No guided tour'; + document.getElementById('guidedTourText1').innerHTML = currentTour + ? currentTour.description + : 'Please add guided tours'; + document.getElementById('guidedTourText1').style.height = '45%'; + document.getElementById('guidedTourStepTitle').innerHTML = null; } - // update step with current step data //============================================================================= - updateStep(){ - + updateStep() { this.currentStep = this.guidedTourController.getCurrentStep(); this.documentBrowser.currentMetadata = - this.guidedTourController.getCurrentStep().document; - this.documentBrowser.currentDoc = this.guidedTourController.getCurrentStep().document; + this.guidedTourController.getCurrentStep().document; + this.documentBrowser.currentDoc = + this.guidedTourController.getCurrentStep().document; this.documentBrowser.updateBrowser(); - document.getElementById("guidedTourText1").innerHTML = this.currentStep.text1; - document.getElementById('guidedTourStepTitle').innerHTML = this.currentStep.title; + document.getElementById('guidedTourText1').innerHTML = + this.currentStep.text1; + document.getElementById('guidedTourStepTitle').innerHTML = + this.currentStep.title; this.documentBrowser.focusOnDoc(); } //start guided tour //============================================================================= - startGuidedTour(){ - - if(this.guidedTourController.getCurrentTour().extendedDocs.length > 0){ + startGuidedTour() { + if (this.guidedTourController.getCurrentTour().extendedDocs.length > 0) { this.tourIndex = 1; this.stepIndex = 1; this.updateStep(); // setup the display (hide & show elements) this.guidedTourController.toggleGuidedTourButtons(false); - document.getElementById("guidedTourDocPreviewImg").style.display = "none"; - document.getElementById("guidedTourText1").style.height = "60%"; - document.getElementById('tourCpt').style.display = "none"; - } - else { + document.getElementById('guidedTourDocPreviewImg').style.display = 'none'; + document.getElementById('guidedTourText1').style.height = '60%'; + document.getElementById('tourCpt').style.display = 'none'; + } else { alert('This guided tour is empty'); //should never happen. If a guided tour - //doesn't have steps, then it is not a guided tour + //doesn't have steps, then it is not a guided tour } - }; + } // Quit current guided tour //============================================================================= - exitGuidedTour(){ - this.guidedTourController.reset(); - }; + exitGuidedTour() { + this.guidedTourController.reset(); + } /** * Update guided tour preview by clicking on "guidedTourNextTourButton" button */ //============================================================================= - nextTour(){ - if(this.tourIndex < this.guidedTourController.guidedTours.length){ + nextTour() { + if (this.tourIndex < this.guidedTourController.guidedTours.length) { this.guidedTourController.getNextTour(); - this.tourIndex ++; + this.tourIndex++; this.previewTour(); } } @@ -182,10 +191,10 @@ export class GuidedTour extends Window { * Update guided tour preview by clicking on "guidedTourPreviousTourButton" button */ //============================================================================= - previousTour(){ + previousTour() { this.guidedTourController.getPreviousTour(); - if(this.tourIndex > 1 ){ - this.tourIndex --; + if (this.tourIndex > 1) { + this.tourIndex--; } this.previewTour(); } @@ -194,43 +203,48 @@ export class GuidedTour extends Window { * Update step by clicking on "guidedTourNextStepButton" button */ //============================================================================= - nextStep(){ - - if(this.stepIndex < this.guidedTourController.getCurrentTour().extendedDocs.length ){ - this.stepIndex ++; + nextStep() { + if ( + this.stepIndex < + this.guidedTourController.getCurrentTour().extendedDocs.length + ) { + this.stepIndex++; this.guidedTourController.getNextStep(); - this.updateStep(); + this.updateStep(); } - } /** * Update step by clicking on "guidedTourPreviousStepButton" button */ //============================================================================= - previousStep(){ - - if( this.stepIndex > 1 ){ + previousStep() { + if (this.stepIndex > 1) { this.guidedTourController.getPreviousStep(); - this.stepIndex --; + this.stepIndex--; this.updateStep(); } } // event listeners (buttons) initializeButtons() { - document.getElementById("guidedTourNextTourButton").addEventListener('mousedown', - this.nextTour.bind(this),false); - document.getElementById("guidedTourPreviousTourButton").addEventListener('mousedown', - this.previousTour.bind(this),false); - document.getElementById("guidedTourStartButton").addEventListener('mousedown', - this.startGuidedTour.bind(this),false); - document.getElementById("guidedTourNextStepButton").addEventListener('mousedown', - this.nextStep.bind(this),false); - document.getElementById("guidedTourPreviousStepButton").addEventListener('mousedown', - this.previousStep.bind(this),false); - document.getElementById("guidedTourExitButton").addEventListener('mousedown', - this.exitGuidedTour.bind(this),false); + document + .getElementById('guidedTourNextTourButton') + .addEventListener('mousedown', this.nextTour.bind(this), false); + document + .getElementById('guidedTourPreviousTourButton') + .addEventListener('mousedown', this.previousTour.bind(this), false); + document + .getElementById('guidedTourStartButton') + .addEventListener('mousedown', this.startGuidedTour.bind(this), false); + document + .getElementById('guidedTourNextStepButton') + .addEventListener('mousedown', this.nextStep.bind(this), false); + document + .getElementById('guidedTourPreviousStepButton') + .addEventListener('mousedown', this.previousStep.bind(this), false); + document + .getElementById('guidedTourExitButton') + .addEventListener('mousedown', this.exitGuidedTour.bind(this), false); } - } diff --git a/src/Widgets/GuidedTour/GuidedTourController.js b/src/Widgets/GuidedTour/GuidedTourController.js index b0fed6c47..2f2be96d7 100644 --- a/src/Widgets/GuidedTour/GuidedTourController.js +++ b/src/Widgets/GuidedTour/GuidedTourController.js @@ -1,20 +1,22 @@ +/** @format */ + //Components import { ModuleView } from '../../Components/ModuleView/ModuleView'; -import { RequestService } from "../../Components/Request/RequestService"; +import { RequestService } from '../../Components/Request/RequestService'; import './GuidedTour.css'; import { GuidedTour } from './GuidedTour.js'; import { DocumentModule } from '../Documents/DocumentModule'; /** -* Class: GuidedTourController -* Description : -* The GuidedTourController is an object handling the view, interracting with the -* server to get information and data (guided tours) -* It handles the display of guided tours in the guided tour window, and all the -* functionalities related to the guided tour (start, exit, next, previous...) -* GuidedTours are made of steps with properties : index, document, text1 and text2. -*/ + * Class: GuidedTourController + * Description : + * The GuidedTourController is an object handling the view, interracting with the + * server to get information and data (guided tours) + * It handles the display of guided tours in the guided tour window, and all the + * functionalities related to the guided tour (start, exit, next, previous...) + * GuidedTours are made of steps with properties : index, document, text1 and text2. + */ export class GuidedTourController extends ModuleView { /** * Constructor for GuidedTourController @@ -37,7 +39,7 @@ export class GuidedTourController extends ModuleView { constructor(documentModule, requestService, config) { super(); - this.guidedTourContainerId = "guidedTourContainer"; + this.guidedTourContainerId = 'guidedTourContainer'; this.documentModule = documentModule; //instance of DocumentModule @@ -65,8 +67,8 @@ export class GuidedTourController extends ModuleView { } /** - * initialize the controller - */ + * initialize the controller + */ //============================================================================= initialize() { this.guidedTour = new GuidedTour(this); @@ -76,11 +78,11 @@ export class GuidedTourController extends ModuleView { } /** - * Get all guided tour from a database */ + * Get all guided tour from a database */ //============================================================================= async getGuidedTours() { let req = await this.requestService.request('GET', this.url, { - authenticate: false + authenticate: false, }); this.guidedTours = JSON.parse(req.responseText); } @@ -92,8 +94,7 @@ export class GuidedTourController extends ModuleView { getCurrentTour() { if (this.guidedTours.length != 0) { return this.guidedTours[this.currentTourIndex]; - } - else { + } else { return null; } } @@ -107,7 +108,7 @@ export class GuidedTourController extends ModuleView { this.currentTourIndex++; } return this.getCurrentTour(); - }; + } /** * Sets the current guided tour to the previous guided tour and returns it. @@ -118,25 +119,24 @@ export class GuidedTourController extends ModuleView { this.currentTourIndex--; } return this.getCurrentTour(); - }; + } /** - * Returns the current tour step - */ + * Returns the current tour step + */ //============================================================================= getCurrentStep() { if (this.getCurrentTour().length != 0) { var steps = this.getCurrentTour().extendedDocs; return steps[this.currentStepIndex]; - } - else { + } else { return null; } } /** - * Sets the current step to the previous step and returns it. - */ + * Sets the current step to the previous step and returns it. + */ //============================================================================= getPreviousStep() { if (this.currentStepIndex > 0) { @@ -146,8 +146,8 @@ export class GuidedTourController extends ModuleView { } /** - * Sets the current step to the next step and returns it. - */ + * Sets the current step to the next step and returns it. + */ //============================================================================= getNextStep() { if (this.currentStepIndex < this.getCurrentTour().extendedDocs.length) { @@ -156,10 +156,9 @@ export class GuidedTourController extends ModuleView { return this.getCurrentStep(); } - /** - * Reset browser at the begining of the guided tours - */ + * Reset browser at the begining of the guided tours + */ //============================================================================= reset() { this.currentStepIndex = 0; @@ -167,19 +166,27 @@ export class GuidedTourController extends ModuleView { this.currentGuidedTour = this.guidedTours[this.currentTourIndex]; this.guidedTour.currentStep = this.getCurrentStep(); this.guidedTour.previewTour(); - } //Hide or show previous / next buttons in browser window //============================================================================= toggleGuidedTourButtons(active) { - document.getElementById("guidedTourPreviousTourButton").style.display = active ? "block" : "none"; - document.getElementById("guidedTourNextTourButton").style.display = active ? "block" : "none"; - document.getElementById("guidedTourPreviousStepButton").style.display = active ? "none" : "block"; - document.getElementById("guidedTourNextStepButton").style.display = active ? "none" : "block"; - document.getElementById('guidedTourStartButton').style.display = active ? "block" : "none"; - document.getElementById("guidedTourExitButton").style.display = active ? "none" : "block"; - + document.getElementById('guidedTourPreviousTourButton').style.display = + active ? 'block' : 'none'; + document.getElementById('guidedTourNextTourButton').style.display = active + ? 'block' + : 'none'; + document.getElementById('guidedTourPreviousStepButton').style.display = + active ? 'none' : 'block'; + document.getElementById('guidedTourNextStepButton').style.display = active + ? 'none' + : 'block'; + document.getElementById('guidedTourStartButton').style.display = active + ? 'block' + : 'none'; + document.getElementById('guidedTourExitButton').style.display = active + ? 'none' + : 'block'; } /////// MODULE MANAGEMENT FOR BASE DEMO @@ -191,5 +198,4 @@ export class GuidedTourController extends ModuleView { disableView() { this.guidedTour.dispose(); } - } diff --git a/src/Widgets/LayerChoice/views/LayerChoice.js b/src/Widgets/LayerChoice/views/LayerChoice.js index ef77d48be..6467deeb0 100644 --- a/src/Widgets/LayerChoice/views/LayerChoice.js +++ b/src/Widgets/LayerChoice/views/LayerChoice.js @@ -1,24 +1,26 @@ +/** @format */ + //Components -import { Window } from "../../../Components/GUI/js/Window"; -import { LayerManager } from "../../../Components/LayerManager/LayerManager"; +import { Window } from '../../../Components/GUI/js/Window'; +import { LayerManager } from '../../../Components/LayerManager/LayerManager'; export class LayerChoice extends Window { /** - * Creates the layer choice windows - * - * @param {LayerManager} layerManager + * Creates the layer choice windows + * + * @param {LayerManager} layerManager */ constructor(layerManager) { super('layer_choice', 'Layer', false); - /** + /** * the layerManager */ this.layerManager = layerManager; } get innerContentHtml() { - return /*html*/` + return /*html*/ `
@@ -61,20 +63,31 @@ export class LayerChoice extends Window { let layers = this.layerManager.getColorLayers(); for (let i = 0; i < layers.length; i++) { let item = document.createElement('div'); - item.innerHTML = ` - Visible
+ item.innerHTML = ` + Visible
- Opacity : ${layers[i].opacity} + Opacity : ${ + layers[i].opacity + }
`; item.oninput = (event) => { - if (event.srcElement.id === "checkbox_" + i) { + if (event.srcElement.id === 'checkbox_' + i) { layers[i].visible = event.srcElement.checked; } - if (event.srcElement.id === "range_" + i) { - this.layerManager.updateOpacity(layers[i], event.srcElement.valueAsNumber); + if (event.srcElement.id === 'range_' + i) { + this.layerManager.updateOpacity( + layers[i], + event.srcElement.valueAsNumber + ); } - let span_opacity = document.getElementById("color_value_opacity_" + i); + let span_opacity = document.getElementById('color_value_opacity_' + i); span_opacity.innerHTML = `${layers[i].opacity}`; this.layerManager.notifyChange(); }; @@ -93,9 +106,14 @@ export class LayerChoice extends Window { Scale : ${layers[i].scale} `; item.oninput = (event) => { - this.layerManager.updateScale(layers[i], event.srcElement.valueAsNumber); + this.layerManager.updateScale( + layers[i], + event.srcElement.valueAsNumber + ); this.layerManager.notifyChange(); - let span_elevation = document.getElementById("elevation_value_scale_" + i); + let span_elevation = document.getElementById( + 'elevation_value_scale_' + i + ); span_elevation.innerHTML = `${layers[i].scale}`; }; list.appendChild(item); @@ -110,7 +128,9 @@ export class LayerChoice extends Window { let div = document.createElement('div'); div.innerHTML = ` - All Visible
+ All Visible
`; div.onchange = (event) => { this.layerManager.changeVisibility(event.srcElement.checked); @@ -119,27 +139,46 @@ export class LayerChoice extends Window { list.append(div); for (let i = 0; i < layers.length; i++) { let item = document.createElement('div'); - item.innerHTML = ` - + item.innerHTML = ` +
- Visible
+ Visible
- Opacity : ${layers[i].opacity} + Opacity : ${ + layers[i].opacity + }
`; item.oninput = (event) => { - if (event.srcElement.id === "checkbox_" + i) { + if (event.srcElement.id === 'checkbox_' + i) { layers[i].visible = event.srcElement.checked; } - if (event.srcElement.id === "range_" + i) { - this.layerManager.updateOpacity(layers[i], event.srcElement.valueAsNumber); + if (event.srcElement.id === 'range_' + i) { + this.layerManager.updateOpacity( + layers[i], + event.srcElement.valueAsNumber + ); } - let div_visible = document.getElementById("visible_" + i); - div_visible.innerHTML = `Visible
`; - let span_opacity = document.getElementById("geometry_value_opacity_" + i); + let div_visible = document.getElementById('visible_' + i); + div_visible.innerHTML = `Visible
`; + let span_opacity = document.getElementById( + 'geometry_value_opacity_' + i + ); span_opacity.innerHTML = `${layers[i].opacity}`; this.layerManager.notifyChange(); }; @@ -179,4 +218,4 @@ export class LayerChoice extends Window { get geometryLayerListElement() { return document.getElementById(this.geometryLayersId); } -} \ No newline at end of file +} diff --git a/src/Widgets/Links/LinkModule.js b/src/Widgets/Links/LinkModule.js index 001d55426..7950cecfb 100644 --- a/src/Widgets/Links/LinkModule.js +++ b/src/Widgets/Links/LinkModule.js @@ -1,12 +1,14 @@ +/** @format */ + //Components -import { RequestService } from "../../Components/Request/RequestService"; -import { Window } from "../../Components/GUI/js/Window"; +import { RequestService } from '../../Components/Request/RequestService'; +import { Window } from '../../Components/GUI/js/Window'; -import { LinkService } from "./Model/LinkService"; -import { DocumentModule } from "../Documents/DocumentModule"; -import { CityObjectModule } from "../CityObjects/CityObjectModule"; -import { LinkView } from "./View/LinkView"; -import { LinkProvider } from "./ViewModel/LinkProvider"; +import { LinkService } from './Model/LinkService'; +import { DocumentModule } from '../Documents/DocumentModule'; +import { CityObjectModule } from '../CityObjects/CityObjectModule'; +import { LinkView } from './View/LinkView'; +import { LinkProvider } from './ViewModel/LinkProvider'; /** * Manages the links between the city objects and the documents. This modules @@ -16,7 +18,7 @@ import { LinkProvider } from "./ViewModel/LinkProvider"; export class LinkModule { /** * Creates the link module. - * + * * @param {DocumentModule} documentModule The document module. * @param {CityObjectModule} cityObjectModule The city objects module. * @param {RequestService} requestService The request service. @@ -27,33 +29,51 @@ export class LinkModule { * @param {string} config.server.url The server URL. * @param {string} config.server.link The link route. */ - constructor(documentModule, cityObjectModule, requestService, itownsView, - cameraControls, config) { + constructor( + documentModule, + cityObjectModule, + requestService, + itownsView, + cameraControls, + config + ) { /** * The link service. - * + * * @type {LinkService} */ this.service = new LinkService(requestService, config); /** * The link provider. - * + * * @type {LinkProvider} */ - this.provider = new LinkProvider(documentModule.provider, cityObjectModule.provider, this.service, config); + this.provider = new LinkProvider( + documentModule.provider, + cityObjectModule.provider, + this.service, + config + ); this.provider.fetchLinks().then(() => { - this.view = new LinkView(documentModule, cityObjectModule, this.provider, - itownsView, cameraControls); + this.view = new LinkView( + documentModule, + cityObjectModule, + this.provider, + itownsView, + cameraControls + ); }); documentModule.view.addEventListener(Window.EVENT_DISABLED, () => { if (!cityObjectModule.provider.getLayer()) { return; } - if (cityObjectModule.provider.getLayer().filter.label === 'linkDisplayedDoc') { + if ( + cityObjectModule.provider.getLayer().filter.label === 'linkDisplayedDoc' + ) { cityObjectModule.provider.removeLayer(); } }); } -} \ No newline at end of file +} diff --git a/src/Widgets/Links/Model/Link.js b/src/Widgets/Links/Model/Link.js index 853d22c7f..59fea25b4 100644 --- a/src/Widgets/Links/Model/Link.js +++ b/src/Widgets/Links/Model/Link.js @@ -1,7 +1,10 @@ /** * Represents a link between a document and a target (in this example, the * only valid target types are city objects). + * + * @format */ + export class Link { /** * Constructs an empty link. @@ -9,21 +12,21 @@ export class Link { constructor() { /** * The ID of the link. - * + * * @type {number} */ this.id; /** * The source (document) ID. - * + * * @type {number} */ this.source_id; /** * The target ID. For the moment, the only targets are city objects. - * + * * @type {number} */ this.target_id; @@ -31,7 +34,7 @@ export class Link { /** * The X coordinate of the centroid. The centroid must be stored in the * in order to travel to the city object. - * + * * @type {number} */ this.centroid_x; @@ -39,7 +42,7 @@ export class Link { /** * The Y coordinate of the centroid. The centroid must be stored in the * in order to travel to the city object. - * + * * @type {number} */ this.centroid_y; @@ -47,9 +50,9 @@ export class Link { /** * The Z coordinate of the centroid. The centroid must be stored in the * in order to travel to the city object. - * + * * @type {number} */ this.centroid_z; } -} \ No newline at end of file +} diff --git a/src/Widgets/Links/Model/LinkService.js b/src/Widgets/Links/Model/LinkService.js index 8d188002b..b5bf88025 100644 --- a/src/Widgets/Links/Model/LinkService.js +++ b/src/Widgets/Links/Model/LinkService.js @@ -1,7 +1,9 @@ +/** @format */ + //Components -import { RequestService } from "../../../Components/Request/RequestService"; +import { RequestService } from '../../../Components/Request/RequestService'; -import { Link } from "./Link"; +import { Link } from './Link'; /** * This class is used to perform requests concerning links. @@ -9,7 +11,7 @@ import { Link } from "./Link"; export class LinkService { /** * Creates a link service Service. - * + * * @param {RequestService} requestService The request service. * @param {object} config The UD-Viz config. * @param {object} config.server The server configuration. @@ -23,22 +25,22 @@ export class LinkService { this.requestService = requestService; /** - * GET url to retrieve supported link types. - * GET url/ to retrieve links of this type. - * POST url/ to create a link of this type. + * GET url to retrieve supported link types. + * GET url/ to retrieve links of this type. + * POST url/ to create a link of this type. */ this.linkURL = `${config.server.url}${config.server.link}`; } /** * Return supported link types. - * + * * @returns {Promise>} An array containing the supported link * types. */ async getSupportedLinkTypes() { let req = await this.requestService.request('GET', this.linkURL, { - authenticate: false + authenticate: false, }); let types = JSON.parse(req.response); return types; @@ -46,19 +48,19 @@ export class LinkService { /** * Retrieves all links matching the given link type and filters. - * + * * @param {string} linkType A supported link type. * @param {FormData} [filters] Filtering criteria for the link. Possible filters * are `source_id` (which must be a document id) and `target_id` (an ID of * type `linkType`). - * + * * @returns {Promise>} An array of links. */ async getLinks(linkType, filters = null) { const url = `${this.linkURL}/${linkType}`; let req = await this.requestService.request('GET', url, { authenticate: false, - urlParameters: filters + urlParameters: filters, }); let links = JSON.parse(req.response); return links; @@ -66,7 +68,7 @@ export class LinkService { /** * Creates a new link with the given type. - * + * * @param {string} linkType A supported link type. * @param {FormData} formData Properties of the created link. It must include * `source_id` (the document id) and `target_id` (ID of the target of type @@ -76,7 +78,7 @@ export class LinkService { const url = `${this.linkURL}/${linkType}`; let req = await this.requestService.request('POST', url, { authenticate: false, - body: formData + body: formData, }); let created = JSON.parse(req.response); return created; @@ -84,14 +86,14 @@ export class LinkService { /** * Deletes a link of the given type with the given ID. - * + * * @param {string} linkType A supported link type. * @param {number} linkId ID of the link to delete. */ async deleteLink(linkType, linkId) { const url = `${this.linkURL}/${linkType}/${linkId}`; let req = await this.requestService.request('DELETE', url, { - authenticate: false + authenticate: false, }); let deleted = JSON.parse(req.response); return deleted; diff --git a/src/Widgets/Links/View/CityObjectLinkInterface.js b/src/Widgets/Links/View/CityObjectLinkInterface.js index b7542b7af..12d9ca96a 100644 --- a/src/Widgets/Links/View/CityObjectLinkInterface.js +++ b/src/Widgets/Links/View/CityObjectLinkInterface.js @@ -1,9 +1,11 @@ -import { LinkService } from "../Model/LinkService"; -import { CityObjectModule } from "../../CityObjects/CityObjectModule"; -import { CityObjectFilterSelector } from "../../CityObjects/View/CityObjectFilterSelector"; -import { LinkProvider } from "../ViewModel/LinkProvider"; -import { CityObjectProvider } from "../../CityObjects/ViewModel/CityObjectProvider"; -import { LinkView } from "./LinkView"; +/** @format */ + +import { LinkService } from '../Model/LinkService'; +import { CityObjectModule } from '../../CityObjects/CityObjectModule'; +import { CityObjectFilterSelector } from '../../CityObjects/View/CityObjectFilterSelector'; +import { LinkProvider } from '../ViewModel/LinkProvider'; +import { CityObjectProvider } from '../../CityObjects/ViewModel/CityObjectProvider'; +import { LinkView } from './LinkView'; /** * The interface extensions for the city object window. @@ -11,7 +13,7 @@ import { LinkView } from "./LinkView"; export class CityObjectLinkInterface { /** * Constructs the city object link interface. - * + * * @param {LinkView} linkView The link view. * @param {CityObjectModule} cityObjectModule The city object module. * @param {LinkProvider} linkProvider The link service. @@ -28,7 +30,7 @@ export class CityObjectLinkInterface { // to show them in the document navigator. cityObjectModule.addExtension('links', { type: 'div', - html: /*html*/` + html: /*html*/ `
@@ -39,18 +41,20 @@ export class CityObjectLinkInterface { linkView.requestDisplayDocuments(); linkProvider.toggleLinkedDocumentsFilter(true); }; - } + }, }); /** * The link provider. - * + * * @type {LinkProvider} */ this.linkProvider = linkProvider; - this.linkProvider.addEventListener(CityObjectProvider.EVENT_CITY_OBJECT_SELECTED, - () => this._updateLinkList()); + this.linkProvider.addEventListener( + CityObjectProvider.EVENT_CITY_OBJECT_SELECTED, + () => this._updateLinkList() + ); } /** @@ -61,7 +65,7 @@ export class CityObjectLinkInterface { return; } let docs = this.linkProvider.getSelectedCityObjectLinkedDocuments(); - let listHtml = `

${docs.length} linked document(s)

` + let listHtml = `

${docs.length} linked document(s)

`; if (docs.length > 0) { listHtml += `

    `; for (let doc of docs) { @@ -99,7 +103,7 @@ export class CityObjectLinkInterface { export class LinkCountFilterSelector extends CityObjectFilterSelector { /** * Creates the filter selector. - * + * * @param {LinkProvider} linkProvider The link provider. */ constructor(linkProvider) { @@ -112,7 +116,7 @@ export class LinkCountFilterSelector extends CityObjectFilterSelector { } get html() { - return /*html*/` + return /*html*/ ` `; @@ -121,4 +125,4 @@ export class LinkCountFilterSelector extends CityObjectFilterSelector { onSubmit(formData) { this.filter.requiredCount = Number(formData.get('requiredCount')) || 1; } -} \ No newline at end of file +} diff --git a/src/Widgets/Links/View/DocumentLinkInterface.js b/src/Widgets/Links/View/DocumentLinkInterface.js index 5a699d2f2..d3baac9ad 100644 --- a/src/Widgets/Links/View/DocumentLinkInterface.js +++ b/src/Widgets/Links/View/DocumentLinkInterface.js @@ -1,11 +1,13 @@ +/** @format */ + //Components -import { focusCameraOn } from "../../../Components/Camera/CameraUtils"; +import { focusCameraOn } from '../../../Components/Camera/CameraUtils'; -import { DocumentModule } from "../../Documents/DocumentModule"; +import { DocumentModule } from '../../Documents/DocumentModule'; import * as THREE from 'three'; -import { DocumentProvider } from "../../Documents/ViewModel/DocumentProvider"; -import { Link } from "../Model/Link"; -import { LinkProvider } from "../ViewModel/LinkProvider"; +import { DocumentProvider } from '../../Documents/ViewModel/DocumentProvider'; +import { Link } from '../Model/Link'; +import { LinkProvider } from '../ViewModel/LinkProvider'; /** * The interface extensions for the document windows. @@ -13,7 +15,7 @@ import { LinkProvider } from "../ViewModel/LinkProvider"; export class DocumentLinkInterface { /** * Constructs the document link interface. - * + * * @param {DocumentModule} documentModule The document module. * @param {LinkProvider} linkProvider The link provider. * @param {*} itownsView The iTowns view. @@ -22,14 +24,14 @@ export class DocumentLinkInterface { constructor(documentModule, linkProvider, itownsView, cameraControls) { /** * The link provider. - * + * * @type {LinkProvider} */ this.provider = linkProvider; /** * The list of links for the currently displayed document. - * + * * @type {Array} */ this.documentLinks = []; @@ -38,18 +40,18 @@ export class DocumentLinkInterface { * The itowns view. */ this.itownsView = itownsView; - + /** * The planar camera controls. */ this.cameraControls = cameraControls; // Adds the extension for the displayed documents. This extension shows the - // links and adds two buttons to highlight the linked city objects, and + // links and adds two buttons to highlight the linked city objects, and // create a new link. documentModule.addInspectorExtension('links', { type: 'div', - html: /*html*/` + html: /*html*/ `
    @@ -59,7 +61,7 @@ export class DocumentLinkInterface {
    `, - oncreated: () => this._init() + oncreated: () => this._init(), }); // Adds an extension in the navigator window to show the status of the @@ -68,18 +70,23 @@ export class DocumentLinkInterface { documentModule.addNavigatorExtension('linkFilter', { type: 'div', container: 'filter', - html: /*html*/` + html: /*html*/ ` `, oncreated: () => { - this.linkFilterElement.onchange = () => this.provider.toggleLinkedDocumentsFilter(); - } + this.linkFilterElement.onchange = () => + this.provider.toggleLinkedDocumentsFilter(); + }, }); - linkProvider.addEventListener(DocumentProvider.EVENT_FILTERED_DOCS_UPDATED, - () => this._updateLinkFilter()); + linkProvider.addEventListener( + DocumentProvider.EVENT_FILTERED_DOCS_UPDATED, + () => this._updateLinkFilter() + ); - linkProvider.addEventListener(DocumentProvider.EVENT_DISPLAYED_DOC_CHANGED, - () => this._updateLinkList()); + linkProvider.addEventListener( + DocumentProvider.EVENT_DISPLAYED_DOC_CHANGED, + () => this._updateLinkList() + ); } /** @@ -95,11 +102,16 @@ export class DocumentLinkInterface { if (!!this.provider.selectedCityObject) { let newLink = new Link(); newLink.source_id = this.provider.displayedDocument.id; - newLink.target_id = this.provider.selectedCityObject.props['cityobject.database_id']; + newLink.target_id = + this.provider.selectedCityObject.props['cityobject.database_id']; newLink.centroid_x = this.provider.selectedCityObject.centroid.x; newLink.centroid_y = this.provider.selectedCityObject.centroid.y; newLink.centroid_z = this.provider.selectedCityObject.centroid.z; - if (confirm('Are you sure you want to associate the document with this city object ?')) { + if ( + confirm( + 'Are you sure you want to associate the document with this city object ?' + ) + ) { try { await this.provider.createLink(newLink); } catch (e) { @@ -145,10 +157,14 @@ export class DocumentLinkInterface { for (let link of links) { newDivHtml += `
  • ID : ${link.target_id} - + travel - + delete
  • `; @@ -167,25 +183,28 @@ export class DocumentLinkInterface { } } - //////////////////// ///// LINK OPERATION /** * If the target is a city object, moves the camera to focus on its centroid. - * + * * @param {Link} link The link to travel to. */ async _travelToLink(link) { - let centroid = new THREE.Vector3(link.centroid_x, link.centroid_y, - link.centroid_z); - await focusCameraOn(this.itownsView, this.cameraControls, centroid, - {duration: 1}); + let centroid = new THREE.Vector3( + link.centroid_x, + link.centroid_y, + link.centroid_z + ); + await focusCameraOn(this.itownsView, this.cameraControls, centroid, { + duration: 1, + }); } /** * Deletes the link. - * + * * @param {Link} link The link to delete. */ async _deleteLink(link) { diff --git a/src/Widgets/Links/View/LinkView.js b/src/Widgets/Links/View/LinkView.js index 803be9b8b..57b9aaa17 100644 --- a/src/Widgets/Links/View/LinkView.js +++ b/src/Widgets/Links/View/LinkView.js @@ -1,12 +1,14 @@ -import { DocumentModule } from "../../Documents/DocumentModule"; -import { CityObjectModule } from "../../CityObjects/CityObjectModule"; -import { LinkService } from "../Model/LinkService"; -import { DocumentLinkInterface } from "./DocumentLinkInterface"; -import { CityObjectLinkInterface } from "./CityObjectLinkInterface"; -import { DocumentInspectorWindow } from "../../Documents/View/DocumentInspectorWindow"; -import { LinkProvider } from "../ViewModel/LinkProvider"; -import { DocumentView } from "../../Documents/View/DocumentView"; -import { CityObjectWindow } from "../../CityObjects/View/CityObjectWindow"; +/** @format */ + +import { DocumentModule } from '../../Documents/DocumentModule'; +import { CityObjectModule } from '../../CityObjects/CityObjectModule'; +import { LinkService } from '../Model/LinkService'; +import { DocumentLinkInterface } from './DocumentLinkInterface'; +import { CityObjectLinkInterface } from './CityObjectLinkInterface'; +import { DocumentInspectorWindow } from '../../Documents/View/DocumentInspectorWindow'; +import { LinkProvider } from '../ViewModel/LinkProvider'; +import { DocumentView } from '../../Documents/View/DocumentView'; +import { CityObjectWindow } from '../../CityObjects/View/CityObjectWindow'; /** * Represents the visual interface of the link module. This class contains @@ -16,45 +18,56 @@ import { CityObjectWindow } from "../../CityObjects/View/CityObjectWindow"; export class LinkView { /** * Constructs the link view. - * + * * @param {DocumentModule} documentModule The document module. * @param {CityObjectModule} cityObjectModule The city object module. * @param {LinkProvider} linkProvider The link service. * @param {*} itownsView The iTowns view. - * @param {*} cameraControls The planar camera controls + * @param {*} cameraControls The planar camera controls */ - constructor(documentModule, cityObjectModule, linkProvider, itownsView, - cameraControls) { - + constructor( + documentModule, + cityObjectModule, + linkProvider, + itownsView, + cameraControls + ) { /** * A reference to the document view. - * + * * @type {DocumentView} */ this.documentView = documentModule.view; /** * A reference to the city object window. - * + * * @type {CityObjectWindow} */ this.cityObjectView = cityObjectModule.view; /** * The interface extensions for the document module. - * + * * @type {DocumentLinkInterface} */ - this.documentInterface = new DocumentLinkInterface(documentModule, - linkProvider, itownsView, cameraControls); + this.documentInterface = new DocumentLinkInterface( + documentModule, + linkProvider, + itownsView, + cameraControls + ); /** * The interface extensions for the city object module. - * + * * @type {CityObjectLinkInterface} */ - this.cityObjectInterface = new CityObjectLinkInterface(this, - cityObjectModule, linkProvider); + this.cityObjectInterface = new CityObjectLinkInterface( + this, + cityObjectModule, + linkProvider + ); } /** @@ -70,4 +83,4 @@ export class LinkView { requestDisplayCityObjects() { this.cityObjectView.enable(); } -} \ No newline at end of file +} diff --git a/src/Widgets/Links/ViewModel/CityObjectLinkFilters.js b/src/Widgets/Links/ViewModel/CityObjectLinkFilters.js index 0aa4a7ac3..37aaf115d 100644 --- a/src/Widgets/Links/ViewModel/CityObjectLinkFilters.js +++ b/src/Widgets/Links/ViewModel/CityObjectLinkFilters.js @@ -1,8 +1,10 @@ +/** @format */ + //Components -import { CityObject } from "../../../Components/3DTiles/Model/CityObject"; +import { CityObject } from '../../../Components/3DTiles/Model/CityObject'; -import { CityObjectFilter } from "../../CityObjects/ViewModel/CityObjectFilter"; -import { LinkProvider } from "./LinkProvider"; +import { CityObjectFilter } from '../../CityObjects/ViewModel/CityObjectFilter'; +import { LinkProvider } from './LinkProvider'; /** * A filter for city objects based how many documents are linked to them. @@ -10,7 +12,7 @@ import { LinkProvider } from "./LinkProvider"; export class LinkCountFilter extends CityObjectFilter { /** * Instantiates the filter. - * + * * @param {LinkProvider} linkProvider The link provider. */ constructor(linkProvider) { @@ -23,7 +25,7 @@ export class LinkCountFilter extends CityObjectFilter { /** * The link provider - * + * * @type {LinkProvider} */ this.provider = linkProvider; @@ -32,8 +34,8 @@ export class LinkCountFilter extends CityObjectFilter { /** * Accepts city objects that have at least `this.requiredCount` linked * documents. - * - * @param {CityObject} cityObject + * + * @param {CityObject} cityObject */ accepts(cityObject) { let linkCount = this.provider.getLinksFromCityObject(cityObject).length; @@ -56,7 +58,7 @@ export class LinkCountFilter extends CityObjectFilter { export class LinkedWithDisplayedDocumentFilter extends CityObjectFilter { /** * Instantiates the filter. - * + * * @param {LinkProvider} linkProvider The link provider. */ constructor(linkProvider) { @@ -64,7 +66,7 @@ export class LinkedWithDisplayedDocumentFilter extends CityObjectFilter { /** * The link provider. - * + * * @type {LinkProvider} */ this.provider = linkProvider; @@ -72,12 +74,15 @@ export class LinkedWithDisplayedDocumentFilter extends CityObjectFilter { /** * Accepts city objects that are linked with the currently displayed document. - * - * @param {CityObject} cityObject + * + * @param {CityObject} cityObject */ accepts(cityObject) { - let found = this.provider.getDisplayedDocumentLinks().find((link) => - link.target_id == cityObject.props['cityobject.database_id']); + let found = this.provider + .getDisplayedDocumentLinks() + .find( + (link) => link.target_id == cityObject.props['cityobject.database_id'] + ); return !!found; } @@ -93,7 +98,7 @@ export class LinkedWithDisplayedDocumentFilter extends CityObjectFilter { export class LinkedWithFilteredDocumentsFilter extends CityObjectFilter { /** * Instantiates the filter. - * + * * @param {LinkProvider} linkProvider The link provider. */ constructor(linkProvider) { @@ -101,7 +106,7 @@ export class LinkedWithFilteredDocumentsFilter extends CityObjectFilter { /** * The link provider. - * + * * @type {LinkProvider} */ this.provider = linkProvider; @@ -109,16 +114,19 @@ export class LinkedWithFilteredDocumentsFilter extends CityObjectFilter { /** * Accepts city objects that are linked with the currently filtered documents. - * - * @param {CityObject} cityObject + * + * @param {CityObject} cityObject */ accepts(cityObject) { - let found = this.provider.getFilteredDocumentsLinks().find((link) => - link.target_id == cityObject.props['cityobject.database_id']); + let found = this.provider + .getFilteredDocumentsLinks() + .find( + (link) => link.target_id == cityObject.props['cityobject.database_id'] + ); return !!found; } toString() { return 'Linked to the filtered documents'; } -} \ No newline at end of file +} diff --git a/src/Widgets/Links/ViewModel/LinkProvider.js b/src/Widgets/Links/ViewModel/LinkProvider.js index 1a0d86a05..2e684b2c2 100644 --- a/src/Widgets/Links/ViewModel/LinkProvider.js +++ b/src/Widgets/Links/ViewModel/LinkProvider.js @@ -1,16 +1,21 @@ -//Components -import { CityObject } from "../../../Components/3DTiles/Model/CityObject"; -import { EventSender } from "../../../Components/Events/EventSender"; -import { CityObjectStyle } from "../../../Components/3DTiles/Model/CityObjectStyle"; - -import { LinkService } from "../Model/LinkService"; -import { DocumentProvider } from "../../Documents/ViewModel/DocumentProvider"; -import { CityObjectProvider } from "../../CityObjects/ViewModel/CityObjectProvider"; -import { Link } from "../Model/Link"; -import { Document } from "../../Documents/Model/Document"; -import { LinkCountFilter, LinkedWithDisplayedDocumentFilter, LinkedWithFilteredDocumentsFilter } from "./CityObjectLinkFilters"; -import { DocumentFilter } from "../../Documents/ViewModel/DocumentFilter"; +/** @format */ +//Components +import { CityObject } from '../../../Components/3DTiles/Model/CityObject'; +import { EventSender } from '../../../Components/Events/EventSender'; +import { CityObjectStyle } from '../../../Components/3DTiles/Model/CityObjectStyle'; + +import { LinkService } from '../Model/LinkService'; +import { DocumentProvider } from '../../Documents/ViewModel/DocumentProvider'; +import { CityObjectProvider } from '../../CityObjects/ViewModel/CityObjectProvider'; +import { Link } from '../Model/Link'; +import { Document } from '../../Documents/Model/Document'; +import { + LinkCountFilter, + LinkedWithDisplayedDocumentFilter, + LinkedWithFilteredDocumentsFilter, +} from './CityObjectLinkFilters'; +import { DocumentFilter } from '../../Documents/ViewModel/DocumentFilter'; /** * The link provider is responsible to manage links fetched from the server, @@ -21,7 +26,7 @@ import { DocumentFilter } from "../../Documents/ViewModel/DocumentFilter"; export class LinkProvider extends EventSender { /** * Constructs the link provider. - * + * * @param {DocumentProvider} documentProvider The document provider. * @param {CityObjectProvider} cityObjectProvider The city object provider. * @param {LinkService} linkService The link service. @@ -38,28 +43,28 @@ export class LinkProvider extends EventSender { /** * The link service. - * + * * @type {LinkService} */ this.linkService = linkService; /** * The document provider. - * + * * @type {DocumentProvider} */ this.documentProvider = documentProvider; /** * The city object provider. - * + * * @type {CityObjectProvider} */ this.cityObjectProvider = cityObjectProvider; /** * A filter for city objects based on their count of linked documents. - * + * * @type {LinkCountFilter} */ this.linkCountFilter = new LinkCountFilter(this); @@ -68,27 +73,32 @@ export class LinkProvider extends EventSender { /** * A filter for city objects based on wether they are linked with the * currently displayed document. - * + * * @type {LinkedWithDisplayedDocumentFilter} */ - this.linkedWithDisplayedDocFilter = new LinkedWithDisplayedDocumentFilter(this); + this.linkedWithDisplayedDocFilter = new LinkedWithDisplayedDocumentFilter( + this + ); this.cityObjectProvider.addFilter(this.linkedWithDisplayedDocFilter); /** * The style for city objects linked with the displayed document. - * + * * @type {CityObjectStyle} */ - this.linkDisplayedDocumentStyle = config.cityObjects.styles.linkedWithDisplayedDocument; + this.linkDisplayedDocumentStyle = + config.cityObjects.styles.linkedWithDisplayedDocument; /** * A filter for city objects based on wether they are linked with any of the * currently filtered documents (ie. the list of documents that appear in * the navigator). - * + * * @type {LinkedWithFilteredDocumentsFilter} */ - this.linkedWithFilteredDocsFilter = new LinkedWithFilteredDocumentsFilter(this); + this.linkedWithFilteredDocsFilter = new LinkedWithFilteredDocumentsFilter( + this + ); this.cityObjectProvider.addFilter(this.linkedWithFilteredDocsFilter); // The following adds a filter for documents, based on wether they are @@ -98,58 +108,62 @@ export class LinkProvider extends EventSender { * This value determines wether the filter is active. */ this.shouldFilterLinkedDocuments = false; - this.documentProvider.addFilter(new DocumentFilter((doc) => { - return !this.shouldFilterLinkedDocuments || - this.selectedCityObjectLinks.find(link => link.source_id === doc.id); - })); + this.documentProvider.addFilter( + new DocumentFilter((doc) => { + return ( + !this.shouldFilterLinkedDocuments || + this.selectedCityObjectLinks.find((link) => link.source_id === doc.id) + ); + }) + ); this.documentProvider.refreshDocumentList(); /** * The cached list of links. - * + * * @type {Array} */ this.links = []; /** * The currently displayed document. - * + * * @type {Document} */ this.displayedDocument = undefined; /** * The links of the currently displayed document. - * + * * @type {Array} */ this.displayedDocumentLinks = []; /** * The list of filtered documents. - * + * * @type {Array} */ this.filteredDocuments = []; /** * The links of the filtered documents. - * + * * @type {Array} */ this.filteredDocumentsLinks = []; /** * The currently selected city object. - * + * * @type {CityObject} */ this.selectedCityObject = undefined; /** * The links of the currently selected city object. - * + * * @type {Array} */ this.selectedCityObjectLinks = []; @@ -160,21 +174,27 @@ export class LinkProvider extends EventSender { this.registerEvent(DocumentProvider.EVENT_FILTERED_DOCS_UPDATED); this.registerEvent(CityObjectProvider.EVENT_CITY_OBJECT_SELECTED); - this.documentProvider.addEventListener(DocumentProvider.EVENT_DISPLAYED_DOC_CHANGED, - (doc) => this._onDisplayedDocumentChange(doc)); + this.documentProvider.addEventListener( + DocumentProvider.EVENT_DISPLAYED_DOC_CHANGED, + (doc) => this._onDisplayedDocumentChange(doc) + ); - this.documentProvider.addEventListener(DocumentProvider.EVENT_FILTERED_DOCS_UPDATED, - (docs) => this._onFilteredDocumentsUpdate(docs)); + this.documentProvider.addEventListener( + DocumentProvider.EVENT_FILTERED_DOCS_UPDATED, + (docs) => this._onFilteredDocumentsUpdate(docs) + ); - this.cityObjectProvider.addEventListener(CityObjectProvider.EVENT_CITY_OBJECT_SELECTED, - (co) => this._onCityObjectSelection(co)); + this.cityObjectProvider.addEventListener( + CityObjectProvider.EVENT_CITY_OBJECT_SELECTED, + (co) => this._onCityObjectSelection(co) + ); } /** * Triggers when the displayed document changed. Updates the displayed * document reference in the link provider and re-applies the styles for the * city objects. The event is propagated. - * + * * @param {Document} doc The newly displayed document. */ _onDisplayedDocumentChange(doc) { @@ -188,7 +208,7 @@ export class LinkProvider extends EventSender { * Triggers when the filtered documents change. Updates the filtered document * and their links in the provider, and re-applies the styles for the city * objects. The event is propagated. - * + * * @param {Array} docs The newly filtered documents. */ _onFilteredDocumentsUpdate(docs) { @@ -202,7 +222,7 @@ export class LinkProvider extends EventSender { * Triggers when a city object is selected. Updates the city object and its * links in the provider, and refreshes the list of documents. The event is * propagated. - * + * * @param {CityObject} co The newly selected city object. */ _onCityObjectSelection(co) { @@ -216,7 +236,7 @@ export class LinkProvider extends EventSender { /** * Fetches the links from the server. - * + * * @async */ async fetchLinks() { @@ -228,7 +248,7 @@ export class LinkProvider extends EventSender { /** * Deletes the link. - * + * * @async * @param {Link} link The link to delete. */ @@ -239,7 +259,7 @@ export class LinkProvider extends EventSender { /** * Creates a new link. - * + * * @param {Link} link The link to create. */ async createLink(link) { @@ -255,7 +275,7 @@ export class LinkProvider extends EventSender { /** * Returns the cached list of links. - * + * * @returns {Array} The cached list of links. */ getLinks() { @@ -264,27 +284,29 @@ export class LinkProvider extends EventSender { /** * Returns the links from a list of documents. - * + * * @param {Array} docs A list of documents. */ getLinksFromDocuments(docs) { - return this.links.filter((link) => - docs.find((doc) => doc.id == link.source_id) !== undefined); + return this.links.filter( + (link) => docs.find((doc) => doc.id == link.source_id) !== undefined + ); } /** * Returns the links from a city object. - * + * * @param {CityObject} cityObject The city object. */ getLinksFromCityObject(cityObject) { - return this.links.filter((link) => - link.target_id == cityObject.props['cityobject.database_id']); + return this.links.filter( + (link) => link.target_id == cityObject.props['cityobject.database_id'] + ); } /** * Returns the links from the displayed document. - * + * * @returns {Array} The list of links. */ getDisplayedDocumentLinks() { @@ -293,7 +315,7 @@ export class LinkProvider extends EventSender { /** * Returns the links from the filtered documents. - * + * * @returns {Array} The list of links. */ getFilteredDocumentsLinks() { @@ -302,7 +324,7 @@ export class LinkProvider extends EventSender { /** * Returns the links from the selected city object. - * + * * @returns {Array} The list of links. */ getSelectedCityObjectLinks() { @@ -311,19 +333,21 @@ export class LinkProvider extends EventSender { /** * Returns the list of documents linked to the selected city object. - * + * * @returns {Array} The list of linked documents. */ getSelectedCityObjectLinkedDocuments() { let allDocuments = this.documentProvider.getAllDocuments().slice(); - let docIdsToFind = this.selectedCityObjectLinks.map(link => link.source_id); - return allDocuments.filter(doc => docIdsToFind.includes(doc.id)); + let docIdsToFind = this.selectedCityObjectLinks.map( + (link) => link.source_id + ); + return allDocuments.filter((doc) => docIdsToFind.includes(doc.id)); } /** * Toggles the filter for the documents, based on wether they are linked with * the selected city object. - * + * * @param {Boolean} [toggle] The desired value (`true` activates the filter). * If not specified, the activation state of the filter is simply negated (ie. * if the filter was active, it is now inactive and vice-versa) @@ -340,13 +364,18 @@ export class LinkProvider extends EventSender { * Filters the city objects that are linked with the displayed document. */ highlightDisplayedDocumentLinks() { - this.cityObjectProvider.setLayer('linkDisplayedDoc', this.linkDisplayedDocumentStyle); + this.cityObjectProvider.setLayer( + 'linkDisplayedDoc', + this.linkDisplayedDocumentStyle + ); } /** * Filters the city objects that are linked with the filtered document. */ highlightFilteredDocumentsLinks() { - this.cityObjectProvider.setLayer('linkFilteredDocs', {materialProps: {color: 'blue'}}); + this.cityObjectProvider.setLayer('linkFilteredDocs', { + materialProps: { color: 'blue' }, + }); } -} \ No newline at end of file +} diff --git a/src/Widgets/Others/About.css b/src/Widgets/Others/About.css index f145d65e8..c9d65097b 100644 --- a/src/Widgets/Others/About.css +++ b/src/Widgets/Others/About.css @@ -1,30 +1,31 @@ +/** @format */ #aboutWindow { - position: absolute; - z-index: 11; - top: 10px; - width: 15%; - right : 22.5%; - color: white; - font-size: 75%; - padding: 0 1rem; - background-color: rgba(30,30,30,0.6); - border : 1px solid rgb(90,90,90); - pointer-events: auto; + position: absolute; + z-index: 11; + top: 10px; + width: 15%; + right: 22.5%; + color: white; + font-size: 75%; + padding: 0 1rem; + background-color: rgba(30, 30, 30, 0.6); + border: 1px solid rgb(90, 90, 90); + pointer-events: auto; } #aboutWindow > div > ul { - padding-left: 5px; + padding-left: 5px; } -#aboutCloseButton{ - position: absolute; - z-index: 40; - top: 0; - right: 3px; - margin : 3px; - border: 1px solid black; - background-color: white; - color: black; - pointer-events: auto; +#aboutCloseButton { + position: absolute; + z-index: 40; + top: 0; + right: 3px; + margin: 3px; + border: 1px solid black; + background-color: white; + color: black; + pointer-events: auto; } diff --git a/src/Widgets/Others/About.js b/src/Widgets/Others/About.js index fbb0be41b..265323ec4 100644 --- a/src/Widgets/Others/About.js +++ b/src/Widgets/Others/About.js @@ -1,3 +1,5 @@ +/** @format */ + //Components import { ModuleView } from '../../Components/ModuleView/ModuleView'; @@ -8,17 +10,16 @@ import './About.css'; * simply include this file in the html, no need to instanciate anything in main.js */ export class AboutWindow extends ModuleView { + constructor() { + super(); + // Create DOM element + let aboutDiv = document.createElement('div'); + aboutDiv.id = 'aboutWindow'; + document.getElementById('contentSection').append(aboutDiv); - constructor(options = {}) { - super(); - // Create DOM element - let aboutDiv = document.createElement("div"); - aboutDiv.id = 'aboutWindow'; - document.getElementById('contentSection').append(aboutDiv); - - // Create HMTL - document.getElementById("aboutWindow").innerHTML = - '
    \ + // Create HMTL + document.getElementById('aboutWindow').innerHTML = + '
    \
    \

    This UD-Viz-Core demo is part of the \ \

  • iTowns
  • \
  • Lyon Métropole Open\ Data
  • \ + href="https://data.grandlyon.com">Lyon Métropole Open Data\
\

\

Legal and operational disclaimer: This demonstration\ @@ -75,19 +76,24 @@ export class AboutWindow extends ModuleView { \ '; - // Close the window...when close button is hit - document.getElementById("aboutCloseButton").addEventListener( - 'mousedown', () => { - this.disable(); - }, false); - } + // Close the window...when close button is hit + document.getElementById('aboutCloseButton').addEventListener( + 'mousedown', + () => { + this.disable(); + }, + false + ); + } - /////// MODULE VIEW MANAGEMENT - enableView() { - document.getElementById('aboutWindow').style.setProperty('display', 'block'); - } + /////// MODULE VIEW MANAGEMENT + enableView() { + document + .getElementById('aboutWindow') + .style.setProperty('display', 'block'); + } - disableView() { - document.getElementById('aboutWindow').style.setProperty('display', 'none'); - } + disableView() { + document.getElementById('aboutWindow').style.setProperty('display', 'none'); + } } diff --git a/src/Widgets/Others/Help.css b/src/Widgets/Others/Help.css index 0c84fa91a..01d0f5fa7 100644 --- a/src/Widgets/Others/Help.css +++ b/src/Widgets/Others/Help.css @@ -1,39 +1,41 @@ +/** @format */ + #helpWindow { - position: absolute; - z-index: 10; - width: 15%; - top: 10px; - left : 22.5%; - color: white; - font-size: 75%; - padding: 0 1rem; - background-color: rgba(30,30,30,0.6); - border : 1px solid rgb(90,90,90); - pointer-events: auto; + position: absolute; + z-index: 10; + width: 15%; + top: 10px; + left: 22.5%; + color: white; + font-size: 75%; + padding: 0 1rem; + background-color: rgba(30, 30, 30, 0.6); + border: 1px solid rgb(90, 90, 90); + pointer-events: auto; } #helpWindow > div > ul { - padding-left: 5px; + padding-left: 5px; } -#helpCloseButton{ - position: absolute; - z-index: 40; - top: 0; - right: 3px; - margin : 3px; - border: 1px solid black; - background-color: white; - color: black; - pointer-events: auto; +#helpCloseButton { + position: absolute; + z-index: 40; + top: 0; + right: 3px; + margin: 3px; + border: 1px solid black; + background-color: white; + color: black; + pointer-events: auto; } @media (max-width: 600px) { - #helpWindow { - display: none; - } + #helpWindow { + display: none; + } } hr { - color: white; + color: white; } diff --git a/src/Widgets/Others/Help.js b/src/Widgets/Others/Help.js index 729416bfa..3abf14592 100644 --- a/src/Widgets/Others/Help.js +++ b/src/Widgets/Others/Help.js @@ -1,24 +1,25 @@ +/** @format */ + //Components import { ModuleView } from '../../Components/ModuleView/ModuleView'; import './Help.css'; /** -* adds a "Help" window that can be open/closed with a button -* simply include this file in the html, no need to instanciate anything in main.js -*/ + * adds a "Help" window that can be open/closed with a button + * simply include this file in the html, no need to instanciate anything in main.js + */ export class HelpWindow extends ModuleView { - - constructor(options = {}) { + constructor() { super(); ///////////// Html elements - var helpDiv = document.createElement("div"); + var helpDiv = document.createElement('div'); helpDiv.id = 'helpWindow'; document.getElementById('contentSection').append(helpDiv); - document.getElementById("helpWindow").innerHTML = + document.getElementById('helpWindow').innerHTML = '

\
\

{ + document.getElementById('helpCloseButton').addEventListener( + 'mousedown', + () => { this.disable(); - }, false); + }, + false + ); } - /////// MODULE VIEW METHODS enableView() { diff --git a/src/Widgets/Temporal/Model/3DTemporalBatchTable.js b/src/Widgets/Temporal/Model/3DTemporalBatchTable.js index 57aa025ae..f965e8024 100644 --- a/src/Widgets/Temporal/Model/3DTemporalBatchTable.js +++ b/src/Widgets/Temporal/Model/3DTemporalBatchTable.js @@ -1,70 +1,90 @@ /** * Implements the batch table of the 3DTILES_temporal - * extension. See the spec in + * extension. See the spec in * ./jsonSchemas/3DTILES_temporal.batchTable.schema.json + * + * @format */ + export class $3DTemporalBatchTable { - /** - * Verifies the integrity and stores the data corresponding to the - * batch table part of the 3DTiles_temporal extension. - * @param {Object} json The json containing the 3DTiles_temporal - * extension batch table part for a given tile. - */ - constructor(json) { - // Poor verification that the handled json corresponds to the temporal - // extension spec. Should be done by comparing it with the JSON schema. - if (!json.startDates || !Array.isArray(json.startDates)) { - console.error("3D Tiles batch table temporal extension requires " + - "a startDates array. Refer to the spec."); - } - if (!json.endDates || !Array.isArray(json.endDates)) { - console.error("3D Tiles batch table temporal extension requires " + - "an endDates array. Refer to the spec."); - } - if (!json.featureIds || !Array.isArray(json.featureIds)) { - console.error("3D Tiles batch table temporal extension requires " + - "a featureIds array. Refer to the spec."); - } - if (json.startDates.length !== json.endDates.length || - json.startDates.length !== json.featureIds.length) { - console.error("3D Tiles temporal extensions arrays startDates " + - "(length: " + json.startDates.length + "), endDates (length: " + - json.endDates.length + ") and json.featureIds (length: " + - json.featureIds.length + ") must be the same length."); - } - - this.startDates = json.startDates; - this.endDates = json.endDates; - this.featureIds = json.featureIds; + /** + * Verifies the integrity and stores the data corresponding to the + * batch table part of the 3DTiles_temporal extension. + * @param {Object} json The json containing the 3DTiles_temporal + * extension batch table part for a given tile. + */ + constructor(json) { + // Poor verification that the handled json corresponds to the temporal + // extension spec. Should be done by comparing it with the JSON schema. + if (!json.startDates || !Array.isArray(json.startDates)) { + console.error( + '3D Tiles batch table temporal extension requires ' + + 'a startDates array. Refer to the spec.' + ); } - - /** - * Checks that the batch table temporal extension has values for a given - * identifier. - * @param {Number} batchId The identifier to check (identifier in the batch, - * i.e. position in the arrays). - */ - hasInfoForId(batchId) { - // The constructor ensures that the three arrays have the same size. - return !!this.startDates[batchId]; + if (!json.endDates || !Array.isArray(json.endDates)) { + console.error( + '3D Tiles batch table temporal extension requires ' + + 'an endDates array. Refer to the spec.' + ); + } + if (!json.featureIds || !Array.isArray(json.featureIds)) { + console.error( + '3D Tiles batch table temporal extension requires ' + + 'a featureIds array. Refer to the spec.' + ); } + if ( + json.startDates.length !== json.endDates.length || + json.startDates.length !== json.featureIds.length + ) { + console.error( + '3D Tiles temporal extensions arrays startDates ' + + '(length: ' + + json.startDates.length + + '), endDates (length: ' + + json.endDates.length + + ') and json.featureIds (length: ' + + json.featureIds.length + + ') must be the same length.' + ); + } + + this.startDates = json.startDates; + this.endDates = json.endDates; + this.featureIds = json.featureIds; + } + + /** + * Checks that the batch table temporal extension has values for a given + * identifier. + * @param {Number} batchId The identifier to check (identifier in the batch, + * i.e. position in the arrays). + */ + hasInfoForId(batchId) { + // The constructor ensures that the three arrays have the same size. + return !!this.startDates[batchId]; + } - /** - * Returns information for the given batchId. - * Can be used to display information associated with an object - * picked with the mouse for instance. - * @param {*} batchId The given identifier (identifier in the batch, - * i.e. position in the arrays). - */ - getInfoById(batchId) { - if (!this.hasInfoForId(batchId)) { - console.error("3D Tiles batch table temporal extension does not " + - "have information for batch ID " + batchId); - } - return { - 'featureId': this.featureIds[batchId], - 'startDate': this.startDates[batchId], - 'endDate': this.endDates[batchId] - }; + /** + * Returns information for the given batchId. + * Can be used to display information associated with an object + * picked with the mouse for instance. + * @param {*} batchId The given identifier (identifier in the batch, + * i.e. position in the arrays). + */ + getInfoById(batchId) { + if (!this.hasInfoForId(batchId)) { + console.error( + '3D Tiles batch table temporal extension does not ' + + 'have information for batch ID ' + + batchId + ); } -} \ No newline at end of file + return { + featureId: this.featureIds[batchId], + startDate: this.startDates[batchId], + endDate: this.endDates[batchId], + }; + } +} diff --git a/src/Widgets/Temporal/Model/3DTemporalBoundingVolume.js b/src/Widgets/Temporal/Model/3DTemporalBoundingVolume.js index a5d518c95..8b3c770a4 100644 --- a/src/Widgets/Temporal/Model/3DTemporalBoundingVolume.js +++ b/src/Widgets/Temporal/Model/3DTemporalBoundingVolume.js @@ -1,25 +1,32 @@ /** * Implements the bounding volume part of the 3DTILES_temporal - * extension. See the spec in + * extension. See the spec in * ./jsonSchemas/3DTILES_temporal.boundingVolume.schema.json + * + * @format */ + export class $3DTemporalBoundingVolume { - /** - * Verifies the integrity and stores the data corresponding to the - * bounding volume part of the 3DTiles_temporal extension. - * @param {Object} json The json containing the 3DTiles_temporal - * extension bounding volume part for a given tile. - */ - constructor(json) { - if (!json.startDate) { - console.error("3D Tiles bounding volume temporal extension " + - "requires a startDate. Refer to the spec."); - } - if (!json.endDate) { - console.error("3D Tiles bounding volume temporal extension " + - "requires an endDate. Refer to the spec."); - } - this.startDate = json.startDate; - this.endDate = json.endDate; + /** + * Verifies the integrity and stores the data corresponding to the + * bounding volume part of the 3DTiles_temporal extension. + * @param {Object} json The json containing the 3DTiles_temporal + * extension bounding volume part for a given tile. + */ + constructor(json) { + if (!json.startDate) { + console.error( + '3D Tiles bounding volume temporal extension ' + + 'requires a startDate. Refer to the spec.' + ); } + if (!json.endDate) { + console.error( + '3D Tiles bounding volume temporal extension ' + + 'requires an endDate. Refer to the spec.' + ); + } + this.startDate = json.startDate; + this.endDate = json.endDate; + } } diff --git a/src/Widgets/Temporal/Model/3DTemporalExtension.js b/src/Widgets/Temporal/Model/3DTemporalExtension.js index 5f22b94f6..f73fb46a5 100644 --- a/src/Widgets/Temporal/Model/3DTemporalExtension.js +++ b/src/Widgets/Temporal/Model/3DTemporalExtension.js @@ -1,135 +1,149 @@ +/** @format */ + import { $3DTemporalTileset } from './3DTemporalTileset.js'; /** - * Entrypoint of the temporal module model. + * Entrypoint of the temporal module model. * Stores all parts of the 3D Tiles temporal extension model */ export class $3DTemporalExtension { - constructor() { - this.extensionName = "3DTILES_temporal"; + constructor() { + this.extensionName = '3DTILES_temporal'; - /** - * A map with feature IDs as keys and transactions of these features - * as value. - */ - this.transactionsPerFeature = new Map(); + /** + * A map with feature IDs as keys and transactions of these features + * as value. + */ + this.transactionsPerFeature = new Map(); - /** - * A map of map with transactions as values and organized - * per tiles and per features. This structure is used for - * optimizing the temporal culling (to decide which features - * should be displayed and with which style depending on the time, - * see TemporalProvider.js for more information). It is structured - * as follows: - * { tileId : featureID : { - * asSource: transaction; - * asDestination: transaction; - * } - * } - * Note that currently only the first transaction where the feature - * is a source or where the feature is a destination is kept. - * NORMALLY a feature shouldn't be the source (reps. the - * destination) of multiple transaction, since in this case one - * should create aggregates. Otherwise it might represent - * concurrent evolutions which are not managed in this - * implementation. However, in practical terms there is cases where - * a feature is the source (resp. destination) of multiple - * transactions. These cases might need to be investigated in more - * depth.... - * @type {Map} - */ - this.transactionsPerTile = new Map(); + /** + * A map of map with transactions as values and organized + * per tiles and per features. This structure is used for + * optimizing the temporal culling (to decide which features + * should be displayed and with which style depending on the time, + * see TemporalProvider.js for more information). It is structured + * as follows: + * { tileId : featureID : { + * asSource: transaction; + * asDestination: transaction; + * } + * } + * Note that currently only the first transaction where the feature + * is a source or where the feature is a destination is kept. + * NORMALLY a feature shouldn't be the source (reps. the + * destination) of multiple transaction, since in this case one + * should create aggregates. Otherwise it might represent + * concurrent evolutions which are not managed in this + * implementation. However, in practical terms there is cases where + * a feature is the source (resp. destination) of multiple + * transactions. These cases might need to be investigated in more + * depth.... + * @type {Map} + */ + this.transactionsPerTile = new Map(); - /** - * The temporal extension part of the batch tables mapped to the tile - * IDs (keys of the map). - */ - this.temporalBatchTables = new Map(); + /** + * The temporal extension part of the batch tables mapped to the tile + * IDs (keys of the map). + */ + this.temporalBatchTables = new Map(); - /** - * The temporal extension part of the bounding volumes part mapped to - * the tile IDs (keys of the map). - */ - this.temporalBoundingVolumes = new Map(); + /** + * The temporal extension part of the bounding volumes part mapped to + * the tile IDs (keys of the map). + */ + this.temporalBoundingVolumes = new Map(); - // Events - // $3DTemporalTileset triggers an event when it is loaded - window.addEventListener( - $3DTemporalTileset.TEMPORAL_TILESET_LOADED, - this.temporalTilesetLoaded.bind(this)); + // Events + // $3DTemporalTileset triggers an event when it is loaded + window.addEventListener( + $3DTemporalTileset.TEMPORAL_TILESET_LOADED, + this.temporalTilesetLoaded.bind(this) + ); - // Another strategy is used for the batch table part and - // for the bounding volume part of the temporal extension - // since we need to know to which tile this batch table - // extension belongs to (that is not stored in the batch - // table extension part). Therefore, we use the - // TilesManager.EVENT_TILE_LOADED instead which is fired - // by the 3D Tiles itowns layer when a tile has been - // loaded. To avoid creating a dependency between this class - // and the tilesManager, we add this event listener in the - // TemporalCntroler which knows both this model and the tilesManager. - // This is not ideal but improving this would asks for more - // modifications in itowns, which is currently not possible. - } + // Another strategy is used for the batch table part and + // for the bounding volume part of the temporal extension + // since we need to know to which tile this batch table + // extension belongs to (that is not stored in the batch + // table extension part). Therefore, we use the + // TilesManager.EVENT_TILE_LOADED instead which is fired + // by the 3D Tiles itowns layer when a tile has been + // loaded. To avoid creating a dependency between this class + // and the tilesManager, we add this event listener in the + // TemporalCntroler which knows both this model and the tilesManager. + // This is not ideal but improving this would asks for more + // modifications in itowns, which is currently not possible. + } - /** - * Fills this.transactionsPerFeature map when the tileset has been loaded - * (all transactions are stored in the temporal extension part of the - * tileset). - * @param {*} event The evet triggered; holds the temporal part of the - * extension in event.detail - */ - temporalTilesetLoaded(event) { - const allTransactions = event.detail.temporalTileset.transactions; + /** + * Fills this.transactionsPerFeature map when the tileset has been loaded + * (all transactions are stored in the temporal extension part of the + * tileset). + * @param {*} event The evet triggered; holds the temporal part of the + * extension in event.detail + */ + temporalTilesetLoaded(event) { + const allTransactions = event.detail.temporalTileset.transactions; - for (let i = 0; i < allTransactions.length; i++) { - const transaction = allTransactions[i]; - for (let j = 0; j < transaction.source.length; j++) { - const source = transaction.source[j]; - if (this.transactionsPerFeature.get(source) === undefined) { - this.transactionsPerFeature.set(source, {}); - } - if (this.transactionsPerFeature.get(source).asSource === - undefined) { - this.transactionsPerFeature.get(source).asSource = - transaction; - } - } - for (let j = 0; j < transaction.destination.length; j++) { - const destination = transaction.destination[j]; - if (this.transactionsPerFeature.get(destination) === undefined) { - this.transactionsPerFeature.set(destination, {}); - } - if (this.transactionsPerFeature.get(destination).asDestination === - undefined) { - this.transactionsPerFeature.get(destination).asDestination = - transaction; - } - } + for (let i = 0; i < allTransactions.length; i++) { + const transaction = allTransactions[i]; + for (let j = 0; j < transaction.source.length; j++) { + const source = transaction.source[j]; + if (this.transactionsPerFeature.get(source) === undefined) { + this.transactionsPerFeature.set(source, {}); + } + if (this.transactionsPerFeature.get(source).asSource === undefined) { + this.transactionsPerFeature.get(source).asSource = transaction; + } + } + for (let j = 0; j < transaction.destination.length; j++) { + const destination = transaction.destination[j]; + if (this.transactionsPerFeature.get(destination) === undefined) { + this.transactionsPerFeature.set(destination, {}); } + if ( + this.transactionsPerFeature.get(destination).asDestination === + undefined + ) { + this.transactionsPerFeature.get(destination).asDestination = + transaction; + } + } } + } - /** - * Triggered when the content of a tile has been loaded. Fills - * this.transactionsPerTile list with the transaction of this tile. - * @param {*} tileContent - */ - updateTileExtensionModel(tileContent) { - this.temporalBoundingVolumes.set(tileContent.tileId, - tileContent.boundingVolume.extensions[this.extensionName]); + /** + * Triggered when the content of a tile has been loaded. Fills + * this.transactionsPerTile list with the transaction of this tile. + * @param {*} tileContent + */ + updateTileExtensionModel(tileContent) { + this.temporalBoundingVolumes.set( + tileContent.tileId, + tileContent.boundingVolume.extensions[this.extensionName] + ); - // The batch table is not mandatory (e.g. the root tile - // has no batch table) - if (tileContent.batchTable) { - this.temporalBatchTables.set(tileContent.tileId, - tileContent.batchTable.extensions[this.extensionName]); - if (! this.transactionsPerTile.has(tileContent.tileId)) { - this.transactionsPerTile.set(tileContent.tileId, new Map()); - } - for (let i = 0; i < this.temporalBatchTables.get(tileContent.tileId).featureIds.length; i++) { - const featureId = this.temporalBatchTables.get(tileContent.tileId).featureIds[i]; - this.transactionsPerTile.get(tileContent.tileId).set(featureId, this.transactionsPerFeature.get(featureId)); - } - } + // The batch table is not mandatory (e.g. the root tile + // has no batch table) + if (tileContent.batchTable) { + this.temporalBatchTables.set( + tileContent.tileId, + tileContent.batchTable.extensions[this.extensionName] + ); + if (!this.transactionsPerTile.has(tileContent.tileId)) { + this.transactionsPerTile.set(tileContent.tileId, new Map()); + } + for ( + let i = 0; + i < this.temporalBatchTables.get(tileContent.tileId).featureIds.length; + i++ + ) { + const featureId = this.temporalBatchTables.get(tileContent.tileId) + .featureIds[i]; + this.transactionsPerTile + .get(tileContent.tileId) + .set(featureId, this.transactionsPerFeature.get(featureId)); + } } + } } diff --git a/src/Widgets/Temporal/Model/3DTemporalPrimaryTransaction.js b/src/Widgets/Temporal/Model/3DTemporalPrimaryTransaction.js index 031ae35e2..2ff3a2d84 100644 --- a/src/Widgets/Temporal/Model/3DTemporalPrimaryTransaction.js +++ b/src/Widgets/Temporal/Model/3DTemporalPrimaryTransaction.js @@ -1,17 +1,19 @@ +/** @format */ + import { $3DTemporalTransaction } from './3DTemporalTransaction.js'; /** * Implements the primary transaction of the 3DTILES_temporal - * extension. See the spec in + * extension. See the spec in * ./jsonSchemas/3DTILES_temporal.primaryTransaction.schema.json */ export class $3DTemporalPrimaryTransaction extends $3DTemporalTransaction { - constructor(json) { - super(json); + constructor(json) { + super(json); - this.type = json.type; - // type testing is not reliable in javascript therefore we have to use - // booleans to do so... - this.isPrimary = true; - } + this.type = json.type; + // type testing is not reliable in javascript therefore we have to use + // booleans to do so... + this.isPrimary = true; + } } diff --git a/src/Widgets/Temporal/Model/3DTemporalTileset.js b/src/Widgets/Temporal/Model/3DTemporalTileset.js index 9dc6a31be..1f56a395b 100644 --- a/src/Widgets/Temporal/Model/3DTemporalTileset.js +++ b/src/Widgets/Temporal/Model/3DTemporalTileset.js @@ -1,53 +1,59 @@ +/** @format */ + import { $3DTemporalPrimaryTransaction } from '../Model/3DTemporalPrimaryTransaction.js'; import { $3DTemporalTransactionAggregate } from '../Model/3DTemporalTransactionAggregate.js'; import { $3DTemporalVersion } from './3DTemporalVersion.js'; /** * Implements the tileset part of the 3DTILES_temporal - * extension. See the spec in + * extension. See the spec in * ./jsonSchemas/3DTILES_temporal.tileset.schema.json */ export class $3DTemporalTileset { - constructor(json) { - this.startDate = json.startDate; - this.endDate = json.endDate; + constructor(json) { + this.startDate = json.startDate; + this.endDate = json.endDate; - this.transactions = []; - // Fill this.transactions - this.parseTransactions(json.transactions); + this.transactions = []; + // Fill this.transactions + this.parseTransactions(json.transactions); - this.temporalVersions = new $3DTemporalVersion(json.versions); - this.versionTransitions = json.versionTransitions; - - // Trapped by 3DTemporalExtension.js that stores this instance of - // $3DTemporalTileset - window.dispatchEvent(new CustomEvent( - $3DTemporalTileset.TEMPORAL_TILESET_LOADED, - {detail: { temporalTileset: this}})); - } + this.temporalVersions = new $3DTemporalVersion(json.versions); + this.versionTransitions = json.versionTransitions; - /** - * Parses transactions from a json file and creates primary and aggregated - * transactions. - * @param {Object} transactions The json holding the transactions. - */ - parseTransactions(transactions) { - for (let i = 0; i < transactions.length; i++) { - let parsedTransac; - if (transactions[i].type) { - // Transactions aggregates don't have a type attribute - parsedTransac = new $3DTemporalPrimaryTransaction(transactions[i]); - } else if (transactions[i].transactions) { - // Primary transactions don't have a transactions attribute - parsedTransac = new $3DTemporalTransactionAggregate(transactions[i]); - // Recursively parse the aggregated transactions. - parsedTransac.transactions = this.parseTransactions(transactions[i].transactions); - } - this.transactions.push(parsedTransac); - } - } + // Trapped by 3DTemporalExtension.js that stores this instance of + // $3DTemporalTileset + window.dispatchEvent( + new CustomEvent($3DTemporalTileset.TEMPORAL_TILESET_LOADED, { + detail: { temporalTileset: this }, + }) + ); + } - static get TEMPORAL_TILESET_LOADED() { - return 'TEMPORAL_TILESET_LOADED'; + /** + * Parses transactions from a json file and creates primary and aggregated + * transactions. + * @param {Object} transactions The json holding the transactions. + */ + parseTransactions(transactions) { + for (let i = 0; i < transactions.length; i++) { + let parsedTransac; + if (transactions[i].type) { + // Transactions aggregates don't have a type attribute + parsedTransac = new $3DTemporalPrimaryTransaction(transactions[i]); + } else if (transactions[i].transactions) { + // Primary transactions don't have a transactions attribute + parsedTransac = new $3DTemporalTransactionAggregate(transactions[i]); + // Recursively parse the aggregated transactions. + parsedTransac.transactions = this.parseTransactions( + transactions[i].transactions + ); } + this.transactions.push(parsedTransac); + } + } + + static get TEMPORAL_TILESET_LOADED() { + return 'TEMPORAL_TILESET_LOADED'; + } } diff --git a/src/Widgets/Temporal/Model/3DTemporalTransaction.js b/src/Widgets/Temporal/Model/3DTemporalTransaction.js index 406a42dec..8f092e0c4 100644 --- a/src/Widgets/Temporal/Model/3DTemporalTransaction.js +++ b/src/Widgets/Temporal/Model/3DTemporalTransaction.js @@ -1,15 +1,18 @@ /** * Implements the transaction concept of the 3DTILES_temporal - * extension. See the spec in + * extension. See the spec in * ./jsonSchemas/3DTILES_temporal.transaction.schema.json + * + * @format */ + export class $3DTemporalTransaction { - constructor(json) { - this.id = json.id; - this.startDate = json.startDate; - this.endDate = json.endDate; - this.source = json.source; - this.destination = json.destination; - this.tags = json.tags; - } + constructor(json) { + this.id = json.id; + this.startDate = json.startDate; + this.endDate = json.endDate; + this.source = json.source; + this.destination = json.destination; + this.tags = json.tags; + } } diff --git a/src/Widgets/Temporal/Model/3DTemporalTransactionAggregate.js b/src/Widgets/Temporal/Model/3DTemporalTransactionAggregate.js index eabcafd93..15af7d1c0 100644 --- a/src/Widgets/Temporal/Model/3DTemporalTransactionAggregate.js +++ b/src/Widgets/Temporal/Model/3DTemporalTransactionAggregate.js @@ -1,17 +1,19 @@ +/** @format */ + import { $3DTemporalTransaction } from './3DTemporalTransaction.js'; /** * Implements the aggregated transaction of the 3DTILES_temporal - * extension. See the spec in + * extension. See the spec in * ./jsonSchemas/3DTILES_temporal.transactionAggregate.schema.json */ export class $3DTemporalTransactionAggregate extends $3DTemporalTransaction { - constructor(json) { - super(json); + constructor(json) { + super(json); - this.transactions = {}; - // type testing is not reliable in javascript therefore we have to use - // booleans to do so... - this.isAggregate = true; - } + this.transactions = {}; + // type testing is not reliable in javascript therefore we have to use + // booleans to do so... + this.isAggregate = true; + } } diff --git a/src/Widgets/Temporal/Model/3DTemporalVersion.js b/src/Widgets/Temporal/Model/3DTemporalVersion.js index 814f1bf58..ead41e705 100644 --- a/src/Widgets/Temporal/Model/3DTemporalVersion.js +++ b/src/Widgets/Temporal/Model/3DTemporalVersion.js @@ -1,17 +1,20 @@ /** * Implements the version concept of the 3DTILES_temporal - * extension. See the spec in + * extension. See the spec in * ./jsonSchemas/3DTILES_temporal.version.schema.json + * + * @format */ + export class $3DTemporalVersion { - constructor(json) { - this.versions = json; - for (let i = 0; i < json.length; i++) { - // Add the fields missing for the graph window - this.versions[i].label = json[i].name; - this.versions[i].level = i; - this.versions[i].group = "consensusScenario"; // Needs to be changed if one wants multiple scenario - this.versions[i].title = json[i].description; - } - } -} \ No newline at end of file + constructor(json) { + this.versions = json; + for (let i = 0; i < json.length; i++) { + // Add the fields missing for the graph window + this.versions[i].label = json[i].name; + this.versions[i].level = i; + this.versions[i].group = 'consensusScenario'; // Needs to be changed if one wants multiple scenario + this.versions[i].title = json[i].description; + } + } +} diff --git a/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.batchTable.schema.json b/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.batchTable.schema.json index 307593267..8fa357703 100644 --- a/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.batchTable.schema.json +++ b/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.batchTable.schema.json @@ -24,7 +24,7 @@ "featuresIds": { "description": "Array of ids of the features. Used in versions and transactions to identify the features.", "type": "array", - "items": {"type": "string"} + "items": { "type": "string" } } } } diff --git a/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.primaryTransaction.json b/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.primaryTransaction.json index 7a1864eef..eac1b5377 100644 --- a/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.primaryTransaction.json +++ b/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.primaryTransaction.json @@ -3,15 +3,24 @@ "id": "3DTILES_temporal.primaryTransaction.schema.json", "title": "3DTILES_temporal_primaryTransaction extension", "type": "object", - "allOf" : [{ - "$ref" : "3DTILES_temporal.transaction.schema.json" - }, { - "properties" : { + "allOf": [ + { + "$ref": "3DTILES_temporal.transaction.schema.json" + }, + { + "properties": { "type": { "description": "Type of transaction", "type": "string", - "enum": ["creation", "demolition", "modification", "union", "division"] + "enum": [ + "creation", + "demolition", + "modification", + "union", + "division" + ] } } - }] + } + ] } diff --git a/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.tileset.schema.json b/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.tileset.schema.json index 2fb94c330..7b56a644c 100644 --- a/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.tileset.schema.json +++ b/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.tileset.schema.json @@ -18,20 +18,22 @@ "versions": { "description": "Versions of the city", "type": "array", - "items": {"$ref": "3DTILES_temporal.version.schema.json"} + "items": { "$ref": "3DTILES_temporal.version.schema.json" } }, "versionTransitions": { "description": "Transitions between versions of the city", "type": "array", - "items": {"$ref": "3DTILES_temporal.versionTransition.schema.json"} + "items": { "$ref": "3DTILES_temporal.versionTransition.schema.json" } }, "transactions": { "description": "Transactions between features", "type": "array", - "items": { "anyOf": [ - {"$ref": "3DTILES_temporal.primaryTransaction.schema.json"}, - {"$ref": "3DTILES_temporal.transactionAggregate.schema.json"} - ]} + "items": { + "anyOf": [ + { "$ref": "3DTILES_temporal.primaryTransaction.schema.json" }, + { "$ref": "3DTILES_temporal.transactionAggregate.schema.json" } + ] + } } } } diff --git a/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.transaction.schema.json b/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.transaction.schema.json index 7b603d6cf..d89ec67f4 100644 --- a/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.transaction.schema.json +++ b/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.transaction.schema.json @@ -21,17 +21,17 @@ "source": { "description": "Array of Features Ids (stored in the 3DTILES_temporal extension of the batch table) representing a state before the transaction", "type": "array", - "items": {"type": "string"} + "items": { "type": "string" } }, "destination": { "description": "Array of Features Ids (stored in the 3DTILES_temporal extension of the batch table) representing a state after the transaction", "type": "array", - "items": {"type": "string"} + "items": { "type": "string" } }, "tags": { "description": "tags of the transaction", "type": "array", - "items": {"type": "string"} + "items": { "type": "string" } } } } diff --git a/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.transactionAggregate.schema.json b/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.transactionAggregate.schema.json index 77c280382..332dc5fe5 100644 --- a/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.transactionAggregate.schema.json +++ b/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.transactionAggregate.schema.json @@ -3,18 +3,23 @@ "id": "3DTILES_temporal.transactionAggregate.schema.json", "title": "3DTILES_temporal_transactionAggregate extension", "type": "object", - "allOf" : [{ - "$ref" : "3DTILES_temporal.transaction.schema.json" - }, { - "properties" : { + "allOf": [ + { + "$ref": "3DTILES_temporal.transaction.schema.json" + }, + { + "properties": { "primaryTransactions": { "description": "Array of transactionAggregate or of primaryTransactions", "type": "array", - "items": { "anyOf": [ - {"$ref": "3DTILES_temporal.primaryTransaction.schema.json"}, - {"$ref": "3DTILES_temporal.transactionAggregate.schema.json"} - ]} + "items": { + "anyOf": [ + { "$ref": "3DTILES_temporal.primaryTransaction.schema.json" }, + { "$ref": "3DTILES_temporal.transactionAggregate.schema.json" } + ] + } } } - }] + } + ] } diff --git a/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.version.schema.schema.json b/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.version.schema.schema.json index de599adae..d04258e3b 100644 --- a/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.version.schema.schema.json +++ b/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.version.schema.schema.json @@ -28,12 +28,12 @@ }, "tags": { "type": "array", - "items": {"type": "string"} + "items": { "type": "string" } }, "featuresIds": { "description": "Array of Features Ids composing the version (stored in the 3DTILES_temporal extension of the batch table)", "type": "array", - "items": {"type": "string"} + "items": { "type": "string" } } } } diff --git a/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.versionTransition.schema.json b/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.versionTransition.schema.json index 7da39fee7..6dc924425 100644 --- a/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.versionTransition.schema.json +++ b/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.versionTransition.schema.json @@ -42,7 +42,7 @@ "transactionsIds": { "type": "array", "description": "ids of the transactions composing this VersionTransition", - "items": {"type": "string"} + "items": { "type": "string" } } } } diff --git a/src/Widgets/Temporal/TemporalModule.js b/src/Widgets/Temporal/TemporalModule.js index c00da400b..0b62d2f75 100644 --- a/src/Widgets/Temporal/TemporalModule.js +++ b/src/Widgets/Temporal/TemporalModule.js @@ -1,12 +1,14 @@ +/** @format */ + import { $3DTemporalExtension } from './Model/3DTemporalExtension.js'; import { TemporalProvider } from './ViewModel/TemporalProvider.js'; -import { TemporalView } from './View/TemporalView.js' +import { TemporalView } from './View/TemporalView.js'; /** * Entrypoint of the temporal module (that can be instanciated in the demos) */ export class TemporalModule { - /** + /** * Constructs a new temporal module. * * @param {TilesManager} tilesManager - The tiles manager associated with @@ -15,13 +17,15 @@ export class TemporalModule { * module. }; */ - constructor(tilesManager, temporalOptions) { - - this.model = new $3DTemporalExtension(); + constructor(tilesManager, temporalOptions) { + this.model = new $3DTemporalExtension(); - this.provider = new TemporalProvider(this.model, tilesManager, - temporalOptions.currentTime); + this.provider = new TemporalProvider( + this.model, + tilesManager, + temporalOptions.currentTime + ); - this.view = new TemporalView(this.provider, temporalOptions); - } -} \ No newline at end of file + this.view = new TemporalView(this.provider, temporalOptions); + } +} diff --git a/src/Widgets/Temporal/View/EnumWindows.js b/src/Widgets/Temporal/View/EnumWindows.js index e7a4538ec..374f8c093 100644 --- a/src/Widgets/Temporal/View/EnumWindows.js +++ b/src/Widgets/Temporal/View/EnumWindows.js @@ -1,8 +1,10 @@ +/** @format */ + export class EnumTemporalWindow { - static get SLIDERWINDOW(){ - return "SLIDERWINDOW"; - } - static get GRAPHWINDOW(){ - return "GRAPHWINDOW"; - } -} \ No newline at end of file + static get SLIDERWINDOW() { + return 'SLIDERWINDOW'; + } + static get GRAPHWINDOW() { + return 'GRAPHWINDOW'; + } +} diff --git a/src/Widgets/Temporal/View/NetworkManager.js b/src/Widgets/Temporal/View/NetworkManager.js index 96f0d6931..0b2e84fb3 100644 --- a/src/Widgets/Temporal/View/NetworkManager.js +++ b/src/Widgets/Temporal/View/NetworkManager.js @@ -1,11 +1,13 @@ -const Network = require('vis-network').Network +/** @format */ + +const Network = require('vis-network').Network; /** -* Manager for the graph -* It take care of all data needed by vis.js -*/ + * Manager for the graph + * It take care of all data needed by vis.js + */ export class NetworkManager { - /** + /** * Constructs a NetworkManager. * * @param {String} id_network - HTML id which will be the container of the graph @@ -30,69 +32,72 @@ export class NetworkManager { * * network {Vis.Network Object} - hold the network/graph instance created by viz.js */ - constructor(id_network="mynetwork", - data={"nodes": null, - "edges": null, - "groups": { - "id":0, - "label":"consensusScenario"} - }, - option=null){ - this.network = null; - this.data = data; - this.option = option; - this.id_network = id_network; - this.getAsynchronousData = null; - - } + constructor( + id_network = 'mynetwork', + data = { + nodes: null, + edges: null, + groups: { + id: 0, + label: 'consensusScenario', + }, + }, + option = null + ) { + this.network = null; + this.data = data; + this.option = option; + this.id_network = id_network; + this.getAsynchronousData = null; + } - /** - * Kill the simulation network - * When the graph is shown, a simulation is running. It allows dynamics interactions - * When killed, the graph disappear. - */ - destroy() { - if (this.network !== null) { - this.network.destroy(); - this.network = null; - } + /** + * Kill the simulation network + * When the graph is shown, a simulation is running. It allows dynamics interactions + * When killed, the graph disappear. + */ + destroy() { + if (this.network !== null) { + this.network.destroy(); + this.network = null; } + } - /** - * Initiate the vis.Network with the container (html), data (nodes & edges) and options (graphics) - * The data is got asynchronously. It's coming from tileset.json so we need to wait for it. - */ - init(){ - this.destroy(); + /** + * Initiate the vis.Network with the container (html), data (nodes & edges) and options (graphics) + * The data is got asynchronously. It's coming from tileset.json so we need to wait for it. + */ + init() { + this.destroy(); - this.data.nodes = this.getAsynchronousData()[0]; - this.data.edges = this.getAsynchronousData()[1]; - const container = document.getElementById(this.id_network); - this.network = new Network(container, this.data, this.option); - } + this.data.nodes = this.getAsynchronousData()[0]; + this.data.edges = this.getAsynchronousData()[1]; + const container = document.getElementById(this.id_network); + this.network = new Network(container, this.data, this.option); + } - /** - * Add callback to the graph - * Click on node = event - * Click on edge = event - * In both case, a date is passed - * @param : callback (function) ( the function to be call when the event is done) - */ - add_event(callback){ - this.network.on("selectNode", function (params) { - let nodeId = this.getNodeAt(params.pointer.DOM); - let node = this.body.nodes[nodeId]; - let time = node.options.name; - callback(time); - }); + /** + * Add callback to the graph + * Click on node = event + * Click on edge = event + * In both case, a date is passed + * @param : callback (function) ( the function to be call when the event is done) + */ + add_event(callback) { + this.network.on('selectNode', function (params) { + let nodeId = this.getNodeAt(params.pointer.DOM); + let node = this.body.nodes[nodeId]; + let time = node.options.name; + callback(time); + }); - this.network.on("selectEdge", function (params) { - let edgeId = this.getEdgeAt(params.pointer.DOM); - let connectedNodesId = this.getConnectedNodes(edgeId); - let from_time = this.body.nodes[connectedNodesId[0]].options.name; - let to_time = this.body.nodes[connectedNodesId[1]].options.name; - let time = (from_time/1 + to_time/1) / 2 ; - callback(time); - }); - } + this.network.on('selectEdge', function (params) { + let edgeId = this.getEdgeAt(params.pointer.DOM); + let connectedNodesId = this.getConnectedNodes(edgeId); + let from_time = this.body.nodes[connectedNodesId[0]].options.name; + let to_time = this.body.nodes[connectedNodesId[1]].options.name; + let time = (from_time / 1 + to_time / 1) / 2; + callback(time); + }); + } } diff --git a/src/Widgets/Temporal/View/TemporalGraphWindow.js b/src/Widgets/Temporal/View/TemporalGraphWindow.js index 0c1d5ab99..4fd949bb6 100644 --- a/src/Widgets/Temporal/View/TemporalGraphWindow.js +++ b/src/Widgets/Temporal/View/TemporalGraphWindow.js @@ -1,7 +1,9 @@ +/** @format */ + //Components -import { Window } from "../../../Components/GUI/js/Window"; +import { Window } from '../../../Components/GUI/js/Window'; -import { NetworkManager } from "./NetworkManager"; +import { NetworkManager } from './NetworkManager'; import './TemporalWindow.css'; /** @@ -16,55 +18,56 @@ import './TemporalWindow.css'; * @param options : optional parameters (min time, max time and current time) */ export class TemporalGraphWindow extends Window { - constructor(refreshCallback, options = {}) { + constructor(refreshCallback, options = {}) { // option : getAsynchronousData - super('temporal', 'Temporal Graph Navigation', false); + super('temporal', 'Temporal Graph Navigation', false); - this.refreshCallback = refreshCallback; + this.refreshCallback = refreshCallback; - // graph - this.networkManager = new NetworkManager(); - this.networkManager.option=options.viewOptions; - this.networkManager.getAsynchronousData = options.temporalWindow.getAsynchronousData; - } + // graph + this.networkManager = new NetworkManager(); + this.networkManager.option = options.viewOptions; + this.networkManager.getAsynchronousData = + options.temporalWindow.getAsynchronousData; + } - get innerContentHtml() { - return /*html*/` + get innerContentHtml() { + return /*html*/ `
`; - } - - windowCreated() { - // Magical code to center an absolute positionned window - this.window.style.setProperty('left', '0'); - this.window.style.setProperty('right', '0'); - this.window.style.setProperty('margin-left', 'auto'); - this.window.style.setProperty('margin-right', 'auto'); - // Put it at the bottom of the page - this.window.style.setProperty('top', 'unset'); - this.window.style.setProperty('bottom', '0'); - this.window.style.setProperty('margin-bottom', 'auto'); - // Window size and center text - this.window.style.setProperty('width', '700px'); - this.window.style.setProperty('height', '215px'); -// this.window.style.setProperty('height', '115px'); - this.window.style.setProperty('text-align', 'center'); - - // Add graph - this.networkManager.init(); - this.networkManager.add_event((param)=>{this.changeTime(param)}); - } + } + windowCreated() { + // Magical code to center an absolute positionned window + this.window.style.setProperty('left', '0'); + this.window.style.setProperty('right', '0'); + this.window.style.setProperty('margin-left', 'auto'); + this.window.style.setProperty('margin-right', 'auto'); + // Put it at the bottom of the page + this.window.style.setProperty('top', 'unset'); + this.window.style.setProperty('bottom', '0'); + this.window.style.setProperty('margin-bottom', 'auto'); + // Window size and center text + this.window.style.setProperty('width', '700px'); + this.window.style.setProperty('height', '215px'); + // this.window.style.setProperty('height', '115px'); + this.window.style.setProperty('text-align', 'center'); - // change the current date and sync the temporal version to this new date - changeTime(time) { - this.currentTime = time; + // Add graph + this.networkManager.init(); + this.networkManager.add_event((param) => { + this.changeTime(param); + }); + } - // Eventually inform who it may concern (e.g. an associated iTowns layer) - // that the currentTime has changed: - this.refreshCallback(this.currentTime); - } + // change the current date and sync the temporal version to this new date + changeTime(time) { + this.currentTime = time; + // Eventually inform who it may concern (e.g. an associated iTowns layer) + // that the currentTime has changed: + this.refreshCallback(this.currentTime); + } } diff --git a/src/Widgets/Temporal/View/TemporalSliderWindow.js b/src/Widgets/Temporal/View/TemporalSliderWindow.js index 47b0da04b..27bd71894 100644 --- a/src/Widgets/Temporal/View/TemporalSliderWindow.js +++ b/src/Widgets/Temporal/View/TemporalSliderWindow.js @@ -1,10 +1,12 @@ +/** @format */ + //Components -import { Window } from "../../../Components/GUI/js/Window"; +import { Window } from '../../../Components/GUI/js/Window'; import './TemporalWindow.css'; /** - * Handles the GUI part enabling the user to specify the chosen "time" (year) + * Handles the GUI part enabling the user to specify the chosen "time" (year) * of observation for displayal of the (3D) scene. * Note that it is not the Temporal View's responsability to * alter/modify/update the scene according to the user specified moment (but @@ -13,25 +15,25 @@ import './TemporalWindow.css'; * @param options : optional parameters (min time, max time and current time) */ export class TemporalSliderWindow extends Window { - constructor(refreshCallback, options = {}) { - super('temporal', 'Temporal Navigation', false); + constructor(refreshCallback, options = {}) { + super('temporal', 'Temporal Navigation', false); - // Minimum and maximum times that can be displayed by this occurence - this.minTime = options.minTime || 2009; - this.maxTime = options.maxTime || 2015; + // Minimum and maximum times that can be displayed by this occurence + this.minTime = options.minTime || 2009; + this.maxTime = options.maxTime || 2015; - // The currently selected timestamp - this.currentTime = options.currentTime || 2009; + // The currently selected timestamp + this.currentTime = options.currentTime || 2009; - // The timestep used to increment or decrement time with the slide buttons. - // Note that timeStep is a "duration" as opposed to a timestamp. - this.timeStep = options.timeStep || 1; + // The timestep used to increment or decrement time with the slide buttons. + // Note that timeStep is a "duration" as opposed to a timestamp. + this.timeStep = options.timeStep || 1; - this.refreshCallback = refreshCallback; - } + this.refreshCallback = refreshCallback; + } - get innerContentHtml() { - return /*html*/` + get innerContentHtml() { + return /*html*/ `
${this.minTime}
${this.maxTime}
@@ -40,45 +42,49 @@ export class TemporalSliderWindow extends Window { value=${this.currentTime} step=${this.timeStep}>
`; - } + } - windowCreated() { - // Magical code to center an absolute positionned window - this.window.style.setProperty('left', '0'); - this.window.style.setProperty('right', '0'); - this.window.style.setProperty('margin-left', 'auto'); - this.window.style.setProperty('margin-right', 'auto'); - // Put it at the bottom of the page - this.window.style.setProperty('top', 'unset'); - this.window.style.setProperty('bottom', '10px'); - this.window.style.setProperty('margin-bottom', 'auto'); - // Window size and center text - this.window.style.setProperty('width', '700px'); - this.window.style.setProperty('height', '115px'); - this.window.style.setProperty('text-align', 'center'); + windowCreated() { + // Magical code to center an absolute positionned window + this.window.style.setProperty('left', '0'); + this.window.style.setProperty('right', '0'); + this.window.style.setProperty('margin-left', 'auto'); + this.window.style.setProperty('margin-right', 'auto'); + // Put it at the bottom of the page + this.window.style.setProperty('top', 'unset'); + this.window.style.setProperty('bottom', '10px'); + this.window.style.setProperty('margin-bottom', 'auto'); + // Window size and center text + this.window.style.setProperty('width', '700px'); + this.window.style.setProperty('height', '115px'); + this.window.style.setProperty('text-align', 'center'); - // Hook up the callbacks - document.getElementById('timeSliderValue').addEventListener( - 'input', this.timeSelection.bind(this), false); - document.getElementById('timeSlider').addEventListener( - 'input', this.timeSelectionSlider.bind(this), false); - } + // Hook up the callbacks + document + .getElementById('timeSliderValue') + .addEventListener('input', this.timeSelection.bind(this), false); + document + .getElementById('timeSlider') + .addEventListener('input', this.timeSelectionSlider.bind(this), false); + } - // Call back on new user input with the date selector - timeSelection() { - this.currentTime = document.getElementById('timeSliderValue').value.toString(); - document.getElementById('timeSlider').value = this.currentTime; - // Eventually inform who it may concern (e.g. an associated iTowns layer) - // that the currentTime has changed: - this.refreshCallback(this.currentTime); - } + // Call back on new user input with the date selector + timeSelection() { + this.currentTime = document + .getElementById('timeSliderValue') + .value.toString(); + document.getElementById('timeSlider').value = this.currentTime; + // Eventually inform who it may concern (e.g. an associated iTowns layer) + // that the currentTime has changed: + this.refreshCallback(this.currentTime); + } - // Call back on new user input with the time slider - timeSelectionSlider() { - this.currentTime = document.getElementById('timeSlider').value.toString(); - document.getElementById('timeSliderValue').value = this.currentTime; - // Eventually inform who it may concern (e.g. an associated iTowns layer) - // that the currentTime has changed: - this.refreshCallback(this.currentTime); - } + // Call back on new user input with the time slider + timeSelectionSlider() { + this.currentTime = document.getElementById('timeSlider').value.toString(); + document.getElementById('timeSliderValue').value = this.currentTime; + // Eventually inform who it may concern (e.g. an associated iTowns layer) + // that the currentTime has changed: + this.refreshCallback(this.currentTime); + } } diff --git a/src/Widgets/Temporal/View/TemporalView.js b/src/Widgets/Temporal/View/TemporalView.js index 794467aa4..532f70f03 100644 --- a/src/Widgets/Temporal/View/TemporalView.js +++ b/src/Widgets/Temporal/View/TemporalView.js @@ -1,3 +1,5 @@ +/** @format */ + //Components import { ModuleView } from '../../../Components/ModuleView/ModuleView.js'; @@ -21,30 +23,38 @@ export class TemporalView extends ModuleView { this.currentTime = temporalOptions.currentTime; function currentTimeUpdated(newDate) { - this.currentTime = Number(newDate); - this.provider.currentTime = this.currentTime; // TODO: verify that the - // flow is good with MVVM - this.provider.changeVisibleTilesStates(); + this.currentTime = Number(newDate); + this.provider.currentTime = this.currentTime; // TODO: verify that the + // flow is good with MVVM + this.provider.changeVisibleTilesStates(); } const refreshCallback = currentTimeUpdated.bind(this); // Callback to get data asynchronously from the tileset.json - function getAsynchronousData(){ - let versions = this.temporalExtension.temporal_tileset.temporalVersions.versions; - let versionTransitions = this.temporalExtension.temporal_tileset.versionTransitions; - return [versions, versionTransitions] - } + function getAsynchronousData() { + let versions = + this.temporalExtension.temporal_tileset.temporalVersions.versions; + let versionTransitions = + this.temporalExtension.temporal_tileset.versionTransitions; + return [versions, versionTransitions]; + } // Select the window type: switch (temporalOptions.view) { - case EnumTemporalWindow.SLIDERWINDOW : - this.temporalWindow = new TemporalSliderWindow(refreshCallback, temporalOptions); - break; - case EnumTemporalWindow.GRAPHWINDOW : - temporalOptions.getAsynchronousData = getAsynchronousData.bind(this); - this.temporalWindow = new TemporalGraphWindow(refreshCallback, temporalOptions); - break; - } + case EnumTemporalWindow.SLIDERWINDOW: + this.temporalWindow = new TemporalSliderWindow( + refreshCallback, + temporalOptions + ); + break; + case EnumTemporalWindow.GRAPHWINDOW: + temporalOptions.getAsynchronousData = getAsynchronousData.bind(this); + this.temporalWindow = new TemporalGraphWindow( + refreshCallback, + temporalOptions + ); + break; + } } ///////////////// @@ -56,4 +66,4 @@ export class TemporalView extends ModuleView { disableView() { this.temporalWindow.dispose(); } -} \ No newline at end of file +} diff --git a/src/Widgets/Temporal/View/TemporalWindow.css b/src/Widgets/Temporal/View/TemporalWindow.css index 8983a912f..e1c9c57c0 100644 --- a/src/Widgets/Temporal/View/TemporalWindow.css +++ b/src/Widgets/Temporal/View/TemporalWindow.css @@ -1,43 +1,45 @@ +/** @format */ + #temporalWindow { - position: absolute; - width: 100%; + position: absolute; + width: 100%; } #timeSliderMinDate { - position: absolute; - left : 10px; - top : 5px; - font: 28px 'Lucida Grande',sans-serif; - font-weight: bold; + position: absolute; + left: 10px; + top: 5px; + font: 28px 'Lucida Grande', sans-serif; + font-weight: bold; } #timeSliderMaxDate { - position: absolute; - right : 10px; - top : 5px; - font: 28px 'Lucida Grande',sans-serif; - font-weight: bold; + position: absolute; + right: 10px; + top: 5px; + font: 28px 'Lucida Grande', sans-serif; + font-weight: bold; } -#timeSliderValue{ - position: absolute; - text-align: center; - margin : auto; - color : black; - font: 28px 'Lucida Grande',sans-serif; - font-weight: bold; - top: 30px; - right : 0; - left : 0; - border: 1px solid black; - background-color: whitesmoke; - height: 40px; - width : 90px; +#timeSliderValue { + position: absolute; + text-align: center; + margin: auto; + color: black; + font: 28px 'Lucida Grande', sans-serif; + font-weight: bold; + top: 30px; + right: 0; + left: 0; + border: 1px solid black; + background-color: whitesmoke; + height: 40px; + width: 90px; } #timeSlider { - width: 65%; - position: absolute; - text-align: center; - margin : auto; - top: 10px; - left: 0; - right : 0; + width: 65%; + position: absolute; + text-align: center; + margin: auto; + top: 10px; + left: 0; + right: 0; } diff --git a/src/Widgets/Temporal/ViewModel/TemporalProvider.js b/src/Widgets/Temporal/ViewModel/TemporalProvider.js index 16f6494e9..622eed27c 100644 --- a/src/Widgets/Temporal/ViewModel/TemporalProvider.js +++ b/src/Widgets/Temporal/ViewModel/TemporalProvider.js @@ -1,224 +1,276 @@ +/** @format */ + //Components -import { TilesManager } from '../../../Components/3DTiles/TilesManager.js' +import { TilesManager } from '../../../Components/3DTiles/TilesManager.js'; import { getVisibleTiles } from '../../../Components/3DTiles/3DTilesUtils.js'; import { CityObjectStyle } from '../../../Components/3DTiles/Model/CityObjectStyle.js'; import { CityObjectID } from '../../../Components/3DTiles/Model/CityObject.js'; /** * The ViewModel of the temporal module. Contains intermediate data structures - * between the model and the view as well as the logic for city objects and + * between the model and the view as well as the logic for city objects and * transactions display. */ export class TemporalProvider { - /** - * Constructs a new temporal provider: initialize data structures - * used for the view (this.COStyles), initialize the possible - * city objects styles that displays transactions and set events. - * @param {$3DTemporalExtension} tempExtModel The model of the temporal - * module (i.e. holding data from the 3D Tiles temporal extension). - * @param {TilesManager} tilesManager The tiles manager associated - * with the itowns 3D Tiles layer holding the temporal extension. - * @param {Number} currentTime The current display time, updated by the - * TemporalView. - */ + /** + * Constructs a new temporal provider: initialize data structures + * used for the view (this.COStyles), initialize the possible + * city objects styles that displays transactions and set events. + * @param {$3DTemporalExtension} tempExtModel The model of the temporal + * module (i.e. holding data from the 3D Tiles temporal extension). + * @param {TilesManager} tilesManager The tiles manager associated + * with the itowns 3D Tiles layer holding the temporal extension. + * @param {Number} currentTime The current display time, updated by the + * TemporalView. + */ constructor(tempExtModel, tilesManager, currentTime) { - this.tempExtModel = tempExtModel; this.tilesManager = tilesManager; this.currentTime = currentTime; - /** Stores city objects (CO) styles per tile and per date - * to avoid computing it multiple times. It's actually a map + /** Stores city objects (CO) styles per tile and per date + * to avoid computing it multiple times. It's actually a map * of a map and its structure is: - * { date: tile : styles[] } } where the position in the styles + * { date: tile : styles[] } } where the position in the styles * array is the id of the city object - * */ + * */ this.COStyles = new Map(); this.initCOStyles(); // Initializes the model. One part of this model is filled when the - // temporal extension is loaded by iTowns; an other part is filled + // temporal extension is loaded by iTowns; an other part is filled // with the event declared below (when a tile is loaded). // See the comment at the end of the $3DTemporalExtension constructor // for more details. this.tilesManager.addEventListener( TilesManager.EVENT_TILE_LOADED, - this.tempExtModel.updateTileExtensionModel.bind( - this.tempExtModel)); + this.tempExtModel.updateTileExtensionModel.bind(this.tempExtModel) + ); // When a tile is loaded, we compute the state of its city objects (e.g. // should they be displayed or not and in which color, etc.) this.tilesManager.addEventListener( - TilesManager.EVENT_TILE_LOADED, - this.changeTileState.bind(this)); + TilesManager.EVENT_TILE_LOADED, + this.changeTileState.bind(this) + ); } /** - * Initializes the styles affected to city objects to represent + * Initializes the styles affected to city objects to represent * transactions (see 3DTiles_temporal extension for more information * on transactions). The names of the styles match transaction names, * except for 'noTransaction' dans 'hide'. */ initCOStyles() { - this.tilesManager.registerStyle('noTransaction', new CityObjectStyle({ - materialProps: { opacity: 1.0, color: 0xffffff } })); // white + this.tilesManager.registerStyle( + 'noTransaction', + new CityObjectStyle({ + materialProps: { opacity: 1.0, color: 0xffffff }, + }) + ); // white - this.tilesManager.registerStyle('creation', new CityObjectStyle({ - materialProps: { opacity: 0.6, color: 0x009900 } })); // green + this.tilesManager.registerStyle( + 'creation', + new CityObjectStyle({ + materialProps: { opacity: 0.6, color: 0x009900 }, + }) + ); // green - this.tilesManager.registerStyle('demolition', new CityObjectStyle({ - materialProps: { opacity: 0.6, color: 0xff0000 } })); // red + this.tilesManager.registerStyle( + 'demolition', + new CityObjectStyle({ + materialProps: { opacity: 0.6, color: 0xff0000 }, + }) + ); // red - this.tilesManager.registerStyle('modification', new CityObjectStyle({ - materialProps: { opacity: 0.6, color: 0xFFD700 } })); // yellow + this.tilesManager.registerStyle( + 'modification', + new CityObjectStyle({ + materialProps: { opacity: 0.6, color: 0xffd700 }, + }) + ); // yellow - this.tilesManager.registerStyle('hide', new CityObjectStyle({ - materialProps: { opacity: 0, color: 0xffffff, alphaTest: 0.3 } })); // hidden + this.tilesManager.registerStyle( + 'hide', + new CityObjectStyle({ + materialProps: { opacity: 0, color: 0xffffff, alphaTest: 0.3 }, + }) + ); // hidden } /** * Sets the style of a given city object in the tiles manager if this - * style has been registered in the tiles manager (e.g. in - * this.initCOStyles()). + * style has been registered in the tiles manager (e.g. in + * this.initCOStyles()). * @param {Number} tileId Id of the tile of the city object. * @param {Number} cityObjectId Id of the city object. * @param {String} styleName Name of the style to apply. */ setCityObjectStyle(tileId, cityObjectId, styleName) { - if(this.tilesManager.isStyleRegistered(styleName)) { - this.tilesManager.setStyle(new CityObjectID(tileId, cityObjectId), - styleName); + if (this.tilesManager.isStyleRegistered(styleName)) { + this.tilesManager.setStyle( + new CityObjectID(tileId, cityObjectId), + styleName + ); } else { - console.warn("Style " + styleName + " is not " + - "registered. Defaulting to style noTransaction.") - this.tilesManager.setStyle(new CityObjectID(tileId, cityObjectId), - 'noTransaction'); + console.warn( + 'Style ' + + styleName + + ' is not ' + + 'registered. Defaulting to style noTransaction.' + ); + this.tilesManager.setStyle( + new CityObjectID(tileId, cityObjectId), + 'noTransaction' + ); } } - /** - * Generates the style name of a transaction. This method is recursive - * for aggregated transactions that may have multiple nested transactions. - * The style name correspond to the one created in the - * initCOStyles method). - * - * @param {$3DTemporalTransaction} transaction The transaction - * to generate the style name from. - * - * @returns {string} If the transaction is a primary transaction, - * returns its type. If it is an aggregated transaction, it returns a - * concatenation of the primary transactions types aggregated in - * transaction, prefixed by 'aggregate'. Currently, no style are - * declared for transactions aggregates for a simpler visual - * rendering. We could also generate styles with random colors - * and add them to a legend and provide a user the possibility to - * update these colors and / or to disable them from the GUI. - */ - getTransactionStyleName(transaction, styleName) { - if (transaction.isPrimary) return transaction.type; - else if (transaction.isAggregate) { - if (styleName === '') styleName = 'aggregate'; // prefix - for (let i = 0 ; i < transaction.transactions.length ; i++) { - styleName = styleName + '-' + this.getTransactionStyleName( - transaction.transactions[i], styleName); - } - return styleName - } else { - console.warn('Transaction which is not a primary nor an aggregate.') - } + /** + * Generates the style name of a transaction. This method is recursive + * for aggregated transactions that may have multiple nested transactions. + * The style name correspond to the one created in the + * initCOStyles method). + * + * @param {$3DTemporalTransaction} transaction The transaction + * to generate the style name from. + * + * @returns {string} If the transaction is a primary transaction, + * returns its type. If it is an aggregated transaction, it returns a + * concatenation of the primary transactions types aggregated in + * transaction, prefixed by 'aggregate'. Currently, no style are + * declared for transactions aggregates for a simpler visual + * rendering. We could also generate styles with random colors + * and add them to a legend and provide a user the possibility to + * update these colors and / or to disable them from the GUI. + */ + getTransactionStyleName(transaction, styleName) { + if (transaction.isPrimary) return transaction.type; + else if (transaction.isAggregate) { + if (styleName === '') styleName = 'aggregate'; // prefix + for (let i = 0; i < transaction.transactions.length; i++) { + styleName = + styleName + + '-' + + this.getTransactionStyleName(transaction.transactions[i], styleName); + } + return styleName; + } else { + console.warn('Transaction which is not a primary nor an aggregate.'); } + } - /* *** Culling with transactions and colors management */ - // Rules for culling: - // * If the feature exists at the currentTime we display it in gray - // * If there is a transaction between the feature and another - // feature at the currentTime: - // * the displayed geometry is the one of the old feature for the - // first half duration of the transaction - // * the displayed geometry is the one of the new feature for the - // second half of the duration - // * the opacity is set to 0.6 - // * the color is set depending on the transaction type - // * else we hide the feature. - culling(BT, tileId, tileTransactions) { - const featuresDisplayStates = []; - for (let i = 0; i < BT.featureIds.length; i++) { - const featureId = BT.featureIds[i]; - if (this.currentTime >= BT.startDates[i] && this.currentTime <= - BT.endDates[i]) { - // ** FEATURE EXISTS - featuresDisplayStates.push('noTransaction'); - this.setCityObjectStyle(tileId, i, 'noTransaction'); - } else if (tileTransactions.has(featureId) && tileTransactions.get(featureId)) { - // ** TRANSACTION CASE - const featureTransactions = tileTransactions.get(featureId); - let hasTransac = false; - if (featureTransactions.asSource) { - const transacAsSource = featureTransactions.asSource - const transacAsSourceHalfDuration = (transacAsSource.endDate - - transacAsSource.startDate) / 2; - if (this.currentTime > transacAsSource.startDate && this.currentTime <= - transacAsSource.startDate + transacAsSourceHalfDuration) { - hasTransac = true; - const transactionStyleName = this.getTransactionStyleName(transacAsSource, ''); - featuresDisplayStates.push(transactionStyleName); - this.setCityObjectStyle(tileId, i, transactionStyleName); - } - } - if (featureTransactions.asDestination) { - const transacAsDest = featureTransactions.asDestination; - const transacAsDestHalfDuration = (transacAsDest.endDate - - transacAsDest.startDate) / 2; - if (this.currentTime > transacAsDest.startDate + - transacAsDestHalfDuration && this.currentTime <= - transacAsDest.endDate) { - hasTransac = true; - const transactionStyleName = this.getTransactionStyleName(transacAsDest, ''); - featuresDisplayStates.push(transactionStyleName); - this.setCityObjectStyle(tileId, i, transactionStyleName); - } - } + /* *** Culling with transactions and colors management */ + // Rules for culling: + // * If the feature exists at the currentTime we display it in gray + // * If there is a transaction between the feature and another + // feature at the currentTime: + // * the displayed geometry is the one of the old feature for the + // first half duration of the transaction + // * the displayed geometry is the one of the new feature for the + // second half of the duration + // * the opacity is set to 0.6 + // * the color is set depending on the transaction type + // * else we hide the feature. + culling(BT, tileId, tileTransactions) { + const featuresDisplayStates = []; + for (let i = 0; i < BT.featureIds.length; i++) { + const featureId = BT.featureIds[i]; + if ( + this.currentTime >= BT.startDates[i] && + this.currentTime <= BT.endDates[i] + ) { + // ** FEATURE EXISTS + featuresDisplayStates.push('noTransaction'); + this.setCityObjectStyle(tileId, i, 'noTransaction'); + } else if ( + tileTransactions.has(featureId) && + tileTransactions.get(featureId) + ) { + // ** TRANSACTION CASE + const featureTransactions = tileTransactions.get(featureId); + let hasTransac = false; + if (featureTransactions.asSource) { + const transacAsSource = featureTransactions.asSource; + const transacAsSourceHalfDuration = + (transacAsSource.endDate - transacAsSource.startDate) / 2; + if ( + this.currentTime > transacAsSource.startDate && + this.currentTime <= + transacAsSource.startDate + transacAsSourceHalfDuration + ) { + hasTransac = true; + const transactionStyleName = this.getTransactionStyleName( + transacAsSource, + '' + ); + featuresDisplayStates.push(transactionStyleName); + this.setCityObjectStyle(tileId, i, transactionStyleName); + } + } + if (featureTransactions.asDestination) { + const transacAsDest = featureTransactions.asDestination; + const transacAsDestHalfDuration = + (transacAsDest.endDate - transacAsDest.startDate) / 2; + if ( + this.currentTime > + transacAsDest.startDate + transacAsDestHalfDuration && + this.currentTime <= transacAsDest.endDate + ) { + hasTransac = true; + const transactionStyleName = this.getTransactionStyleName( + transacAsDest, + '' + ); + featuresDisplayStates.push(transactionStyleName); + this.setCityObjectStyle(tileId, i, transactionStyleName); + } + } - if (!hasTransac) { - // ** TRANSACTION NOT AT THE RIGHT DATE - featuresDisplayStates.push('hide'); - this.setCityObjectStyle(tileId, i, 'hide'); - } - } else { - // ** FEATURE DOES NOT EXIST AND THERE IS NO TRANSACTION + if (!hasTransac) { + // ** TRANSACTION NOT AT THE RIGHT DATE + featuresDisplayStates.push('hide'); + this.setCityObjectStyle(tileId, i, 'hide'); + } + } else { + // ** FEATURE DOES NOT EXIST AND THERE IS NO TRANSACTION - // ** MANAGE CREATIONS AND DEMOLITIONS (this step must be - // done because the creation and demolitions transactions - // are currently not in the tileset. However, the tileset - // should have them later on). - const halfVintage = 1.5; + // ** MANAGE CREATIONS AND DEMOLITIONS (this step must be + // done because the creation and demolitions transactions + // are currently not in the tileset. However, the tileset + // should have them later on). + const halfVintage = 1.5; - if (this.currentTime + halfVintage >= BT.startDates[i] && - this.currentTime < BT.startDates[i]) { - // ** CREATION - featuresDisplayStates.push('creation'); - this.setCityObjectStyle(tileId, i, 'creation'); - } else if (this.currentTime - halfVintage < BT.endDates[i] && - this.currentTime > BT.endDates[i]) { - // ** DEMOLITION - featuresDisplayStates.push('demolition'); - this.setCityObjectStyle(tileId, i, 'demolition'); - } else { - // ** FEATURE DOES NOT EXIST - featuresDisplayStates.push('hide'); - this.setCityObjectStyle(tileId, i, 'hide'); - } - } + if ( + this.currentTime + halfVintage >= BT.startDates[i] && + this.currentTime < BT.startDates[i] + ) { + // ** CREATION + featuresDisplayStates.push('creation'); + this.setCityObjectStyle(tileId, i, 'creation'); + } else if ( + this.currentTime - halfVintage < BT.endDates[i] && + this.currentTime > BT.endDates[i] + ) { + // ** DEMOLITION + featuresDisplayStates.push('demolition'); + this.setCityObjectStyle(tileId, i, 'demolition'); + } else { + // ** FEATURE DOES NOT EXIST + featuresDisplayStates.push('hide'); + this.setCityObjectStyle(tileId, i, 'hide'); + } } + } - return featuresDisplayStates; + return featuresDisplayStates; } /** - * Computes and sets the style of the features of a given tile. + * Computes and sets the style of the features of a given tile. * @param {Number} tileId The id of the given tile. */ computeTileState(tileId) { @@ -226,53 +278,63 @@ export class TemporalProvider { if (tileId === 0) return; // Skip the root tile which has no geometry // If it has already been computed, don't do it again - if (this.COStyles.has(this.currentTime) && - this.COStyles.get(this.currentTime).has(tileId)) { - const tileDisplayStates = this.COStyles.get(this.currentTime).get(tileId); - for (let i = 0 ; i < tileDisplayStates.length ; i++) { - this.setCityObjectStyle(tileId, i, tileDisplayStates[i]); - } + if ( + this.COStyles.has(this.currentTime) && + this.COStyles.get(this.currentTime).has(tileId) + ) { + const tileDisplayStates = this.COStyles.get(this.currentTime).get(tileId); + for (let i = 0; i < tileDisplayStates.length; i++) { + this.setCityObjectStyle(tileId, i, tileDisplayStates[i]); + } } else { - if (this.tempExtModel.temporalBatchTables.has(tileId)) { - const tileTemporalBT = this.tempExtModel.temporalBatchTables.get(tileId); - if (! this.COStyles.has(this.currentTime)) { - this.COStyles.set(this.currentTime, new Map()); - } - this.COStyles.get(this.currentTime).set(tileId, this.culling(tileTemporalBT, tileId, this.tempExtModel.transactionsPerTile.get(tileId))); - } else { + if (this.tempExtModel.temporalBatchTables.has(tileId)) { + const tileTemporalBT = + this.tempExtModel.temporalBatchTables.get(tileId); + if (!this.COStyles.has(this.currentTime)) { + this.COStyles.set(this.currentTime, new Map()); + } + this.COStyles.get(this.currentTime).set( + tileId, + this.culling( + tileTemporalBT, + tileId, + this.tempExtModel.transactionsPerTile.get(tileId) + ) + ); + } else { console.warn(`Cannot compute features states for tile ${tileId} since the temporal extension of the batch table has not yet been loaded for this tile`); return; - } + } } } /** * Computes and applies the display state of a tile. This method - * is triggered by an event (TilesManager.EVENT_TILE_LOADED) - * indicating that a new tile content has been loaded (e.g. because it + * is triggered by an event (TilesManager.EVENT_TILE_LOADED) + * indicating that a new tile content has been loaded (e.g. because it * becomes visible by the camera) * @param {Object} tileContent The tile content loaded. */ changeTileState(tileContent) { - this.computeTileState(tileContent.tileId); - this.tilesManager.applyStyleToTile(tileContent.tileId, - { updateView: false }); - } + this.computeTileState(tileContent.tileId); + this.tilesManager.applyStyleToTile(tileContent.tileId, { + updateView: false, + }); + } /** - * Computes and applies the display state of currently visible tiles - * (i.e. those in the camera field of view and having features - * at the current display time). This method is triggered by the + * Computes and applies the display state of currently visible tiles + * (i.e. those in the camera field of view and having features + * at the current display time). This method is triggered by the * TemporalView when the time of the view is updated. */ changeVisibleTilesStates() { - const tiles = getVisibleTiles(this.tilesManager.layer); - for (let i = 0; i < tiles.length; i++) { - this.computeTileState(tiles[i].tileId); - } - this.tilesManager.applyStyles(); + const tiles = getVisibleTiles(this.tilesManager.layer); + for (let i = 0; i < tiles.length; i++) { + this.computeTileState(tiles[i].tileId); + } + this.tilesManager.applyStyles(); } - -} \ No newline at end of file +} From 684709ac27169f51d4e020c97844eb31bcd99ea8 Mon Sep 17 00:00:00 2001 From: valentinMachado Date: Tue, 8 Jun 2021 11:10:10 +0200 Subject: [PATCH 19/68] eslint return no error --- .eslintrc.js | 1 + .travis.yml | 11 +- package.json | 3 +- src/Components/3DTiles/3DTilesUtils.js | 20 +- src/Components/3DTiles/Model/CityObject.js | 2 +- .../3DTiles/Model/CityObjectStyle.js | 4 +- src/Components/3DTiles/StyleManager.js | 14 +- src/Components/3DTiles/TilesManager.js | 60 +-- src/Components/Camera/CameraUtils.js | 17 +- src/Components/Camera/PositionerWindow.js | 4 +- .../DataProcessing/DataProcessing.js | 36 +- src/Components/Events/EventSender.js | 96 ++--- src/Components/GUI/js/Draggable.js | 70 ++-- src/Components/GUI/js/Window.js | 396 +++++++++--------- src/Components/GUI/js/WindowExtension.js | 8 +- src/Components/GUI/js/WindowManager.js | 2 +- src/Components/LayerManager/LayerManager.js | 254 +++++------ src/Components/ModuleView/ModuleView.js | 84 ++-- src/Components/Request/RequestService.js | 132 +++--- src/Game/Components/AssetsManager.js | 22 +- .../Shared/GameObject/Components/Collider.js | 50 ++- src/Game/Shared/GameObject/GameObject.js | 9 - src/Game/Shared/WorldState.js | 2 +- src/Game/UDVDebugger/UDVDebugger.js | 18 - .../View/CityObjectFilterWindow.js | 4 +- .../CityObjects/View/CityObjectWindow.js | 6 +- .../CityObjects/ViewModel/AttributeFilter.js | 6 +- .../ViewModel/CityObjectProvider.js | 6 +- .../Documents/View/DocumentNavigatorWindow.js | 16 +- .../3DTilesDebug/views/3DTilesDebugWindow.js | 4 +- .../Contribute/View/DocumentCreationWindow.js | 2 +- .../views/DocumentCommentsWindow.js | 8 +- .../Geocoding/services/GeocodingService.js | 4 +- .../Geocoding/views/GeocodingView.js | 4 +- .../GuidedTour/GuidedTourController.js | 4 +- src/Widgets/LayerChoice/views/LayerChoice.js | 36 +- .../Links/View/CityObjectLinkInterface.js | 7 +- .../Links/View/DocumentLinkInterface.js | 12 +- 38 files changed, 715 insertions(+), 719 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 00b804fc4..6b41370fc 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -19,5 +19,6 @@ module.exports = { 'linebreak-style': ['error', 'unix'], quotes: ['error', 'single'], semi: ['error', 'always'], + 'no-unused-vars': 'off', }, }; diff --git a/.travis.yml b/.travis.yml index fcaa6727f..3683952db 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,10 +18,9 @@ install: jobs: include: - - stage: test + - stage: build script: - - npm run test - # - stage: lint - # script: - # - ./node_modules/eslint/bin/eslint.js --version - # - npm run lint + - npm run build + - stage: eslint + script: + - npm run eslint diff --git a/package.json b/package.json index 28ac51c2e..f9a72ec1b 100644 --- a/package.json +++ b/package.json @@ -4,8 +4,7 @@ "description": "A collection of itowns plugins", "main": "src", "scripts": { - "eslint": "./node_modules/.bin/eslint ./src", - "test": "npm run build", + "eslint": "./node_modules/.bin/eslint ./src --fix", "build": "cross-env NODE_ENV=production webpack", "build-debug": "cross-env NODE_ENV=development webpack", "debug": "nodemon --verbose --watch src --delay 2500ms ./bin/debug.js -e js,css,html" diff --git a/src/Components/3DTiles/3DTilesUtils.js b/src/Components/3DTiles/3DTilesUtils.js index 97f192b35..4d49d5235 100644 --- a/src/Components/3DTiles/3DTilesUtils.js +++ b/src/Components/3DTiles/3DTilesUtils.js @@ -9,9 +9,9 @@ import { objectEquals } from '../DataProcessing/DataProcessing.js'; * @param {*} tile A 3DTiles tile object from THREE.js. */ export function getBatchTableFromTile(tile) { - if (!!tile.batchTable) { + if (tile.batchTable) { return tile.batchTable; - } else if (!!tile.parent) { + } else if (tile.parent) { return getBatchTableFromTile(tile.parent); } return undefined; @@ -66,11 +66,11 @@ export function getVisibleTiles(layer) { let rootTile = layer.object3d.children[0]; let tiles = []; let exploreTree = (node) => { - if (!!node) { - if (!!node.batchTable) { + if (node) { + if (node.batchTable) { // It's an actual tile tiles.push(node); - }; + } for (let childIndex = 0; childIndex < node.children.length; childIndex++) { let child = node.children[childIndex]; if (child.type === 'Object3D') { @@ -157,8 +157,8 @@ export function setTileVerticesColor(tile, newColor, indexArray = null) { if (!!indexArray && (lowerBound > i || upperBound < i)) { //If i is not one of the selected indexes, we keep the previous color let previousColor = (tile.geometry.attributes.color) ? - tile.geometry.attributes.color.array.slice(i * 3, i * 3 + 3) : - tile.material.color.toArray(); + tile.geometry.attributes.color.array.slice(i * 3, i * 3 + 3) : + tile.material.color.toArray(); vertexColor = previousColor; } @@ -215,8 +215,8 @@ export function createTileGroups(tile, materialsProps, ranges) { let mesh = getMeshFromTile(tile); let defaultMaterial = Array.isArray(mesh.material) ? - mesh.material[0] : - mesh.material; + mesh.material[0] : + mesh.material; // Reset the materials mesh.material = [ defaultMaterial ]; @@ -335,7 +335,7 @@ export function createTileGroupsFromBatchIDs(tile, groups) { if (materialIndex < 0) { // If the material is new, push it materialIndex = materials.length; - materials.push(group.material) + materials.push(group.material); } // Push the batch IDs and remember their material diff --git a/src/Components/3DTiles/Model/CityObject.js b/src/Components/3DTiles/Model/CityObject.js index 2cf7a218e..b50305560 100644 --- a/src/Components/3DTiles/Model/CityObject.js +++ b/src/Components/3DTiles/Model/CityObject.js @@ -1,4 +1,4 @@ -import { Tile } from "./Tile.js"; +import { Tile } from './Tile.js'; import * as THREE from 'three'; /** diff --git a/src/Components/3DTiles/Model/CityObjectStyle.js b/src/Components/3DTiles/Model/CityObjectStyle.js index 0ee07dff1..7c3c4c509 100644 --- a/src/Components/3DTiles/Model/CityObjectStyle.js +++ b/src/Components/3DTiles/Model/CityObjectStyle.js @@ -1,4 +1,4 @@ -import * as THREE from "three"; +import * as THREE from 'three'; /** * Represents the style of a tile part. Accepted parameters are : @@ -14,7 +14,7 @@ export class CityObjectStyle { */ this.materialProps = null; - if (typeof(params) !== "object") { + if (typeof(params) !== 'object') { throw 'TilePartStyle require parameters in its constructor'; } diff --git a/src/Components/3DTiles/StyleManager.js b/src/Components/3DTiles/StyleManager.js index c72c513eb..5f668076e 100644 --- a/src/Components/3DTiles/StyleManager.js +++ b/src/Components/3DTiles/StyleManager.js @@ -1,7 +1,7 @@ -import { CityObjectStyle } from "./Model/CityObjectStyle.js"; -import { CityObjectID } from "./Model/CityObject.js"; -import { createTileGroups } from "./3DTilesUtils.js"; -import { Tile } from "./Model/Tile.js"; +import { CityObjectStyle } from './Model/CityObjectStyle.js'; +import { CityObjectID } from './Model/CityObject.js'; +import { createTileGroups } from './3DTilesUtils.js'; +import { Tile } from './Model/Tile.js'; /** * Class used to manage the styles of city objects. @@ -115,9 +115,9 @@ export class StyleManager { * @returns {CityObjectStyle} */ getStyle(identifier) { - if (typeof(identifier) === "string") { + if (typeof(identifier) === 'string') { return this.registeredStyles[identifier]; - } else if (typeof(identifier) === "number") { + } else if (typeof(identifier) === 'number') { return this.anonymousStyles[identifier]; } throw 'Style identifier must be a string or a number'; @@ -197,7 +197,7 @@ export class StyleManager { this._registerUsage(styleIdentifier, cityObjectId); } else if (Array.isArray(cityObjectId)) { cityObjectId.sort((idA, idB) => { - return idA.tileId - idB.tileId + return idA.tileId - idB.tileId; }); for (let id of cityObjectId) { if (this.styleTable[id.tileId] === undefined) { diff --git a/src/Components/3DTiles/TilesManager.js b/src/Components/3DTiles/TilesManager.js index 792e03d0c..12b645fa5 100644 --- a/src/Components/3DTiles/TilesManager.js +++ b/src/Components/3DTiles/TilesManager.js @@ -1,9 +1,9 @@ -import { Tile } from "./Model/Tile.js"; -import { getVisibleTiles, updateITownsView } from "./3DTilesUtils.js"; -import { CityObjectID, CityObject, createCityObjectID } from "./Model/CityObject.js"; -import { CityObjectStyle } from "./Model/CityObjectStyle.js"; -import { StyleManager } from "./StyleManager.js"; -import { EventSender } from "../Events/EventSender.js"; +import { Tile } from './Model/Tile.js'; +import { getVisibleTiles, updateITownsView } from './3DTilesUtils.js'; +import { CityObjectID, CityObject, createCityObjectID } from './Model/CityObject.js'; +import { CityObjectStyle } from './Model/CityObjectStyle.js'; +import { StyleManager } from './StyleManager.js'; +import { EventSender } from '../Events/EventSender.js'; /** * Manages the tiles and the style for city objects. @@ -54,15 +54,15 @@ export class TilesManager extends EventSender { this.tiles = []; if (this.totalTileCount !== 0) { - // Load existing tiles - const tiles = getVisibleTiles(this.layer); - for (let tile of tiles) { - if (this.tiles[tile.tileId] === undefined) { - this.tiles[tile.tileId] = new Tile(this.layer, tile.tileId); - this.tiles[tile.tileId].loadCityObjects(); - this.loadedTileCount += 1; - } + // Load existing tiles + const tiles = getVisibleTiles(this.layer); + for (let tile of tiles) { + if (this.tiles[tile.tileId] === undefined) { + this.tiles[tile.tileId] = new Tile(this.layer, tile.tileId); + this.tiles[tile.tileId].loadCityObjects(); + this.loadedTileCount += 1; } + } } ///// EVENTS @@ -93,22 +93,22 @@ export class TilesManager extends EventSender { } loadTile(tile) { - // Update the totalTileCount. - // TODO: this should be managed with an event: when the tileset is - // loaded (i.e. tileIndex filled), then totalTileCount should be set. - this.totalTileCount = this.layer.tileset.tiles.length; - // Verifies that the tile has not been already added (might be removed - // when tile unloading will be managed) - if (this.tiles[tile.tileId] === undefined) { - this.tiles[tile.tileId] = new Tile(this.layer, tile.tileId); - this.tiles[tile.tileId].loadCityObjects(); - this.loadedTileCount += 1; - } - // Callback when a tile is loaded. - // TODO: Les tuiles d'iTowns devraient etre rendues invisibles plutot - // que d'etre déchargées et rechargées. A ce moment là, ce callback - // pourra etre dans le if ci dessus - this.sendEvent(TilesManager.EVENT_TILE_LOADED, tile); + // Update the totalTileCount. + // TODO: this should be managed with an event: when the tileset is + // loaded (i.e. tileIndex filled), then totalTileCount should be set. + this.totalTileCount = this.layer.tileset.tiles.length; + // Verifies that the tile has not been already added (might be removed + // when tile unloading will be managed) + if (this.tiles[tile.tileId] === undefined) { + this.tiles[tile.tileId] = new Tile(this.layer, tile.tileId); + this.tiles[tile.tileId].loadCityObjects(); + this.loadedTileCount += 1; + } + // Callback when a tile is loaded. + // TODO: Les tuiles d'iTowns devraient etre rendues invisibles plutot + // que d'etre déchargées et rechargées. A ce moment là, ce callback + // pourra etre dans le if ci dessus + this.sendEvent(TilesManager.EVENT_TILE_LOADED, tile); } /** diff --git a/src/Components/Camera/CameraUtils.js b/src/Components/Camera/CameraUtils.js index 74d5815b5..f5cb1794e 100644 --- a/src/Components/Camera/CameraUtils.js +++ b/src/Components/Camera/CameraUtils.js @@ -1,6 +1,10 @@ +/** @format */ + +const THREE = require('three'); + /** * Makes the camera move to focus on the target position. - * + * * @param {itowns.View} view The iTowns view. * @param {itowns.PlanarControls} controls The camera controls. * @param {THREE.Vector3} targetPos The target position. @@ -23,10 +27,11 @@ export function focusCameraOn(view, controls, targetPos, options = {}) { const horizontalDist = options.horizontalDistance || 1000; let cameraPos = view.camera.camera3D.position.clone(); - const direction = (new THREE.Vector3()).subVectors(targetPos, cameraPos); - const currentDist = Math.sqrt(direction.x * direction.x + - direction.y * direction.y); - cameraPos.addScaledVector(direction, (1 - horizontalDist / currentDist)); + const direction = new THREE.Vector3().subVectors(targetPos, cameraPos); + const currentDist = Math.sqrt( + direction.x * direction.x + direction.y * direction.y + ); + cameraPos.addScaledVector(direction, 1 - horizontalDist / currentDist); cameraPos.z = targetPos.z + verticalDist; const travelDuration = duration ? duration : 'auto'; const timeoutDuration = duration ? duration * 1000 : 0; @@ -36,4 +41,4 @@ export function focusCameraOn(view, controls, targetPos, options = {}) { reject(e); } }); -} \ No newline at end of file +} diff --git a/src/Components/Camera/PositionerWindow.js b/src/Components/Camera/PositionerWindow.js index 81ad9ecef..fc2c3eed3 100644 --- a/src/Components/Camera/PositionerWindow.js +++ b/src/Components/Camera/PositionerWindow.js @@ -1,4 +1,4 @@ -import { Window } from "../GUI/js/Window"; +import { Window } from '../GUI/js/Window'; import { MAIN_LOOP_EVENTS } from 'itowns'; import * as THREE from 'three'; @@ -60,7 +60,7 @@ export class PositionerWindow extends Window { this.buttonValidateElement.onclick = () => { this._validate(); - } + }; } ///////////////////////// diff --git a/src/Components/DataProcessing/DataProcessing.js b/src/Components/DataProcessing/DataProcessing.js index c0c6f0baa..4da11ed30 100644 --- a/src/Components/DataProcessing/DataProcessing.js +++ b/src/Components/DataProcessing/DataProcessing.js @@ -3,14 +3,17 @@ * would update those fields to an empty string if they were sent in the * body. To check if a value is empty, this function just convert it into * a boolean. + * + * @format * @param {FormData} formData The form data. * @returns The same data, without the fields containing an empty value. */ + export function removeEmptyValues(formData) { let emptyKeys = []; formData.forEach((value, key) => { if (!value) { - emptyKeys.push(key) + emptyKeys.push(key); } }); emptyKeys.forEach((key) => { @@ -24,7 +27,7 @@ export function removeEmptyValues(formData) { * on a file) to a data URI. This is required, for example, to display images * fetched from the server. As we need authentication headers to retrieve some * protected files, we get the raw data dynamically and need to convert it to - * a data URI do display it. + * a data URI do display it. * The basic scheme of the URI is defined in the * [RFC 2397](https://tools.ietf.org/html/rfc2397), with the mediaType set to * `mimeType` and the raw data converted to base64. @@ -45,12 +48,13 @@ export function imageToDataURI(arrayBuffer, mimeType, chunkSize = 8 * 1024) { // String.fromCharCode), we need to split it into chunks let responseAsString = ''; for (let i = 0; i < responseArray.length / chunkSize; i++) { - responseAsString += String.fromCharCode.apply(null, - responseArray.slice(i * chunkSize, (i + 1) * chunkSize)); + responseAsString += String.fromCharCode.apply( + null, + responseArray.slice(i * chunkSize, (i + 1) * chunkSize) + ); } - let b64data = 'data:' + mimeType - + ';base64,' + btoa(responseAsString); + let b64data = 'data:' + mimeType + ';base64,' + btoa(responseAsString); return b64data; } @@ -58,11 +62,11 @@ export function imageToDataURI(arrayBuffer, mimeType, chunkSize = 8 * 1024) { * Gets an attribute of an object from the given path. To get nested attributes, * the path qualifiers must be separated by dots ('.'). If the path is not * nested (does not contain any dot), the function is equivalent to `obj[path]`. - * - * - * @param {object} obj - * @param {string} path - * + * + * + * @param {object} obj + * @param {string} path + * * @example * const obj = {test: {msg: "Hello world !"}}; * console.log(getAttributeByPath(obj, "test.msg")); // prints "Hello world !"; @@ -83,7 +87,7 @@ export function getAttributeByPath(obj, path) { /** * Checks the equality of two objects by their properties. For two objects to * be equal, they must have the same keys and the same values. - * + * * @param {any} a An object. * @param {any} b An object. */ @@ -91,16 +95,16 @@ export function objectEquals(a, b) { // Set of a's keys let keys = new Set(Object.keys(a)); for (let key of Object.keys(b)) { - if (!keys.has(key)) { + if (!keys.has(key)) { // If b has a key unknown to a, they aren't equal - return false; + return false; } } for (let key of keys) { // For each key of a, b must also have the key and the values must be equal if (b[key] === undefined || a[key] !== b[key]) { - return false; + return false; } } return true; -}; \ No newline at end of file +} diff --git a/src/Components/Events/EventSender.js b/src/Components/Events/EventSender.js index 212c1a9e5..78fe89c43 100644 --- a/src/Components/Events/EventSender.js +++ b/src/Components/Events/EventSender.js @@ -4,98 +4,98 @@ * specific events, or to all events. */ export class EventSender { - constructor() { - /** + constructor() { + /** * The listeners attached to a specific event. * * @type {Object. any>>} */ - this.eventListeners = {}; - /** + this.eventListeners = {}; + /** * The listeners attached to no particular event. They will receive * all notifications. * * @type {Array<(data: any) => any>} */ - this.allEventsListeners = []; - } + this.allEventsListeners = []; + } - /** + /** * Registers an event. Should be called by the implementing class to * specify its own events. * @param event The event to register. Can be of any type. The class will be * able to send only the events that it has registered. */ - registerEvent(event) { - this.eventListeners[event] = []; - } + registerEvent(event) { + this.eventListeners[event] = []; + } - /** + /** * Registers an event listener attached to a specific event. The `action` * function will be called only when `event` is fired. * * @param event The event to listen to. * @param {(data: any)} action The function to call. */ - addEventListener(event, action) { - if (this.eventListeners[event]) { - this.eventListeners[event].push(action); - } else { - throw `This event is not defined by this listener : ${event}`; - } + addEventListener(event, action) { + if (this.eventListeners[event]) { + this.eventListeners[event].push(action); + } else { + throw `This event is not defined by this listener : ${event}`; } + } - /** + /** * Registers an event listener attached to no specific event. The `action` * function will be called when any event is fired. * * @param {(event: any, data: any)} action The function to call. */ - addListener(action) { - if (typeof(action) !== 'function') { - throw 'A listener must be a function'; - } - this.allEventsListeners.push(action); + addListener(action) { + if (typeof(action) !== 'function') { + throw 'A listener must be a function'; } + this.allEventsListeners.push(action); + } - /** + /** * Sends an event to the listeners. `event` must be first registers through the `registerEvent` * method. An argument can be passed but is optional. * * @param event The event to fire. Must be first registered. * @param data The optional data to pass as parameter. */ - async sendEvent(event, data = null) { - let listeners = this.eventListeners[event]; - if (!!listeners) { - for (let action of listeners) { - action(data); - } - for (let action of this.allEventsListeners) { - action(event, data); - } - } else { - throw `This event must be registered before being sent : ${event}`; - } + async sendEvent(event, data = null) { + let listeners = this.eventListeners[event]; + if (listeners) { + for (let action of listeners) { + action(data); + } + for (let action of this.allEventsListeners) { + action(event, data); + } + } else { + throw `This event must be registered before being sent : ${event}`; } + } - /** + /** * Removes a specific event listener. * * @param {(data: any) => any} action The event listener to remove. This * should be the same reference that was used to register it. */ - removeEventListener(action) { - for (let eventListeners of Object.values(this.eventListeners)) { - let index = eventListeners.findIndex((list) => action === list); - if (index >= 0) { - eventListeners.splice(index, 1); - } - } + removeEventListener(action) { + for (let eventListeners of Object.values(this.eventListeners)) { + let index = eventListeners.findIndex((list) => action === list); + if (index >= 0) { + eventListeners.splice(index, 1); + } + } - let index = this.allEventsListeners.findIndex((list) => action === list); - if (index >= 0) { - this.allEventsListeners.splice(index, 1); - } + let index = this.allEventsListeners.findIndex((list) => action === list); + if (index >= 0) { + this.allEventsListeners.splice(index, 1); } + } } \ No newline at end of file diff --git a/src/Components/GUI/js/Draggable.js b/src/Components/GUI/js/Draggable.js index fe4149478..7ae2bef9e 100644 --- a/src/Components/GUI/js/Draggable.js +++ b/src/Components/GUI/js/Draggable.js @@ -1,44 +1,44 @@ // Code from https://www.w3schools.com/howto/howto_js_draggable.asp // Make the DIV element draggable: export function dragElement(elmnt, dragelmnt) { - var pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0; + var pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0; - dragelmnt.onmousedown = dragMouseDown; + dragelmnt.onmousedown = dragMouseDown; - function dragMouseDown(e) { - e = e || window.event; - // get the mouse cursor position at startup: - pos3 = e.clientX; - pos4 = e.clientY; - document.onmouseup = closeDragElement; - // call a function whenever the cursor moves: - document.onmousemove = elementDrag; - } + function dragMouseDown(e) { + e = e || window.event; + // get the mouse cursor position at startup: + pos3 = e.clientX; + pos4 = e.clientY; + document.onmouseup = closeDragElement; + // call a function whenever the cursor moves: + document.onmousemove = elementDrag; + } - function elementDrag(e) { - e = e || window.event; - e.preventDefault(); - // calculate the new cursor position: - pos1 = pos3 - e.clientX; - pos2 = pos4 - e.clientY; - pos3 = e.clientX; - pos4 = e.clientY; - // set the element's new position: - let newTop = (elmnt.offsetTop - pos2); - if (newTop < 0) { - newTop = 0; - } - let newLeft = (elmnt.offsetLeft - pos1); - if (newLeft < 0) { - newLeft = 0; - } - elmnt.style.top = newTop + "px"; - elmnt.style.left = newLeft + "px"; + function elementDrag(e) { + e = e || window.event; + e.preventDefault(); + // calculate the new cursor position: + pos1 = pos3 - e.clientX; + pos2 = pos4 - e.clientY; + pos3 = e.clientX; + pos4 = e.clientY; + // set the element's new position: + let newTop = (elmnt.offsetTop - pos2); + if (newTop < 0) { + newTop = 0; } - - function closeDragElement() { - // stop moving when mouse button is released: - document.onmouseup = null; - document.onmousemove = null; + let newLeft = (elmnt.offsetLeft - pos1); + if (newLeft < 0) { + newLeft = 0; } + elmnt.style.top = newTop + 'px'; + elmnt.style.left = newLeft + 'px'; + } + + function closeDragElement() { + // stop moving when mouse button is released: + document.onmouseup = null; + document.onmousemove = null; + } } \ No newline at end of file diff --git a/src/Components/GUI/js/Window.js b/src/Components/GUI/js/Window.js index 229bccd08..47d92c3b7 100644 --- a/src/Components/GUI/js/Window.js +++ b/src/Components/GUI/js/Window.js @@ -1,6 +1,6 @@ import { dragElement } from './Draggable.js'; import { ModuleView } from '../../ModuleView/ModuleView.js'; -import { windowManager } from "./WindowManager.js"; +import { windowManager } from './WindowManager.js'; import { WindowExtension } from './WindowExtension.js'; // Documentation is on the Wiki @@ -12,7 +12,7 @@ import { WindowExtension } from './WindowExtension.js'; * @extends ModuleView */ export class Window extends ModuleView { - /** + /** * Creates a window. * * @param {string} uniqueName The name used to generate HTML ids. @@ -21,160 +21,160 @@ export class Window extends ModuleView { * the 'close' button is hit. If set to true, the window will `hide`. If set * to false, the window will `dispose`. */ - constructor(uniqueName, title, hideOnClose = true) { - super(); + constructor(uniqueName, title, hideOnClose = true) { + super(); - /** + /** * Name of the window. Used to generate unique ids. * * @member {string} */ - this.name = uniqueName; - /** + this.name = uniqueName; + /** * Title displayed on the window. * * @member {string} */ - this.title = title; - /** + this.title = title; + /** * Behaviour of the window when the 'close' button is hit. If set to * true, the window will `hide`. If set to false, the window will * `dispose`. * * @member {boolean} */ - this.hideOnClose = hideOnClose; + this.hideOnClose = hideOnClose; - /** + /** * Defines if the window has its default style. If set to false, you * should override the `html` getter and set the `windowDisplayWhenVisible` * property. * * @type {true} */ - this.defaultStyle = true; + this.defaultStyle = true; - /** + /** * Define the css `display` property when the window is visible. * * @type {string} */ - this.windowDisplayWhenVisible = 'grid'; + this.windowDisplayWhenVisible = 'grid'; - /** + /** * The list of extensions for this window. * * @type {Array} */ - this.windowExtensions = []; + this.windowExtensions = []; - this.registerEvent(Window.EVENT_CREATED); - this.registerEvent(Window.EVENT_DESTROYED); - this.registerEvent(Window.EVENT_SHOWN); - this.registerEvent(Window.EVENT_HIDDEN); + this.registerEvent(Window.EVENT_CREATED); + this.registerEvent(Window.EVENT_DESTROYED); + this.registerEvent(Window.EVENT_SHOWN); + this.registerEvent(Window.EVENT_HIDDEN); - windowManager.registerWindow(this); - } + windowManager.registerWindow(this); + } - //////////// Methods to override - //////////////////////////////// + //////////// Methods to override + //////////////////////////////// - /** + /** * HTML string representing the inner content of the window. * * @abstract */ - get innerContentHtml() { - return null; - }; + get innerContentHtml() { + return null; + } - /** + /** * Method called when the window is created. During and after the call, * all HTML properties are not null. * * @abstract */ - windowCreated() { + windowCreated() { - }; + } - /** + /** * Method called when the window is destroyed. * * @abstract */ - windowDestroyed() { + windowDestroyed() { - }; + } - //////////// Do NOT override these methods - ////////////////////////////////////////// + //////////// Do NOT override these methods + ////////////////////////////////////////// - /** + /** * Creates the HTML elements of the window and add them to the given parent * node. Calls the `windowCreated` hook method and sends two events, * `EVENT_CREATED` and `EVENT_SHOWN`. * * @param {HTMLElement} htmlElement */ - appendTo(htmlElement) { - if (!this.isCreated) { - this.parentElement = htmlElement; - let windowDiv = document.createElement('div'); - windowDiv.innerHTML = this.html; - windowDiv.id = this.windowId; - htmlElement.appendChild(windowDiv); - if (this.defaultStyle) { - windowDiv.className = "window"; - dragElement(windowDiv, this.header); - this.headerCloseButton.onclick = this.disable.bind(this); - } - - for (let extension of this.windowExtensions) { - extension.appendTo(this.window); - } - - this.windowCreated(); - this.sendEvent(Window.EVENT_CREATED); - this.sendEvent(Window.EVENT_SHOWN); - } + appendTo(htmlElement) { + if (!this.isCreated) { + this.parentElement = htmlElement; + let windowDiv = document.createElement('div'); + windowDiv.innerHTML = this.html; + windowDiv.id = this.windowId; + htmlElement.appendChild(windowDiv); + if (this.defaultStyle) { + windowDiv.className = 'window'; + dragElement(windowDiv, this.header); + this.headerCloseButton.onclick = this.disable.bind(this); + } + + for (let extension of this.windowExtensions) { + extension.appendTo(this.window); + } + + this.windowCreated(); + this.sendEvent(Window.EVENT_CREATED); + this.sendEvent(Window.EVENT_SHOWN); } + } - /** + /** * Destroys the window. Calls the `windowDestroyed` hook method and sends an * `EVENT_DESTROYED` event. */ - dispose() { - if (this.isCreated) { - this.parentElement.removeChild(this.window); + dispose() { + if (this.isCreated) { + this.parentElement.removeChild(this.window); - this.windowDestroyed(); - this.sendEvent(Window.EVENT_DESTROYED); - } + this.windowDestroyed(); + this.sendEvent(Window.EVENT_DESTROYED); } + } - /** + /** * Shows the window. Sends an `EVENT_SHOWN` event. */ - show() { - if (this.isCreated && !this.isVisible) { - this.window.style.setProperty('display', this.windowDisplayWhenVisible); - this.sendEvent(Window.EVENT_SHOWN); - } + show() { + if (this.isCreated && !this.isVisible) { + this.window.style.setProperty('display', this.windowDisplayWhenVisible); + this.sendEvent(Window.EVENT_SHOWN); } + } - /** + /** * Hides the window. Sends an `EVENT_DESTROYED` event. */ - hide() { - if (this.isVisible) { - this.window.style.setProperty('display', 'none'); - this.sendEvent(Window.EVENT_HIDDEN); - } + hide() { + if (this.isVisible) { + this.window.style.setProperty('display', 'none'); + this.sendEvent(Window.EVENT_HIDDEN); } + } - get html() { - return ` + get html() { + return `

${this.title}

@@ -185,12 +185,12 @@ export class Window extends ModuleView {

`; - } + } - //////////// Extensions management - ////////////////////////////////// + //////////// Extensions management + ////////////////////////////////// - /** + /** * Adds a new extension in the window. * * @param {string} label The unique label for the extension. @@ -206,138 +206,138 @@ export class Window extends ModuleView { * @param {function} [options.callback] The callback to call when the user * clicks on a `button` extension. This has no effects on `div` extensions. */ - addExtension(label, options) { - options.id = `${this.windowId}__extensions_${label.toLowerCase().replace(/ +/, '_')}`; - let extension = new WindowExtension(label, options); - if (!!this.windowExtensions.find(ext => ext.label === label)) { - throw 'Extension already exist : ' + label; - } - this.windowExtensions.push(extension); - - if (this.isCreated) { - extension.appendTo(this.window); - } + addExtension(label, options) { + options.id = `${this.windowId}__extensions_${label.toLowerCase().replace(/ +/, '_')}`; + let extension = new WindowExtension(label, options); + if (this.windowExtensions.find(ext => ext.label === label)) { + throw 'Extension already exist : ' + label; } + this.windowExtensions.push(extension); - /** + if (this.isCreated) { + extension.appendTo(this.window); + } + } + + /** * Removes an existing extension from the window. * * @param {string} label The label identifying the extension to remove. */ - removeExtension(label) { - let index = this.windowExtensions.findIndex(ext => ext.label === label); - if (index < 0) { - throw 'Extension does not exist : ' + label; - } - - let extension = this.windowExtensions[index]; - if (this.isCreated) { - let extensionElement = document.getElementById(extension.id); - extensionElement.parentElement.removeChild(extensionElement); - } - - this.windowExtensions.splice(index, 1); + removeExtension(label) { + let index = this.windowExtensions.findIndex(ext => ext.label === label); + if (index < 0) { + throw 'Extension does not exist : ' + label; } - //////////// Module view overrides - ////////////////////////////////// + let extension = this.windowExtensions[index]; + if (this.isCreated) { + let extensionElement = document.getElementById(extension.id); + extensionElement.parentElement.removeChild(extensionElement); + } - /** + this.windowExtensions.splice(index, 1); + } + + //////////// Module view overrides + ////////////////////////////////// + + /** * Creates and show the window. * * @override */ - async enableView() { - this.appendTo(this.parentElement); - this.show(); - } + async enableView() { + this.appendTo(this.parentElement); + this.show(); + } - /** + /** * If `hideOnClose` is `true`, hides the window. Else, destroys it. * * @override */ - async disableView() { - if (this.hideOnClose) { - this.hide(); - } else { - this.dispose(); - } - } - - //////////// IDs, HTML and other getters - //////////////////////////////////////// - - get isCreated() { - let windowDiv = this.window; - return windowDiv !== null && windowDiv !== undefined; - } - - get isVisible() { - return this.isCreated && window.getComputedStyle(this.window).getPropertyValue('display') === this.windowDisplayWhenVisible; - } - - get windowId() { - return `_window_${this.name}`; - } - - get window() { - return document.getElementById(this.windowId); - } - - get headerId() { - return `_window_header_${this.name}`; - } - - get header() { - return document.getElementById(this.headerId); - } - - get headerTitleId() { - return `_window_header_title_${this.name}`; - } - - get headerTitle() { - return document.getElementById(this.headerTitleId); - } - - get headerCloseButtonId() { - return `_window_header_close_button_${this.name}`; - } - - get headerCloseButton() { - return document.getElementById(this.headerCloseButtonId); - } - - get contentId() { - return `_window_content_${this.name}`; - } - - get content() { - return document.getElementById(this.contentId); - } - - get innerContentId() { - return `_window_inner_content_${this.name}`; - } - - get innerContent() { - return document.getElementById(this.innerContentId); - } - - //////////// Events - /////////////////// - - static get EVENT_CREATED() { - return 'WINDOW_CREATED'; - } - static get EVENT_DESTROYED() { - return 'WINDOW_DESTROYED'; - } - static get EVENT_HIDDEN() { - return 'WINDOW_HIDDEN'; - } - static get EVENT_SHOWN() { - return 'WINDOW_SHOWN'; + async disableView() { + if (this.hideOnClose) { + this.hide(); + } else { + this.dispose(); } + } + + //////////// IDs, HTML and other getters + //////////////////////////////////////// + + get isCreated() { + let windowDiv = this.window; + return windowDiv !== null && windowDiv !== undefined; + } + + get isVisible() { + return this.isCreated && window.getComputedStyle(this.window).getPropertyValue('display') === this.windowDisplayWhenVisible; + } + + get windowId() { + return `_window_${this.name}`; + } + + get window() { + return document.getElementById(this.windowId); + } + + get headerId() { + return `_window_header_${this.name}`; + } + + get header() { + return document.getElementById(this.headerId); + } + + get headerTitleId() { + return `_window_header_title_${this.name}`; + } + + get headerTitle() { + return document.getElementById(this.headerTitleId); + } + + get headerCloseButtonId() { + return `_window_header_close_button_${this.name}`; + } + + get headerCloseButton() { + return document.getElementById(this.headerCloseButtonId); + } + + get contentId() { + return `_window_content_${this.name}`; + } + + get content() { + return document.getElementById(this.contentId); + } + + get innerContentId() { + return `_window_inner_content_${this.name}`; + } + + get innerContent() { + return document.getElementById(this.innerContentId); + } + + //////////// Events + /////////////////// + + static get EVENT_CREATED() { + return 'WINDOW_CREATED'; + } + static get EVENT_DESTROYED() { + return 'WINDOW_DESTROYED'; + } + static get EVENT_HIDDEN() { + return 'WINDOW_HIDDEN'; + } + static get EVENT_SHOWN() { + return 'WINDOW_SHOWN'; + } } \ No newline at end of file diff --git a/src/Components/GUI/js/WindowExtension.js b/src/Components/GUI/js/WindowExtension.js index 8a95604ef..71b9e9201 100644 --- a/src/Components/GUI/js/WindowExtension.js +++ b/src/Components/GUI/js/WindowExtension.js @@ -105,17 +105,17 @@ export class WindowExtension { */ findContainer(htmlRoot) { let queries = []; - if (!!this.container) { + if (this.container) { queries.push(`[data-ext-container="${this.type}-${this.container}"]`); queries.push(`[data-ext-container="${this.container}"]`); } - queries.push(`[data-ext-container="${this.type}"]`) - queries.push(`[data-ext-container-default="${this.type}"]`) + queries.push(`[data-ext-container="${this.type}"]`); + queries.push(`[data-ext-container-default="${this.type}"]`); let container; for (let query of queries) { container = htmlRoot.querySelector(query); - if (!!container) { + if (container) { break; } } diff --git a/src/Components/GUI/js/WindowManager.js b/src/Components/GUI/js/WindowManager.js index 5456ce52e..b57112f77 100644 --- a/src/Components/GUI/js/WindowManager.js +++ b/src/Components/GUI/js/WindowManager.js @@ -1,4 +1,4 @@ -import { Window } from "./Window.js"; +import { Window } from './Window.js'; const BASE_Z_INDEX = 100; diff --git a/src/Components/LayerManager/LayerManager.js b/src/Components/LayerManager/LayerManager.js index 3b15de9d0..d1435421c 100644 --- a/src/Components/LayerManager/LayerManager.js +++ b/src/Components/LayerManager/LayerManager.js @@ -1,247 +1,247 @@ -import { getFirstTileIntersection, getBatchIdFromIntersection, getObject3DFromTile, getVisibleTileCount } from "../3DTiles/3DTilesUtils.js"; +import { getFirstTileIntersection, getBatchIdFromIntersection, getObject3DFromTile, getVisibleTileCount } from '../3DTiles/3DTilesUtils.js'; export class LayerManager { - /** + /** * Creates a new TilesManager from an iTowns view and the 3DTiles layer. * * @param {*} view The iTowns view. */ - constructor(view) { - /** + constructor(view) { + /** * The iTowns view. */ - this.view = view; + this.view = view; - /** + /** * The set of tiles Manager that have been loaded. * @type {Array} */ - this.tilesManagers = []; - } + this.tilesManagers = []; + } - /** + /** * Register a new or modify an existing registered style for all tilesManager. * * @param {string} name A name to identify the style. * @param {CityObjectStyle} style The style to register. */ - registerStyle(name, style) { - this.tilesManagers.forEach(function(tilesManager){ - tilesManager.registerStyle(name, style); - }); - } + registerStyle(name, style) { + this.tilesManagers.forEach(function(tilesManager){ + tilesManager.registerStyle(name, style); + }); + } - /** + /** * Removes all styles currently registered. */ - removeAll3DTilesStyles() { - this.tilesManagers.forEach(function(tilesManager){ - tilesManager.removeAllStyles(); - }); - } + removeAll3DTilesStyles() { + this.tilesManagers.forEach(function(tilesManager){ + tilesManager.removeAllStyles(); + }); + } - /** + /** * Applies the current styles added with `setStyle` or `addStyle`. * * @param {object} options Options of the method. * @param {() => any} [options.updateFunction] The function used to update the * view. Default is `udpateITownsView(view, layer)`. */ - applyAll3DTilesStyles(options = {}) { - this.tilesManagers.forEach(function(tilesManager){ - tilesManager.applyStyles(options); - }); - } + applyAll3DTilesStyles(options = {}) { + this.tilesManagers.forEach(function(tilesManager){ + tilesManager.applyStyles(options); + }); + } - /** + /** * Check if at least one 3DTiles layer is visible * * @returns {boolean} */ - isOneLayerVisible() { - for (let i = 0; i < this.tilesManagers.length; i++) { - if (this.tilesManagers[i].layer.visible) { - return true; - } - } - return false; + isOneLayerVisible() { + for (let i = 0; i < this.tilesManagers.length; i++) { + if (this.tilesManagers[i].layer.visible) { + return true; + } } + return false; + } - /** + /** * Change the visibilty of all 3DTiles layers * */ - changeVisibility(bool) { - this.tilesManagers.forEach(function(tilesManager){ - tilesManager.layer.visible = bool ; - }); - } + changeVisibility(bool) { + this.tilesManagers.forEach(function(tilesManager){ + tilesManager.layer.visible = bool ; + }); + } - /** + /** * Update the scale of the given layer * @param {itowns.Layer} layer one layer loaded. * @param {float} scale Value of the new scale */ - updateScale(layer, scale) { - layer.scale = scale; - this.notifyChange(); - } + updateScale(layer, scale) { + layer.scale = scale; + this.notifyChange(); + } - /** + /** * Update the opacity of the given layer * @param {itowns.Layer} layer one layer loaded. * @param {float} opacity Value of the new scale */ - updateOpacity(layer, opacity) { - layer.opacity = opacity; - this.notifyChange(); - } - /** + updateOpacity(layer, opacity) { + layer.opacity = opacity; + this.notifyChange(); + } + /** * Update the view when called. Must be called when a change have been made * The view.camera.camera3D is passed to actualize all of the layer, but the * the documentation of notifyChange says taht it should not be needed */ - notifyChange() { - this.view.notifyChange(this.view.camera.camera3D); - } + notifyChange() { + this.view.notifyChange(this.view.camera.camera3D); + } - /** + /** * Returns the city object under the mouse cursor. * * @param {MouseEvent} event The mouse event. * * @returns {CityObject | undefined} */ - pickCityObject(event) { - /** + pickCityObject(event) { + /** * Make sure the event is captured by a click listener attached * to the div#viewerDiv, which contains the iTowns canvas. All click * listeners should be instantiated this way as of iTowns 2.24.0 */ - if (event.currentTarget.id.toUpperCase() === 'VIEWERDIV') { - // Get the intersecting objects where our mouse pointer is - let intersections = []; - //As the current pickObjectsAt on all layer is not working, we need - //to call pickObjectsAt() for each layer. - for (let i = 0; i < this.tilesManagers.length; i++) { - intersections = intersections.concat(this.view.pickObjectsAt( - event, - 5, - this.tilesManagers[i].layer - )); - } - let firstInter = getFirstTileIntersection(intersections); - if (!!firstInter) { - let tilesManager = this.getTilesManagerByLayerID(firstInter.layer.id); - let batchId = getBatchIdFromIntersection(firstInter); - let tileId = getObject3DFromTile(firstInter.object).tileId; - return tilesManager.tiles[tileId].cityObjects[batchId]; - } - } - return undefined; - } - - /** + if (event.currentTarget.id.toUpperCase() === 'VIEWERDIV') { + // Get the intersecting objects where our mouse pointer is + let intersections = []; + //As the current pickObjectsAt on all layer is not working, we need + //to call pickObjectsAt() for each layer. + for (let i = 0; i < this.tilesManagers.length; i++) { + intersections = intersections.concat(this.view.pickObjectsAt( + event, + 5, + this.tilesManagers[i].layer + )); + } + let firstInter = getFirstTileIntersection(intersections); + if (firstInter) { + let tilesManager = this.getTilesManagerByLayerID(firstInter.layer.id); + let batchId = getBatchIdFromIntersection(firstInter); + let tileId = getObject3DFromTile(firstInter.object).tileId; + return tilesManager.tiles[tileId].cityObjects[batchId]; + } + } + return undefined; + } + + /** * Returns a tilesManager given a layer ID. * * @param {string} id the layer ID. * * @returns {TilesManager} */ - getTilesManagerByLayerID(id) { - for (let i = 0; i < this.tilesManagers.length; i++) { - if (this.tilesManagers[i].layer.id === id) - return this.tilesManagers[i]; - } + getTilesManagerByLayerID(id) { + for (let i = 0; i < this.tilesManagers.length; i++) { + if (this.tilesManagers[i].layer.id === id) + return this.tilesManagers[i]; } + } - /** + /** * Get all Layers loaded in the view. */ - getLayers() { - return this.view.getLayers(); - } + getLayers() { + return this.view.getLayers(); + } - /** + /** * Get the number of tiles that have been loaded, across all the tileset that * have been loaded * * @returns {int} */ - getLoaded3DTilesTileCount() { - let loadedTileCount = 0; - for (let i = 0; i < this.tilesManagers.length; i++) { - loadedTileCount += this.tilesManagers[i].loadedTileCount; - } - return loadedTileCount; + getLoaded3DTilesTileCount() { + let loadedTileCount = 0; + for (let i = 0; i < this.tilesManagers.length; i++) { + loadedTileCount += this.tilesManagers[i].loadedTileCount; } + return loadedTileCount; + } - /** + /** * Get the number of tiles across all the tileset * * @returns {int} */ - getTotal3DTilesTileCount() { - let totalTileCount = 0; - for (let i = 0; i < this.tilesManagers.length; i++) { - totalTileCount += this.tilesManagers[i].totalTileCount; - } - return totalTileCount; + getTotal3DTilesTileCount() { + let totalTileCount = 0; + for (let i = 0; i < this.tilesManagers.length; i++) { + totalTileCount += this.tilesManagers[i].totalTileCount; } + return totalTileCount; + } - /** + /** * Get the number of tiles visible, across all the tileset that * have been loaded * * @returns {int} */ - getVisible3DTilesTileCountFromLayers() { - let visibleTileCount = 0; - for (let i = 0; i < this.tilesManagers.length; i++) { - visibleTileCount += getVisibleTileCount(this.tilesManagers[i].layer); - } - return visibleTileCount; + getVisible3DTilesTileCountFromLayers() { + let visibleTileCount = 0; + for (let i = 0; i < this.tilesManagers.length; i++) { + visibleTileCount += getVisibleTileCount(this.tilesManagers[i].layer); } + return visibleTileCount; + } - /** + /** * Get Color layers in the view * * @returns {Array} */ - getColorLayers() { - return this.view.getLayers(layer => layer.isColorLayer); - } + getColorLayers() { + return this.view.getLayers(layer => layer.isColorLayer); + } - /** + /** * Get Elevation layers in the view * * @returns {Array} */ - getElevationLayers() { - return this.view.getLayers(layer => layer.isElevationLayer); - } + getElevationLayers() { + return this.view.getLayers(layer => layer.isElevationLayer); + } - /** + /** * Get Geometry layers in the view * * @returns {Array} */ - getGeometryLayers() { - return this.view.getLayers(layer => layer.isGeometryLayer); - } + getGeometryLayers() { + return this.view.getLayers(layer => layer.isGeometryLayer); + } - /** + /** * Get Geometry layers in the view, without the planar one * * @returns {Array} */ - getGeometryLayersWithoutPlanar() { - return this.view.getLayers(layer => layer.id !== "planar" + getGeometryLayersWithoutPlanar() { + return this.view.getLayers(layer => layer.id !== 'planar' && layer.isGeometryLayer); - } + } } diff --git a/src/Components/ModuleView/ModuleView.js b/src/Components/ModuleView/ModuleView.js index de1e4847b..77e4f819c 100644 --- a/src/Components/ModuleView/ModuleView.js +++ b/src/Components/ModuleView/ModuleView.js @@ -5,82 +5,82 @@ import { EventSender } from '../Events/EventSender.js'; * a module, but is strongly advised as it simplifies the integration is demos. */ export class ModuleView extends EventSender { - /** + /** * Creates a new ModuleView. */ - constructor() { - super(); + constructor() { + super(); - /** + /** * Represents the parent HTML element of this view. Must be defined * by the user of the view * * @member {HTMLElement} */ - this.parentElement = null; + this.parentElement = null; - this.registerEvent(ModuleView.EVENT_ENABLED); - this.registerEvent(ModuleView.EVENT_DISABLED); - } + this.registerEvent(ModuleView.EVENT_ENABLED); + this.registerEvent(ModuleView.EVENT_DISABLED); + } - ///////// Overideable methods - // These methods should be overriden by the implementing class - // By default, they do nothing. They are supposed to enable - // or disable the view. (Can be done by destroying / creating, or - // by hiding, showing). - // These methods should never be called manually as they do not - // send appropriate events. - /** + ///////// Overideable methods + // These methods should be overriden by the implementing class + // By default, they do nothing. They are supposed to enable + // or disable the view. (Can be done by destroying / creating, or + // by hiding, showing). + // These methods should never be called manually as they do not + // send appropriate events. + /** * Must be overriden by the implementing class. Supposedly enables the view. * @abstract */ - async enableView() { } - /** + async enableView() { } + /** * Must be overriden by the implementing class. Supposedly disables the view. * @abstract */ - async disableView() { } + async disableView() { } - ///////// Do not override - // These methods are the public methods called to destroy or - // create the view. - /** + ///////// Do not override + // These methods are the public methods called to destroy or + // create the view. + /** * Enables the view (depends on the implementation). * * Sends a EVENT_ENABLED event once the view is enabled. * * @async */ - async enable() { - await this.enableView(); - this.sendEvent(ModuleView.EVENT_ENABLED); - } + async enable() { + await this.enableView(); + this.sendEvent(ModuleView.EVENT_ENABLED); + } - /** + /** * Disables the view (depends on the implementation). * * Sends a EVENT_DISABLED event once the view is disabled. * * @async */ - async disable() { - await this.disableView(); - this.sendEvent(ModuleView.EVENT_DISABLED); - } + async disable() { + await this.disableView(); + this.sendEvent(ModuleView.EVENT_DISABLED); + } - ///////// Events - // Events called when enabling / disabling the view - /** + ///////// Events + // Events called when enabling / disabling the view + /** * Event sent when the view is enabled */ - static get EVENT_ENABLED() { - return 'MODULE_VIEW_ENABLED'; - } + static get EVENT_ENABLED() { + return 'MODULE_VIEW_ENABLED'; + } - /** + /** * Event sent when the view is disabled */ - static get EVENT_DISABLED() { - return 'MODULE_VIEW_DISABLED'; - } + static get EVENT_DISABLED() { + return 'MODULE_VIEW_DISABLED'; + } } \ No newline at end of file diff --git a/src/Components/Request/RequestService.js b/src/Components/Request/RequestService.js index c11472fa6..6b39fe2cb 100644 --- a/src/Components/Request/RequestService.js +++ b/src/Components/Request/RequestService.js @@ -1,30 +1,30 @@ // Service used to make HTTP requests and manage authentication // Wiki : https://github.com/MEPP-team/UD-Viz/wiki/Request-Service#request-service export function RequestService() { - // eslint-disable-next-line no-unused-expressions - this.authenticationService; - this.useAuthentication = false; + // eslint-disable-next-line no-unused-expressions + this.authenticationService; + this.useAuthentication = false; - // eslint-disable-next-line func-names - this.initialize = function () { + // eslint-disable-next-line func-names + this.initialize = function () { - }; + }; - /** + /** * @deprecated Prefer using `RequestService.request` instead. * // eslint-disable-next-line valid-jsdoc */ - // eslint-disable-next-line func-names - this.send = function (method, url, body = '', authenticate = true) { - return this.request(method, url, { - // eslint-disable-next-line object-shorthand - body: body, - // eslint-disable-next-line object-shorthand - authenticate: authenticate, - }); - }; + // eslint-disable-next-line func-names + this.send = function (method, url, body = '', authenticate = true) { + return this.request(method, url, { + // eslint-disable-next-line object-shorthand + body: body, + // eslint-disable-next-line object-shorthand + authenticate: authenticate, + }); + }; - /** + /** * Performs an HTTP request. * * @async @@ -43,64 +43,64 @@ export function RequestService() { * * @returns {Promise} */ - this.request = (method, url, options = {}) => { - const args = options || {}; - const body = args.body || ''; - let authenticate = (args.authenticate !== null + this.request = (method, url, options = {}) => { + const args = options || {}; + const body = args.body || ''; + let authenticate = (args.authenticate !== null && args.authenticate !== undefined) ? - args.authenticate : true; - if (authenticate === 'auto') { - authenticate = !!window.sessionStorage.getItem('user.token'); + args.authenticate : true; + if (authenticate === 'auto') { + authenticate = !!window.sessionStorage.getItem('user.token'); + } + const responseType = args.responseType || null; + const urlParameters = args.urlParameters || null; + return new Promise((resolve, reject) => { + const req = new XMLHttpRequest(); + if (!!urlParameters) { // eslint-disable-line no-extra-boolean-cast + url += '?'; + for (const [paramKey, paramValue] of Object.entries(urlParameters)) { + url += `${encodeURIComponent(paramKey)}=${encodeURIComponent(paramValue)}&`; } - const responseType = args.responseType || null; - const urlParameters = args.urlParameters || null; - return new Promise((resolve, reject) => { - const req = new XMLHttpRequest(); - if (!!urlParameters) { // eslint-disable-line no-extra-boolean-cast - url += '?'; - for (const [paramKey, paramValue] of Object.entries(urlParameters)) { - url += `${encodeURIComponent(paramKey)}=${encodeURIComponent(paramValue)}&`; - } - } - req.open(method, url, true); + } + req.open(method, url, true); - if (this.useAuthentication && authenticate) { - const token = window.sessionStorage.getItem('user.token'); - if (token === null) { - reject(new AuthNeededError()); - return; - } - req.setRequestHeader('Authorization', `Bearer ${token}`); - } + if (this.useAuthentication && authenticate) { + const token = window.sessionStorage.getItem('user.token'); + if (token === null) { + reject(new AuthNeededError()); + return; + } + req.setRequestHeader('Authorization', `Bearer ${token}`); + } - if (!!responseType) { // eslint-disable-line no-extra-boolean-cast - req.responseType = responseType; - } + if (!!responseType) { // eslint-disable-line no-extra-boolean-cast + req.responseType = responseType; + } - req.send(body); + req.send(body); - req.onload = () => { - if (req.status >= 200 && req.status < 300) { - resolve(req); - } else { - reject(req.responseText); - } - }; - }); - }; + req.onload = () => { + if (req.status >= 200 && req.status < 300) { + resolve(req); + } else { + reject(req.responseText); + } + }; + }); + }; - // eslint-disable-next-line func-names - this.setAuthenticationService = function (authenticationService) { - this.authenticationService = authenticationService; - this.useAuthentication = true; - }; + // eslint-disable-next-line func-names + this.setAuthenticationService = function (authenticationService) { + this.authenticationService = authenticationService; + this.useAuthentication = true; + }; - this.initialize(); + this.initialize(); } export class AuthNeededError extends Error { - constructor() { - super('Login needed for this request'); - this.name = 'AuthNeededError'; - } + constructor() { + super('Login needed for this request'); + this.name = 'AuthNeededError'; + } } diff --git a/src/Game/Components/AssetsManager.js b/src/Game/Components/AssetsManager.js index 73901e897..5df2acd3a 100644 --- a/src/Game/Components/AssetsManager.js +++ b/src/Game/Components/AssetsManager.js @@ -277,19 +277,27 @@ export class AssetsManager { const parent = new THREE.Object3D(); switch (anchor) { case 'center': - let center = bbox.min.lerp(bbox.max, 0.5); - obj.position.sub(center); + { + let center = bbox.min.lerp(bbox.max, 0.5); + obj.position.sub(center); + } break; case 'max': - obj.position.sub(bbox.max); + { + obj.position.sub(bbox.max); + } break; case 'min': - obj.position.sub(bbox.min); + { + obj.position.sub(bbox.min); + } break; case 'center_min': - let centerMin = bbox.min.clone().lerp(bbox.max, 0.5); - centerMin.z = bbox.min.z; - obj.position.sub(centerMin); + { + let centerMin = bbox.min.clone().lerp(bbox.max, 0.5); + centerMin.z = bbox.min.z; + obj.position.sub(centerMin); + } break; default: } diff --git a/src/Game/Shared/GameObject/Components/Collider.js b/src/Game/Shared/GameObject/Components/Collider.js index 2f15cda5b..f1f0661e3 100644 --- a/src/Game/Shared/GameObject/Components/Collider.js +++ b/src/Game/Shared/GameObject/Components/Collider.js @@ -93,37 +93,41 @@ class ShapeWrapper { initFromJSON(json) { switch (json.type) { case 'Circle': - const circle = new Circle(json.center.x, json.center.y, json.radius); + { + const circle = new Circle(json.center.x, json.center.y, json.radius); - this.update = function (worldtransform) { - const wp = worldtransform.getPosition(); - circle.x = json.center.x + wp.x; - circle.y = json.center.y + wp.y; - }; + this.update = function (worldtransform) { + const wp = worldtransform.getPosition(); + circle.x = json.center.x + wp.x; + circle.y = json.center.y + wp.y; + }; - this.shape = circle; + this.shape = circle; + } break; case 'Polygon': - const points = []; - json.points.forEach(function (p) { - points.push([p.x, p.y]); - }); - - const polygon = new Polygon(0, 0, points); - - //attach userData to perform update - this.update = function (worldtransform) { + { const points = []; json.points.forEach(function (p) { - const wp = worldtransform.getPosition(); - const point = [p.x + wp.x, p.y + wp.y]; - points.push(point); - //TODO handle rotation + points.push([p.x, p.y]); }); - polygon.setPoints(points); - }; - this.shape = polygon; + const polygon = new Polygon(0, 0, points); + + //attach userData to perform update + this.update = function (worldtransform) { + const points = []; + json.points.forEach(function (p) { + const wp = worldtransform.getPosition(); + const point = [p.x + wp.x, p.y + wp.y]; + points.push(point); + //TODO handle rotation + }); + polygon.setPoints(points); + }; + + this.shape = polygon; + } break; default: } diff --git a/src/Game/Shared/GameObject/GameObject.js b/src/Game/Shared/GameObject/GameObject.js index 0285a6e2c..aaa84509d 100644 --- a/src/Game/Shared/GameObject/GameObject.js +++ b/src/Game/Shared/GameObject/GameObject.js @@ -10,7 +10,6 @@ const THREE = require('three'); const RenderComponent = require('./Components/Render'); const ColliderComponent = require('./Components/Collider'); const WorldScriptComponent = require('./Components/WorldScript'); -const JSONUtils = require('../../../Components/SystemUtils/JSONUtils'); const LocalScriptModule = require('./Components/LocalScript'); const THREEUtils = require('../Components/THREEUtils'); @@ -290,14 +289,6 @@ const GameObjectModule = class GameObject { return obj; } - getTransform() { - return this.transform; - } - - setTransform(transform) { - this.transform = transform; - } - clone() { return new GameObject(this.toJSON(true)); } diff --git a/src/Game/Shared/WorldState.js b/src/Game/Shared/WorldState.js index 5acc1a471..879011021 100644 --- a/src/Game/Shared/WorldState.js +++ b/src/Game/Shared/WorldState.js @@ -63,7 +63,7 @@ const WorldStateModule = class WorldState { if (uuidGO.includes(uuid)) count++; }); if (uuidGO.length != count) { - debugger; + throw new Error('count of go error'); } const result = new WorldState({ diff --git a/src/Game/UDVDebugger/UDVDebugger.js b/src/Game/UDVDebugger/UDVDebugger.js index f3a731399..04c68bc7d 100644 --- a/src/Game/UDVDebugger/UDVDebugger.js +++ b/src/Game/UDVDebugger/UDVDebugger.js @@ -125,22 +125,4 @@ export class UDVDebugger { this.root.style.width = w + 'px'; this.root.style.height = h + 'px'; } - - //TODO used twice put it in a UTILS - async loadConfigFile(filePath, cb) { - return new Promise((resolve, reject) => { - $.ajax({ - type: 'GET', - url: filePath, - datatype: 'json', - success: (data) => { - resolve(data); - }, - error: (e) => { - console.error(e); - reject(); - }, - }); - }); - } } diff --git a/src/Widgets/CityObjects/View/CityObjectFilterWindow.js b/src/Widgets/CityObjects/View/CityObjectFilterWindow.js index e9b018a86..180524de2 100644 --- a/src/Widgets/CityObjects/View/CityObjectFilterWindow.js +++ b/src/Widgets/CityObjects/View/CityObjectFilterWindow.js @@ -67,7 +67,7 @@ export class CityObjectFilterWindow extends Window { * add. */ addFilterSelector(filterSelector) { - if (!!this.getFilterSelector(filterSelector.filterLabel)) { + if (this.getFilterSelector(filterSelector.filterLabel)) { throw ( 'A filter selector with the same filter label already exist: ' + filterSelector.filterLabel @@ -119,7 +119,7 @@ export class CityObjectFilterWindow extends Window { _onFilterSelection() { this.filterSectionElement.innerHTML = ''; let selector = this._getCurrentSelector(); - if (!!selector) { + if (selector) { selector.appendFormFieldsTo(this.filterSectionElement); } } diff --git a/src/Widgets/CityObjects/View/CityObjectWindow.js b/src/Widgets/CityObjects/View/CityObjectWindow.js index 5359230a6..fdbf9c113 100644 --- a/src/Widgets/CityObjects/View/CityObjectWindow.js +++ b/src/Widgets/CityObjects/View/CityObjectWindow.js @@ -1,5 +1,7 @@ /** @format */ +const THREE = require('three'); + //Components import { Window } from '../../../Components/GUI/js/Window'; import { CityObjectStyle } from '../../../Components/3DTiles/Model/CityObjectStyle'; @@ -168,7 +170,7 @@ export class CityObjectWindow extends Window { _updateLayerDescription() { if (this.isCreated) { let layer = this.provider.getLayer(); - if (!!layer) { + if (layer) { this.selectedFilterElement.innerText = layer.filter.toString(); this.layerColorIndicatorElement.style.display = ''; this.layerColorIndicatorElement.style.background = @@ -200,7 +202,7 @@ export class CityObjectWindow extends Window { * @param {string} filterLabel The selected filter label. */ _onFilterSelected(filterLabel) { - if (!!filterLabel) { + if (filterLabel) { this.provider.setLayer(filterLabel, this.defaultLayerStyle); } else { this.provider.removeLayer(); diff --git a/src/Widgets/CityObjects/ViewModel/AttributeFilter.js b/src/Widgets/CityObjects/ViewModel/AttributeFilter.js index 3b8a3c056..8ba36058f 100644 --- a/src/Widgets/CityObjects/ViewModel/AttributeFilter.js +++ b/src/Widgets/CityObjects/ViewModel/AttributeFilter.js @@ -73,16 +73,16 @@ export class AttributeFilter extends CityObjectFilter { let result = ''; let attributes = []; - if (!!this.tileId) { + if (this.tileId) { attributes.push(['tileId', this.tileId]); } - if (!!this.batchId) { + if (this.batchId) { attributes.push(['batchId', this.batchId]); } for (let entry of Object.entries(this.props)) { - if (!!entry[1]) { + if (entry[1]) { attributes.push([entry[0], entry[1]]); } } diff --git a/src/Widgets/CityObjects/ViewModel/CityObjectProvider.js b/src/Widgets/CityObjects/ViewModel/CityObjectProvider.js index 99b40e6a5..ee839dfc4 100644 --- a/src/Widgets/CityObjects/ViewModel/CityObjectProvider.js +++ b/src/Widgets/CityObjects/ViewModel/CityObjectProvider.js @@ -85,7 +85,7 @@ export class CityObjectProvider extends EventSender { */ selectCityObject(mouseEvent) { let cityObject = this.layerManager.pickCityObject(mouseEvent); - if (!!cityObject) { + if (cityObject) { this.selectedCityObject = cityObject; this.removeLayer(); this.sendEvent(CityObjectProvider.EVENT_CITY_OBJECT_SELECTED, cityObject); @@ -160,7 +160,7 @@ export class CityObjectProvider extends EventSender { let filter = this.filters[filterLabel]; if (filter === undefined) { - throw 'No filter found with the label : ' + label; + throw 'No filter found with the label : ' + filterLabel; } this.cityOjectLayer = new CityObjectLayer(filter, style); @@ -198,7 +198,7 @@ export class CityObjectProvider extends EventSender { */ _updateTilesManager() { this.layerManager.removeAll3DTilesStyles(); - if (!!this.selectedCityObject) { + if (this.selectedCityObject) { let tileManager = this.layerManager.getTilesManagerByLayerID( this.selectedCityObject.tile.layer.id ); diff --git a/src/Widgets/Documents/View/DocumentNavigatorWindow.js b/src/Widgets/Documents/View/DocumentNavigatorWindow.js index 12897b158..a2becb139 100644 --- a/src/Widgets/Documents/View/DocumentNavigatorWindow.js +++ b/src/Widgets/Documents/View/DocumentNavigatorWindow.js @@ -145,8 +145,8 @@ export class DocumentNavigatorWindow extends AbstractDocumentWindow { item.innerHTML = /*html*/ `
${doc.title}
Refering ${new Date( - doc.refDate - ).toLocaleDateString()}
+ doc.refDate + ).toLocaleDateString()}
`; item.classList.add('navigator-result-doc'); item.onclick = () => { @@ -170,10 +170,10 @@ export class DocumentNavigatorWindow extends AbstractDocumentWindow { } let previouslySelected = this.documentListElement.querySelector('.document-selected'); - if (!!previouslySelected) { + if (previouslySelected) { previouslySelected.classList.remove('document-selected'); } - if (!!document) { + if (document) { let newIndex = this.provider.getDisplayedDocumentIndex(); let newSelected = this.documentListElement.querySelector( `li:nth-child(${newIndex + 1})` @@ -203,22 +203,22 @@ export class DocumentNavigatorWindow extends AbstractDocumentWindow { rightsHolder !== '' ? rightsHolder : undefined; let pubStartDate = this.inputPubDateStartElement.value; - this.searchFilter.pubStartDate = !!pubStartDate + this.searchFilter.pubStartDate = pubStartDate ? new Date(pubStartDate) : undefined; let pubEndDate = this.inputPubDateEndElement.value; - this.searchFilter.pubEndDate = !!pubEndDate + this.searchFilter.pubEndDate = pubEndDate ? new Date(pubEndDate) : undefined; let refStartDate = this.inputRefDateStartElement.value; - this.searchFilter.refStartDate = !!refStartDate + this.searchFilter.refStartDate = refStartDate ? new Date(refStartDate) : undefined; let refEndDate = this.inputRefDateEndElement.value; - this.searchFilter.refEndDate = !!refEndDate + this.searchFilter.refEndDate = refEndDate ? new Date(refEndDate) : undefined; diff --git a/src/Widgets/Extensions/3DTilesDebug/views/3DTilesDebugWindow.js b/src/Widgets/Extensions/3DTilesDebug/views/3DTilesDebugWindow.js index 0fac2b999..d618741c1 100644 --- a/src/Widgets/Extensions/3DTilesDebug/views/3DTilesDebugWindow.js +++ b/src/Widgets/Extensions/3DTilesDebug/views/3DTilesDebugWindow.js @@ -1,5 +1,7 @@ /** @format */ +const THREE = require('three'); + //Components import { Window } from '../../../../Components/GUI/js/Window'; import { CityObjectStyle } from '../../../../Components/3DTiles/Model/CityObjectStyle'; @@ -154,7 +156,7 @@ export class Debug3DTilesWindow extends Window { this.clickDivElement.innerHTML += `
${key} : ${value}`; } - if (!!this.selectedCityObject) { + if (this.selectedCityObject) { this.selectedTilesManager.removeStyle( this.selectedCityObject.cityObjectId ); diff --git a/src/Widgets/Extensions/Contribute/View/DocumentCreationWindow.js b/src/Widgets/Extensions/Contribute/View/DocumentCreationWindow.js index 4b06675d8..f8c7d77a2 100644 --- a/src/Widgets/Extensions/Contribute/View/DocumentCreationWindow.js +++ b/src/Widgets/Extensions/Contribute/View/DocumentCreationWindow.js @@ -266,7 +266,7 @@ export class DocumentCreationWindow extends AbstractDocumentWindow { * @private */ _updateFormButtons() { - if (!!this.docImageElement.value) { + if (this.docImageElement.value) { this.buttonPositionElement.disabled = false; } else { this.buttonPositionElement.disabled = true; diff --git a/src/Widgets/Extensions/DocumentComments/views/DocumentCommentsWindow.js b/src/Widgets/Extensions/DocumentComments/views/DocumentCommentsWindow.js index 8b4f957a3..b295541d9 100644 --- a/src/Widgets/Extensions/DocumentComments/views/DocumentCommentsWindow.js +++ b/src/Widgets/Extensions/DocumentComments/views/DocumentCommentsWindow.js @@ -80,12 +80,12 @@ export class DocumentCommentsWindow extends AbstractDocumentWindow { div.innerHTML = `

${comment.author.firstName} ${ - comment.author.lastName - }

+ comment.author.lastName +}

${text}

${new Date( - comment.date - ).toLocaleString()}

+ comment.date + ).toLocaleString()}

`; document.getElementById('documentComments_left').appendChild(div); diff --git a/src/Widgets/Extensions/Geocoding/services/GeocodingService.js b/src/Widgets/Extensions/Geocoding/services/GeocodingService.js index 1e25f87d4..29b50f89d 100644 --- a/src/Widgets/Extensions/Geocoding/services/GeocodingService.js +++ b/src/Widgets/Extensions/Geocoding/services/GeocodingService.js @@ -63,7 +63,7 @@ export class GeocodingService { authenticate: false, }); const response = JSON.parse(req.response); - const results = (!!this.basePath ? response[this.basePath] : response).map( + const results = (this.basePath ? response[this.basePath] : response).map( (res) => { return { lat: Number(getAttributeByPath(res, this.latPath)), @@ -72,7 +72,7 @@ export class GeocodingService { } ); - if (!!this.requestTimeIntervalMs) { + if (this.requestTimeIntervalMs) { this.canDoRequest = false; setTimeout(() => { this.canDoRequest = true; diff --git a/src/Widgets/Extensions/Geocoding/views/GeocodingView.js b/src/Widgets/Extensions/Geocoding/views/GeocodingView.js index dec63944f..d57b9dff0 100644 --- a/src/Widgets/Extensions/Geocoding/views/GeocodingView.js +++ b/src/Widgets/Extensions/Geocoding/views/GeocodingView.js @@ -110,7 +110,7 @@ export class GeocodingView extends ModuleView { let i = 0; //step 1 : convert the lat/lng to coordinates used by itowns let targetPos = this.getWorldCoordinates(lat, lng); - if (!!targetPos.z) { + if (targetPos.z) { //if we could convert the coords (ie. they are on the map) //step 2 : add a mesh representing a pin this.addPin(targetPos); @@ -141,7 +141,7 @@ export class GeocodingView extends ModuleView { this.planarView.tileLayer, coords ); - const targetZ = !!elevation ? elevation : undefined; + const targetZ = elevation ? elevation : undefined; return new THREE.Vector3(targetX, targetY, targetZ); } diff --git a/src/Widgets/GuidedTour/GuidedTourController.js b/src/Widgets/GuidedTour/GuidedTourController.js index 2f2be96d7..fc464dc80 100644 --- a/src/Widgets/GuidedTour/GuidedTourController.js +++ b/src/Widgets/GuidedTour/GuidedTourController.js @@ -21,9 +21,9 @@ export class GuidedTourController extends ModuleView { /** * Constructor for GuidedTourController * The controller reads data from a database to build one or more guided tours - * Each guided tour is a succession of "steps" + * Each guided tour is a succession of "steps" * Each step has a document + tour text + doc text (steps are instances of - * the TourStep class) + * the TourStep class) * Multiple guided tours are supported (only one tour is finished for the demo) * For the demo : options.preventUserFromChangingTour allows to hide the buttons for changing tour * diff --git a/src/Widgets/LayerChoice/views/LayerChoice.js b/src/Widgets/LayerChoice/views/LayerChoice.js index 6467deeb0..aaa68e565 100644 --- a/src/Widgets/LayerChoice/views/LayerChoice.js +++ b/src/Widgets/LayerChoice/views/LayerChoice.js @@ -67,14 +67,14 @@ export class LayerChoice extends Window { layers[i].id }-spoiler" class="section-title">${layers[i].id} Visible
+ layers[i].visible ? 'checked' : '' +}>
Opacity : ${ - layers[i].opacity - } + layers[i].opacity +}
`; item.oninput = (event) => { @@ -129,8 +129,8 @@ export class LayerChoice extends Window { let div = document.createElement('div'); div.innerHTML = ` All Visible
+ this.layerManager.isOneLayerVisible() ? 'checked' : '' +}>
`; div.onchange = (event) => { this.layerManager.changeVisibility(event.srcElement.checked); @@ -143,22 +143,22 @@ export class LayerChoice extends Window { layers[i].id }-spoiler"> + layers[i].id +}-spoiler" class="subsection-title">${ + layers[i].id +}
Visible
+ layers[i].visible ? 'checked' : '' +}>
Opacity : ${ - layers[i].opacity - } + layers[i].opacity +}
`; diff --git a/src/Widgets/Links/View/CityObjectLinkInterface.js b/src/Widgets/Links/View/CityObjectLinkInterface.js index 12d9ca96a..70a61f20f 100644 --- a/src/Widgets/Links/View/CityObjectLinkInterface.js +++ b/src/Widgets/Links/View/CityObjectLinkInterface.js @@ -1,6 +1,5 @@ /** @format */ -import { LinkService } from '../Model/LinkService'; import { CityObjectModule } from '../../CityObjects/CityObjectModule'; import { CityObjectFilterSelector } from '../../CityObjects/View/CityObjectFilterSelector'; import { LinkProvider } from '../ViewModel/LinkProvider'; @@ -67,7 +66,7 @@ export class CityObjectLinkInterface { let docs = this.linkProvider.getSelectedCityObjectLinkedDocuments(); let listHtml = `

${docs.length} linked document(s)

`; if (docs.length > 0) { - listHtml += `

    `; + listHtml += '

      '; for (let doc of docs) { listHtml += `
    • ${doc.title}
    • `; } @@ -80,7 +79,7 @@ export class CityObjectLinkInterface { ////// GETTERS get linkListId() { - return `city_objects_link_list`; + return 'city_objects_link_list'; } get linkListElement() { @@ -88,7 +87,7 @@ export class CityObjectLinkInterface { } get showDocsButtonId() { - return `city_objects_link_show_doc`; + return 'city_objects_link_show_doc'; } get showDocsButtonElement() { diff --git a/src/Widgets/Links/View/DocumentLinkInterface.js b/src/Widgets/Links/View/DocumentLinkInterface.js index d3baac9ad..4822c1831 100644 --- a/src/Widgets/Links/View/DocumentLinkInterface.js +++ b/src/Widgets/Links/View/DocumentLinkInterface.js @@ -99,7 +99,7 @@ export class DocumentLinkInterface { }; this.createLinkButtonElement.onclick = async () => { - if (!!this.provider.selectedCityObject) { + if (this.provider.selectedCityObject) { let newLink = new Link(); newLink.source_id = this.provider.displayedDocument.id; newLink.target_id = @@ -158,13 +158,13 @@ export class DocumentLinkInterface { newDivHtml += `
    • ID : ${link.target_id} + link + )}" class="clickable-text"> travel + link + )}" class="clickable-text"> delete
    • `; @@ -229,7 +229,7 @@ export class DocumentLinkInterface { } get linkFilterId() { - return `city_object_link_filter`; + return 'city_object_link_filter'; } get linkFilterElement() { From 9408ecc696a0ef44dc754beb3b4a015342d1e96e Mon Sep 17 00:00:00 2001 From: valentinMachado Date: Tue, 1 Jun 2021 10:23:05 +0200 Subject: [PATCH 20/68] data nudefined => null --- src/Game/Shared/Command.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Game/Shared/Command.js b/src/Game/Shared/Command.js index 1d95f67bb..1253e1b81 100644 --- a/src/Game/Shared/Command.js +++ b/src/Game/Shared/Command.js @@ -10,7 +10,7 @@ const CommandModule = class Command { this.type = json.type; this.userID = json.userID; this.avatarID = json.avatarID; - this.data = json.data; + this.data = json.data || null; } getData() { @@ -38,7 +38,6 @@ const CommandModule = class Command { } toJSON() { - return { type: this.type, avatarID: this.avatarID, From 5b7f84d9528acff9594a7763fa852732461abd46 Mon Sep 17 00:00:00 2001 From: valentinMachado Date: Thu, 3 Jun 2021 10:48:23 +0200 Subject: [PATCH 21/68] add getter gameview --- src/Game/GameView/GameView.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/Game/GameView/GameView.js b/src/Game/GameView/GameView.js index a0f89cf7d..d6968417b 100644 --- a/src/Game/GameView/GameView.js +++ b/src/Game/GameView/GameView.js @@ -314,6 +314,18 @@ export class GameView { cameraShadow.updateProjectionMatrix(); } + getWorldStateInterpolator() { + return this.worldStateInterpolator; + } + + getLastState() { + return this.lastState; + } + + getInputManager() { + return this.inputManager; + } + updateViewServer(dt) { //TODO itowns BUG if (!isNaN(dt)) { From 086ebe38bd55f3918238dddc68b6f0edb665197f Mon Sep 17 00:00:00 2001 From: valentinMachado Date: Thu, 3 Jun 2021 10:56:03 +0200 Subject: [PATCH 22/68] remove debug --- src/Game/GameView/GameView.js | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/Game/GameView/GameView.js b/src/Game/GameView/GameView.js index d6968417b..ab750e29f 100644 --- a/src/Game/GameView/GameView.js +++ b/src/Game/GameView/GameView.js @@ -21,15 +21,9 @@ import { isFunction } from 'jquery'; const udvShared = require('../Shared/Shared'); const Command = udvShared.Command; const WorldState = udvShared.WorldState; -const Data = udvShared.Data; - -//DEBUG -let id = 0; export class GameView { constructor(params) { - this.id = id; - id++; params.htmlParent = params.htmlParent || document.body; From 61dcf4386403cc297788553d71e550a386b7079f Mon Sep 17 00:00:00 2001 From: valentinMachado Date: Thu, 3 Jun 2021 16:49:31 +0200 Subject: [PATCH 23/68] rename quat parse --- src/Game/Components/AssetsManager.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Game/Components/AssetsManager.js b/src/Game/Components/AssetsManager.js index e9a3fc3af..1b174cf70 100644 --- a/src/Game/Components/AssetsManager.js +++ b/src/Game/Components/AssetsManager.js @@ -260,10 +260,10 @@ export class AssetsManager { const noShadow = modelData.noShadow || false; //rotation - const quatTHREE2UDV = new THREE.Quaternion().setFromEuler( + const quatYUP2ZUP = new THREE.Quaternion().setFromEuler( new THREE.Euler(-Math.PI * 0.5, 0, Math.PI) ); - obj.applyQuaternion(quatTHREE2UDV); + obj.applyQuaternion(quatYUP2ZUP); const bbox = new THREE.Box3().setFromObject(obj); const parent = new THREE.Object3D(); @@ -277,6 +277,7 @@ export class AssetsManager { break; case 'min': obj.position.sub(bbox.min); + console.log(id, bbox.min); break; case 'center_min': let centerMin = bbox.min.clone().lerp(bbox.max, 0.5); @@ -284,7 +285,6 @@ export class AssetsManager { obj.position.sub(centerMin); break; default: - throw new Error('no anchor'); } //scale From 44aada54309d3e6a6dc72a1cd1bb52bd225ea231 Mon Sep 17 00:00:00 2001 From: valentinMachado Date: Thu, 3 Jun 2021 18:10:11 +0200 Subject: [PATCH 24/68] remove log --- src/Game/Components/AssetsManager.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Game/Components/AssetsManager.js b/src/Game/Components/AssetsManager.js index 1b174cf70..86ef40dd1 100644 --- a/src/Game/Components/AssetsManager.js +++ b/src/Game/Components/AssetsManager.js @@ -277,7 +277,6 @@ export class AssetsManager { break; case 'min': obj.position.sub(bbox.min); - console.log(id, bbox.min); break; case 'center_min': let centerMin = bbox.min.clone().lerp(bbox.max, 0.5); From d9aff36d569981872ea1bbf012f6e69ef42063f4 Mon Sep 17 00:00:00 2001 From: valentinMachado Date: Fri, 4 Jun 2021 10:59:13 +0200 Subject: [PATCH 25/68] add outdated setter --- src/Game/Shared/GameObject/GameObject.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Game/Shared/GameObject/GameObject.js b/src/Game/Shared/GameObject/GameObject.js index 598744107..b99191bed 100644 --- a/src/Game/Shared/GameObject/GameObject.js +++ b/src/Game/Shared/GameObject/GameObject.js @@ -58,8 +58,6 @@ const GameObjectModule = class GameObject { //assets has been initialized this.initialized = false; - - //TODO remove me //default object3d this.object3D = new THREE.Object3D(); this.object3D.name = this.name + '_object3D'; @@ -207,6 +205,10 @@ const GameObjectModule = class GameObject { return this.outdated; } + setOutdated(value) { + this.outdated = value; + } + executeScripts(event, params) { const script = this.getComponent(WorldScriptComponent.TYPE); if (!script) return null; From 0300a417749fdd8d721f41d6c747bc3f04e7cd2b Mon Sep 17 00:00:00 2001 From: valentinMachado Date: Fri, 4 Jun 2021 12:25:19 +0200 Subject: [PATCH 26/68] refacto --- src/Game/{ => Shared}/Components/THREEUtils.js | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/Game/{ => Shared}/Components/THREEUtils.js (100%) diff --git a/src/Game/Components/THREEUtils.js b/src/Game/Shared/Components/THREEUtils.js similarity index 100% rename from src/Game/Components/THREEUtils.js rename to src/Game/Shared/Components/THREEUtils.js From 87c1c2d8fc688e32688296e5de0c2b334dcf6bf6 Mon Sep 17 00:00:00 2001 From: valentinMachado Date: Fri, 4 Jun 2021 12:25:29 +0200 Subject: [PATCH 27/68] refacto bis --- src/Game/Components/AssetsManager.js | 2 +- src/Game/Components/Components.js | 2 +- src/Game/GameView/GameView.js | 5 +---- src/Game/Shared/Components/Components.js | 2 ++ src/Game/Shared/Components/THREEUtils.js | 12 ++++++++---- src/Game/Shared/GameObject/GameObject.js | 25 +++++++++++++----------- 6 files changed, 27 insertions(+), 21 deletions(-) diff --git a/src/Game/Components/AssetsManager.js b/src/Game/Components/AssetsManager.js index 86ef40dd1..34e2b632d 100644 --- a/src/Game/Components/AssetsManager.js +++ b/src/Game/Components/AssetsManager.js @@ -4,7 +4,7 @@ import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'; import * as THREE from 'three'; import * as jquery from 'jquery'; import GameObjectModule from '../Shared/GameObject/GameObject'; -import { THREEUtils } from '../Components/THREEUtils'; +const THREEUtils = require('../Shared/Components/THREEUtils'); const DEFAULT_MATERIAL = new THREE.MeshLambertMaterial({ color: 0x00ff00 }); diff --git a/src/Game/Components/Components.js b/src/Game/Components/Components.js index 1abd65a66..d65691aab 100644 --- a/src/Game/Components/Components.js +++ b/src/Game/Components/Components.js @@ -4,4 +4,4 @@ export { WebSocketService } from './WebSocketService'; export { WorldStateInterpolator } from './WorldStateInterpolator'; export { AssetsManager } from './AssetsManager'; export { InputManager } from './InputManager'; -export { THREEUtils } from './THREEUtils'; + diff --git a/src/Game/GameView/GameView.js b/src/Game/GameView/GameView.js index ab750e29f..5d8c41a7b 100644 --- a/src/Game/GameView/GameView.js +++ b/src/Game/GameView/GameView.js @@ -7,8 +7,6 @@ import { AssetsManager } from '../Components/AssetsManager'; import { InputManager } from '../Components/InputManager'; import { Cameraman, Routine } from '../Components/Cameraman'; -import { THREEUtils } from '../Components/THREEUtils'; - import * as THREE from 'three'; import * as proj4 from 'proj4'; import * as itowns from 'itowns'; @@ -16,15 +14,14 @@ import * as itowns from 'itowns'; import './GameView.css'; import LocalScript from '../Shared/GameObject/Components/LocalScript'; import Render from '../Shared/GameObject/Components/Render'; -import { isFunction } from 'jquery'; const udvShared = require('../Shared/Shared'); const Command = udvShared.Command; const WorldState = udvShared.WorldState; +const THREEUtils = udvShared.Components.THREEUtils; export class GameView { constructor(params) { - params.htmlParent = params.htmlParent || document.body; //html diff --git a/src/Game/Shared/Components/Components.js b/src/Game/Shared/Components/Components.js index 919edc2bd..c4d0d74e4 100644 --- a/src/Game/Shared/Components/Components.js +++ b/src/Game/Shared/Components/Components.js @@ -2,8 +2,10 @@ const commonJsData = require('./Data'); const commonJsPrefabUtils = require('./PrefabUtils'); +const commonJsTHREEUtils = require('./THREEUtils'); module.exports = { Data: commonJsData, PrefabUtils: commonJsPrefabUtils, + THREEUtils: commonJsTHREEUtils, }; diff --git a/src/Game/Shared/Components/THREEUtils.js b/src/Game/Shared/Components/THREEUtils.js index 8ed2f06b0..759049a1c 100644 --- a/src/Game/Shared/Components/THREEUtils.js +++ b/src/Game/Shared/Components/THREEUtils.js @@ -1,10 +1,10 @@ /** @format */ -import * as THREE from 'three'; +const THREE = require('three'); //TODO create an object Transform with a clone method -const THREEUtils = { +module.exports = { textureEncoding: THREE.RGBDEncoding, addLights(scene) { @@ -37,6 +37,10 @@ const THREEUtils = { // renderer.toneMapping = THREE.ReinhardToneMapping; // renderer.toneMappingExposure = 1; }, -}; -export { THREEUtils }; + Transform: class { + constructor() { + console.log('new transform'); + } + }, +}; diff --git a/src/Game/Shared/GameObject/GameObject.js b/src/Game/Shared/GameObject/GameObject.js index b99191bed..f337c1131 100644 --- a/src/Game/Shared/GameObject/GameObject.js +++ b/src/Game/Shared/GameObject/GameObject.js @@ -12,6 +12,7 @@ const ColliderComponent = require('./Components/Collider'); const WorldScriptComponent = require('./Components/WorldScript'); const JSONUtils = require('../../../Components/SystemUtils/JSONUtils'); const LocalScriptModule = require('./Components/LocalScript'); +const THREEUtils = require('../Components/THREEUtils'); const GameObjectModule = class GameObject { constructor(json, parent) { @@ -29,6 +30,7 @@ const GameObjectModule = class GameObject { //name this.name = json.name || 'none'; + //TODO remove me //prefabId this.prefabId = json.prefabId || null; @@ -61,6 +63,9 @@ const GameObjectModule = class GameObject { //default object3d this.object3D = new THREE.Object3D(); this.object3D.name = this.name + '_object3D'; + + //buffer + this.eulerBuffer = new THREE.Euler(0, 0, 0, 'ZXY'); //to avoid new THREE.Euler on fetchObject3D } updateNoStaticFromGO(go, assetsManager) { @@ -279,20 +284,18 @@ const GameObjectModule = class GameObject { if (!obj) obj = this.object3D; } - //transform + //position obj.position.copy(this.getPosition()); - //TODO rotation n'est plus un THREE VEctor3 mais un euler - obj.rotation.copy( - new THREE.Euler( - this.transform.rotation.x, - this.transform.rotation.y, - this.transform.rotation.z, - 'ZXY' - ) - ); + //rot + const rot = this.getRotation(); + this.eulerBuffer.x = rot.x; + this.eulerBuffer.y = rot.y; + this.eulerBuffer.z = rot.z; + obj.rotation.copy(this.eulerBuffer); + //scale obj.scale.copy(this.getScale()); - //reset + //add children if recursive if (recursive) { this.children.forEach(function (child) { const childObj = child.fetchObject3D(); From 44a351e54d1882a4092434ca4ff87c0afee32d9d Mon Sep 17 00:00:00 2001 From: valentinMachado Date: Fri, 4 Jun 2021 13:17:37 +0200 Subject: [PATCH 28/68] rename --- src/Game/Shared/GameObject/Components/Render.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Game/Shared/GameObject/Components/Render.js b/src/Game/Shared/GameObject/Components/Render.js index d3eee94fb..aea94fcd0 100644 --- a/src/Game/Shared/GameObject/Components/Render.js +++ b/src/Game/Shared/GameObject/Components/Render.js @@ -92,7 +92,7 @@ const RenderModule = class Render { //stock data in userData this.object3D.userData = { - uuid: this.parent.getUUID(), + gameObjectUUID: this.parent.getUUID(), }; //get the 3D model From 2d583fca44229f99f24d72f4fb6c040c85504c8a Mon Sep 17 00:00:00 2001 From: valentinMachado Date: Fri, 4 Jun 2021 14:19:05 +0200 Subject: [PATCH 29/68] transform class --- src/Game/Shared/Components/THREEUtils.js | 62 ++++++++++++++++++++++-- 1 file changed, 59 insertions(+), 3 deletions(-) diff --git a/src/Game/Shared/Components/THREEUtils.js b/src/Game/Shared/Components/THREEUtils.js index 759049a1c..992b9ac27 100644 --- a/src/Game/Shared/Components/THREEUtils.js +++ b/src/Game/Shared/Components/THREEUtils.js @@ -38,9 +38,65 @@ module.exports = { // renderer.toneMappingExposure = 1; }, - Transform: class { - constructor() { - console.log('new transform'); + Transform: class Transform { + constructor(position, rotation, scale) { + this.position = position || new THREE.Vector3(); + this.rotation = rotation || new THREE.Vector3(); + this.scale = scale || new THREE.Vector3(1, 1, 1); + } + + getPosition() { + return this.position; + } + + setPosition(position) { + this.position = position; + } + + getRotation() { + return this.rotation; + } + + setRotation(rotation) { + this.rotation = rotation; + } + + getScale() { + return this.scale; + } + + setScale(scale) { + this.scale = scale; + } + + clone() { + return new Transform( + this.position.clone(), + this.rotation.clone(), + this.scale.clone() + ); + } + + setFromJSON(json) { + if (json) { + if (json.position) { + this.position.x = json.position.x; + this.position.y = json.position.y; + this.position.z = json.position.z; + } + + if (json.rotation) { + this.rotation.x = json.rotation.x; + this.rotation.y = json.rotation.y; + this.rotation.z = json.rotation.z; + } + + if (json.scale) { + this.scale.x = json.scale.x; + this.scale.y = json.scale.y; + this.scale.z = json.scale.z; + } + } } }, }; From 436737e717069574bee903834e0038a430426750 Mon Sep 17 00:00:00 2001 From: valentinMachado Date: Fri, 4 Jun 2021 15:27:06 +0200 Subject: [PATCH 30/68] transform refacto --- src/Game/Components/Cameraman.js | 1 + src/Game/Shared/Components/THREEUtils.js | 28 +++-- .../Shared/GameObject/Components/Collider.js | 11 +- src/Game/Shared/GameObject/GameObject.js | 103 +++++------------- src/Game/UDVDebugger/UDVDebugger.js | 4 +- 5 files changed, 53 insertions(+), 94 deletions(-) diff --git a/src/Game/Components/Cameraman.js b/src/Game/Components/Cameraman.js index 327beed0a..76cc75bd3 100644 --- a/src/Game/Components/Cameraman.js +++ b/src/Game/Components/Cameraman.js @@ -111,6 +111,7 @@ export class Cameraman { quaternion.multiply(quaternionCam); quaternion.multiply(quaternionAngle); + //this is not a transform of THREEUtils.Transform return { position: position, quaternion: quaternion }; } diff --git a/src/Game/Shared/Components/THREEUtils.js b/src/Game/Shared/Components/THREEUtils.js index 992b9ac27..520ec4d96 100644 --- a/src/Game/Shared/Components/THREEUtils.js +++ b/src/Game/Shared/Components/THREEUtils.js @@ -2,8 +2,6 @@ const THREE = require('three'); -//TODO create an object Transform with a clone method - module.exports = { textureEncoding: THREE.RGBDEncoding, @@ -77,24 +75,32 @@ module.exports = { ); } + lerp(transform, ratio) { + this.position.lerp(transform.getPosition(), ratio); + this.rotation.lerp(transform.getRotation(), ratio); + this.scale.lerp(transform.getScale(), ratio); + } + + toJSON() { + return { + position: this.position.toArray(), + rotation: this.rotation.toArray(), + scale: this.scale.toArray(), + }; + } + setFromJSON(json) { if (json) { if (json.position) { - this.position.x = json.position.x; - this.position.y = json.position.y; - this.position.z = json.position.z; + this.position.fromArray(json.position); } if (json.rotation) { - this.rotation.x = json.rotation.x; - this.rotation.y = json.rotation.y; - this.rotation.z = json.rotation.z; + this.rotation.fromArray(json.rotation); } if (json.scale) { - this.scale.x = json.scale.x; - this.scale.y = json.scale.y; - this.scale.z = json.scale.z; + this.scale.fromArray(json.scale); } } } diff --git a/src/Game/Shared/GameObject/Components/Collider.js b/src/Game/Shared/GameObject/Components/Collider.js index 585a0f87a..2f15cda5b 100644 --- a/src/Game/Shared/GameObject/Components/Collider.js +++ b/src/Game/Shared/GameObject/Components/Collider.js @@ -96,8 +96,9 @@ class ShapeWrapper { const circle = new Circle(json.center.x, json.center.y, json.radius); this.update = function (worldtransform) { - circle.x = json.center.x + worldtransform.position.x; - circle.y = json.center.y + worldtransform.position.y; + const wp = worldtransform.getPosition(); + circle.x = json.center.x + wp.x; + circle.y = json.center.y + wp.y; }; this.shape = circle; @@ -114,10 +115,8 @@ class ShapeWrapper { this.update = function (worldtransform) { const points = []; json.points.forEach(function (p) { - const point = [ - p.x + worldtransform.position.x, - p.y + worldtransform.position.y, - ]; + const wp = worldtransform.getPosition(); + const point = [p.x + wp.x, p.y + wp.y]; points.push(point); //TODO handle rotation }); diff --git a/src/Game/Shared/GameObject/GameObject.js b/src/Game/Shared/GameObject/GameObject.js index f337c1131..a75d20fec 100644 --- a/src/Game/Shared/GameObject/GameObject.js +++ b/src/Game/Shared/GameObject/GameObject.js @@ -35,7 +35,8 @@ const GameObjectModule = class GameObject { this.prefabId = json.prefabId || null; //transform - this.setTransformFromJSON(json.transform); + this.transform = new THREEUtils.Transform(); + this.transform.setFromJSON(json.transform); //static this.static = json.static || false; @@ -84,7 +85,7 @@ const GameObjectModule = class GameObject { setFromJSON(json) { this.components = {}; //clear this.setComponentsFromJSON(json); - this.setTransformFromJSON(json.transform); + this.transform.setFromJSON(json.transform); this.name = json.name; this.static = json.static; @@ -112,17 +113,13 @@ const GameObjectModule = class GameObject { } computeWorldTransform() { - const result = { - position: new THREE.Vector3(), - rotation: new THREE.Vector3(), - scale: new THREE.Vector3(1, 1, 1), - }; + const result = new THREEUtils.Transform(); let current = this; do { - result.position.add(current.getPosition()); - result.rotation.add(current.getRotation()); - result.scale.multiply(current.getScale()); + result.getPosition().add(current.getPosition()); + result.getRotation().add(current.getRotation()); + result.getScale().multiply(current.getScale()); current = current.parent; } while (current); @@ -131,21 +128,19 @@ const GameObjectModule = class GameObject { } move(vector) { - this.transform.position.add(vector); + this.transform.getPosition().add(vector); this.outdated = true; } clampRotation() { - this.transform.rotation.x = - (Math.PI * 2 + this.transform.rotation.x) % (Math.PI * 2); - this.transform.rotation.y = - (Math.PI * 2 + this.transform.rotation.y) % (Math.PI * 2); - this.transform.rotation.z = - (Math.PI * 2 + this.transform.rotation.z) % (Math.PI * 2); + const r = this.transform.getRotation(); + r.x = (Math.PI * 2 + r.x) % (Math.PI * 2); + r.y = (Math.PI * 2 + r.y) % (Math.PI * 2); + r.z = (Math.PI * 2 + r.z) % (Math.PI * 2); } rotate(vector) { - this.transform.rotation.add(vector); + this.transform.getRotation().add(vector); this.clampRotation(); this.outdated = true; } @@ -166,12 +161,9 @@ const GameObjectModule = class GameObject { } computeForwardVector() { + const r = this.transform.getRotation(); const quaternion = new THREE.Quaternion().setFromEuler( - new THREE.Euler( - this.transform.rotation.x, - this.transform.rotation.y, - this.transform.rotation.z - ) + new THREE.Euler(r.x, r.y, r.z) ); const result = this.getDefaultForward().applyQuaternion(quaternion); return result; @@ -306,35 +298,12 @@ const GameObjectModule = class GameObject { return obj; } - setTransformFromJSON(json) { - if (!this.transform) { - const defaultTransform = { - position: new THREE.Vector3(), - rotation: new THREE.Vector3(), - scale: new THREE.Vector3(1, 1, 1), - }; - this.transform = defaultTransform; - } - - if (json) { - if (json.position) { - this.transform.position.x = json.position.x; - this.transform.position.y = json.position.y; - this.transform.position.z = json.position.z; - } - - if (json.rotation) { - this.transform.rotation.x = json.rotation.x; - this.transform.rotation.y = json.rotation.y; - this.transform.rotation.z = json.rotation.z; - } + getTransform() { + return this.transform; + } - if (json.scale) { - this.transform.scale.x = json.scale.x; - this.transform.scale.y = json.scale.y; - this.transform.scale.z = json.scale.z; - } - } + setTransform(transform) { + this.transform = transform; } clone() { @@ -406,31 +375,31 @@ const GameObjectModule = class GameObject { } getRotation() { - return this.transform.rotation; + return this.transform.getRotation(); } setRotation(vector) { - this.transform.rotation.set(vector.x, vector.y, vector.z); + this.transform.getRotation().set(vector.x, vector.y, vector.z); this.clampRotation(); this.outdated = true; } setPosition(vector) { - this.transform.position.set(vector.x, vector.y, vector.z); + this.transform.getPosition().set(vector.x, vector.y, vector.z); this.outdated = true; } getPosition() { - return this.transform.position; + return this.transform.getPosition(); } setScale(vector) { - this.transform.scale.set(vector.x, vector.y, vector.z); + this.transform.getScale().set(vector.x, vector.y, vector.z); this.outdated = true; } getScale() { - return this.transform.scale; + return this.transform.getScale(); } getName() { @@ -453,10 +422,6 @@ const GameObjectModule = class GameObject { children.push(child.toJSON(withServerComponent)); }); - const position = this.transform.position; - const rot = this.transform.rotation; - const scale = this.transform.scale; - const components = {}; for (let type in this.components) { const c = this.components[type]; @@ -465,11 +430,6 @@ const GameObjectModule = class GameObject { } } - //TODO not declare here or use THREE.Vector3.toJSON - const V2JSON = function (vector) { - return { x: vector.x, y: vector.y, z: vector.z }; - }; - return { name: this.name, type: GameObjectModule.TYPE, @@ -479,11 +439,7 @@ const GameObjectModule = class GameObject { parentUUID: this.parentUUID, components: components, children: children, - transform: { - position: V2JSON(position), - rotation: V2JSON(rot), - scale: V2JSON(scale), - }, + transform: this.transform.toJSON(), }; } }; @@ -492,10 +448,7 @@ GameObjectModule.TYPE = 'GameObject'; GameObjectModule.interpolateInPlace = function (g1, g2, ratio) { //modify g1 transform - g1.transform.position.lerp(g2.transform.position, ratio); - g1.transform.rotation.lerp(g2.transform.rotation, ratio); - g1.transform.scale.lerp(g2.transform.scale, ratio); - + g1.getTransform().lerp(g2.getTransform(), ratio); return g1; }; diff --git a/src/Game/UDVDebugger/UDVDebugger.js b/src/Game/UDVDebugger/UDVDebugger.js index e2b195daa..f3a731399 100644 --- a/src/Game/UDVDebugger/UDVDebugger.js +++ b/src/Game/UDVDebugger/UDVDebugger.js @@ -102,8 +102,8 @@ export class UDVDebugger { }; const loc = { - x: avatarGO.transform.position.x / pixelWorldUnit.width, - y: avatarGO.transform.position.y / pixelWorldUnit.height, + x: avatarGO.getPosition().x / pixelWorldUnit.width, + y: avatarGO.getPosition().y / pixelWorldUnit.height, }; // console.log(loc); From 499f9afa713d4dc5bababf24ab8bf93cebc9651f Mon Sep 17 00:00:00 2001 From: valentinMachado Date: Mon, 7 Jun 2021 09:07:30 +0200 Subject: [PATCH 31/68] remove prefabId --- src/Game/Shared/Components/Components.js | 2 -- src/Game/Shared/Components/Data.js | 2 +- src/Game/Shared/Components/PrefabUtils.js | 28 ----------------------- src/Game/Shared/GameObject/GameObject.js | 10 +------- 4 files changed, 2 insertions(+), 40 deletions(-) delete mode 100644 src/Game/Shared/Components/PrefabUtils.js diff --git a/src/Game/Shared/Components/Components.js b/src/Game/Shared/Components/Components.js index c4d0d74e4..94608c1f0 100644 --- a/src/Game/Shared/Components/Components.js +++ b/src/Game/Shared/Components/Components.js @@ -1,11 +1,9 @@ /** @format */ const commonJsData = require('./Data'); -const commonJsPrefabUtils = require('./PrefabUtils'); const commonJsTHREEUtils = require('./THREEUtils'); module.exports = { Data: commonJsData, - PrefabUtils: commonJsPrefabUtils, THREEUtils: commonJsTHREEUtils, }; diff --git a/src/Game/Shared/Components/Data.js b/src/Game/Shared/Components/Data.js index 3b4343102..373abdc4c 100644 --- a/src/Game/Shared/Components/Data.js +++ b/src/Game/Shared/Components/Data.js @@ -17,7 +17,7 @@ module.exports = Object.freeze({ }, }, - //THREAD + //THREAD TODO move this to worldthread and rename this file Constants pack(obj) { let OString = JSON.stringify(obj); diff --git a/src/Game/Shared/Components/PrefabUtils.js b/src/Game/Shared/Components/PrefabUtils.js deleted file mode 100644 index 2c6352b77..000000000 --- a/src/Game/Shared/Components/PrefabUtils.js +++ /dev/null @@ -1,28 +0,0 @@ -/** @format */ - -const JSONUtils = require('../../../Components/SystemUtils/JSONUtils'); - -module.exports = { - parsePrefab(goJSON, manager) { - console.warn('deprecated ?'); - const parse = function (json, cb) { - if (json.children instanceof Object) { - for (let key in json.children) { - cb(json.children, key); - } - } - }; - - parse(goJSON, function (json, key) { - const value = json[key]; - - if (value.prefabId != undefined) { - const prefabJSON = manager.fetchPrefabJSON(value.prefabId); - JSONUtils.overWrite(prefabJSON, json); - json[key] = prefabJSON; - } - }); - - return goJSON; - }, -}; diff --git a/src/Game/Shared/GameObject/GameObject.js b/src/Game/Shared/GameObject/GameObject.js index a75d20fec..0285a6e2c 100644 --- a/src/Game/Shared/GameObject/GameObject.js +++ b/src/Game/Shared/GameObject/GameObject.js @@ -30,10 +30,6 @@ const GameObjectModule = class GameObject { //name this.name = json.name || 'none'; - //TODO remove me - //prefabId - this.prefabId = json.prefabId || null; - //transform this.transform = new THREEUtils.Transform(); this.transform.setFromJSON(json.transform); @@ -90,14 +86,10 @@ const GameObjectModule = class GameObject { this.static = json.static; //TODO recursive call for children + if (this.children.length) console.warn('children not set from ', json); } initAssetsComponents(manager, udvShared, isServerSide = false) { - if (this.prefabId) { - const json = manager.fetchPrefabJSON(this.prefabId); - JSONUtils.overWrite(json, this.json); - this.setFromJSON(json); - } if (!this.initialized) { this.initialized = true; From fdf307c28828f5702cbf53dcf663429ac595c607 Mon Sep 17 00:00:00 2001 From: valentinMachado Date: Mon, 7 Jun 2021 09:29:47 +0200 Subject: [PATCH 32/68] move function in utils --- src/Components/SystemUtils/File.js | 16 +++++++++++++++ src/Components/SystemUtils/JSONUtils.js | 27 +++++++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/src/Components/SystemUtils/File.js b/src/Components/SystemUtils/File.js index 43afe413f..2e076ba55 100644 --- a/src/Components/SystemUtils/File.js +++ b/src/Components/SystemUtils/File.js @@ -14,6 +14,7 @@ module.exports = { downloadAnchorNode.click(); downloadAnchorNode.remove(); }, + loadJSON(filePath) { return new Promise((resolve, reject) => { jquery.ajax({ @@ -30,4 +31,19 @@ module.exports = { }); }); }, + + readSingleFile(e, onLoad) { + try { + const file = e.target.files[0]; + if (!file) { + return; + } + const _this = this; + const reader = new FileReader(); + reader.onload = onLoad; + reader.readAsText(file); + } catch (e) { + throw new Error(e); + } + }, }; diff --git a/src/Components/SystemUtils/JSONUtils.js b/src/Components/SystemUtils/JSONUtils.js index 918af82a0..cddb0cd94 100644 --- a/src/Components/SystemUtils/JSONUtils.js +++ b/src/Components/SystemUtils/JSONUtils.js @@ -38,4 +38,31 @@ module.exports = { } }); }, + + separator: '&', + + pack(jsonArray) { + let result = ''; + for (let key in jsonArray) { + result += JSON.stringify(jsonArray[key]); + result += this.separator; + } + + //remove seprator at the end + if (result.endsWith(this.separator)) { + result = result.slice(0, result.length - this.separator.length); + } + return result; + }, + + unpack(string) { + const prefabs = string.split(this.separator); + const result = {}; + prefabs.forEach(function (p) { + const json = JSON.parse(p); + result[json.name] = json; + }); + + return result; + }, }; From d2be29953299734b5c83549823344c23a546b4b8 Mon Sep 17 00:00:00 2001 From: valentinMachado Date: Mon, 7 Jun 2021 09:43:09 +0200 Subject: [PATCH 33/68] static func bind --- src/Game/Shared/GameObject/Components/Render.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/Game/Shared/GameObject/Components/Render.js b/src/Game/Shared/GameObject/Components/Render.js index aea94fcd0..3ccd4e19a 100644 --- a/src/Game/Shared/GameObject/Components/Render.js +++ b/src/Game/Shared/GameObject/Components/Render.js @@ -155,4 +155,20 @@ const RenderModule = class Render { RenderModule.TYPE = 'Render'; +RenderModule.bindName = function (goJSON, name) { + try { + goJSON.components.Render.name = name; + } catch (e) { + throw new Error(e); + } +}; + +RenderModule.bindColor = function (goJSON, color) { + try { + goJSON.components.Render.color = color; + } catch (e) { + throw new Error(e); + } +}; + module.exports = RenderModule; From d5e3da1b47891eab6643f33dda76978319f89a1a Mon Sep 17 00:00:00 2001 From: valentinMachado Date: Mon, 7 Jun 2021 10:57:21 +0200 Subject: [PATCH 34/68] add TODO --- src/Game/Components/AssetsManager.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Game/Components/AssetsManager.js b/src/Game/Components/AssetsManager.js index 34e2b632d..b60062e6b 100644 --- a/src/Game/Components/AssetsManager.js +++ b/src/Game/Components/AssetsManager.js @@ -201,6 +201,7 @@ export class AssetsManager { return frame; } + //TODO assetManager load video with config a return video with id createVideo(path, w = 1, h = 1, size) { const video = document.createElement('video'); video.src = path; From 41df7c13d255902c89d7f4acfdcde83ec0fab311 Mon Sep 17 00:00:00 2001 From: valentinMachado Date: Mon, 7 Jun 2021 13:58:16 +0200 Subject: [PATCH 35/68] video are now localscript --- src/Game/Components/AssetsManager.js | 9 +++++++++ src/Game/GameView/GameView.js | 8 +++----- src/Game/Shared/GameObject/Components/Render.js | 16 +++++----------- 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/src/Game/Components/AssetsManager.js b/src/Game/Components/AssetsManager.js index b60062e6b..73901e897 100644 --- a/src/Game/Components/AssetsManager.js +++ b/src/Game/Components/AssetsManager.js @@ -10,6 +10,8 @@ const DEFAULT_MATERIAL = new THREE.MeshLambertMaterial({ color: 0x00ff00 }); export class AssetsManager { constructor() { + this.conf = null; + //manager to load scripts this.prefabs = {}; this.worldScripts = {}; @@ -47,6 +49,11 @@ export class AssetsManager { return new GameObjectModule(this.prefabs[idprefab]); } + fetchVideoPath(idVideo) { + if (!this.conf.videos[idVideo]) console.error('no video with id ', idVideo); + return this.conf.videos[idVideo].path; + } + fetchPrefabJSON(idprefab) { if (!this.prefabs[idprefab]) console.error('no prefab with id ', idprefab); return JSON.parse(JSON.stringify(this.prefabs[idprefab])); @@ -323,6 +330,8 @@ export class AssetsManager { } loadFromConfig(config) { + this.conf = config; + //load config file const _this = this; const loader = new GLTFLoader(); diff --git a/src/Game/GameView/GameView.js b/src/Game/GameView/GameView.js index 5d8c41a7b..4a440d0d1 100644 --- a/src/Game/GameView/GameView.js +++ b/src/Game/GameView/GameView.js @@ -404,11 +404,9 @@ export class GameView { if (!_this.isLocal) g.initAssetsComponents(_this.assetsManager, udvShared); - g.traverse(function (child) { - const scriptComponent = child.getComponent(LocalScript.TYPE); - if (scriptComponent) - scriptComponent.execute(LocalScript.EVENT.INIT, [ctx]); - }); + const scriptComponent = g.getComponent(LocalScript.TYPE); + if (scriptComponent) + scriptComponent.execute(LocalScript.EVENT.INIT, [ctx]); //add static object to obstacle if (g.isStatic()) { diff --git a/src/Game/Shared/GameObject/Components/Render.js b/src/Game/Shared/GameObject/Components/Render.js index 3ccd4e19a..3f5440965 100644 --- a/src/Game/Shared/GameObject/Components/Render.js +++ b/src/Game/Shared/GameObject/Components/Render.js @@ -86,6 +86,11 @@ const RenderModule = class Render { } } + addObject3D(obj) { + this.object3D.add(obj); + this.originalObject3D = this.object3D.clone(); + } + initAssets(assetsManager) { this.object3D = new THREE.Object3D(); this.object3D.name = 'Render Object3D ' + this.parent.getName(); @@ -129,17 +134,6 @@ const RenderModule = class Render { ); this.object3D.add(mediaImg); } - - if (this.media.video) { - const result = assetsManager.createVideo( - this.media.video.path, - this.media.video.width, - this.media.video.height, - this.media.video.size - ); - this.tickCb.push(result.tick); - this.object3D.add(result.frame); - } } const color = this.color; From 6f557f60f032774f628307108dc759f6f7475dd9 Mon Sep 17 00:00:00 2001 From: valentinMachado Date: Mon, 7 Jun 2021 16:13:39 +0200 Subject: [PATCH 36/68] export transform control --- src/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/index.js b/src/index.js index 1f076ff5e..c396989d3 100644 --- a/src/index.js +++ b/src/index.js @@ -27,8 +27,8 @@ export { jquery }; //three import * as THREE from 'three'; import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'; -import { PointerLockControls } from 'three/examples/jsm/controls/PointerLockControls'; -export { THREE, OrbitControls, PointerLockControls }; +import { TransformControls } from 'three/examples/jsm/controls/TransformControls'; +export { THREE, OrbitControls, TransformControls }; //proj4 import * as proj4 from 'proj4'; From 38480dfb50bfb199f44b218d9d73fd5561c57b34 Mon Sep 17 00:00:00 2001 From: valentinMachado Date: Tue, 8 Jun 2021 10:35:59 +0200 Subject: [PATCH 37/68] format with prettier widgets sources --- .eslintrc.js | 23 + package.json | 2 + .../3DTiles/3DTilesBuildingUtils.js | 17 +- .../View/CameraPositionerView.js | 15 +- src/Widgets/CityObjects/CityObjectModule.js | 24 +- .../View/AttributeFilterSelector.js | 20 +- .../View/CityObjectFilterSelector.js | 27 +- .../View/CityObjectFilterWindow.js | 35 +- .../CityObjects/View/CityObjectWindow.css | 6 +- .../CityObjects/View/CityObjectWindow.js | 84 ++-- .../CityObjects/ViewModel/AttributeFilter.js | 22 +- .../CityObjects/ViewModel/CityObjectFilter.js | 16 +- .../CityObjects/ViewModel/CityObjectLayer.js | 14 +- .../ViewModel/CityObjectProvider.js | 61 ++- .../View/DocumentVisualizer.css | 6 +- .../View/DocumentVisualizerWindow.js | 73 +-- src/Widgets/Documents/DocumentModule.js | 12 +- src/Widgets/Documents/Model/Document.js | 25 +- .../Documents/Model/DocumentService.js | 86 ++-- .../Documents/View/AbstractDocumentWindow.js | 37 +- .../Documents/View/DocumentInspectorWindow.js | 38 +- .../Documents/View/DocumentNavigatorWindow.js | 80 ++-- src/Widgets/Documents/View/DocumentView.js | 47 +- src/Widgets/Documents/View/DocumentWindow.css | 10 +- .../Documents/ViewModel/DocumentFilter.js | 14 +- .../Documents/ViewModel/DocumentProvider.js | 97 ++-- .../ViewModel/DocumentSearchFilter.js | 46 +- .../3DTilesDebug/views/3DTilesDebugWindow.js | 68 ++- .../services/AuthenticationService.js | 291 ++++++------ .../views/AuthenticationView.css | 182 ++++---- .../views/AuthenticationView.js | 263 +++++------ .../Extensions/Contribute/ContributeModule.js | 48 +- .../Contribute/Service/ContributeService.js | 16 +- .../Extensions/Contribute/View/Contribute.css | 14 +- .../Contribute/View/DocumentCreationWindow.js | 95 ++-- .../View/DocumentDeletionInterface.js | 20 +- .../Contribute/View/DocumentUpdateWindow.js | 40 +- .../DocumentCommentsModule.js | 20 +- .../services/DocumentCommentsService.js | 97 ++-- .../views/DocumentCommentsStyle.css | 132 +++--- .../views/DocumentCommentsWindow.js | 139 +++--- .../DocumentValidationModule.js | 23 +- .../Service/DocumentsInValidationSource.js | 8 +- .../Service/ValidationService.js | 16 +- .../DocumentValidation/View/ValidationView.js | 105 +++-- src/Widgets/Extensions/Extensions.js | 2 - .../Geocoding/services/GeocodingService.js | 40 +- .../Geocoding/views/GeocodingStyle.css | 18 +- .../Geocoding/views/GeocodingView.js | 43 +- src/Widgets/GuidedTour/GuidedTour.css | 370 +++++++-------- src/Widgets/GuidedTour/GuidedTour.js | 176 +++---- .../GuidedTour/GuidedTourController.js | 82 ++-- src/Widgets/LayerChoice/views/LayerChoice.js | 95 ++-- src/Widgets/Links/LinkModule.js | 54 ++- src/Widgets/Links/Model/Link.js | 17 +- src/Widgets/Links/Model/LinkService.js | 32 +- .../Links/View/CityObjectLinkInterface.js | 36 +- .../Links/View/DocumentLinkInterface.js | 79 ++-- src/Widgets/Links/View/LinkView.js | 59 ++- .../Links/ViewModel/CityObjectLinkFilters.js | 48 +- src/Widgets/Links/ViewModel/LinkProvider.js | 155 ++++--- src/Widgets/Others/About.css | 45 +- src/Widgets/Others/About.js | 54 ++- src/Widgets/Others/Help.css | 54 +-- src/Widgets/Others/Help.js | 25 +- .../Temporal/Model/3DTemporalBatchTable.js | 142 +++--- .../Model/3DTemporalBoundingVolume.js | 43 +- .../Temporal/Model/3DTemporalExtension.js | 244 +++++----- .../Model/3DTemporalPrimaryTransaction.js | 18 +- .../Temporal/Model/3DTemporalTileset.js | 82 ++-- .../Temporal/Model/3DTemporalTransaction.js | 21 +- .../Model/3DTemporalTransactionAggregate.js | 18 +- .../Temporal/Model/3DTemporalVersion.js | 27 +- .../3DTILES_temporal.batchTable.schema.json | 2 +- .../3DTILES_temporal.primaryTransaction.json | 21 +- .../3DTILES_temporal.tileset.schema.json | 14 +- .../3DTILES_temporal.transaction.schema.json | 6 +- ..._temporal.transactionAggregate.schema.json | 23 +- ...DTILES_temporal.version.schema.schema.json | 4 +- ...LES_temporal.versionTransition.schema.json | 2 +- src/Widgets/Temporal/TemporalModule.js | 24 +- src/Widgets/Temporal/View/EnumWindows.js | 16 +- src/Widgets/Temporal/View/NetworkManager.js | 133 +++--- .../Temporal/View/TemporalGraphWindow.js | 85 ++-- .../Temporal/View/TemporalSliderWindow.js | 112 ++--- src/Widgets/Temporal/View/TemporalView.js | 46 +- src/Widgets/Temporal/View/TemporalWindow.css | 68 +-- .../Temporal/ViewModel/TemporalProvider.js | 428 ++++++++++-------- 88 files changed, 3115 insertions(+), 2462 deletions(-) create mode 100644 .eslintrc.js diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 000000000..00b804fc4 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,23 @@ +/** @format */ + +module.exports = { + env: { + browser: true, + es2021: true, + node: true, + }, + extends: 'eslint:recommended', + parserOptions: { + ecmaVersion: 2020, + sourceType: 'module', + ecmaFeatures: { + jsx: true, + }, + }, + rules: { + indent: [2, 2, { SwitchCase: 1 }], + 'linebreak-style': ['error', 'unix'], + quotes: ['error', 'single'], + semi: ['error', 'always'], + }, +}; diff --git a/package.json b/package.json index 3b689cd3b..28ac51c2e 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,7 @@ "description": "A collection of itowns plugins", "main": "src", "scripts": { + "eslint": "./node_modules/.bin/eslint ./src", "test": "npm run build", "build": "cross-env NODE_ENV=production webpack", "build-debug": "cross-env NODE_ENV=development webpack", @@ -36,6 +37,7 @@ "child-process-promise": "^2.2.1", "cross-env": "^7.0.3", "css-loader": "^0.28.10", + "eslint": "^7.28.0", "nodemon": "^2.0.7", "style-loader": "^0.20.3", "url-loader": "^1.0.1", diff --git a/src/Components/3DTiles/3DTilesBuildingUtils.js b/src/Components/3DTiles/3DTilesBuildingUtils.js index fdc61ab5f..086c003b0 100644 --- a/src/Components/3DTiles/3DTilesBuildingUtils.js +++ b/src/Components/3DTiles/3DTilesBuildingUtils.js @@ -1,11 +1,16 @@ -import { setTileVerticesColor, getBatchIdFromIntersection, - getBatchTableFromTile, - getTileInLayer} from "./3DTilesUtils"; +/** @format */ + +import { + setTileVerticesColor, + getBatchIdFromIntersection, + getBatchTableFromTile, + getTileInLayer, +} from './3DTilesUtils'; /** * Gets a building ID from an intersection. The intersecting object must * be a "Mesh" object with a batch id. - * + * * @param {*} inter An intersection */ export function getBuildingIdFromIntersection(inter) { @@ -28,7 +33,7 @@ export function getBuildingInfoFromBuildingId(tilesInfo, buildingId) { /** * Sets the color of one building in the scene. - * + * * @param {*} layer The 3DTiles layer. * @param {*} buildingInfo The building info. * @param {Array} color The color. @@ -39,4 +44,4 @@ export function colorBuilding(layer, buildingInfo, color) { throw 'Building not in the view - tile is not loaded'; } setTileVerticesColor(tile, color, buildingInfo.arrayIndexes); -} \ No newline at end of file +} diff --git a/src/Widgets/CameraPositioner/View/CameraPositionerView.js b/src/Widgets/CameraPositioner/View/CameraPositionerView.js index 095105b5c..7dd3ff773 100644 --- a/src/Widgets/CameraPositioner/View/CameraPositionerView.js +++ b/src/Widgets/CameraPositioner/View/CameraPositionerView.js @@ -1,7 +1,9 @@ +/** @format */ + //Components -import { ModuleView } from "../../../Components/ModuleView/ModuleView"; -import { PositionerWindow } from "../../../Components/Camera/PositionerWindow"; -import { Window } from "../../../Components/GUI/js/Window"; +import { ModuleView } from '../../../Components/ModuleView/ModuleView'; +import { PositionerWindow } from '../../../Components/Camera/PositionerWindow'; +import { Window } from '../../../Components/GUI/js/Window'; export class CameraPositionerView extends ModuleView { constructor(itownsView, cameraControls) { @@ -9,8 +11,9 @@ export class CameraPositionerView extends ModuleView { this.positionerWindow = new PositionerWindow(itownsView, cameraControls); - this.positionerWindow.addEventListener(Window.EVENT_DISABLED, - () => this.disable()); + this.positionerWindow.addEventListener(Window.EVENT_DISABLED, () => + this.disable() + ); } enableView() { @@ -20,4 +23,4 @@ export class CameraPositionerView extends ModuleView { disableView() { this.positionerWindow.dispose(); } -} \ No newline at end of file +} diff --git a/src/Widgets/CityObjects/CityObjectModule.js b/src/Widgets/CityObjects/CityObjectModule.js index e32169f93..678b45085 100644 --- a/src/Widgets/CityObjects/CityObjectModule.js +++ b/src/Widgets/CityObjects/CityObjectModule.js @@ -1,8 +1,10 @@ +/** @format */ + //Components -import { CityObjectStyle } from "../../Components/3DTiles/Model/CityObjectStyle"; +import { CityObjectStyle } from '../../Components/3DTiles/Model/CityObjectStyle'; -import { CityObjectProvider } from "./ViewModel/CityObjectProvider"; -import { CityObjectWindow } from "./View/CityObjectWindow"; +import { CityObjectProvider } from './ViewModel/CityObjectProvider'; +import { CityObjectWindow } from './View/CityObjectWindow'; /** * Manages the city objects and allows the user to visualize them with @@ -14,7 +16,7 @@ export class CityObjectModule { * Manages the city objects and allows the user to visualize them with * filters. Other modules can extend the functionnalities of the city object * module by adding filters. - * + * * @param {LayerManager} layerManager The layer manager. * @param {object} config The UDV configuration. * @param {object} config.cityObjects The city objects config. @@ -43,7 +45,7 @@ export class CityObjectModule { /** * Adds an event listener to the city object provider. - * + * * @param {string} event The event of the city object provider. * @param {(data: any) => any} action The listener method. */ @@ -53,7 +55,7 @@ export class CityObjectModule { /** * Removes the event listener from the city object provider. - * + * * @param {(data: any) => any} action The listener to remove. */ removeEventListener(action) { @@ -61,9 +63,9 @@ export class CityObjectModule { } /** - * Creates a new extension for the city object window. An extension is + * Creates a new extension for the city object window. An extension is * a piece of HTML identified by a label. - * + * * @param {string} label The extension label. * @param {object} options The options for the extension. * @param {string} options.type The type of the extension. Can either be @@ -83,7 +85,7 @@ export class CityObjectModule { /** * Removes an existing extension in the city object window. - * + * * @param {string} label The extension label. */ removeExtension(label) { @@ -92,11 +94,11 @@ export class CityObjectModule { /** * Adds a filter selector in the city object filter window. - * + * * @param {CityObjectFilterSelector} filterSelector The filter selector to * add. */ addFilterSelector(filterSelector) { this.view.addFilterSelector(filterSelector); } -} \ No newline at end of file +} diff --git a/src/Widgets/CityObjects/View/AttributeFilterSelector.js b/src/Widgets/CityObjects/View/AttributeFilterSelector.js index 90064ea1f..1a8757afe 100644 --- a/src/Widgets/CityObjects/View/AttributeFilterSelector.js +++ b/src/Widgets/CityObjects/View/AttributeFilterSelector.js @@ -1,6 +1,8 @@ -import { CityObjectFilterSelector } from "./CityObjectFilterSelector"; -import { CityObjectProvider } from "../ViewModel/CityObjectProvider"; -import { AttributeFilter } from "../ViewModel/AttributeFilter"; +/** @format */ + +import { CityObjectFilterSelector } from './CityObjectFilterSelector'; +import { CityObjectProvider } from '../ViewModel/CityObjectProvider'; +import { AttributeFilter } from '../ViewModel/AttributeFilter'; /** * A filter selector for the `AttributeFilter` filter. It allows the user to @@ -11,7 +13,7 @@ import { AttributeFilter } from "../ViewModel/AttributeFilter"; export class AttributeFilterSelector extends CityObjectFilterSelector { /** * Constructs the attribute filter selector from the provider. - * + * * @param {CityObjectProvider} provider The city object provider. */ constructor(provider) { @@ -19,7 +21,7 @@ export class AttributeFilterSelector extends CityObjectFilterSelector { /** * The associated attribute filter. - * + * * @type {AttributeFilter} */ this.filter = new AttributeFilter(); @@ -29,7 +31,7 @@ export class AttributeFilterSelector extends CityObjectFilterSelector { } get html() { - return /*html*/` + return /*html*/ ` @@ -42,9 +44,9 @@ export class AttributeFilterSelector extends CityObjectFilterSelector { /** * Sets the `tileId`, `batchId` and `props` attributes of the attribut filter * from the given form data. - * + * * @override - * + * * @param {FormData} formData */ onSubmit(formData) { @@ -56,4 +58,4 @@ export class AttributeFilterSelector extends CityObjectFilterSelector { } } } -} \ No newline at end of file +} diff --git a/src/Widgets/CityObjects/View/CityObjectFilterSelector.js b/src/Widgets/CityObjects/View/CityObjectFilterSelector.js index 34dd96dde..1ba6f26eb 100644 --- a/src/Widgets/CityObjects/View/CityObjectFilterSelector.js +++ b/src/Widgets/CityObjects/View/CityObjectFilterSelector.js @@ -2,26 +2,29 @@ * Represents an option in the list of filters the user can select. It also * stores additional HTML that can be put in a form if the filter accepts * parameters. + * + * @format */ + export class CityObjectFilterSelector { /** * Constructs a filter selector from the associated filter label and a * display name. - * + * * @param {string} filterLabel The associated filter. * @param {string} displayName The displayed name in the `select` tag. */ - constructor(filterLabel, displayName) { + constructor(filterLabel, displayName) { /** * The label of the corresponding filter. - * + * * @type {string} */ this.filterLabel = filterLabel; /** * The displayed name of the filter. - * + * * @type {string} */ this.displayName = displayName; @@ -29,7 +32,7 @@ export class CityObjectFilterSelector { /** * The HTML that will be put in the filter form. - * + * * @returns {string} */ get html() { @@ -40,29 +43,25 @@ export class CityObjectFilterSelector { /** * Triggers when the HTML elements are created. */ - onCreated() { - - } + onCreated() {} /** * Triggers when the form is submitted. - * + * * @param {FormData} formData The form data corresponding to the filter * selector form. */ - onSubmit(formData) { - - } + onSubmit(formData) {} /** * Adds the HTML content of the filter selector in the given HTLM element. * This element should be a form, or part of a form. Calls the `onCreated` * hook. - * + * * @param {HTMLElement} parentElement The parent element to add the fields. */ appendFormFieldsTo(parentElement) { parentElement.innerHTML = this.html; this.onCreated(); } -} \ No newline at end of file +} diff --git a/src/Widgets/CityObjects/View/CityObjectFilterWindow.js b/src/Widgets/CityObjects/View/CityObjectFilterWindow.js index 7de85fa85..e9b018a86 100644 --- a/src/Widgets/CityObjects/View/CityObjectFilterWindow.js +++ b/src/Widgets/CityObjects/View/CityObjectFilterWindow.js @@ -1,7 +1,9 @@ +/** @format */ + //Components -import { Window } from "../../../Components/GUI/js/Window"; +import { Window } from '../../../Components/GUI/js/Window'; -import { CityObjectFilterSelector } from "./CityObjectFilterSelector"; +import { CityObjectFilterSelector } from './CityObjectFilterSelector'; /** * The filter selection window. This window allows the user to pick a filter @@ -17,7 +19,7 @@ export class CityObjectFilterWindow extends Window { /** * The list of filter selectors. - * + * * @type {Array} */ this.filterSelectors = []; @@ -27,7 +29,7 @@ export class CityObjectFilterWindow extends Window { } get innerContentHtml() { - return /*html*/` + return /*html*/ `

      Filter selection

      @@ -55,19 +57,21 @@ export class CityObjectFilterWindow extends Window { this.filterFormElement.onsubmit = () => { this._onSubmit(); return false; - } + }; } /** * Adds a filter selector in the filter selectos list. - * + * * @param {CityObjectFilterSelector} filterSelector The filter selector to * add. */ addFilterSelector(filterSelector) { if (!!this.getFilterSelector(filterSelector.filterLabel)) { - throw 'A filter selector with the same filter label already exist: ' - + filterSelector.filterLabel; + throw ( + 'A filter selector with the same filter label already exist: ' + + filterSelector.filterLabel + ); } this.filterSelectors.push(filterSelector); this._createFilterSelect(); @@ -75,7 +79,7 @@ export class CityObjectFilterWindow extends Window { /** * Returns the filter selector corresponding to the given filter label. - * + * * @param {string} filterLabel The label of the filter. */ getFilterSelector(filterLabel) { @@ -125,12 +129,14 @@ export class CityObjectFilterWindow extends Window { * selected the 'No filter' option. */ _getCurrentSelector() { - let selected = this.filterSelectElement.options[this.filterSelectElement.selectedIndex].label; + let selected = + this.filterSelectElement.options[this.filterSelectElement.selectedIndex] + .label; if (selected === 'no-filter') { return undefined; } - + let selector = this.getFilterSelector(selected); if (selector === undefined) { @@ -154,7 +160,10 @@ export class CityObjectFilterWindow extends Window { let formData = new FormData(this.filterFormElement); selector.onSubmit(formData); - this.sendEvent(CityObjectFilterWindow.EVENT_FILTER_SELECTED, selector.filterLabel); + this.sendEvent( + CityObjectFilterWindow.EVENT_FILTER_SELECTED, + selector.filterLabel + ); this.disable(); } @@ -191,4 +200,4 @@ export class CityObjectFilterWindow extends Window { static get EVENT_FILTER_SELECTED() { return 'EVENT_FILTER_SELECTED'; } -} \ No newline at end of file +} diff --git a/src/Widgets/CityObjects/View/CityObjectWindow.css b/src/Widgets/CityObjects/View/CityObjectWindow.css index a5d4c1d4a..9f403a2a0 100644 --- a/src/Widgets/CityObjects/View/CityObjectWindow.css +++ b/src/Widgets/CityObjects/View/CityObjectWindow.css @@ -1,3 +1,5 @@ +/** @format */ + .city-object-title { margin: 5px 0 5px 0; font-weight: bold; @@ -13,7 +15,7 @@ margin: 10px; } -.city-object-filter-section input[type="text"] { +.city-object-filter-section input[type='text'] { width: 100%; box-sizing: border-box; } @@ -27,4 +29,4 @@ border: 1px solid #f2f2f2; margin: 2px; margin-left: 10px; -} \ No newline at end of file +} diff --git a/src/Widgets/CityObjects/View/CityObjectWindow.js b/src/Widgets/CityObjects/View/CityObjectWindow.js index d9940dbae..5359230a6 100644 --- a/src/Widgets/CityObjects/View/CityObjectWindow.js +++ b/src/Widgets/CityObjects/View/CityObjectWindow.js @@ -1,11 +1,13 @@ +/** @format */ + //Components -import { Window } from "../../../Components/GUI/js/Window"; -import { CityObjectStyle } from "../../../Components/3DTiles/Model/CityObjectStyle"; +import { Window } from '../../../Components/GUI/js/Window'; +import { CityObjectStyle } from '../../../Components/3DTiles/Model/CityObjectStyle'; -import { CityObjectProvider } from "../ViewModel/CityObjectProvider"; -import { CityObjectFilterSelector } from "./CityObjectFilterSelector"; -import { CityObjectFilterWindow } from "./CityObjectFilterWindow"; -import { AttributeFilterSelector } from "./AttributeFilterSelector"; +import { CityObjectProvider } from '../ViewModel/CityObjectProvider'; +import { CityObjectFilterSelector } from './CityObjectFilterSelector'; +import { CityObjectFilterWindow } from './CityObjectFilterWindow'; +import { AttributeFilterSelector } from './AttributeFilterSelector'; import './CityObjectWindow.css'; @@ -17,7 +19,7 @@ import './CityObjectWindow.css'; export class CityObjectWindow extends Window { /** * Constructs the window from the provider. - * + * * @param {CityObjectProvider} provider The city object provider. */ constructor(provider) { @@ -25,35 +27,35 @@ export class CityObjectWindow extends Window { /** * The city object provider. - * + * * @type {CityObjectProvider} */ this.provider = provider; /** * The window for selected filters. - * + * * @type {CityObjectFilterWindow} */ this.filterWindow = new CityObjectFilterWindow(); /** * The style for the layer chosen by the user, through the filter window. - * + * * @type {CityObjectStyle | string} */ - this.defaultLayerStyle = {materialProps: {color: 0xffa14f}}; + this.defaultLayerStyle = { materialProps: { color: 0xffa14f } }; /** * Wether the use is currently selecting a city object. - * + * * @type {boolean} */ this.isSelectingCityObject = false; /** * The list of extensions - * + * * @type {Array<{html: string, label: string, id: string}>} */ this.extensions = []; @@ -61,7 +63,7 @@ export class CityObjectWindow extends Window { let viewerDiv = document.getElementById('viewerDiv'); /** * The event listener for mouse clicks. - * + * * @type {(event: MouseEvent) => any} */ this.mouseClickListener = (event) => { @@ -77,29 +79,34 @@ export class CityObjectWindow extends Window { viewerDiv.removeEventListener('mousedown', this.mouseClickListener); }); - // Adding a filter selector for the attribute filter - this.filterWindow.addFilterSelector(new AttributeFilterSelector(this.provider)); + this.filterWindow.addFilterSelector( + new AttributeFilterSelector(this.provider) + ); // The event listener for filter selection (in the filter window). Updates // the layer in the provider. this.filterWindow.addEventListener( CityObjectFilterWindow.EVENT_FILTER_SELECTED, - (filterLabel) => this._onFilterSelected(filterLabel)); + (filterLabel) => this._onFilterSelected(filterLabel) + ); // The event listener for the layer change. Updates the layer description. - this.provider.addEventListener(CityObjectProvider.EVENT_LAYER_CHANGED, - () => this._updateLayerDescription()); + this.provider.addEventListener(CityObjectProvider.EVENT_LAYER_CHANGED, () => + this._updateLayerDescription() + ); // Event listener for city object selection - this.provider.addEventListener(CityObjectProvider.EVENT_CITY_OBJECT_SELECTED, - (cityObject) => this._updateSelectedCityObjectDescription(cityObject)); + this.provider.addEventListener( + CityObjectProvider.EVENT_CITY_OBJECT_SELECTED, + (cityObject) => this._updateSelectedCityObjectDescription(cityObject) + ); this._updateLayerDescription(); this._updateSelectedCityObjectDescription(); } get innerContentHtml() { - return /*html*/` + return /*html*/ `

      Filter

      @@ -140,14 +147,12 @@ export class CityObjectWindow extends Window { this._createExtensionElement(extension); } - this.selectFilterButtonElement.onclick = - () => this.filterWindow.enable(); + this.selectFilterButtonElement.onclick = () => this.filterWindow.enable(); - this.clearFilterButtonElement.onclick = - () => this.provider.removeLayer(); + this.clearFilterButtonElement.onclick = () => this.provider.removeLayer(); - this.clearSelectionButtonElement.onclick = - () => this._clearCityObjectSelection(); + this.clearSelectionButtonElement.onclick = () => + this._clearCityObjectSelection(); this.clearSelectionButtonElement.disabled = true; @@ -167,7 +172,7 @@ export class CityObjectWindow extends Window { this.selectedFilterElement.innerText = layer.filter.toString(); this.layerColorIndicatorElement.style.display = ''; this.layerColorIndicatorElement.style.background = - '#' + (new THREE.Color(layer.style.materialProps.color)).getHexString(); + '#' + new THREE.Color(layer.style.materialProps.color).getHexString(); } else { this.selectedFilterElement.innerText = ''; this.layerColorIndicatorElement.style.display = 'none'; @@ -180,7 +185,7 @@ export class CityObjectWindow extends Window { /** * Adds a filter selector in the city object filter window. - * + * * @param {CityObjectFilterSelector} filterSelector The filter selector to * add. */ @@ -191,7 +196,7 @@ export class CityObjectWindow extends Window { /** * Triggered when the user selects a filter in the filter selection window. * Sets the correct layer in the provider. - * + * * @param {string} filterLabel The selected filter label. */ _onFilterSelected(filterLabel) { @@ -205,7 +210,7 @@ export class CityObjectWindow extends Window { /** * Sets the default style for the layer defined by the user (through the * filter selection window). - * + * * @param {CityObjectStyle | string} style The default style for the layer. */ setDefaultLayerStyle(style) { @@ -225,7 +230,7 @@ export class CityObjectWindow extends Window { /** * Updates the description for the selected city object. - * + * * @param {CityObject} cityObject The selected city object. */ _updateSelectedCityObjectDescription(cityObject) { @@ -233,8 +238,11 @@ export class CityObjectWindow extends Window { return; } - this.selectionColorIndicatorElement.style.background = '#' + - (new THREE.Color(this.provider.defaultSelectionStyle.materialProps.color)).getHexString(); + this.selectionColorIndicatorElement.style.background = + '#' + + new THREE.Color( + this.provider.defaultSelectionStyle.materialProps.color + ).getHexString(); if (!cityObject) { this.selectedCityObjectElement.innerHTML = ''; @@ -244,7 +252,7 @@ export class CityObjectWindow extends Window { this.clearSelectionButtonElement.disabled = false; - let html = /*html*/` + let html = /*html*/ `

      Attributes

      Tile ID : ${cityObject.tile.tileId}
      @@ -252,7 +260,7 @@ export class CityObjectWindow extends Window { Layer : ${cityObject.tile.layer.name} `; for (let prop of Object.entries(cityObject.props)) { - html += /*html*/` + html += /*html*/ `
      ${prop[0]} : ${prop[1]} `; } @@ -318,4 +326,4 @@ export class CityObjectWindow extends Window { get selectionColorIndicatorElement() { return document.getElementById(this.selectionColorIndicatorId); } -} \ No newline at end of file +} diff --git a/src/Widgets/CityObjects/ViewModel/AttributeFilter.js b/src/Widgets/CityObjects/ViewModel/AttributeFilter.js index a429f4ec9..3b8a3c056 100644 --- a/src/Widgets/CityObjects/ViewModel/AttributeFilter.js +++ b/src/Widgets/CityObjects/ViewModel/AttributeFilter.js @@ -1,7 +1,9 @@ +/** @format */ + //Components -import { CityObject } from "../../../Components/3DTiles/Model/CityObject"; +import { CityObject } from '../../../Components/3DTiles/Model/CityObject'; -import { CityObjectFilter } from "./CityObjectFilter"; +import { CityObjectFilter } from './CityObjectFilter'; /** * A specialization of `CityObjectFilter` to filter the city objects from @@ -37,9 +39,9 @@ export class AttributeFilter extends CityObjectFilter { * Accepts city objects according to their attributes. For each attribute in * this filter that evaluates to `true` (ie. neither undefined, null nor an * empty string), equality is tested with the city object. - * + * * @param {CityObject} cityObject The city object to evaluate. - * + * * @returns {boolean} Wether the city object is acceptable. */ accepts(cityObject) { @@ -52,8 +54,10 @@ export class AttributeFilter extends CityObjectFilter { } for (let key of Object.keys(this.props)) { - if (!cityObject.props[key] || - (!!this.props[key] && this.props[key] != cityObject.props[key])) { + if ( + !cityObject.props[key] || + (!!this.props[key] && this.props[key] != cityObject.props[key]) + ) { return false; } } @@ -92,11 +96,11 @@ export class AttributeFilter extends CityObjectFilter { result += ', '; } } - result += ')' + result += ')'; } else { - result += 'All city objects' + result += 'All city objects'; } return result; } -} \ No newline at end of file +} diff --git a/src/Widgets/CityObjects/ViewModel/CityObjectFilter.js b/src/Widgets/CityObjects/ViewModel/CityObjectFilter.js index a10f47931..aebddc3a5 100644 --- a/src/Widgets/CityObjects/ViewModel/CityObjectFilter.js +++ b/src/Widgets/CityObjects/ViewModel/CityObjectFilter.js @@ -1,5 +1,7 @@ +/** @format */ + //Components -import { CityObject } from "../../../Components/3DTiles/Model/CityObject"; +import { CityObject } from '../../../Components/3DTiles/Model/CityObject'; /** * Represents a filter for city objects. It is basically a function that takes @@ -9,7 +11,7 @@ export class CityObjectFilter { /** * Constructs a new city object filter, from an acceptation function. If no * acceptation function was provided, the filter accepts all city objects. - * + * * @param {string} label The unique label identifying the filter. * @param {(CityObject) => boolean} [accepts] The function responsible to * filter the city objects. It must evaluate wether a city object is @@ -18,12 +20,12 @@ export class CityObjectFilter { constructor(label, accepts) { /** * The unique identifier of the filter. - * + * * @type {string} */ this.label = label; - if (typeof(accepts) === 'function') { + if (typeof accepts === 'function') { this.accepts = accepts; } else { // Necessary if inheritance is used, I'm not sure why though @@ -34,9 +36,9 @@ export class CityObjectFilter { /** * The function responsible to filter the city objects. It evaluates wether * a city object is acceptable according to the filter. - * + * * @param {CityObject} cityObject The city object to evaluate. - * + * * @returns {boolean} Wether the city object is acceptable. */ accepts(cityObject) { @@ -50,4 +52,4 @@ export class CityObjectFilter { toString() { return this.label; } -} \ No newline at end of file +} diff --git a/src/Widgets/CityObjects/ViewModel/CityObjectLayer.js b/src/Widgets/CityObjects/ViewModel/CityObjectLayer.js index fd258568c..9d2a59f63 100644 --- a/src/Widgets/CityObjects/ViewModel/CityObjectLayer.js +++ b/src/Widgets/CityObjects/ViewModel/CityObjectLayer.js @@ -1,7 +1,9 @@ +/** @format */ + //Components -import { CityObjectStyle } from "../../../Components/3DTiles/Model/CityObjectStyle"; +import { CityObjectStyle } from '../../../Components/3DTiles/Model/CityObjectStyle'; -import { CityObjectFilter } from "./CityObjectFilter"; +import { CityObjectFilter } from './CityObjectFilter'; /** * A layer represents an association between a set of city objects and a style. @@ -10,7 +12,7 @@ import { CityObjectFilter } from "./CityObjectFilter"; export class CityObjectLayer { /** * Constructs a layer from a filter and a style. - * + * * @param {CityObjectFilter} filter The filter associated with the layer. * @param {CityObjectStyle | string} style The style associated with the * layer. @@ -22,16 +24,16 @@ export class CityObjectLayer { /** * The filter associated with the layer. - * + * * @type {CityObjectFilter} */ this.filter = filter; /** * The style associated with the layer. - * + * * @type {CityObjectStyle | string} */ this.style = style; } -} \ No newline at end of file +} diff --git a/src/Widgets/CityObjects/ViewModel/CityObjectProvider.js b/src/Widgets/CityObjects/ViewModel/CityObjectProvider.js index e130e6dd4..99b40e6a5 100644 --- a/src/Widgets/CityObjects/ViewModel/CityObjectProvider.js +++ b/src/Widgets/CityObjects/ViewModel/CityObjectProvider.js @@ -1,11 +1,16 @@ +/** @format */ + //Components -import { CityObjectStyle } from "../../../Components/3DTiles/Model/CityObjectStyle"; -import { CityObjectID, CityObject } from "../../../Components/3DTiles/Model/CityObject"; -import { EventSender } from "../../../Components/Events/EventSender"; -import { LayerManager } from "../../../Components/LayerManager/LayerManager"; +import { CityObjectStyle } from '../../../Components/3DTiles/Model/CityObjectStyle'; +import { + CityObjectID, + CityObject, +} from '../../../Components/3DTiles/Model/CityObject'; +import { EventSender } from '../../../Components/Events/EventSender'; +import { LayerManager } from '../../../Components/LayerManager/LayerManager'; -import { CityObjectFilter } from "./CityObjectFilter"; -import { CityObjectLayer } from "./CityObjectLayer"; +import { CityObjectFilter } from './CityObjectFilter'; +import { CityObjectLayer } from './CityObjectLayer'; /** * The city object provider manages the city object by organizing them in two @@ -16,49 +21,49 @@ import { CityObjectLayer } from "./CityObjectLayer"; export class CityObjectProvider extends EventSender { /** * Constructs a city object provider, using a layer manager. - * + * * @param {LayerManager} layerManager The layer manager. */ constructor(layerManager) { super(); /** * The tiles manager. - * + * * @type {LayerManager} */ this.layerManager = layerManager; /** * The available filters. - * + * * @type {Object.} */ this.filters = {}; /** * The current highlighted layer. - * + * * @type {CityObjectLayer} */ this.cityOjectLayer = undefined; /** * The array of city objects in the layer. - * + * * @type {Array} */ this.layerCityObjectIds = []; /** * The selected city object. - * + * * @type {CityObject} */ this.selectedCityObject = undefined; /** * The style applied to the selected city object. - * + * * @type {CityObjectStyle | string} */ this.defaultSelectionStyle = { materialProps: { color: 0x13ddef } }; @@ -75,7 +80,7 @@ export class CityObjectProvider extends EventSender { /** * Selects a city object from a mouse event. If a city object is actually * under the mouse, the `EVENT_CITY_OBJECT_SELECTED` event is sent. - * + * * @param {MouseEvent} mouseEvent The mouse click event. */ selectCityObject(mouseEvent) { @@ -101,7 +106,7 @@ export class CityObjectProvider extends EventSender { /** * Sets the style for the selected city object. - * + * * @param {CityObjectStyle | string} style The style. */ setSelectionStyle(style) { @@ -115,7 +120,7 @@ export class CityObjectProvider extends EventSender { * Adds a filter to the dictionnary of available filters. The key shall be * the `label` attribute of the filter. After that, the * `EVENT_FILTERS_UPDATED` event is sent. - * + * * @param {CityObjectFilter} cityObjectFilter The filter to add. */ addFilter(cityObjectFilter) { @@ -132,7 +137,7 @@ export class CityObjectProvider extends EventSender { /** * Returns the currently available filters. - * + * * @return {Array} The currently available filters. */ getFilters() { @@ -145,7 +150,7 @@ export class CityObjectProvider extends EventSender { /** * Sets the current layer. The layer is defined by a filter (ie. a set * of city objects) and a style. Sends the `EVENT_LAYER_CHANGED` event. - * + * * @param {string} filterLabel Label of the filter that defines the layer. * The filter must first be registered using `addFilter`. * @param {CityObjectStyle | string} style The style to associate to the @@ -169,7 +174,7 @@ export class CityObjectProvider extends EventSender { /** * Returns the current layer. - * + * * @returns {CityObjectLayer} The current layer. */ getLayer() { @@ -188,13 +193,15 @@ export class CityObjectProvider extends EventSender { /** * Updates the tiles manager so that it has the correct styles associated with * the right city objects. - * + * * @private */ _updateTilesManager() { this.layerManager.removeAll3DTilesStyles(); if (!!this.selectedCityObject) { - let tileManager = this.layerManager.getTilesManagerByLayerID(this.selectedCityObject.tile.layer.id); + let tileManager = this.layerManager.getTilesManagerByLayerID( + this.selectedCityObject.tile.layer.id + ); if (this.cityOjectLayer === undefined) { this.layerCityObjectIds = []; @@ -203,10 +210,16 @@ export class CityObjectProvider extends EventSender { .findAllCityObjects(this.cityOjectLayer.filter.accepts) .map((co) => co.cityObjectId); - tileManager.setStyle(this.layerCityObjectIds, this.cityOjectLayer.style); + tileManager.setStyle( + this.layerCityObjectIds, + this.cityOjectLayer.style + ); } - tileManager.setStyle(this.selectedCityObject.cityObjectId, this.defaultSelectionStyle); + tileManager.setStyle( + this.selectedCityObject.cityObjectId, + this.defaultSelectionStyle + ); } } @@ -234,4 +247,4 @@ export class CityObjectProvider extends EventSender { static get EVENT_CITY_OBJECT_SELECTED() { return 'EVENT_CITY_OBJECT_SELECTED'; } -} \ No newline at end of file +} diff --git a/src/Widgets/DocumentVisualizer/View/DocumentVisualizer.css b/src/Widgets/DocumentVisualizer/View/DocumentVisualizer.css index 54c94e584..5318063d5 100644 --- a/src/Widgets/DocumentVisualizer/View/DocumentVisualizer.css +++ b/src/Widgets/DocumentVisualizer/View/DocumentVisualizer.css @@ -1,3 +1,5 @@ +/** @format */ + .orienter-box { width: 55%; height: 55%; @@ -18,7 +20,7 @@ .orienter-box .controls-panel { width: 80%; max-width: 500px; - background: rgba(30,30,30,.6); + background: rgba(30, 30, 30, 0.6); border: 1px solid #000; padding: 5px; color: white; @@ -41,4 +43,4 @@ .orienter-box .controls-panel .slider-container input { width: 100%; -} \ No newline at end of file +} diff --git a/src/Widgets/DocumentVisualizer/View/DocumentVisualizerWindow.js b/src/Widgets/DocumentVisualizer/View/DocumentVisualizerWindow.js index 1eba8039d..0f6018ca0 100644 --- a/src/Widgets/DocumentVisualizer/View/DocumentVisualizerWindow.js +++ b/src/Widgets/DocumentVisualizer/View/DocumentVisualizerWindow.js @@ -1,9 +1,11 @@ -import { AbstractDocumentWindow } from "../../Documents/View/AbstractDocumentWindow"; -import * as THREE from "three"; +/** @format */ + +import { AbstractDocumentWindow } from '../../Documents/View/AbstractDocumentWindow'; +import * as THREE from 'three'; import './DocumentVisualizer.css'; -import { DocumentProvider } from "../../Documents/ViewModel/DocumentProvider"; -import { DocumentModule } from "../../Documents/DocumentModule"; +import { DocumentProvider } from '../../Documents/ViewModel/DocumentProvider'; +import { DocumentModule } from '../../Documents/DocumentModule'; /** * Represents the document visualizer, under the form of an oriented image. It @@ -13,7 +15,7 @@ import { DocumentModule } from "../../Documents/DocumentModule"; export class DocumentVisualizerWindow extends AbstractDocumentWindow { /** * Creates a new document image orienter. - * + * * @param {DocumentModule} documentModule The document module. * @param {*} itownsView The iTowns view. * @param {*} cameraControls The planar camera controls. @@ -34,40 +36,40 @@ export class DocumentVisualizerWindow extends AbstractDocumentWindow { this.disable(); await this.startTravelToDisplayedDocument(); this.requestDisplay(); - } + }, }); /** * The iTowns view. - * + * * @type {any} */ this.itownsView = itownsView; /** * The camera controls. - * + * * @type {any} */ this.cameraControls = cameraControls; /** * The visualization camera position. - * + * * @type {THREE.Vector3} */ this.position = undefined; /** * The visualization camera orientation. - * + * * @type {THREE.Quaternion} */ this.quaternion = undefined; } get html() { - return /*html*/` + return /*html*/ `

      @@ -84,7 +86,7 @@ export class DocumentVisualizerWindow extends AbstractDocumentWindow { windowCreated() { this.hide(); - this.window.classList.add("orienter-box"); + this.window.classList.add('orienter-box'); this.window.style.position = 'absolute'; this.closeButtonElement.onclick = () => { @@ -98,8 +100,10 @@ export class DocumentVisualizerWindow extends AbstractDocumentWindow { documentWindowReady() { // Dispose the window when the displayed document change - this.provider.addEventListener(DocumentProvider.EVENT_DISPLAYED_DOC_CHANGED, - () => this.disable()); + this.provider.addEventListener( + DocumentProvider.EVENT_DISPLAYED_DOC_CHANGED, + () => this.disable() + ); } ////////////////////// @@ -108,7 +112,7 @@ export class DocumentVisualizerWindow extends AbstractDocumentWindow { /** * Triggered when the opacity of the slider changes. This method apply the * change on the image and the output element. - * + * * @private */ _onOpacityChange() { @@ -120,7 +124,7 @@ export class DocumentVisualizerWindow extends AbstractDocumentWindow { /** * Sets the orientation for the camera. `startTravel` should be called after * this method to apply the new position. - * + * * @param {THREE.Vector3} position The visualization camera position. */ setTargetPosition(position) { @@ -130,7 +134,7 @@ export class DocumentVisualizerWindow extends AbstractDocumentWindow { /** * Sets the orientation for the camera. `startTravel` should be called after * this method to apply the new orientation. - * + * * @param {THREE.Quaternion} position The visualization camera orientation. */ setTargetQuaternion(quaternion) { @@ -139,7 +143,7 @@ export class DocumentVisualizerWindow extends AbstractDocumentWindow { /** * Sets the image source. - * + * * @param {string} newSrc The image source. */ setImageSrc(newSrc) { @@ -149,7 +153,7 @@ export class DocumentVisualizerWindow extends AbstractDocumentWindow { /** * Retrieve the displayed document and start a travel to its visualization * location. - * + * * @async */ async startTravelToDisplayedDocument() { @@ -161,9 +165,11 @@ export class DocumentVisualizerWindow extends AbstractDocumentWindow { let imageSrc = await this.provider.getDisplayedDocumentImage(); - if (isNaN(currentDoc.visualization.positionX) || - isNaN(currentDoc.visualization.quaternionX)) { - return; + if ( + isNaN(currentDoc.visualization.positionX) || + isNaN(currentDoc.visualization.quaternionX) + ) { + return; } var docViewPos = new THREE.Vector3(); @@ -187,10 +193,10 @@ export class DocumentVisualizerWindow extends AbstractDocumentWindow { /** * Starts the document orientation. The processes first assign the correct src * to the image, then sets the opacity to 0. After the travel is finished, - * the opacity is gradually restored. + * the opacity is gradually restored. * To call this function, the `position`, `quaternion` and `imageSrc` * attributes must all have been set beforehand. - * + * * @async */ startTravel() { @@ -198,8 +204,7 @@ export class DocumentVisualizerWindow extends AbstractDocumentWindow { this.opacitySliderElement.value = 0; this.opacityElement.value = 0; - this.cameraControls.initiateTravel(this.position, 2, - this.quaternion, true); + this.cameraControls.initiateTravel(this.position, 2, this.quaternion, true); this.itownsView.notifyChange(); return new Promise((resolve, reject) => { @@ -212,14 +217,14 @@ export class DocumentVisualizerWindow extends AbstractDocumentWindow { this._onOpacityChange(); if (nextValue >= 1) { nextValue = 1; - clearInterval(intervalHandle) + clearInterval(intervalHandle); } }; intervalHandle = setInterval(increaseOpacity, 15); resolve(); }, 2000); } catch (e) { - reject(e); + reject(e); } }); } @@ -228,7 +233,7 @@ export class DocumentVisualizerWindow extends AbstractDocumentWindow { ///// GETTERS get closeButtonId() { - return `${this.windowId}_close_button` + return `${this.windowId}_close_button`; } get closeButtonElement() { @@ -236,15 +241,15 @@ export class DocumentVisualizerWindow extends AbstractDocumentWindow { } get opacitySliderId() { - return `${this.windowId}_opacity_slider` + return `${this.windowId}_opacity_slider`; } get opacitySliderElement() { return document.getElementById(this.opacitySliderId); } - + get opacityId() { - return `${this.windowId}_opacity` + return `${this.windowId}_opacity`; } get opacityElement() { @@ -252,10 +257,10 @@ export class DocumentVisualizerWindow extends AbstractDocumentWindow { } get imageId() { - return `${this.windowId}_image` + return `${this.windowId}_image`; } get imageElement() { return document.getElementById(this.imageId); } -} \ No newline at end of file +} diff --git a/src/Widgets/Documents/DocumentModule.js b/src/Widgets/Documents/DocumentModule.js index 5dc2fe8a5..1ef144c04 100644 --- a/src/Widgets/Documents/DocumentModule.js +++ b/src/Widgets/Documents/DocumentModule.js @@ -1,9 +1,11 @@ +/** @format */ + //Components -import { RequestService } from "../../Components/Request/RequestService"; +import { RequestService } from '../../Components/Request/RequestService'; -import { DocumentService, DocumentSource } from "./Model/DocumentService"; -import { DocumentProvider } from "./ViewModel/DocumentProvider"; -import { DocumentView } from "./View/DocumentView"; +import { DocumentService, DocumentSource } from './Model/DocumentService'; +import { DocumentProvider } from './ViewModel/DocumentProvider'; +import { DocumentView } from './View/DocumentView'; /** * The entry point of the documents module. @@ -74,7 +76,7 @@ export class DocumentModule { * for a button. */ addInspectorExtension(label, options) { - this.view.inspectorWindow.addExtension(label, options) + this.view.inspectorWindow.addExtension(label, options); } /** diff --git a/src/Widgets/Documents/Model/Document.js b/src/Widgets/Documents/Model/Document.js index 3b0d85a86..73931814e 100644 --- a/src/Widgets/Documents/Model/Document.js +++ b/src/Widgets/Documents/Model/Document.js @@ -1,6 +1,9 @@ /** * Represents a document. + * + * @format */ + export class Document { /** * Creates a new document. @@ -8,70 +11,70 @@ export class Document { constructor() { /** * The ID of the document. - * + * * @type {number} */ this.id; /** * The title of the document. - * + * * @type {string} */ this.title; /** * The source of the document. - * + * * @type {string} */ this.source; /** * The holder of the rights for the document. - * + * * @type {string} */ this.rightsHolder; /** * The description of the document. - * + * * @type {string} */ this.description; /** * The reference data, in an ISO 8601 format. - * + * * @type {string} */ this.refDate; /** * The publication data, in an ISO 8601 format. - * + * * @type {string} */ this.publicationDate; /** * The creator id. - * + * * @type {number} */ this.user_id; /** * The validation status information. - * + * * @type {{status: string}} */ this.validationStatus; /** * Visualization information. - * + * * @type {{ * positionX: number, * positionY: number, @@ -84,4 +87,4 @@ export class Document { */ this.visualization; } -} \ No newline at end of file +} diff --git a/src/Widgets/Documents/Model/DocumentService.js b/src/Widgets/Documents/Model/DocumentService.js index 780dcccf2..1c6b3f05f 100644 --- a/src/Widgets/Documents/Model/DocumentService.js +++ b/src/Widgets/Documents/Model/DocumentService.js @@ -1,8 +1,10 @@ +/** @format */ + //Components -import { RequestService } from "../../../Components/Request/RequestService"; -import { imageToDataURI } from "../../../Components/DataProcessing/DataProcessing"; +import { RequestService } from '../../../Components/Request/RequestService'; +import { imageToDataURI } from '../../../Components/DataProcessing/DataProcessing'; -import { Document } from "./Document"; +import { Document } from './Document'; /** * This class is responsible of fetching the documents from the server. It is @@ -11,7 +13,7 @@ import { Document } from "./Document"; export class DocumentService { /** * Constructs a new document service. - * + * * @param {RequestService} requestService The request service. * @param {object} config The configuration of UD-Viz. * @param {object} config.server The server configuration. @@ -24,14 +26,14 @@ export class DocumentService { constructor(requestService, config) { /** * The request service. - * + * * @type {RequestService} */ this.requestService = requestService; - + /** * If authentication should be used for the request. - * + * * @type {boolean} */ this.authenticate = false; @@ -41,14 +43,14 @@ export class DocumentService { /** * The object that defines the server URLs to fetch documents. - * + * * @type {DocumentSource} */ this.source = new DefaultDocumentSource(config); /** * The list of documents. - * + * * @type {Array} */ this.documents = []; @@ -56,15 +58,15 @@ export class DocumentService { /** * Sets the source of documents. - * + * * @param {DocumentSource} docSource The document source. * @param {boolean} [authenticate] Specifies if authentication should be used * to fetch documents. - * + * * @returns {DocumentSource} The previous source. */ setSource(docSource, authenticate = false) { - if (! (docSource instanceof DocumentSource)) { + if (!(docSource instanceof DocumentSource)) { throw 'The document source must be an instance of DocumentSource'; } @@ -77,14 +79,17 @@ export class DocumentService { /** * Fetches the documents from the server and return them in an array. - * + * * @async - * + * * @returns {Promise>} */ async fetchDocuments() { - let req = await this.requestService.request('GET', - this.source.getDocumentUrl(), { authenticate: this.authenticate }); + let req = await this.requestService.request( + 'GET', + this.source.getDocumentUrl(), + { authenticate: this.authenticate } + ); if (req.status !== 200) { throw 'Could not fetch the documents: ' + req.statusText; @@ -97,20 +102,22 @@ export class DocumentService { /** * Fetches the image corresponding to the given document. - * + * * @param {Document} doc The document to fetch the image. - * + * * @returns {string} The data string of the image. */ async fetchDocumentImage(doc) { let imgUrl = this.source.getImageUrl(doc); let req = await this.requestService.request('GET', imgUrl, { responseType: 'arraybuffer', - authenticate: this.authenticate + authenticate: this.authenticate, }); if (req.status >= 200 && req.status < 300) { - return imageToDataURI(req.response, - req.getResponseHeader('Content-Type')); + return imageToDataURI( + req.response, + req.getResponseHeader('Content-Type') + ); } throw 'Could not get the file'; } @@ -120,15 +127,13 @@ export class DocumentService { * An object that holds and returns the URLs for documents. */ export class DocumentSource { - constructor() { - - } + constructor() {} /** * Returns the URL to retrieve the documents. - * + * * @abstract - * + * * @returns {string} */ getDocumentUrl() { @@ -137,11 +142,11 @@ export class DocumentSource { /** * Returns the URL to retrieve the image of the document. - * + * * @param {Document} doc The document. - * + * * @abstract - * + * * @returns {string} */ getImageUrl(doc) { @@ -154,7 +159,7 @@ export class DocumentSource { */ class DefaultDocumentSource extends DocumentSource { /** - * + * * @param {object} config The configuration of UD-Viz. * @param {object} config.server The server configuration. * @param {string} config.server.url The server url. @@ -166,23 +171,28 @@ class DefaultDocumentSource extends DocumentSource { /** * The URL to fetch the documents. - * + * * @type {string} */ this.documentUrl; /** * The route to fetch the document images. - * + * * @type {string} */ this.fileRoute; - if (!!config && !!config.server && !!config.server.url && - !!config.server.document && !!config.server.file) { + if ( + !!config && + !!config.server && + !!config.server.url && + !!config.server.document && + !!config.server.file + ) { this.documentUrl = config.server.url; - if (this.documentUrl.slice(-1) !== "/") { - this.documentUrl += "/"; + if (this.documentUrl.slice(-1) !== '/') { + this.documentUrl += '/'; } this.documentUrl += config.server.document; this.fileRoute = config.server.file; @@ -197,10 +207,10 @@ class DefaultDocumentSource extends DocumentSource { /** * @override - * + * * @param {Document} doc The document. */ getImageUrl(doc) { return this.documentUrl + '/' + doc.id + '/' + this.fileRoute; } -} \ No newline at end of file +} diff --git a/src/Widgets/Documents/View/AbstractDocumentWindow.js b/src/Widgets/Documents/View/AbstractDocumentWindow.js index a6187e726..971eb235e 100644 --- a/src/Widgets/Documents/View/AbstractDocumentWindow.js +++ b/src/Widgets/Documents/View/AbstractDocumentWindow.js @@ -1,51 +1,54 @@ +/** @format */ + //Components -import { Window } from "../../../Components/GUI/js/Window"; +import { Window } from '../../../Components/GUI/js/Window'; -import { DocumentProvider } from "../ViewModel/DocumentProvider"; -import { DocumentView } from "./DocumentView"; +import { DocumentProvider } from '../ViewModel/DocumentProvider'; +import { DocumentView } from './DocumentView'; -import './DocumentWindow.css' +import './DocumentWindow.css'; export class AbstractDocumentWindow extends Window { /** * Constructs an abstract document window from a name. - * + * * @param {string} name The name of the window. */ constructor(name) { - super(`document2-${name.replace(/ +/, "-").toLowerCase()}`, - `Document - ${name}`, true); + super( + `document2-${name.replace(/ +/, '-').toLowerCase()}`, + `Document - ${name}`, + true + ); /** * The document provider. - * + * * @type {DocumentProvider} */ this.provider = undefined; /** * The document view. - * + * * @type {DocumentView} */ this.view = undefined; } - + /** * Function called when the document provider and the view have been set up. * Operations that depends on them can be performed in this function. - * + * * @override */ - documentWindowReady() { - - } + documentWindowReady() {} /** * Sets the provider and the view. Should be called by `DocumentView`. Once * this is done, the window is actually usable ; this triggers the * `documentWindowReady` method. - * + * * @param {DocumentView} view The document view. * @param {DocumentProvider} provider The document provider. */ @@ -58,11 +61,11 @@ export class AbstractDocumentWindow extends Window { /** * Request to show a this document window. - * + * * @param {boolean} [hideOtherWindows] Set to `true` to hide other document * windows. */ requestDisplay(hideOtherWindows = false) { this.view.requestWindowDisplay(this, hideOtherWindows); } -} \ No newline at end of file +} diff --git a/src/Widgets/Documents/View/DocumentInspectorWindow.js b/src/Widgets/Documents/View/DocumentInspectorWindow.js index 49a1fd4a3..030fcc07a 100644 --- a/src/Widgets/Documents/View/DocumentInspectorWindow.js +++ b/src/Widgets/Documents/View/DocumentInspectorWindow.js @@ -1,6 +1,8 @@ -import { DocumentProvider } from "../ViewModel/DocumentProvider"; -import { Document } from "../Model/Document"; -import { AbstractDocumentWindow } from "./AbstractDocumentWindow"; +/** @format */ + +import { DocumentProvider } from '../ViewModel/DocumentProvider'; +import { Document } from '../Model/Document'; +import { AbstractDocumentWindow } from './AbstractDocumentWindow'; /** * The window responsible for displaying the currently displayed document, as @@ -31,7 +33,7 @@ export class DocumentInspectorWindow extends AbstractDocumentWindow { } get innerContentHtml() { - return /*html*/` + return /*html*/ `

      Title:

      @@ -86,8 +88,10 @@ export class DocumentInspectorWindow extends AbstractDocumentWindow { } documentWindowReady() { - this.provider.addEventListener(DocumentProvider.EVENT_DISPLAYED_DOC_CHANGED, - (doc) => this.onDisplayedDocumentChange(doc)); + this.provider.addEventListener( + DocumentProvider.EVENT_DISPLAYED_DOC_CHANGED, + (doc) => this.onDisplayedDocumentChange(doc) + ); } /////////////////////// @@ -133,10 +137,12 @@ export class DocumentInspectorWindow extends AbstractDocumentWindow { this.docDescriptionElement.innerText = newDocument.description; this.docSourceElement.innerText = newDocument.source; this.docRightsHolderElement.innerText = newDocument.rightsHolder; - this.docPubDateElement.innerText = - (new Date(newDocument.publicationDate)).toLocaleDateString(); - this.docRefDateElement.innerText = - (new Date(newDocument.refDate)).toLocaleDateString(); + this.docPubDateElement.innerText = new Date( + newDocument.publicationDate + ).toLocaleDateString(); + this.docRefDateElement.innerText = new Date( + newDocument.refDate + ).toLocaleDateString(); this.docImageElement.src = await this.provider.getDisplayedDocumentImage(); } @@ -144,7 +150,7 @@ export class DocumentInspectorWindow extends AbstractDocumentWindow { ///// GETTERS get docTitleId() { - return `${this.windowId}_title` + return `${this.windowId}_title`; } get docTitleElement() { @@ -152,7 +158,7 @@ export class DocumentInspectorWindow extends AbstractDocumentWindow { } get docDescriptionId() { - return `${this.windowId}_desc` + return `${this.windowId}_desc`; } get docDescriptionElement() { @@ -160,7 +166,7 @@ export class DocumentInspectorWindow extends AbstractDocumentWindow { } get docSourceId() { - return `${this.windowId}_source` + return `${this.windowId}_source`; } get docSourceElement() { @@ -168,7 +174,7 @@ export class DocumentInspectorWindow extends AbstractDocumentWindow { } get docRightsHolderId() { - return `${this.windowId}_rights_holder` + return `${this.windowId}_rights_holder`; } get docRightsHolderElement() { @@ -176,7 +182,7 @@ export class DocumentInspectorWindow extends AbstractDocumentWindow { } get docPubDateId() { - return `${this.windowId}_pub_date` + return `${this.windowId}_pub_date`; } get docPubDateElement() { @@ -184,7 +190,7 @@ export class DocumentInspectorWindow extends AbstractDocumentWindow { } get docRefDateId() { - return `${this.windowId}_ref_date` + return `${this.windowId}_ref_date`; } get docRefDateElement() { diff --git a/src/Widgets/Documents/View/DocumentNavigatorWindow.js b/src/Widgets/Documents/View/DocumentNavigatorWindow.js index c73d11943..12897b158 100644 --- a/src/Widgets/Documents/View/DocumentNavigatorWindow.js +++ b/src/Widgets/Documents/View/DocumentNavigatorWindow.js @@ -1,7 +1,9 @@ -import { DocumentProvider } from "../ViewModel/DocumentProvider"; -import { Document } from "../Model/Document"; -import { DocumentSearchFilter } from "../ViewModel/DocumentSearchFilter"; -import { AbstractDocumentWindow } from "./AbstractDocumentWindow"; +/** @format */ + +import { DocumentProvider } from '../ViewModel/DocumentProvider'; +import { Document } from '../Model/Document'; +import { DocumentSearchFilter } from '../ViewModel/DocumentSearchFilter'; +import { AbstractDocumentWindow } from './AbstractDocumentWindow'; /** * Represents the navigator window for the documents. It contains the filters on @@ -26,18 +28,18 @@ export class DocumentNavigatorWindow extends AbstractDocumentWindow { * a panel. * * @type {Object. any, - * html: string - * }>} - */ - this.extensions = {}; + * type: 'button' | 'panel', + * label: string, + * id: string, + * callback?: (doc: Document[]) => any, + * html: string + * }>} + */ + this.extensions = {}; } get innerContentHtml() { - return /*html*/` + return /*html*/ `

      Document(s) @@ -111,10 +113,14 @@ export class DocumentNavigatorWindow extends AbstractDocumentWindow { documentWindowReady() { this.provider.addFilter(this.searchFilter); - this.provider.addEventListener(DocumentProvider.EVENT_FILTERED_DOCS_UPDATED, - (documents) => this._onFilteredDocumentsUpdate(documents)); - this.provider.addEventListener(DocumentProvider.EVENT_DISPLAYED_DOC_CHANGED, - (doc) => this._onDisplayedDocumentChange(doc)); + this.provider.addEventListener( + DocumentProvider.EVENT_FILTERED_DOCS_UPDATED, + (documents) => this._onFilteredDocumentsUpdate(documents) + ); + this.provider.addEventListener( + DocumentProvider.EVENT_DISPLAYED_DOC_CHANGED, + (doc) => this._onDisplayedDocumentChange(doc) + ); } ////////////////////////////// @@ -136,11 +142,13 @@ export class DocumentNavigatorWindow extends AbstractDocumentWindow { list.innerHTML = ''; for (let doc of documents) { let item = document.createElement('li'); - item.innerHTML = /*html*/` + item.innerHTML = /*html*/ `
      ${doc.title}
      -
      Refering ${(new Date(doc.refDate)).toLocaleDateString()}
      +
      Refering ${new Date( + doc.refDate + ).toLocaleDateString()}
      `; - item.classList.add('navigator-result-doc') + item.classList.add('navigator-result-doc'); item.onclick = () => { this.provider.setDisplayedDocument(doc); }; @@ -167,13 +175,13 @@ export class DocumentNavigatorWindow extends AbstractDocumentWindow { } if (!!document) { let newIndex = this.provider.getDisplayedDocumentIndex(); - let newSelected = this.documentListElement - .querySelector(`li:nth-child(${newIndex + 1})`); + let newSelected = this.documentListElement.querySelector( + `li:nth-child(${newIndex + 1})` + ); newSelected.classList.add('document-selected'); } } - //////////////////////// ///// SEARCH AND FILTERS @@ -181,31 +189,37 @@ export class DocumentNavigatorWindow extends AbstractDocumentWindow { * Event on the 'search' button click. */ async search() { - let keywords = this.inputKeywordsElement.value.split(/[ ,;]/) - .filter((k) => k !== "").map((k) => k.toLowerCase()); + let keywords = this.inputKeywordsElement.value + .split(/[ ,;]/) + .filter((k) => k !== '') + .map((k) => k.toLowerCase()); this.searchFilter.keywords = keywords; let source = this.inputSourceElement.value.toLowerCase(); - this.searchFilter.source = (source !== "") ? source : undefined; + this.searchFilter.source = source !== '' ? source : undefined; let rightsHolder = this.inputRightsHolderElement.value.toLowerCase(); - this.searchFilter.rightsHolder = (rightsHolder !== "") ? rightsHolder - : undefined; + this.searchFilter.rightsHolder = + rightsHolder !== '' ? rightsHolder : undefined; let pubStartDate = this.inputPubDateStartElement.value; - this.searchFilter.pubStartDate = (!!pubStartDate) ? new Date(pubStartDate) + this.searchFilter.pubStartDate = !!pubStartDate + ? new Date(pubStartDate) : undefined; let pubEndDate = this.inputPubDateEndElement.value; - this.searchFilter.pubEndDate = (!!pubEndDate) ? new Date(pubEndDate) + this.searchFilter.pubEndDate = !!pubEndDate + ? new Date(pubEndDate) : undefined; let refStartDate = this.inputRefDateStartElement.value; - this.searchFilter.refStartDate = (!!refStartDate) ? new Date(refStartDate) + this.searchFilter.refStartDate = !!refStartDate + ? new Date(refStartDate) : undefined; let refEndDate = this.inputRefDateEndElement.value; - this.searchFilter.refEndDate = (!!refEndDate) ? new Date(refEndDate) + this.searchFilter.refEndDate = !!refEndDate + ? new Date(refEndDate) : undefined; this.provider.refreshDocumentList(); @@ -269,7 +283,7 @@ export class DocumentNavigatorWindow extends AbstractDocumentWindow { } get inputRightsHolderId() { - return `${this.windowId}_rights_holder` + return `${this.windowId}_rights_holder`; } get inputRightsHolderElement() { diff --git a/src/Widgets/Documents/View/DocumentView.js b/src/Widgets/Documents/View/DocumentView.js index 2083334e3..cd1b66b86 100644 --- a/src/Widgets/Documents/View/DocumentView.js +++ b/src/Widgets/Documents/View/DocumentView.js @@ -1,11 +1,13 @@ +/** @format */ + //Components -import { ModuleView } from "../../../Components/ModuleView/ModuleView"; -import { Window } from "../../../Components/GUI/js/Window"; +import { ModuleView } from '../../../Components/ModuleView/ModuleView'; +import { Window } from '../../../Components/GUI/js/Window'; -import { DocumentProvider } from "../ViewModel/DocumentProvider"; -import { DocumentNavigatorWindow } from "./DocumentNavigatorWindow"; -import { DocumentInspectorWindow } from "./DocumentInspectorWindow"; -import { AbstractDocumentWindow } from "./AbstractDocumentWindow"; +import { DocumentProvider } from '../ViewModel/DocumentProvider'; +import { DocumentNavigatorWindow } from './DocumentNavigatorWindow'; +import { DocumentInspectorWindow } from './DocumentInspectorWindow'; +import { AbstractDocumentWindow } from './AbstractDocumentWindow'; /** * The entry point of the document view. It holds the two main windows, inspector @@ -15,7 +17,7 @@ import { AbstractDocumentWindow } from "./AbstractDocumentWindow"; export class DocumentView extends ModuleView { /** * Creates a document view. - * + * * @param {DocumentProvider} provider The document provider. */ constructor(provider) { @@ -23,35 +25,35 @@ export class DocumentView extends ModuleView { /** * The document provider. - * + * * @type {DocumentProvider} */ this.provider = provider; /** * The search window. - * + * * @type {DocumentNavigatorWindow} */ this.navigatorWindow = new DocumentNavigatorWindow(); /** * The inspector window. - * + * * @type {DocumentInspectorWindow} */ this.inspectorWindow = new DocumentInspectorWindow(); /** * The different windows of the view. - * + * * @type {Array} */ - this.windows = [] + this.windows = []; /** * The windows that have been temporarily hidden. - * + * * @type {Array} */ this.hiddenWindows = []; @@ -70,13 +72,15 @@ export class DocumentView extends ModuleView { /** * Adds a new window to display information about documents. The document * provider is passed as parameter in this function. - * + * * @param {AbstractDocumentWindow} newWindow The window to add. */ addDocumentWindow(newWindow) { - if (! (newWindow instanceof AbstractDocumentWindow)) { - throw 'Only instances of AbstractDocumentWindow can be added to the ' + - 'document view'; + if (!(newWindow instanceof AbstractDocumentWindow)) { + throw ( + 'Only instances of AbstractDocumentWindow can be added to the ' + + 'document view' + ); } this.windows.push(newWindow); @@ -85,14 +89,15 @@ export class DocumentView extends ModuleView { /** * Request to show a specific document window. - * + * * @param {AbstractDocumentWindow} windowToDisplay The window to show. * @param {boolean} [hideOtherWindows] Set to `true` to hide other document * windows. */ requestWindowDisplay(windowToDisplay, hideOtherWindows = false) { - let found = this.windows - .findIndex(w => w.windowId === windowToDisplay.windowId) >= 0; + let found = + this.windows.findIndex((w) => w.windowId === windowToDisplay.windowId) >= + 0; if (!found) { throw 'Window must be registered first'; } @@ -135,4 +140,4 @@ export class DocumentView extends ModuleView { window.dispose(); } } -} \ No newline at end of file +} diff --git a/src/Widgets/Documents/View/DocumentWindow.css b/src/Widgets/Documents/View/DocumentWindow.css index 44b9f6c50..9c73225e9 100644 --- a/src/Widgets/Documents/View/DocumentWindow.css +++ b/src/Widgets/Documents/View/DocumentWindow.css @@ -1,6 +1,8 @@ -/* Generic for document windows */ - - +/** + * /* Generic for document windows + * + * @format + */ /* Search window */ @@ -9,7 +11,7 @@ margin-top: 5px; } -.search-form input[type="text"], +.search-form input[type='text'], .search-form select { box-sizing: border-box; width: 100%; diff --git a/src/Widgets/Documents/ViewModel/DocumentFilter.js b/src/Widgets/Documents/ViewModel/DocumentFilter.js index 71e5fdaf8..c7d60f9e6 100644 --- a/src/Widgets/Documents/ViewModel/DocumentFilter.js +++ b/src/Widgets/Documents/ViewModel/DocumentFilter.js @@ -1,4 +1,6 @@ -import { Document } from "../Model/Document"; +/** @format */ + +import { Document } from '../Model/Document'; /** * A filter for documents. It is essentially a function that determines if a @@ -7,7 +9,7 @@ import { Document } from "../Model/Document"; export class DocumentFilter { /** * Constructs a new document filter, from an acceptation function. - * + * * @param {(Document) => boolean} accepts The function responsible to filter * the documents. It must evaluate wether a document is acceptable according * to the filter. @@ -16,7 +18,7 @@ export class DocumentFilter { /** * The function responsible to filter the documents. It must evaluate wether * a document is acceptable according to the filter. - * + * * @type {(Document) => boolean} */ this.accepts = accepts; @@ -24,13 +26,13 @@ export class DocumentFilter { /** * Applies the filter to the documents. - * + * * @param {Array} documents The documents to filter. - * + * * @returns {Array} */ apply(documents) { let filtered = documents.filter(this.accepts); return filtered; } -} \ No newline at end of file +} diff --git a/src/Widgets/Documents/ViewModel/DocumentProvider.js b/src/Widgets/Documents/ViewModel/DocumentProvider.js index addd47825..41f171072 100644 --- a/src/Widgets/Documents/ViewModel/DocumentProvider.js +++ b/src/Widgets/Documents/ViewModel/DocumentProvider.js @@ -1,9 +1,11 @@ +/** @format */ + //Components -import { EventSender } from "../../../Components/Events/EventSender"; +import { EventSender } from '../../../Components/Events/EventSender'; -import { DocumentService } from "../Model/DocumentService"; -import { Document } from "../Model/Document"; -import { DocumentFilter } from "./DocumentFilter"; +import { DocumentService } from '../Model/DocumentService'; +import { Document } from '../Model/Document'; +import { DocumentFilter } from './DocumentFilter'; /** * Represents the set of documents that is displayed in the view. This includes @@ -15,7 +17,7 @@ import { DocumentFilter } from "./DocumentFilter"; export class DocumentProvider extends EventSender { /** * Constructs a new documents provider. - * + * * @param {DocumentService} service The document service. */ constructor(service) { @@ -23,35 +25,35 @@ export class DocumentProvider extends EventSender { /** * The document service. - * + * * @type {DocumentService} */ this.service = service; /** * The list of filters. - * + * * @type {Array} */ this.filters = []; /** * The list of all documents. - * + * * @type {Array} */ this.allDocuments = []; /** * The list of filtered documents. - * + * * @type {Array} */ this.filteredDocuments = []; /** * The currently displayed document. - * + * * @type {number} */ this.displayedDocumentIndex = undefined; @@ -77,28 +79,33 @@ export class DocumentProvider extends EventSender { if (this.filteredDocuments.length > 0) { if (previousDocument) { let previousDisplayedId = previousDocument.id; - let newIndex = this.filteredDocuments.findIndex(doc => - doc.id === previousDisplayedId); - this.displayedDocumentIndex = (newIndex >= 0) ? newIndex : 0; + let newIndex = this.filteredDocuments.findIndex( + (doc) => doc.id === previousDisplayedId + ); + this.displayedDocumentIndex = newIndex >= 0 ? newIndex : 0; } else { this.displayedDocumentIndex = 0; } } else { this.displayedDocumentIndex = undefined; } - await this.sendEvent(DocumentProvider.EVENT_FILTERED_DOCS_UPDATED, - this.getFilteredDocuments()); - await this.sendEvent(DocumentProvider.EVENT_DISPLAYED_DOC_CHANGED, - this.getDisplayedDocument()); + await this.sendEvent( + DocumentProvider.EVENT_FILTERED_DOCS_UPDATED, + this.getFilteredDocuments() + ); + await this.sendEvent( + DocumentProvider.EVENT_DISPLAYED_DOC_CHANGED, + this.getDisplayedDocument() + ); } /** * Adds a filter to the filtering pipeline. - * + * * @param {DocumentFilter} newFilter The new filter to add. */ addFilter(newFilter) { - if (! (newFilter instanceof DocumentFilter)) { + if (!(newFilter instanceof DocumentFilter)) { throw 'addFilter() expects a DocumentFilter parameter'; } this.filters.push(newFilter); @@ -106,12 +113,13 @@ export class DocumentProvider extends EventSender { /** * Sets the given document as the displayed one. - * + * * @param {Document} doc The document. */ setDisplayedDocument(doc) { - let index = this.filteredDocuments.findIndex((filteredDoc) => - doc.id === filteredDoc.id); + let index = this.filteredDocuments.findIndex( + (filteredDoc) => doc.id === filteredDoc.id + ); if (index < 0) { throw 'Document not found.'; @@ -123,12 +131,14 @@ export class DocumentProvider extends EventSender { /** * Change the displayed document index. Sends a `DISPLAYED_DOCUMENT_CHANGED` * event. - * + * * @param {number} index The new document index. */ setDisplayedDocumentIndex(index) { if (this.displayedDocumentIndex === undefined) { - console.warn('Cannot change displayed document if no document is present'); + console.warn( + 'Cannot change displayed document if no document is present' + ); return; } @@ -137,34 +147,41 @@ export class DocumentProvider extends EventSender { } this.displayedDocumentIndex = index; - this.sendEvent(DocumentProvider.EVENT_DISPLAYED_DOC_CHANGED, - this.getDisplayedDocument()); + this.sendEvent( + DocumentProvider.EVENT_DISPLAYED_DOC_CHANGED, + this.getDisplayedDocument() + ); } /** * Shift the displayed document index. The filtered array is treated as * cyclical. Sends a `DISPLAYED_DOCUMENT_CHANGED` event. - * + * * @param {number} offset The offset that will be applied to the current * index. */ shiftDisplayedDocumentIndex(offset) { if (this.displayedDocumentIndex === undefined) { - console.warn('Cannot change displayed document if no document is present'); + console.warn( + 'Cannot change displayed document if no document is present' + ); return; } offset = offset % this.filteredDocuments.length; - this.displayedDocumentIndex = (this.filteredDocuments.length + - this.displayedDocumentIndex + offset) % this.filteredDocuments.length; - - this.sendEvent(DocumentProvider.EVENT_DISPLAYED_DOC_CHANGED, - this.getDisplayedDocument()); + this.displayedDocumentIndex = + (this.filteredDocuments.length + this.displayedDocumentIndex + offset) % + this.filteredDocuments.length; + + this.sendEvent( + DocumentProvider.EVENT_DISPLAYED_DOC_CHANGED, + this.getDisplayedDocument() + ); } /** * Returns the list of all documents. - * + * * @returns {Array} */ getAllDocuments() { @@ -173,7 +190,7 @@ export class DocumentProvider extends EventSender { /** * Returns the filtered list of documents. - * + * * @returns {Array} */ getFilteredDocuments() { @@ -182,7 +199,7 @@ export class DocumentProvider extends EventSender { /** * Returns the currently displayed document. - * + * * @returns {Document | undefined} */ getDisplayedDocument() { @@ -195,7 +212,7 @@ export class DocumentProvider extends EventSender { /** * Returns the displayed document index. - * + * * @returns {number | undefined} */ getDisplayedDocumentIndex() { @@ -206,9 +223,9 @@ export class DocumentProvider extends EventSender { * Returns the image corresponding to the displayed document. It is a string * that can be put into the `src` attribute of an `img` tag (so either an * URL or a base64 encoded file). - * + * * @async - * + * * @returns {Promise} */ async getDisplayedDocumentImage() { @@ -229,4 +246,4 @@ export class DocumentProvider extends EventSender { static get EVENT_DISPLAYED_DOC_CHANGED() { return 'EVENT_DISPLAYED_DOC_CHANGED'; } -} \ No newline at end of file +} diff --git a/src/Widgets/Documents/ViewModel/DocumentSearchFilter.js b/src/Widgets/Documents/ViewModel/DocumentSearchFilter.js index 2c6444523..9d9087262 100644 --- a/src/Widgets/Documents/ViewModel/DocumentSearchFilter.js +++ b/src/Widgets/Documents/ViewModel/DocumentSearchFilter.js @@ -1,5 +1,7 @@ -import { DocumentFilter } from "./DocumentFilter"; -import { Document } from "../Model/Document"; +/** @format */ + +import { DocumentFilter } from './DocumentFilter'; +import { Document } from '../Model/Document'; /** * A document filter to use with the search window. It filters the documents @@ -17,14 +19,14 @@ export class DocumentSearchFilter extends DocumentFilter { /** * A list of keywords to search in the title or the description of the * document. These keywords should be in lowercase. - * + * * @type {Array} */ this.keywords = []; /** * A string representing the source. Should be in lowercase. - * + * * @type {string} */ this.source = undefined; @@ -36,28 +38,28 @@ export class DocumentSearchFilter extends DocumentFilter { /** * The lower bound of the publication date. - * + * * @type {Date} */ this.pubStartDate = undefined; /** * The upper bound of the publication date. - * + * * @type {Date} */ this.pubEndDate = undefined; /** * The lower bound of the refering date. - * + * * @type {Date} */ this.refStartDate = undefined; /** * The upper bound of the refering date. - * + * * @type {Date} */ this.refEndDate = undefined; @@ -65,14 +67,16 @@ export class DocumentSearchFilter extends DocumentFilter { /** * The function to filter the documents. - * + * * @param {Document} doc The document to filter. */ filterDocument(doc) { if (this.keywords.length > 0) { for (let keyword of this.keywords) { - if (!doc.title.toLowerCase().includes(keyword) && - !doc.description.toLowerCase().includes(keyword)) { + if ( + !doc.title.toLowerCase().includes(keyword) && + !doc.description.toLowerCase().includes(keyword) + ) { return false; } } @@ -82,16 +86,24 @@ export class DocumentSearchFilter extends DocumentFilter { return false; } - if (!!this.rightsHolder && - !doc.rightsHolder.toLowerCase().includes(this.rightsHolder)) { + if ( + !!this.rightsHolder && + !doc.rightsHolder.toLowerCase().includes(this.rightsHolder) + ) { return false; } - if (!!this.pubStartDate && !(this.pubStartDate <= new Date(doc.publicationDate))) { + if ( + !!this.pubStartDate && + !(this.pubStartDate <= new Date(doc.publicationDate)) + ) { return false; } - if (!!this.pubEndDate && !(this.pubEndDate >= new Date(doc.publicationDate))) { + if ( + !!this.pubEndDate && + !(this.pubEndDate >= new Date(doc.publicationDate)) + ) { return false; } @@ -102,7 +114,7 @@ export class DocumentSearchFilter extends DocumentFilter { if (!!this.refEndDate && !(this.refEndDate >= new Date(doc.refDate))) { return false; } - + return true; } @@ -118,4 +130,4 @@ export class DocumentSearchFilter extends DocumentFilter { this.refStartDate = undefined; this.refEndDate = undefined; } -} \ No newline at end of file +} diff --git a/src/Widgets/Extensions/3DTilesDebug/views/3DTilesDebugWindow.js b/src/Widgets/Extensions/3DTilesDebug/views/3DTilesDebugWindow.js index e9b59eb72..0fac2b999 100644 --- a/src/Widgets/Extensions/3DTilesDebug/views/3DTilesDebugWindow.js +++ b/src/Widgets/Extensions/3DTilesDebug/views/3DTilesDebugWindow.js @@ -1,13 +1,15 @@ +/** @format */ + //Components -import { Window } from "../../../../Components/GUI/js/Window"; -import { CityObjectStyle } from "../../../../Components/3DTiles/Model/CityObjectStyle"; -import { CityObjectID } from "../../../../Components/3DTiles/Model/CityObject"; -import { TilesManager } from "../../../../Components/3DTiles/TilesManager"; +import { Window } from '../../../../Components/GUI/js/Window'; +import { CityObjectStyle } from '../../../../Components/3DTiles/Model/CityObjectStyle'; +import { CityObjectID } from '../../../../Components/3DTiles/Model/CityObject'; +import { TilesManager } from '../../../../Components/3DTiles/TilesManager'; export class Debug3DTilesWindow extends Window { /** * Creates the debug window. - * + * * @param {layer} layerManager The tiles manager. */ constructor(layerManager) { @@ -15,17 +17,20 @@ export class Debug3DTilesWindow extends Window { /** * The tiles manager. - * + * * @type {layerManager} */ this.layerManager = layerManager; // Selection - this.layerManager.registerStyle('selected', new CityObjectStyle({ - materialProps: { color: 0x00ff00 } - })); + this.layerManager.registerStyle( + 'selected', + new CityObjectStyle({ + materialProps: { color: 0x00ff00 }, + }) + ); this.selectedCityObject = undefined; this.selectedTilesManager = undefined; - + let viewerDiv = document.getElementById('viewerDiv'); let clickListener = (event) => { this.onMouseClick(event); @@ -50,7 +55,7 @@ export class Debug3DTilesWindow extends Window { } get innerContentHtml() { - return /*html*/` + return /*html*/ `

      0 / ? tiles loaded.

      0 tiles visible.

      @@ -94,7 +99,10 @@ export class Debug3DTilesWindow extends Window { // Sets the number of loaded tiles and add an event for dynamic change of this value. this.updateTBIInfoParagraphElement(); for (let i = 0; i < this.layerManager.tilesManagers.length; i++) { - this.layerManager.tilesManagers[i].addEventListener(TilesManager.EVENT_TILE_LOADED, (tile) => this.updateTBIInfoParagraphElement(tile)); + this.layerManager.tilesManagers[i].addEventListener( + TilesManager.EVENT_TILE_LOADED, + (tile) => this.updateTBIInfoParagraphElement(tile) + ); } this.groupColorOpacityInputElement.oninput = () => { this.groupColorOpacitySpanElement.innerText = @@ -127,7 +135,8 @@ export class Debug3DTilesWindow extends Window { */ onMouseMove(event) { // Update the current visible tile count - let visibleTileCount = this.layerManager.getVisible3DTilesTileCountFromLayers(); + let visibleTileCount = + this.layerManager.getVisible3DTilesTileCountFromLayers(); this.visibleTilesParagraphElement.innerText = `${visibleTileCount} tiles visible.`; } @@ -135,30 +144,37 @@ export class Debug3DTilesWindow extends Window { * If the user is currently hovering a building, fetches the building info * and colors the building. If a building was already selected, it returns to * its original coloring. - * + * * @param {MouseEvent} event The mouse event. */ onMouseClick(event) { let cityObject = this.layerManager.pickCityObject(event); if (cityObject !== undefined) { - for (let [key, value] of Object.entries(cityObject.props)) { this.clickDivElement.innerHTML += `
      ${key} : ${value}`; } if (!!this.selectedCityObject) { - this.selectedTilesManager.removeStyle(this.selectedCityObject.cityObjectId); + this.selectedTilesManager.removeStyle( + this.selectedCityObject.cityObjectId + ); this.selectedTilesManager.applyStyles(); } this.selectedCityObject = cityObject; - this.selectedTilesManager = this.layerManager.getTilesManagerByLayerID(this.selectedCityObject.tile.layer.id); - this.selectedTilesManager.setStyle(this.selectedCityObject.cityObjectId, 'selected'); + this.selectedTilesManager = this.layerManager.getTilesManagerByLayerID( + this.selectedCityObject.tile.layer.id + ); + this.selectedTilesManager.setStyle( + this.selectedCityObject.cityObjectId, + 'selected' + ); this.selectedTilesManager.applyStyles({ - updateFunction: - this.selectedTilesManager.view.notifyChange.bind(this.selectedTilesManager.view) + updateFunction: this.selectedTilesManager.view.notifyChange.bind( + this.selectedTilesManager.view + ), }); - this.clickDivElement.innerHTML = /*html*/` + this.clickDivElement.innerHTML = /*html*/ ` 3D Tiles : ${this.selectedTilesManager.layer.name}
      Vertex indexes : ${cityObject.indexStart} to ${cityObject.indexEnd} (${cityObject.indexCount})
      @@ -174,11 +190,15 @@ export class Debug3DTilesWindow extends Window { submitStyleForm() { try { let tileId = Number.parseInt(this.groupColorTileInputElement.value); - let batchIds = JSON.parse('[' + this.groupColorBatchInputElement.value + ']'); + let batchIds = JSON.parse( + '[' + this.groupColorBatchInputElement.value + ']' + ); let color = new THREE.Color(this.groupColorColorInputElement.value); let opacity = Number.parseFloat(this.groupColorOpacityInputElement.value); - this.layerManager.tilesManagers[0].setStyle(new CityObjectID(tileId, batchIds), - { materialProps: { color, opacity } }); + this.layerManager.tilesManagers[0].setStyle( + new CityObjectID(tileId, batchIds), + { materialProps: { color, opacity } } + ); this.layerManager.tilesManagers[0].applyStyles(); } catch (e) { alert(e); diff --git a/src/Widgets/Extensions/Authentication/services/AuthenticationService.js b/src/Widgets/Extensions/Authentication/services/AuthenticationService.js index ea5ba7c1c..bb912024e 100644 --- a/src/Widgets/Extensions/Authentication/services/AuthenticationService.js +++ b/src/Widgets/Extensions/Authentication/services/AuthenticationService.js @@ -1,148 +1,161 @@ -import {RequestService} from "../../../../Components/Request/RequestService" +/** @format */ + +import { RequestService } from '../../../../Components/Request/RequestService'; export function AuthenticationService(requestService, config) { - this.observers = []; - this.config = config; - this.loginUrl = `${config.server.url}${config.server.login}`; - //route to manage users (register) - this.userUrl = `${config.server.url}${config.server.user}`; - //route to get personal information - this.userMeUrl = `${config.server.url}${config.server.userMe}`; - this.requestService = new RequestService(); - this.loginRequiredKeys = ['username', 'password']; - this.registerRequiredKeys = ['username', 'firstName', 'lastName', 'password', 'email']; - this.storageKeys = { - token: 'user.token', - firstname: 'user.firstname', - lastname: 'user.lastname', - username: 'user.username', - email: 'user.email' - }; - - this.requestService = requestService; - - this.initialize = function initialize() { - this.requestService.setAuthenticationService(this); - }; - - this.login = async function login(formData) { - if (!this.formCheck(formData, this.loginRequiredKeys)) { - throw 'Invalid form'; - } - - if (this.isUserLoggedIn()) { - throw 'Already logged in'; - } - - const result = (await this.requestService.send('POST', this.loginUrl, formData, false)).response; - const resultJson = JSON.parse(result); - if (!resultJson) { - throw 'Username or password is incorrect' - } - const jwt = resultJson.token; - if (jwt !== undefined && jwt !== null) { - this.storeToken(jwt); - let response = JSON.parse((await this.requestService.send('GET', this.userMeUrl)).response); - const user = { - firstname: response.firstName, - lastname: response.lastName, - username: response.username, - email: response.email - }; - - this.storeUser(user); - - this.notifyObservers(); - } else { - throw 'Username or password is incorrect'; - } - }; - - this.logout = function logout() { - if (!this.isUserLoggedIn()) { - throw 'Not logged in'; - } - this.removeUserFromSession(); - - this.notifyObservers(); - }; - - this.register = async function register(formData) { - if (!this.formCheck(formData, this.registerRequiredKeys)) { - throw 'Invalid form'; - } - if (this.isUserLoggedIn()) { - throw 'Already logged in'; - } - const result = (await this.requestService.send('POST', this.userUrl, formData, false)).response; - const obj = JSON.parse(result); - - this.notifyObservers(); - }; - - this.formCheck = function formCheck(formData, requiredKeys) { - for (var key of requiredKeys) { - if (formData.get(key) === null) { - console.error(`Missing key in form : ${key}`) - return false; - } - } - return true; - }; - - this.removeUserFromSession = function removeUserFromSession() { - window.sessionStorage.removeItem(this.storageKeys.token); - window.sessionStorage.removeItem(this.storageKeys.firstname); - window.sessionStorage.removeItem(this.storageKeys.lastname); - window.sessionStorage.removeItem(this.storageKeys.username); - window.sessionStorage.removeItem(this.storageKeys.email); - }; - - this.storeToken = function (token) { - window.sessionStorage.setItem(this.storageKeys.token, token); + this.observers = []; + this.config = config; + this.loginUrl = `${config.server.url}${config.server.login}`; + //route to manage users (register) + this.userUrl = `${config.server.url}${config.server.user}`; + //route to get personal information + this.userMeUrl = `${config.server.url}${config.server.userMe}`; + this.requestService = new RequestService(); + this.loginRequiredKeys = ['username', 'password']; + this.registerRequiredKeys = [ + 'username', + 'firstName', + 'lastName', + 'password', + 'email', + ]; + this.storageKeys = { + token: 'user.token', + firstname: 'user.firstname', + lastname: 'user.lastname', + username: 'user.username', + email: 'user.email', + }; + + this.requestService = requestService; + + this.initialize = function initialize() { + this.requestService.setAuthenticationService(this); + }; + + this.login = async function login(formData) { + if (!this.formCheck(formData, this.loginRequiredKeys)) { + throw 'Invalid form'; + } + + if (this.isUserLoggedIn()) { + throw 'Already logged in'; } - this.storeUser = function storeUser(user) { - window.sessionStorage.setItem(this.storageKeys.firstname, user.firstname); - window.sessionStorage.setItem(this.storageKeys.lastname, user.lastname); - window.sessionStorage.setItem(this.storageKeys.username, user.username); - window.sessionStorage.setItem(this.storageKeys.email, user.email); - }; - - this.getUser = function getUser() { - let user = {}; - user.token = window.sessionStorage.getItem(this.storageKeys.token); - if (user.token === null || user.token === undefined) { - return null; - } - user.firstname = window.sessionStorage.getItem(this.storageKeys.firstname); - user.lastname = window.sessionStorage.getItem(this.storageKeys.lastname); - user.username = window.sessionStorage.getItem(this.storageKeys.username); - user.email = window.sessionStorage.getItem(this.storageKeys.email); - return user; - }; - - this.isUserLoggedIn = function isUserLoggedIn() { - try { - let user = this.getUser(); - return user !== null && user !== undefined; - } catch (e) { - console.error(e); - return false; - } - }; - - // Observers - this.addObserver = function (observerFunction) { - this.observers.push(observerFunction); + const result = ( + await this.requestService.send('POST', this.loginUrl, formData, false) + ).response; + const resultJson = JSON.parse(result); + if (!resultJson) { + throw 'Username or password is incorrect'; + } + const jwt = resultJson.token; + if (jwt !== undefined && jwt !== null) { + this.storeToken(jwt); + let response = JSON.parse( + (await this.requestService.send('GET', this.userMeUrl)).response + ); + const user = { + firstname: response.firstName, + lastname: response.lastName, + username: response.username, + email: response.email, + }; + + this.storeUser(user); + + this.notifyObservers(); + } else { + throw 'Username or password is incorrect'; } + }; - this.notifyObservers = function () { - for (let observer of this.observers) { - observer(); - } + this.logout = function logout() { + if (!this.isUserLoggedIn()) { + throw 'Not logged in'; } + this.removeUserFromSession(); + this.notifyObservers(); + }; + + this.register = async function register(formData) { + if (!this.formCheck(formData, this.registerRequiredKeys)) { + throw 'Invalid form'; + } + if (this.isUserLoggedIn()) { + throw 'Already logged in'; + } + const result = ( + await this.requestService.send('POST', this.userUrl, formData, false) + ).response; + const obj = JSON.parse(result); + + this.notifyObservers(); + }; + + this.formCheck = function formCheck(formData, requiredKeys) { + for (var key of requiredKeys) { + if (formData.get(key) === null) { + console.error(`Missing key in form : ${key}`); + return false; + } + } + return true; + }; + + this.removeUserFromSession = function removeUserFromSession() { + window.sessionStorage.removeItem(this.storageKeys.token); + window.sessionStorage.removeItem(this.storageKeys.firstname); + window.sessionStorage.removeItem(this.storageKeys.lastname); + window.sessionStorage.removeItem(this.storageKeys.username); + window.sessionStorage.removeItem(this.storageKeys.email); + }; + + this.storeToken = function (token) { + window.sessionStorage.setItem(this.storageKeys.token, token); + }; + + this.storeUser = function storeUser(user) { + window.sessionStorage.setItem(this.storageKeys.firstname, user.firstname); + window.sessionStorage.setItem(this.storageKeys.lastname, user.lastname); + window.sessionStorage.setItem(this.storageKeys.username, user.username); + window.sessionStorage.setItem(this.storageKeys.email, user.email); + }; + + this.getUser = function getUser() { + let user = {}; + user.token = window.sessionStorage.getItem(this.storageKeys.token); + if (user.token === null || user.token === undefined) { + return null; + } + user.firstname = window.sessionStorage.getItem(this.storageKeys.firstname); + user.lastname = window.sessionStorage.getItem(this.storageKeys.lastname); + user.username = window.sessionStorage.getItem(this.storageKeys.username); + user.email = window.sessionStorage.getItem(this.storageKeys.email); + return user; + }; + + this.isUserLoggedIn = function isUserLoggedIn() { + try { + let user = this.getUser(); + return user !== null && user !== undefined; + } catch (e) { + console.error(e); + return false; + } + }; + + // Observers + this.addObserver = function (observerFunction) { + this.observers.push(observerFunction); + }; + + this.notifyObservers = function () { + for (let observer of this.observers) { + observer(); + } + }; - this.initialize(); -} \ No newline at end of file + this.initialize(); +} diff --git a/src/Widgets/Extensions/Authentication/views/AuthenticationView.css b/src/Widgets/Extensions/Authentication/views/AuthenticationView.css index 7730f89eb..519e1b38b 100644 --- a/src/Widgets/Extensions/Authentication/views/AuthenticationView.css +++ b/src/Widgets/Extensions/Authentication/views/AuthenticationView.css @@ -1,147 +1,149 @@ +/** @format */ + #loginRegistrationWindow * { - box-sizing: border-box; + box-sizing: border-box; } #loginRegistrationWindow { - grid-template-columns: 1fr 1fr; - box-sizing: border-box; - position: absolute; - top: 0; - height: 100%; - width: 100%; - color: black; - font-size: 75%; - background-color: rgba(30, 30, 30, 0.3); - border: 1px solid rgb(90, 90, 90); - pointer-events: auto; - display: grid; - z-index: 50000; + grid-template-columns: 1fr 1fr; + box-sizing: border-box; + position: absolute; + top: 0; + height: 100%; + width: 100%; + color: black; + font-size: 75%; + background-color: rgba(30, 30, 30, 0.3); + border: 1px solid rgb(90, 90, 90); + pointer-events: auto; + display: grid; + z-index: 50000; } #loginRegistrationWindow > div > ul { - padding-left: 5px; + padding-left: 5px; } #loginRegistrationCloseButton { - margin-top: 2.2vw; - margin-left: 24.8vw; - grid-column: 2; - grid-row: 1; - height: 2vw; - width: 5vw; + margin-top: 2.2vw; + margin-left: 24.8vw; + grid-column: 2; + grid-row: 1; + height: 2vw; + width: 5vw; } #RegistrationForm { - margin: 2vw 0 auto auto; - display: grid; - grid-row: 1; - grid-column: 1; - width: 30vw; - height: 42vw; - padding: 1.5vw 6%; - color: white; - background-color: rgba(45, 52, 54, 0.9); - border: 0.15vw solid #2c2c2c; + margin: 2vw 0 auto auto; + display: grid; + grid-row: 1; + grid-column: 1; + width: 30vw; + height: 42vw; + padding: 1.5vw 6%; + color: white; + background-color: rgba(45, 52, 54, 0.9); + border: 0.15vw solid #2c2c2c; } #LoginForm { - margin: 2vw auto auto 0; - width: 30vw; - height: 42vw; - display: grid; - grid-row: 1; - grid-column: 2; - padding: 1.5vw 6%; - grid-template-rows: 5vw 2.5vw repeat(2, 5vw 3.5vw) 7vw 1fr; - color: white; - background-color: rgba(45, 52, 54, 0.9); - border: 0.15vw solid #2c2c2c; + margin: 2vw auto auto 0; + width: 30vw; + height: 42vw; + display: grid; + grid-row: 1; + grid-column: 2; + padding: 1.5vw 6%; + grid-template-rows: 5vw 2.5vw repeat(2, 5vw 3.5vw) 7vw 1fr; + color: white; + background-color: rgba(45, 52, 54, 0.9); + border: 0.15vw solid #2c2c2c; } #loginRegistrationWindow h2 { - text-align: center; - font-size: 3vw; - margin: 0; - font-weight: 700; + text-align: center; + font-size: 3vw; + margin: 0; + font-weight: 700; } -#LoginButton, #RegisterButton { - font-size: 2vw; - height: 4vw; - padding: 0 20%; - border-radius: 0.5vw; - color: white; - background-color: #1aaa55; - border: 0.2vw solid #168f48; +#LoginButton, +#RegisterButton { + font-size: 2vw; + height: 4vw; + padding: 0 20%; + border-radius: 0.5vw; + color: white; + background-color: #1aaa55; + border: 0.2vw solid #168f48; } -#LoginButton:hover, #RegisterButton:hover { - background-color: #168f48; +#LoginButton:hover, +#RegisterButton:hover { + background-color: #168f48; } #RegistrationForm label { - font-size: 1vw; - margin: auto 0 1% 1% ; + font-size: 1vw; + margin: auto 0 1% 1%; } #RegistrationForm label::after { - content: "*"; - color: red; - margin-left: 0.2vw; + content: '*'; + color: red; + margin-left: 0.2vw; } #RegistrationForm input { - font-size: 1.5vw; - padding: 2%; - background-color: #eeeeef; - border: 0.05vw solid black; + font-size: 1.5vw; + padding: 2%; + background-color: #eeeeef; + border: 0.05vw solid black; } #RegistrationForm button { - margin: 1.5vw auto auto; + margin: 1.5vw auto auto; } #LoginForm label { - font-size: 2.5vw; - margin: auto 0 1% 1% ; + font-size: 2.5vw; + margin: auto 0 1% 1%; } #LoginForm input { - font-size: 1.5vw; - padding: 2%; - background-color: #eeeeef; - border: 0.05vw solid black; + font-size: 1.5vw; + padding: 2%; + background-color: #eeeeef; + border: 0.05vw solid black; } #LoginForm div { - font-size: 2vw; - margin: 2vw auto; + font-size: 2vw; + margin: 2vw auto; } #LoginForm button { - margin: 3vw auto auto; + margin: 3vw auto auto; } .ErrorBox { - color: red; - font-weight: bold; - text-align: center; + color: red; + font-weight: bold; + text-align: center; } - -#loginRegistrationWindow label -{ - display: block; - width: 200px; - float: left; +#loginRegistrationWindow label { + display: block; + width: 200px; + float: left; } #profileMenu label { - display: block; - float: left; + display: block; + float: left; } -.SuccessBox{ - color: green; - text-align: center; -} \ No newline at end of file +.SuccessBox { + color: green; + text-align: center; +} diff --git a/src/Widgets/Extensions/Authentication/views/AuthenticationView.js b/src/Widgets/Extensions/Authentication/views/AuthenticationView.js index 31a5f4177..f423710f1 100644 --- a/src/Widgets/Extensions/Authentication/views/AuthenticationView.js +++ b/src/Widgets/Extensions/Authentication/views/AuthenticationView.js @@ -1,17 +1,18 @@ +/** @format */ + //Components import { ModuleView } from '../../../../Components/ModuleView/ModuleView'; import './AuthenticationView.css'; export class AuthenticationView extends ModuleView { + constructor(authenticationService) { + super(); + this.authenticationService = authenticationService; + } - constructor(authenticationService) { - super(); - this.authenticationService = authenticationService; - } - - html() { - return ` + html() { + return ` \

      Registration

      \

      @@ -43,139 +44,139 @@ export class AuthenticationView extends ModuleView { \ \ `; - } - - appendToElement(htmlElement) { - let div = document.createElement('div'); - div.innerHTML = this.html(); - div.id = "loginRegistrationWindow"; - htmlElement.appendChild(div); - document.getElementById('loginRegistrationCloseButton').onclick = () => { - this.disable() - }; - document.getElementById('LoginButton').onclick = () => { - this.logInFunction() - }; - document.getElementById('RegisterButton').onclick = () => { - this.registerFunction() - }; - document.getElementById('PasswordRegistration').onkeypress = () => { - if ((event.key) == "Enter") this.registerFunction() - }; - document.getElementById('PasswordLogin').onkeypress = () => { - if ((event.key) == "Enter") this.logInFunction() - }; - } - - - dispose() { - let div = document.getElementById('loginRegistrationWindow'); - return div.parentNode.removeChild(div); - } - - displayRegisterError(msg) { - let errorField = document.getElementById('RegisterInfo'); - errorField.className = "ErrorBox" - errorField.innerHTML = msg; + } + + appendToElement(htmlElement) { + let div = document.createElement('div'); + div.innerHTML = this.html(); + div.id = 'loginRegistrationWindow'; + htmlElement.appendChild(div); + document.getElementById('loginRegistrationCloseButton').onclick = () => { + this.disable(); }; - - displayLoginError(msg) { - let errorField = document.getElementById('LoginInfo'); - errorField.innerHTML = msg; + document.getElementById('LoginButton').onclick = () => { + this.logInFunction(); }; - - displayRegisterSuccess(msg) { - let successField = document.getElementById('RegisterInfo'); - successField.className = "SuccessBox"; - successField.innerHTML = msg; - } - - isVisible() { - let div = document.getElementById('loginRegistrationWindow'); - return div !== undefined && div !== null; + document.getElementById('RegisterButton').onclick = () => { + this.registerFunction(); + }; + document.getElementById('PasswordRegistration').onkeypress = () => { + if (event.key == 'Enter') this.registerFunction(); + }; + document.getElementById('PasswordLogin').onkeypress = () => { + if (event.key == 'Enter') this.logInFunction(); + }; + } + + dispose() { + let div = document.getElementById('loginRegistrationWindow'); + return div.parentNode.removeChild(div); + } + + displayRegisterError(msg) { + let errorField = document.getElementById('RegisterInfo'); + errorField.className = 'ErrorBox'; + errorField.innerHTML = msg; + } + + displayLoginError(msg) { + let errorField = document.getElementById('LoginInfo'); + errorField.innerHTML = msg; + } + + displayRegisterSuccess(msg) { + let successField = document.getElementById('RegisterInfo'); + successField.className = 'SuccessBox'; + successField.innerHTML = msg; + } + + isVisible() { + let div = document.getElementById('loginRegistrationWindow'); + return div !== undefined && div !== null; + } + verifyNotEmptyValuesForm(formIds) { + var validate = true; + for (var id in formIds) { + let element = document.getElementById(formIds[id]); + element.setAttribute('style', ''); + if (element.value == '') { + element.setAttribute('style', ' border: 3px solid red'); + validate = false; + } } - verifyNotEmptyValuesForm(formIds) { - var validate = true; - for (var id in formIds) { - let element = document.getElementById(formIds[id]); - element.setAttribute("style", ""); - if (element.value == "") { - element.setAttribute("style", " border: 3px solid red"); - validate = false; - } - } - return validate; + return validate; + } + deleteValuesForm(formIds) { + for (var id in formIds) { + let element = document.getElementById(formIds[id]); + element.value = ''; } - deleteValuesForm(formIds) { - for (var id in formIds) { - let element = document.getElementById(formIds[id]); - element.value = ""; - } + } + verifymail() { + // This regular expression checks an email in the form of 'name@example.com' + let RegularExpression = + /^(([^<>()[]\.,;:s@]+(.[^<>()[]\.,;:s@]+)*)|(.+))@(([[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}])|(([a-zA-Z-0-9]+.)+[a-zA-Z]{2,}))$/; + let element = document.getElementById('Email'); + if (RegularExpression.test(element.value)) { + element.setAttribute('style', ''); + this.displayRegisterError(''); + return true; + } else { + element.setAttribute('style', ' border: 3px solid red'); + this.displayRegisterError('Please insert a valid mail'); + return false; } - verifymail() { - // This regular expression checks an email in the form of 'name@example.com' - let RegularExpression = /^(([^<>()[]\.,;:s@]+(.[^<>()[]\.,;:s@]+)*)|(.+))@(([[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}])|(([a-zA-Z-0-9]+.)+[a-zA-Z]{2,}))$/; - let element = document.getElementById("Email"); - if (RegularExpression.test(element.value)) { - element.setAttribute("style", ""); - this.displayRegisterError(""); - return true; - } - else { - element.setAttribute("style", " border: 3px solid red"); - this.displayRegisterError("Please insert a valid mail"); - return false; + } + + async logInFunction() { + this.displayLoginError(''); + const loginForm = document.getElementById('LoginForm'); + const formData = new FormData(loginForm); + var formIds = ['login', 'PasswordLogin']; + if (this.verifyNotEmptyValuesForm(formIds)) { + try { + await this.authenticationService.login(formData); + this.disable(); + } catch (e) { + if (e.status === 401) { + this.displayLoginError('Login or password invalid'); } + } } - - async logInFunction() { - this.displayLoginError(''); - const loginForm = document.getElementById('LoginForm'); - const formData = new FormData(loginForm); - var formIds = ['login', 'PasswordLogin']; - if (this.verifyNotEmptyValuesForm(formIds)) { - try { - await this.authenticationService.login(formData); - this.disable(); - } catch (e) { - if (e.status === 401) { - this.displayLoginError("Login or password invalid"); - } - - } + } + + async registerFunction() { + this.displayRegisterError(''); + const registerForm = document.getElementById('RegistrationForm'); + const formData = new FormData(registerForm); + var formIds = [ + 'Firstname', + 'Lastname', + 'Username', + 'Email', + 'PasswordRegistration', + ]; + if (this.verifyNotEmptyValuesForm(formIds) & this.verifymail()) { + try { + await this.authenticationService.register(formData); + this.deleteValuesForm(formIds); + this.displayRegisterSuccess('Your registration succeed'); + } catch (e) { + if (e.status == '422') { + this.displayRegisterError('The user already exist'); + } else { + this.displayRegisterError(e.response); } + } } + } + /////// MODULE MANAGEMENT FOR BASE DEMO - async registerFunction() { - this.displayRegisterError(''); - const registerForm = document.getElementById('RegistrationForm'); - const formData = new FormData(registerForm); - var formIds = ['Firstname', 'Lastname', 'Username', 'Email', 'PasswordRegistration']; - if (this.verifyNotEmptyValuesForm(formIds) & this.verifymail()) { - try { - await this.authenticationService.register(formData); - this.deleteValuesForm(formIds); - this.displayRegisterSuccess("Your registration succeed"); + enableView() { + this.appendToElement(this.parentElement); + } - } catch (e) { - if (e.status == '422') { - this.displayRegisterError('The user already exist'); - } - else { - this.displayRegisterError(e.response); - } - } - } - - - }; - /////// MODULE MANAGEMENT FOR BASE DEMO - - enableView() { - this.appendToElement(this.parentElement); - } - - disableView() { - this.dispose(); - } + disableView() { + this.dispose(); + } } diff --git a/src/Widgets/Extensions/Contribute/ContributeModule.js b/src/Widgets/Extensions/Contribute/ContributeModule.js index 49a80d6c2..9f9e7a963 100644 --- a/src/Widgets/Extensions/Contribute/ContributeModule.js +++ b/src/Widgets/Extensions/Contribute/ContributeModule.js @@ -1,13 +1,15 @@ +/** @format */ + //Widgets -import { DocumentModule } from "../../Documents/DocumentModule"; +import { DocumentModule } from '../../Documents/DocumentModule'; //Components -import { RequestService } from "../../../Components/Request/RequestService"; +import { RequestService } from '../../../Components/Request/RequestService'; -import { DocumentCreationWindow } from "./View/DocumentCreationWindow"; -import { DocumentUpdateWindow } from "./View/DocumentUpdateWindow"; -import { ContributeService } from "./Service/ContributeService"; -import { DocumentDeletionInterface } from "./View/DocumentDeletionInterface"; +import { DocumentCreationWindow } from './View/DocumentCreationWindow'; +import { DocumentUpdateWindow } from './View/DocumentUpdateWindow'; +import { ContributeService } from './Service/ContributeService'; +import { DocumentDeletionInterface } from './View/DocumentDeletionInterface'; /** * This module is used to manage the update, deletion and creation of documents. @@ -17,7 +19,7 @@ import { DocumentDeletionInterface } from "./View/DocumentDeletionInterface"; export class ContributeModule { /** * Constructs a new contribute module. - * + * * @param {DocumentModule} documentModule The document module. * @param {DocumentImageOrienter} documentImageOrienter The document image * orienter module. @@ -29,17 +31,33 @@ export class ContributeModule { * @param {string} config.server.url The server url. * @param {string} config.server.document The base route for documents. */ - constructor(documentModule, documentImageOrienter, requestService, itownsView, cameraControls, config) { - this.contributeService = new ContributeService(requestService, - documentModule.provider, config) + constructor( + documentModule, + documentImageOrienter, + requestService, + itownsView, + cameraControls, + config + ) { + this.contributeService = new ContributeService( + requestService, + documentModule.provider, + config + ); - this.creationWindow = new DocumentCreationWindow(this.contributeService, - itownsView, cameraControls, documentImageOrienter); - this.updateWindow = new DocumentUpdateWindow(this.contributeService, - documentModule); + this.creationWindow = new DocumentCreationWindow( + this.contributeService, + itownsView, + cameraControls, + documentImageOrienter + ); + this.updateWindow = new DocumentUpdateWindow( + this.contributeService, + documentModule + ); new DocumentDeletionInterface(documentModule, this.contributeService); documentModule.addDocumentWindow(this.creationWindow); documentModule.addDocumentWindow(this.updateWindow); } -} \ No newline at end of file +} diff --git a/src/Widgets/Extensions/Contribute/Service/ContributeService.js b/src/Widgets/Extensions/Contribute/Service/ContributeService.js index 14703380a..22e1a28f0 100644 --- a/src/Widgets/Extensions/Contribute/Service/ContributeService.js +++ b/src/Widgets/Extensions/Contribute/Service/ContributeService.js @@ -1,9 +1,11 @@ +/** @format */ + //Widgets -import { DocumentProvider } from "../../../Documents/ViewModel/DocumentProvider"; -import { Document } from "../../../Documents/Model/Document"; +import { DocumentProvider } from '../../../Documents/ViewModel/DocumentProvider'; +import { Document } from '../../../Documents/Model/Document'; //Components -import { RequestService } from "../../../../Components/Request/RequestService"; +import { RequestService } from '../../../../Components/Request/RequestService'; /** * This class performs the requests on the server to update and create @@ -74,7 +76,7 @@ export class ContributeService { let url = this.documentUrl + '/' + id; let response = await this.requestService.request('PUT', url, { - body: updatedData + body: updatedData, }); if (response.status >= 200 && response.status < 300) { @@ -95,9 +97,9 @@ export class ContributeService { * @returns {Document} The created document. */ async createDocument(creationData) { - let response = await (this.requestService.request('POST', this.documentUrl, { - body: creationData - })); + let response = await this.requestService.request('POST', this.documentUrl, { + body: creationData, + }); if (response.status >= 200 && response.status < 300) { let created = JSON.parse(response.responseText); diff --git a/src/Widgets/Extensions/Contribute/View/Contribute.css b/src/Widgets/Extensions/Contribute/View/Contribute.css index e46ed1231..1def77c2b 100644 --- a/src/Widgets/Extensions/Contribute/View/Contribute.css +++ b/src/Widgets/Extensions/Contribute/View/Contribute.css @@ -1,12 +1,16 @@ -/* forms */ +/** + * /* forms + * + * @format + */ -.doc-update-creation-form input[type="date"], -.doc-update-creation-form input[type="text"], -.doc-update-creation-form input[type="file"], +.doc-update-creation-form input[type='date'], +.doc-update-creation-form input[type='text'], +.doc-update-creation-form input[type='file'], .doc-update-creation-form textarea, .doc-update-creation-form select { display: block; width: 100%; max-width: 100%; box-sizing: border-box; -} \ No newline at end of file +} diff --git a/src/Widgets/Extensions/Contribute/View/DocumentCreationWindow.js b/src/Widgets/Extensions/Contribute/View/DocumentCreationWindow.js index dadf8b750..4b06675d8 100644 --- a/src/Widgets/Extensions/Contribute/View/DocumentCreationWindow.js +++ b/src/Widgets/Extensions/Contribute/View/DocumentCreationWindow.js @@ -1,71 +1,80 @@ +/** @format */ + import * as THREE from 'three'; //Widgets -import { DocumentVisualizerWindow } from "../../../DocumentVisualizer/View/DocumentVisualizerWindow"; -import { AbstractDocumentWindow } from "../../../Documents/View/AbstractDocumentWindow"; +import { DocumentVisualizerWindow } from '../../../DocumentVisualizer/View/DocumentVisualizerWindow'; +import { AbstractDocumentWindow } from '../../../Documents/View/AbstractDocumentWindow'; //Components -import { Window } from "../../../../Components/GUI/js/Window"; -import { PositionerWindow } from "../../../../Components/Camera/PositionerWindow"; +import { Window } from '../../../../Components/GUI/js/Window'; +import { PositionerWindow } from '../../../../Components/Camera/PositionerWindow'; -import { ContributeService } from "../Service/ContributeService"; +import { ContributeService } from '../Service/ContributeService'; export class DocumentCreationWindow extends AbstractDocumentWindow { /** * Creates a new document creation window. - * + * * @param {ContributeService} contributeService The contribute service to * perform requests. * @param {*} itownsView The iTowns view. * @param {*} cameraControls The planar camera controls. * @param {DocumentVisualizerWindow} documentImageOrienter The document image orienter module. */ - constructor(contributeService, itownsView, cameraControls, documentImageOrienter) { + constructor( + contributeService, + itownsView, + cameraControls, + documentImageOrienter + ) { super('Creation'); - /** * The contribute service to perform requests. - * + * * @type {ContributeService} */ this.contributeService = contributeService; /** * The camera positioner utility tool. - * + * * @type {PositionerWindow} */ this.positioner = new PositionerWindow(itownsView, cameraControls); - this.positioner.addEventListener(PositionerWindow.EVENT_POSITION_SUBMITTED, - (data) => this._registerPositionAndQuaternion(data)); - this.addEventListener(Window.EVENT_DISABLED, - () => this.positioner.disable()); + this.positioner.addEventListener( + PositionerWindow.EVENT_POSITION_SUBMITTED, + (data) => this._registerPositionAndQuaternion(data) + ); + this.addEventListener(Window.EVENT_DISABLED, () => + this.positioner.disable() + ); /** * The camera controls - * + * * @type {*} */ this.controls = cameraControls; /** * The registered camera position for the document visualization. - * + * * @type {THREE.Vector3} */ this.cameraPosition = undefined; /** * The registered camera orientation for the document visualization. - * + * * @type {THREE.Quaternion} */ this.cameraQuaternion = undefined; /** * The document image orienter module. - * + * * @type {DocumentVisualizerWindow} */ this.documentImageOrienter = documentImageOrienter; @@ -73,18 +82,20 @@ export class DocumentCreationWindow extends AbstractDocumentWindow { // same time. this.documentImageOrienter.addEventListener(Window.EVENT_DISABLED, () => { if (this.positioner.isVisible) { - this.positioner.disable() - }}); + this.positioner.disable(); + } + }); this.positioner.addEventListener(Window.EVENT_DISABLED, () => { this._exitEditMode(); if (this.documentImageOrienter.isVisible) { - this.documentImageOrienter.disable() - }}); + this.documentImageOrienter.disable(); + } + }); /** * The settings for an accurate movement of the camera. These settings * should be used in the `PlanarControls` class. - * + * * @type {{rotateSpeed: number, zoomInFactor: number, zoomOutFactor: number, * maxPanSpeed: number, minPanSpeed: number}} */ @@ -93,16 +104,16 @@ export class DocumentCreationWindow extends AbstractDocumentWindow { zoomInFactor: 0.04, zoomOutFactor: 0.04, maxPanSpeed: 5.0, - minPanSpeed: 0.01 + minPanSpeed: 0.01, }; /** * The saved state of the planar controls settings. This is used to restore * the default settings when needed. - * + * * @type {{rotateSpeed: number, zoomInFactor: number, zoomOutFactor: number, - * maxPanSpeed: number, minPanSpeed: number}} - */ + * maxPanSpeed: number, minPanSpeed: number}} + */ this.savedControlsSettings = {}; for (let key of Object.keys(this.accurateControlsSettings)) { this.savedControlsSettings[key] = this.controls[key]; @@ -110,7 +121,7 @@ export class DocumentCreationWindow extends AbstractDocumentWindow { } get innerContentHtml() { - return /*html*/` + return /*html*/ `

      Document data

      @@ -161,7 +172,7 @@ export class DocumentCreationWindow extends AbstractDocumentWindow { this.view.navigatorWindow.addExtension('Create', { type: 'button', html: 'Create a new document', - callback: () => this.view.requestWindowDisplay(this, true) + callback: () => this.view.requestWindowDisplay(this, true), }); } @@ -171,7 +182,7 @@ export class DocumentCreationWindow extends AbstractDocumentWindow { /** * Displays the document positioning interfaces : the window positioner and * the document image orienter. - * + * * @private */ _startPositioningDocument() { @@ -214,7 +225,7 @@ export class DocumentCreationWindow extends AbstractDocumentWindow { /** * Sets the initial values for the form. - * + * * @private */ _initForm() { @@ -231,13 +242,13 @@ export class DocumentCreationWindow extends AbstractDocumentWindow { /** * Checks if the form is ready to be validated. Every entry must have a * non-empty value, and the camera position / orientation must have been set. - * + * * @private */ _formValidation() { let data = new FormData(this.formElement); for (let entry of data.entries()) { - if (!entry[1] || entry[1] === "") { + if (!entry[1] || entry[1] === '') { return false; } } @@ -251,7 +262,7 @@ export class DocumentCreationWindow extends AbstractDocumentWindow { * Update the form buttons depending on the current form state. If the * document have been chosen, we can position it. If the form is valid, * we can create the document. - * + * * @private */ _updateFormButtons() { @@ -270,11 +281,11 @@ export class DocumentCreationWindow extends AbstractDocumentWindow { /** * Registers the camera position and orientation. - * + * * @param {{ * position: THREE.Vector3, * quaternion: THREE.Quaternion - * }} cameraState Position and orientation of the camera. + * }} cameraState Position and orientation of the camera. */ _registerPositionAndQuaternion(cameraState) { this.cameraPosition = cameraState.position; @@ -284,7 +295,7 @@ export class DocumentCreationWindow extends AbstractDocumentWindow { /** * Proceeds to create the document from the form data. - * + * * @private */ async _submitCreation() { @@ -300,7 +311,7 @@ export class DocumentCreationWindow extends AbstractDocumentWindow { data.append('quaternionY', this.cameraQuaternion.y); data.append('quaternionZ', this.cameraQuaternion.z); data.append('quaternionW', this.cameraQuaternion.w); - + try { await this.contributeService.createDocument(data); this.disable(); @@ -343,11 +354,11 @@ export class DocumentCreationWindow extends AbstractDocumentWindow { get docTitleElement() { return document.getElementById(this.docTitleId); } - + get docImageId() { return `${this.windowId}_image`; } - + get docImageElement() { return document.getElementById(this.docImageId); } @@ -361,7 +372,7 @@ export class DocumentCreationWindow extends AbstractDocumentWindow { } get docRightsHolderId() { - return `${this.windowId}_rights_holder` + return `${this.windowId}_rights_holder`; } get docRightsHolderElement() { @@ -391,4 +402,4 @@ export class DocumentCreationWindow extends AbstractDocumentWindow { get refDateElement() { return document.getElementById(this.refDateId); } -} \ No newline at end of file +} diff --git a/src/Widgets/Extensions/Contribute/View/DocumentDeletionInterface.js b/src/Widgets/Extensions/Contribute/View/DocumentDeletionInterface.js index 0740599a7..4f3a9f135 100644 --- a/src/Widgets/Extensions/Contribute/View/DocumentDeletionInterface.js +++ b/src/Widgets/Extensions/Contribute/View/DocumentDeletionInterface.js @@ -1,7 +1,9 @@ +/** @format */ + //Widgets -import { DocumentModule } from "../../../Documents/DocumentModule"; +import { DocumentModule } from '../../../Documents/DocumentModule'; -import { ContributeService } from "../Service/ContributeService"; +import { ContributeService } from '../Service/ContributeService'; /** * Represents a really simple interface to delete a document. It is just a @@ -11,7 +13,7 @@ import { ContributeService } from "../Service/ContributeService"; export class DocumentDeletionInterface { /** * Creates a button in the document browser to perform the deletion. - * + * * @param {DocumentModule} documentModule The document module. * @param {ContributeService} contributeService The contribute service. */ @@ -21,8 +23,12 @@ export class DocumentDeletionInterface { container: 'right', html: 'Delete', callback: async () => { - if (!confirm('You are going to delete the document. This operation ' + - 'is irreversible. Do you want to continue ?')) { + if ( + !confirm( + 'You are going to delete the document. This operation ' + + 'is irreversible. Do you want to continue ?' + ) + ) { return; } try { @@ -30,7 +36,7 @@ export class DocumentDeletionInterface { } catch (e) { alert(e); } - } + }, }); } -} \ No newline at end of file +} diff --git a/src/Widgets/Extensions/Contribute/View/DocumentUpdateWindow.js b/src/Widgets/Extensions/Contribute/View/DocumentUpdateWindow.js index 97635bdb4..0d87516b5 100644 --- a/src/Widgets/Extensions/Contribute/View/DocumentUpdateWindow.js +++ b/src/Widgets/Extensions/Contribute/View/DocumentUpdateWindow.js @@ -1,12 +1,13 @@ -//Widgets -import { AbstractDocumentWindow } from "../../../Documents/View/AbstractDocumentWindow"; -import { DocumentProvider } from "../../../Documents/ViewModel/DocumentProvider"; -import { DocumentModule } from "../../../Documents/DocumentModule"; +/** @format */ -import { ContributeService } from "../Service/ContributeService"; +//Widgets +import { AbstractDocumentWindow } from '../../../Documents/View/AbstractDocumentWindow'; +import { DocumentProvider } from '../../../Documents/ViewModel/DocumentProvider'; +import { DocumentModule } from '../../../Documents/DocumentModule'; -import "./Contribute.css"; +import { ContributeService } from '../Service/ContributeService'; +import './Contribute.css'; /** * This window is used to update a document. It contains a form that allows to @@ -34,12 +35,12 @@ export class DocumentUpdateWindow extends AbstractDocumentWindow { type: 'button', container: 'right', html: 'Update', - callback: () => this._initWindow() + callback: () => this._initWindow(), }); } get innerContentHtml() { - return /*html*/` + return /*html*/ `

      @@ -75,12 +76,14 @@ export class DocumentUpdateWindow extends AbstractDocumentWindow { this.cancelButtonElement.onclick = () => { this.disable(); - } + }; } documentWindowReady() { - this.provider.addEventListener(DocumentProvider.EVENT_DISPLAYED_DOC_CHANGED, - () => this.disable()); + this.provider.addEventListener( + DocumentProvider.EVENT_DISPLAYED_DOC_CHANGED, + () => this.disable() + ); } /////////////////////// @@ -114,15 +117,16 @@ export class DocumentUpdateWindow extends AbstractDocumentWindow { } this.docTitleElement.innerText = doc.title; - this.docImageElement.src = - await this.provider.getDisplayedDocumentImage(); + this.docImageElement.src = await this.provider.getDisplayedDocumentImage(); this.sourceElement.value = doc.source; this.docRightsHolderElement.value = doc.rightsHolder; this.descriptionElement.value = doc.description; - this.pubDateElement.value = (new Date(doc.publicationDate)) - .toISOString().substring(0, 10); - this.refDateElement.value = (new Date(doc.refDate)) - .toISOString().substring(0, 10); + this.pubDateElement.value = new Date(doc.publicationDate) + .toISOString() + .substring(0, 10); + this.refDateElement.value = new Date(doc.refDate) + .toISOString() + .substring(0, 10); } ///////////////// @@ -186,7 +190,7 @@ export class DocumentUpdateWindow extends AbstractDocumentWindow { } get docRightsHolderId() { - return `${this.windowId}_rights_holder` + return `${this.windowId}_rights_holder`; } get docRightsHolderElement() { diff --git a/src/Widgets/Extensions/DocumentComments/DocumentCommentsModule.js b/src/Widgets/Extensions/DocumentComments/DocumentCommentsModule.js index 5a59342d3..5d578b5fb 100644 --- a/src/Widgets/Extensions/DocumentComments/DocumentCommentsModule.js +++ b/src/Widgets/Extensions/DocumentComments/DocumentCommentsModule.js @@ -1,10 +1,12 @@ -import { DocumentModule } from "../../Documents/DocumentModule"; +/** @format */ + +import { DocumentModule } from '../../Documents/DocumentModule'; //Components -import { RequestService } from "../../../Components/Request/RequestService"; +import { RequestService } from '../../../Components/Request/RequestService'; -import { DocumentCommentsService } from "./services/DocumentCommentsService"; -import { DocumentCommentsWindow } from "./views/DocumentCommentsWindow"; +import { DocumentCommentsService } from './services/DocumentCommentsService'; +import { DocumentCommentsWindow } from './views/DocumentCommentsWindow'; /** * The class that represents the document comments module. It contains a @@ -15,7 +17,7 @@ export class DocumentCommentsModule { /** * Creates the document comments module. Creates a service and a comments * window. - * + * * @param {DocumentModule} documentModule The document module. * @param {RequestService} requestService The request service. * @param {object} config The UDV config. @@ -26,10 +28,14 @@ export class DocumentCommentsModule { * @param {string} config.server.user The route for users. */ constructor(documentModule, requestService, config) { - this.service = new DocumentCommentsService(documentModule.provider, requestService, config); + this.service = new DocumentCommentsService( + documentModule.provider, + requestService, + config + ); this.commentsWindow = new DocumentCommentsWindow(this.service); documentModule.addDocumentWindow(this.commentsWindow); } -} \ No newline at end of file +} diff --git a/src/Widgets/Extensions/DocumentComments/services/DocumentCommentsService.js b/src/Widgets/Extensions/DocumentComments/services/DocumentCommentsService.js index acb130033..809919ab9 100644 --- a/src/Widgets/Extensions/DocumentComments/services/DocumentCommentsService.js +++ b/src/Widgets/Extensions/DocumentComments/services/DocumentCommentsService.js @@ -1,56 +1,67 @@ +/** @format */ + //Components -import { RequestService } from "../../../../Components/Request/RequestService"; +import { RequestService } from '../../../../Components/Request/RequestService'; -import { DocumentProvider } from "../../../Documents/ViewModel/DocumentProvider"; +import { DocumentProvider } from '../../../Documents/ViewModel/DocumentProvider'; /** * The service that performs the requests for document comments. This include * retrieve and create operations. */ export class DocumentCommentsService { - /** - * Creates a document comments service. - * - * @param {DocumentProvider} documentProvider The document provider. - * @param {RequestService} requestService The request service. - * @param {object} config The UD-Viz config. - * @param {object} config.server The server access config. - * @param {string} config.server.url The server URL. - * @param {string} config.server.document The route for documents. - * @param {string} config.server.comment The route for comments. - * @param {string} config.server.user The route for users. - */ - constructor (documentProvider, requestService, config) { - this.documentProvider = documentProvider; + /** + * Creates a document comments service. + * + * @param {DocumentProvider} documentProvider The document provider. + * @param {RequestService} requestService The request service. + * @param {object} config The UD-Viz config. + * @param {object} config.server The server access config. + * @param {string} config.server.url The server URL. + * @param {string} config.server.document The route for documents. + * @param {string} config.server.comment The route for comments. + * @param {string} config.server.user The route for users. + */ + constructor(documentProvider, requestService, config) { + this.documentProvider = documentProvider; - this.requestService = requestService; - - this.documentUrl = `${config.server.url}${config.server.document}`; - this.commentRoute = config.server.comment; - this.authorUrl = `${config.server.url}${config.server.user}`; - } + this.requestService = requestService; + + this.documentUrl = `${config.server.url}${config.server.document}`; + this.commentRoute = config.server.comment; + this.authorUrl = `${config.server.url}${config.server.user}`; + } - async getComments() { - let currentDocument = this.documentProvider.getDisplayedDocument(); - if (currentDocument !== null && currentDocument !== undefined) { - let url = this.documentUrl + "/" + currentDocument.id + "/" + this.commentRoute; - let response = (await this.requestService.request('GET', url, {authenticate: 'auto'})).response; - let jsonResponse = JSON.parse(response); - for (let element of jsonResponse) { - let url = this.authorUrl + "/" + element.user_id; - let responseAuthor = (await this.requestService.request('GET', url, {authenticate: 'auto'})).response; - element.author = JSON.parse(responseAuthor); - } - return jsonResponse; - } - return []; + async getComments() { + let currentDocument = this.documentProvider.getDisplayedDocument(); + if (currentDocument !== null && currentDocument !== undefined) { + let url = + this.documentUrl + '/' + currentDocument.id + '/' + this.commentRoute; + let response = ( + await this.requestService.request('GET', url, { authenticate: 'auto' }) + ).response; + let jsonResponse = JSON.parse(response); + for (let element of jsonResponse) { + let url = this.authorUrl + '/' + element.user_id; + let responseAuthor = ( + await this.requestService.request('GET', url, { + authenticate: 'auto', + }) + ).response; + element.author = JSON.parse(responseAuthor); + } + return jsonResponse; } + return []; + } - async publishComment(formData) { - let currentDocument = this.documentProvider.getDisplayedDocument(); - if (currentDocument !== null && currentDocument !== undefined) { - let url = this.documentUrl + "/" + currentDocument.id + "/" + this.commentRoute; - let response = (await this.requestService.send('POST', url, formData)).response; - } + async publishComment(formData) { + let currentDocument = this.documentProvider.getDisplayedDocument(); + if (currentDocument !== null && currentDocument !== undefined) { + let url = + this.documentUrl + '/' + currentDocument.id + '/' + this.commentRoute; + let response = (await this.requestService.send('POST', url, formData)) + .response; } -} \ No newline at end of file + } +} diff --git a/src/Widgets/Extensions/DocumentComments/views/DocumentCommentsStyle.css b/src/Widgets/Extensions/DocumentComments/views/DocumentCommentsStyle.css index 549729463..2e3d8cd59 100644 --- a/src/Widgets/Extensions/DocumentComments/views/DocumentCommentsStyle.css +++ b/src/Widgets/Extensions/DocumentComments/views/DocumentCommentsStyle.css @@ -1,76 +1,78 @@ +/** @format */ + #documentComments_innerWindow { - width: 100%; - height: 100%; - padding : 0; - margin: 0; - vertical-align:top; - display: grid; - grid-template-columns: 55% 45%; - } + width: 100%; + height: 100%; + padding: 0; + margin: 0; + vertical-align: top; + display: grid; + grid-template-columns: 55% 45%; +} - #documentComments_left{ - vertical-align:top; - overflow-y: auto; - } +#documentComments_left { + vertical-align: top; + overflow-y: auto; +} - #documentComments_right{ - vertical-align:top; - } +#documentComments_right { + vertical-align: top; +} - #documentComments_inputComment{ - height: 150px; - width: 90%; - margin: auto; - border-radius: 3px; - resize: none; - margin-top: 5px; - font-size: 10pt; - } +#documentComments_inputComment { + height: 150px; + width: 90%; + margin: auto; + border-radius: 3px; + resize: none; + margin-top: 5px; + font-size: 10pt; +} - #documentComments_inputButton{ - margin: 10%; - width: 70%; - } +#documentComments_inputButton { + margin: 10%; + width: 70%; +} - .commentRow { - width: 100%; - text-align: center; - } +.commentRow { + width: 100%; + text-align: center; +} - .talk-bubble { - margin: 3%; - position: relative; - width: 95%; - background-color: #e3dfff; - border-radius: 5px; - margin: 5px; - } +.talk-bubble { + margin: 3%; + position: relative; + width: 95%; + background-color: #e3dfff; + border-radius: 5px; + margin: 5px; +} - .talktext{ - padding: 0.3em; - text-align: left; - line-height: 0.9em; - } +.talktext { + padding: 0.3em; + text-align: left; + line-height: 0.9em; +} - .talktext-comment { - /* remove webkit p margins */ - color: #2f2d2e; - padding-left: 10px; - padding-right: 10px; - font-size: 100%; - } +.talktext-comment { + /* remove webkit p margins */ + color: #2f2d2e; + padding-left: 10px; + padding-right: 10px; + font-size: 100%; +} - .talktext-author { - border-bottom: 1px solid rgba(0, 0, 0, 0.3); - margin-top: 0; - padding: 5px; - font-weight: bold; - color: #41292c; - } +.talktext-author { + border-bottom: 1px solid rgba(0, 0, 0, 0.3); + margin-top: 0; + padding: 5px; + font-weight: bold; + color: #41292c; +} - .talktext-date { - color: #7d7d7d; - margin-bottom: 0; - text-align: right; - font-size: 90%; - } +.talktext-date { + color: #7d7d7d; + margin-bottom: 0; + text-align: right; + font-size: 90%; +} diff --git a/src/Widgets/Extensions/DocumentComments/views/DocumentCommentsWindow.js b/src/Widgets/Extensions/DocumentComments/views/DocumentCommentsWindow.js index 9ec060ff7..8b4f957a3 100644 --- a/src/Widgets/Extensions/DocumentComments/views/DocumentCommentsWindow.js +++ b/src/Widgets/Extensions/DocumentComments/views/DocumentCommentsWindow.js @@ -1,3 +1,5 @@ +/** @format */ + import { AbstractDocumentWindow } from '../../../Documents/View/AbstractDocumentWindow'; import { DocumentCommentsService } from '../services/DocumentCommentsService'; @@ -8,20 +10,19 @@ import './DocumentCommentsStyle.css'; * a comments creation interface. */ export class DocumentCommentsWindow extends AbstractDocumentWindow { + /** + * Creates a document comments window to add in the document browser. + * + * @param {DocumentCommentsService} documentCommentsService The document comments + * service. + */ + constructor(documentCommentsService) { + super('Comments'); + this.documentCommentsService = documentCommentsService; + } - /** - * Creates a document comments window to add in the document browser. - * - * @param {DocumentCommentsService} documentCommentsService The document comments - * service. - */ - constructor(documentCommentsService) { - super('Comments'); - this.documentCommentsService = documentCommentsService; - } - - get innerContentHtml() { - return /*html*/` + get innerContentHtml() { + return /*html*/ `
      @@ -38,65 +39,75 @@ export class DocumentCommentsWindow extends AbstractDocumentWindow {
      `; - } + } - windowCreated() { - this.hide(); + windowCreated() { + this.hide(); - this.window.style.width = '500px'; - this.window.style.height = '500px'; - this.window.style.left = '290px'; - this.window.style.top = '10px'; - this.innerContent.style.height = '100%'; - document.getElementById('documentComments_inputButton').onclick = this.publishComment.bind(this); - this.getComments(); - } + this.window.style.width = '500px'; + this.window.style.height = '500px'; + this.window.style.left = '290px'; + this.window.style.top = '10px'; + this.innerContent.style.height = '100%'; + document.getElementById('documentComments_inputButton').onclick = + this.publishComment.bind(this); + this.getComments(); + } - documentWindowReady() { - this.view.inspectorWindow.addExtension('Comments', { - type: 'button', - container: 'left', - html: 'Comments', - callback: () => { - this.view.requestWindowDisplay(this); - this.getComments(); - } - }); - } + documentWindowReady() { + this.view.inspectorWindow.addExtension('Comments', { + type: 'button', + container: 'left', + html: 'Comments', + callback: () => { + this.view.requestWindowDisplay(this); + this.getComments(); + }, + }); + } - getComments() { - this.documentCommentsService.getComments().then((comments) => { - document.getElementById('documentComments_left').innerHTML = ''; - for (let comment of comments) { - let text = (typeof comment.description === 'string') ? comment.description.replace(/(?:\r\n|\r|\n)/g, '
      ') : ''; - let div = document.createElement('div'); - div.className = 'talk-bubble'; - div.innerHTML = ` + getComments() { + this.documentCommentsService.getComments().then( + (comments) => { + document.getElementById('documentComments_left').innerHTML = ''; + for (let comment of comments) { + let text = + typeof comment.description === 'string' + ? comment.description.replace(/(?:\r\n|\r|\n)/g, '
      ') + : ''; + let div = document.createElement('div'); + div.className = 'talk-bubble'; + div.innerHTML = `
      -

      ${comment.author.firstName} ${comment.author.lastName}

      +

      ${comment.author.firstName} ${ + comment.author.lastName + }

      ${text}

      -

      ${(new Date(comment.date)).toLocaleString()}

      +

      ${new Date( + comment.date + ).toLocaleString()}

      `; - document.getElementById('documentComments_left').appendChild(div); - } - }, (reason) => { - alert(reason); - this.disable(); - }); - } - - - async publishComment() { - let form = document.getElementById('documentComments_inputForm'); - let form_data = new FormData(form); - try { - await this.documentCommentsService.publishComment(form_data).then(() => { - document.getElementById('documentComments_inputComment').value = ''; - this.getComments(); - }); - } catch (e) { - alert(e); + document.getElementById('documentComments_left').appendChild(div); } + }, + (reason) => { + alert(reason); + this.disable(); + } + ); + } + + async publishComment() { + let form = document.getElementById('documentComments_inputForm'); + let form_data = new FormData(form); + try { + await this.documentCommentsService.publishComment(form_data).then(() => { + document.getElementById('documentComments_inputComment').value = ''; + this.getComments(); + }); + } catch (e) { + alert(e); } + } } diff --git a/src/Widgets/Extensions/DocumentValidation/DocumentValidationModule.js b/src/Widgets/Extensions/DocumentValidation/DocumentValidationModule.js index 613856240..c2b78f986 100644 --- a/src/Widgets/Extensions/DocumentValidation/DocumentValidationModule.js +++ b/src/Widgets/Extensions/DocumentValidation/DocumentValidationModule.js @@ -1,9 +1,11 @@ +/** @format */ + //Widgets -import { DocumentModule } from "../../Documents/DocumentModule"; +import { DocumentModule } from '../../Documents/DocumentModule'; -import { ValidationService } from "./Service/ValidationService"; -import { DocumentsInValidationDocumentSource } from "./Service/DocumentsInValidationSource"; -import { ValidationView } from "./View/ValidationView"; +import { ValidationService } from './Service/ValidationService'; +import { DocumentsInValidationDocumentSource } from './Service/DocumentsInValidationSource'; +import { ValidationView } from './View/ValidationView'; /** * The document extension to manage documents validation. It allows the user to @@ -16,15 +18,18 @@ export class DocumentValidationModule { * Creates the document validation module. Creates a validation service to * manage HTTP requests, a validation source to change the retrieving URL * and finally the view elements. - * - * @param {DocumentModule} documentModule The documents module. + * + * @param {DocumentModule} documentModule The documents module. */ constructor(documentModule, requestService, config) { this.validationService = new ValidationService(requestService, config); this.validationSource = new DocumentsInValidationDocumentSource(config); - new ValidationView(documentModule, this.validationService, - this.validationSource); + new ValidationView( + documentModule, + this.validationService, + this.validationSource + ); } -} \ No newline at end of file +} diff --git a/src/Widgets/Extensions/DocumentValidation/Service/DocumentsInValidationSource.js b/src/Widgets/Extensions/DocumentValidation/Service/DocumentsInValidationSource.js index 41331cd21..7f4469ec6 100644 --- a/src/Widgets/Extensions/DocumentValidation/Service/DocumentsInValidationSource.js +++ b/src/Widgets/Extensions/DocumentValidation/Service/DocumentsInValidationSource.js @@ -1,4 +1,6 @@ -import { DocumentSource } from "../../../Documents/Model/DocumentService"; +/** @format */ + +import { DocumentSource } from '../../../Documents/Model/DocumentService'; /** * The document source for documents in validation. @@ -6,7 +8,7 @@ import { DocumentSource } from "../../../Documents/Model/DocumentService"; export class DocumentsInValidationDocumentSource extends DocumentSource { /** * Creates the document source. - * + * * @param {object} config The UD-Viz configuration. * @param {object} config.server The configuration for the server. * @param {string} config.server.url The base URL of the server. @@ -29,4 +31,4 @@ export class DocumentsInValidationDocumentSource extends DocumentSource { getImageUrl(doc) { return this.documentUrl + '/' + doc.id + '/' + this.fileRoute; } -} \ No newline at end of file +} diff --git a/src/Widgets/Extensions/DocumentValidation/Service/ValidationService.js b/src/Widgets/Extensions/DocumentValidation/Service/ValidationService.js index 056388c79..173f352fe 100644 --- a/src/Widgets/Extensions/DocumentValidation/Service/ValidationService.js +++ b/src/Widgets/Extensions/DocumentValidation/Service/ValidationService.js @@ -1,7 +1,9 @@ +/** @format */ + //Components -import { RequestService } from "../../../../Components/Request/RequestService"; +import { RequestService } from '../../../../Components/Request/RequestService'; -import { Document } from "../../../Documents/Model/Document"; +import { Document } from '../../../Documents/Model/Document'; /** * This class is responsible for the validation requests. @@ -9,7 +11,7 @@ import { Document } from "../../../Documents/Model/Document"; export class ValidationService { /** * Constructs a validation service. - * + * * @param {RequestService} requestService The request service. * @param {object} config The UD-Viz configuration. * @param {object} config.server The configuration for the server. @@ -23,14 +25,14 @@ export class ValidationService { /** * Sends the request to validate the document. - * + * * @param {Document} doc The document to validate. */ async validate(doc) { let formData = new FormData(); formData.append('id', doc.id); let response = await this.requestService.request('POST', this.validateUrl, { - body: formData + body: formData, }); - }; -} \ No newline at end of file + } +} diff --git a/src/Widgets/Extensions/DocumentValidation/View/ValidationView.js b/src/Widgets/Extensions/DocumentValidation/View/ValidationView.js index e919a8efd..542e89866 100644 --- a/src/Widgets/Extensions/DocumentValidation/View/ValidationView.js +++ b/src/Widgets/Extensions/DocumentValidation/View/ValidationView.js @@ -1,17 +1,19 @@ -import { DocumentModule } from "../../../Documents/DocumentModule"; -import { DocumentSource } from "../../../Documents/Model/DocumentService"; -import { Document } from "../../../Documents/Model/Document"; +/** @format */ + +import { DocumentModule } from '../../../Documents/DocumentModule'; +import { DocumentSource } from '../../../Documents/Model/DocumentService'; +import { Document } from '../../../Documents/Model/Document'; //Components -import { Window } from "../../../../Components/GUI/js/Window"; +import { Window } from '../../../../Components/GUI/js/Window'; -import { ValidationService } from "../Service/ValidationService"; -import { DocumentsInValidationDocumentSource } from "../Service/DocumentsInValidationSource"; +import { ValidationService } from '../Service/ValidationService'; +import { DocumentsInValidationDocumentSource } from '../Service/DocumentsInValidationSource'; /** * This class represents the visual elements and their logic for the * validation module : - * + * * - Button "See documents in validation" to change the document source * - Panel "Currently seing ..." to inform the user that he/she is consulting * documents in validation or validated documents @@ -20,7 +22,7 @@ import { DocumentsInValidationDocumentSource } from "../Service/DocumentsInValid export class ValidationView { /** * Creates the view. - * + * * @param {DocumentModule} documentModule The document module. * @param {ValidationService} validationService The validation service. * @param {DocumentsInValidationDocumentSource} validationSource The source @@ -33,7 +35,7 @@ export class ValidationView { /** * Defines wether the interface displays documents to validate (`true`) or * validated documents (`false`). - * + * * @type {boolean} */ this.displayingDocumentsToValidate = false; @@ -41,14 +43,14 @@ export class ValidationView { /** * Stores the previous document source to restore it (the source for * validated documents). - * + * * @type {DocumentSource} */ this.previousDocumentSource = undefined; /** * The validation source. - * + * * @type {DocumentsInValidationDocumentSource} */ this.validationSource = validationSource; @@ -58,17 +60,19 @@ export class ValidationView { documentModule.addNavigatorExtension('Validation Filter', { type: 'div', container: 'filter', - html: /*html*/` + html: /*html*/ ` - ` + `, }); - documentModule.view.navigatorWindow.addEventListener(Window.EVENT_CREATED, - () => this._initView()); + documentModule.view.navigatorWindow.addEventListener( + Window.EVENT_CREATED, + () => this._initView() + ); } _initView() { @@ -76,7 +80,7 @@ export class ValidationView { this._toggleValidation(); this.switchElement.onchange = () => { this._toggleValidation(); - } + }; } /////////////////////////////////////// @@ -86,7 +90,7 @@ export class ValidationView { * Toggles the visualization of documents in validation, then refreshes the * document list with the new source. If the refresh fails (probably because * the user isn't logged in), reverts back to displaying validated documents. - * + * * @private */ _toggleValidation() { @@ -95,42 +99,46 @@ export class ValidationView { if (this.displayingDocumentsToValidate) { this._showDocumentsInValidation(); } else { - this._showValidatedDocuments() + this._showValidatedDocuments(); } - this.documentModule.refreshDocumentList().then(() => { - }, (reason) => { - this._showValidatedDocuments(); - this.displayingDocumentsToValidate = false; - this.switchElement.value = "validated"; - alert(reason); - }); + this.documentModule.refreshDocumentList().then( + () => {}, + (reason) => { + this._showValidatedDocuments(); + this.displayingDocumentsToValidate = false; + this.switchElement.value = 'validated'; + alert(reason); + } + ); } /** * Sets the document source to be documents in validation, and adds a * 'Validate' button in the browser. - * + * * @private */ _showDocumentsInValidation() { // Change the document source - this.previousDocumentSource = this.documentModule - .changeDocumentSource(this.validationSource, true); - + this.previousDocumentSource = this.documentModule.changeDocumentSource( + this.validationSource, + true + ); + // Adds the validate button this.documentModule.addInspectorExtension('Validate', { type: 'button', container: 'right', html: 'Validate', - callback: (doc) => this._validateDocument(doc) + callback: (doc) => this._validateDocument(doc), }); } /** * Sets to document source to validated documents, and removes the 'Validate' * button in the browser. - * + * * @private */ _showValidatedDocuments() { @@ -138,8 +146,10 @@ export class ValidationView { return; } - this.documentModule.changeDocumentSource(this.previousDocumentSource, - false); + this.documentModule.changeDocumentSource( + this.previousDocumentSource, + false + ); try { this.documentModule.removeBrowserExtension('Validate'); @@ -150,21 +160,28 @@ export class ValidationView { /** * Validates the document. - * + * * @private - * + * * @param {Document} doc The document to validate. */ _validateDocument(doc) { - if (!confirm('Are you sure do validate this document ? ' + - 'This operation is irreversible.')) { + if ( + !confirm( + 'Are you sure do validate this document ? ' + + 'This operation is irreversible.' + ) + ) { return; } - this.validationService.validate(this.documentModule.provider.getDisplayedDocument()).catch((reason) => { - alert(reason.statusText); - }).then(() => { - this.documentModule.refreshDocumentList(); - }); + this.validationService + .validate(this.documentModule.provider.getDisplayedDocument()) + .catch((reason) => { + alert(reason.statusText); + }) + .then(() => { + this.documentModule.refreshDocumentList(); + }); } ///////////// @@ -173,8 +190,8 @@ export class ValidationView { get switchId() { return 'document-validation-view-switch'; } - + get switchElement() { return document.getElementById(this.switchId); } -} \ No newline at end of file +} diff --git a/src/Widgets/Extensions/Extensions.js b/src/Widgets/Extensions/Extensions.js index d3f3f2a77..eca6b8968 100644 --- a/src/Widgets/Extensions/Extensions.js +++ b/src/Widgets/Extensions/Extensions.js @@ -15,5 +15,3 @@ export { Debug3DTilesWindow } from './3DTilesDebug/views/3DTilesDebugWindow'; export { ContributeModule } from './Contribute/ContributeModule'; export { DocumentValidationModule } from './DocumentValidation/DocumentValidationModule'; - - diff --git a/src/Widgets/Extensions/Geocoding/services/GeocodingService.js b/src/Widgets/Extensions/Geocoding/services/GeocodingService.js index 567047265..1e25f87d4 100644 --- a/src/Widgets/Extensions/Geocoding/services/GeocodingService.js +++ b/src/Widgets/Extensions/Geocoding/services/GeocodingService.js @@ -1,6 +1,8 @@ +/** @format */ + //Components -import { RequestService } from "../../../../Components/Request/RequestService"; -import { getAttributeByPath } from "../../../../Components/DataProcessing/DataProcessing"; +import { RequestService } from '../../../../Components/Request/RequestService'; +import { getAttributeByPath } from '../../../../Components/DataProcessing/DataProcessing'; export class GeocodingService { /** @@ -29,7 +31,7 @@ export class GeocodingService { * @param {String} searchString Either an address or the name of a place. */ async getCoordinates(searchString) { - if ((!!this.requestTimeIntervalMs) && !this.canDoRequest) { + if (!!this.requestTimeIntervalMs && !this.canDoRequest) { throw 'Cannot perform a request for now.'; } @@ -39,32 +41,36 @@ export class GeocodingService { //build the URL according to parameter description (in config file) let url = this.geocodingUrl + '?'; for (let [paramName, param] of Object.entries(this.parameters)) { - if (param.fill === "value") { + if (param.fill === 'value') { url += `${paramName}=${param.value}`; - } else if (param.fill === "query") { + } else if (param.fill === 'query') { url += `${paramName}=${queryString}`; - } else if (param.fill === "extent") { - url += paramName + '=' + param.format - .replace('SOUTH', this.extent.south) - .replace('WEST', this.extent.west) - .replace('NORTH', this.extent.north) - .replace('EAST', this.extent.east); + } else if (param.fill === 'extent') { + url += + paramName + + '=' + + param.format + .replace('SOUTH', this.extent.south) + .replace('WEST', this.extent.west) + .replace('NORTH', this.extent.north) + .replace('EAST', this.extent.east); } - url += "&"; + url += '&'; } //make the request const req = await this.requestService.request('GET', url, { - authenticate: false + authenticate: false, }); const response = JSON.parse(req.response); - const results = ((!!this.basePath) ? response[this.basePath] : response) - .map(res => { + const results = (!!this.basePath ? response[this.basePath] : response).map( + (res) => { return { lat: Number(getAttributeByPath(res, this.latPath)), - lng: Number(getAttributeByPath(res, this.lngPath)) + lng: Number(getAttributeByPath(res, this.lngPath)), }; - }); + } + ); if (!!this.requestTimeIntervalMs) { this.canDoRequest = false; diff --git a/src/Widgets/Extensions/Geocoding/views/GeocodingStyle.css b/src/Widgets/Extensions/Geocoding/views/GeocodingStyle.css index 32b53ef05..b627d18dc 100644 --- a/src/Widgets/Extensions/Geocoding/views/GeocodingStyle.css +++ b/src/Widgets/Extensions/Geocoding/views/GeocodingStyle.css @@ -1,3 +1,5 @@ +/** @format */ + #_geocoding_view { position: absolute; z-index: 200; @@ -32,9 +34,17 @@ } @keyframes open { - 0% { width: 0; opacity: 0; } - 20% { width: 0; opacity: 1; } - 100% { width: 300px; } + 0% { + width: 0; + opacity: 0; + } + 20% { + width: 0; + opacity: 1; + } + 100% { + width: 300px; + } } #_geocoding_view_centered { @@ -54,4 +64,4 @@ background-color: rgba(255, 255, 255, 0.5); padding: 5px 10px 5px 10px; border-radius: 10px; -} \ No newline at end of file +} diff --git a/src/Widgets/Extensions/Geocoding/views/GeocodingView.js b/src/Widgets/Extensions/Geocoding/views/GeocodingView.js index e51f5635d..dec63944f 100644 --- a/src/Widgets/Extensions/Geocoding/views/GeocodingView.js +++ b/src/Widgets/Extensions/Geocoding/views/GeocodingView.js @@ -1,13 +1,15 @@ +/** @format */ + import * as THREE from 'three'; import * as itowns from 'itowns'; -import Coordinates from "itowns/lib/Core/Geographic/Coordinates"; +import Coordinates from 'itowns/lib/Core/Geographic/Coordinates'; import proj4 from 'proj4'; //Components -import { ModuleView } from "../../../../Components/ModuleView/ModuleView"; -import { focusCameraOn } from "../../../../Components/Camera/CameraUtils"; +import { ModuleView } from '../../../../Components/ModuleView/ModuleView'; +import { focusCameraOn } from '../../../../Components/Camera/CameraUtils'; -import { GeocodingService } from "../services/GeocodingService"; +import { GeocodingService } from '../services/GeocodingService'; import './GeocodingStyle.css'; export class GeocodingView extends ModuleView { @@ -28,12 +30,15 @@ export class GeocodingView extends ModuleView { // (planarView of iTowns). It is indeed needed in getWorldCoordinates() // to convert the coordinates received from the geocoding service (WGS84) // to this coordinate system. - proj4.defs('EPSG:3946', '+proj=lcc +lat_1=45.25 +lat_2=46.75' + - ' +lat_0=46 +lon_0=3 +x_0=1700000 +y_0=5200000 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs'); + proj4.defs( + 'EPSG:3946', + '+proj=lcc +lat_1=45.25 +lat_2=46.75' + + ' +lat_0=46 +lon_0=3 +x_0=1700000 +y_0=5200000 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs' + ); } get html() { - return /*html*/` + return /*html*/ `
      { this.doGeocoding(); return false; - } + }; } } @@ -73,16 +78,16 @@ export class GeocodingView extends ModuleView { if (this.isCreated) { let div = this.viewElement; let input = this.searchInputElement; - input.style.transition = 'width 0.3s ease-out, opacity 0.4s ease-out' + input.style.transition = 'width 0.3s ease-out, opacity 0.4s ease-out'; input.style.width = '0'; input.style.opacity = '0'; input.ontransitionend = (event) => { - if (event.propertyName === "opacity") { + if (event.propertyName === 'opacity') { div.parentElement.removeChild(div); this.removePins(); resolve(); } - } + }; } else { resolve(); } @@ -100,8 +105,8 @@ export class GeocodingView extends ModuleView { try { let coords = await this.geocodingService.getCoordinates(searchString); - coords.forEach(c => { - let {lat, lng} = c; + coords.forEach((c) => { + let { lat, lng } = c; let i = 0; //step 1 : convert the lat/lng to coordinates used by itowns let targetPos = this.getWorldCoordinates(lat, lng); @@ -132,8 +137,11 @@ export class GeocodingView extends ModuleView { getWorldCoordinates(lat, lng) { const [targetX, targetY] = proj4('EPSG:3946').forward([lng, lat]); const coords = new Coordinates('EPSG:3946', targetX, targetY, 0); - const elevation = itowns.DEMUtils.getElevationValueAt(this.planarView.tileLayer, coords); - const targetZ = (!!elevation) ? elevation : undefined; + const elevation = itowns.DEMUtils.getElevationValueAt( + this.planarView.tileLayer, + coords + ); + const targetZ = !!elevation ? elevation : undefined; return new THREE.Vector3(targetX, targetY, targetZ); } @@ -146,12 +154,12 @@ export class GeocodingView extends ModuleView { async addPin(position) { const pinHeight = 50; const cylGeom = new THREE.CylinderGeometry(1, 8, pinHeight, 8); - const cylMat = new THREE.MeshToonMaterial({color: 0xff0000}); + const cylMat = new THREE.MeshToonMaterial({ color: 0xff0000 }); const cylMesh = new THREE.Mesh(cylGeom, cylMat); position.z += pinHeight / 2; this.addMeshToScene(cylMesh, position); const sphereGeom = new THREE.SphereGeometry(10, 16, 16); - const sphereMat = new THREE.MeshToonMaterial({color: 0xff00000}); + const sphereMat = new THREE.MeshToonMaterial({ color: 0xff00000 }); const sphereMesh = new THREE.Mesh(sphereGeom, sphereMat); position.z += pinHeight / 2; this.addMeshToScene(sphereMesh, position); @@ -277,7 +285,6 @@ export class GeocodingView extends ModuleView { * @override */ async disableView() { - await this.dispose(); } } diff --git a/src/Widgets/GuidedTour/GuidedTour.css b/src/Widgets/GuidedTour/GuidedTour.css index 8e0c4ca70..7939dd539 100644 --- a/src/Widgets/GuidedTour/GuidedTour.css +++ b/src/Widgets/GuidedTour/GuidedTour.css @@ -1,187 +1,187 @@ -#guidedTourTab{ - position: absolute; - margin : 3px; - border: 1px solid black; - background-color: white; - color: black; - height: 30px; - top: 0; - left: 5%; - pointer-events: auto; -} - -#guidedTourWindow{ - position: relative; - text-align: center; - color : black; - height: 100%; - font-size: 14; - pointer-events: none; -} - -#guidedTourTitle{ - display:inline-block; - margin-top: 10px; - color: black; - background-color: ivory; - text-align: center; - font-size: 16px; - font-weight: bold; - overflow: hidden; -} - -#guidedTourStepTitle{ - display:inline-block; - margin-top: 10px; - color: white; - text-align: center; - font-weight: bold; - overflow: hidden; -} - -#guidedTourText1{ - display:inline-block; - margin: 10px; - padding: 5px; - padding-left: 10px; - padding-right: 10px; - line-height: 130%; - /* height adjusted in GuidedTour.js, 45% or 60% */ - height: 45%; - color : black; - background-color: ivory ; - border : 1px solid rgb(90,90,90); - text-align: justify; - overflow: scroll; - pointer-events: auto; -} - -#guidedTourText2{ - display: none; - margin-top: 20px; - margin: 10px; - padding: 5px; - padding-left: 10px; - padding-right: 10px; - line-height: 130%; - height: 20%; - color : black; - background-color: ivory ; - border : 1px solid rgb(90,90,90); - text-align: justify; - overflow: scroll; - pointer-events: auto; -} - -#guidedTourDocTitle{ - display:inline-block; - margin-top: 10px; - color: white; - text-align: center; - font-weight: bold; - overflow: hidden; -} - -#guidedTourDocPreview{ - height: 25%; - display:inline-block; - margin: 5% ; -} - -#guidedTourDocPreviewImg{ - width: 100%; /* or any custom size */ - height: 100%; - object-fit: contain; -} - -#guidedTourStartButton{ - position: absolute; - bottom : 5px; - left: 0; - right: 0; - margin: auto; - border: 1px solid black; - background-color: white; - color: black; - height: 30px; - pointer-events: auto; -} - - -#guidedTourNextTourButton{ - position: absolute; - bottom : 5px; - right: 5px; - margin: auto; - font-size: 30px; - border: 1px solid black; - background-color: white; - color: black; - height: 40px; - pointer-events: auto; -} - -#guidedTourPreviousTourButton{ - position: absolute; - bottom : 5px; - left : 5px; - margin : auto; - font-size: 30px; - border: 1px solid black; - background-color: white; - color: black; - height: 40px; - pointer-events: auto; -} - -#guidedTourNextStepButton{ - position: absolute; - bottom : 5px; - right: 5px; - margin: auto; - font-size: 30px; - border: 1px solid black; - background-color: white; - color: black; - height: 40px; - pointer-events: auto; -} - -#guidedTourPreviousStepButton{ - position: absolute; - bottom : 5px; - left : 5px; - margin : auto; - font-size: 30px; - border: 1px solid black; - background-color: white; - color: black; - height: 40px; - pointer-events: auto; -} - -#guidedTourExitButton{ - position: absolute; - display:none; - bottom : 5px; - left: 0; - right: 0; - margin: auto; - border: 1px solid black; - background-color: white; - color: black; - height: 30px; - pointer-events: auto; -} - -#tourCpt{ - position: absolute; - margin-top: 10px; - color: white; - left : 15px; - bottom : 100px; - font-size: 14px; - font-weight: bold; - overflow: hidden; +/** @format */ +#guidedTourTab { + position: absolute; + margin: 3px; + border: 1px solid black; + background-color: white; + color: black; + height: 30px; + top: 0; + left: 5%; + pointer-events: auto; +} + +#guidedTourWindow { + position: relative; + text-align: center; + color: black; + height: 100%; + font-size: 14; + pointer-events: none; +} + +#guidedTourTitle { + display: inline-block; + margin-top: 10px; + color: black; + background-color: ivory; + text-align: center; + font-size: 16px; + font-weight: bold; + overflow: hidden; +} + +#guidedTourStepTitle { + display: inline-block; + margin-top: 10px; + color: white; + text-align: center; + font-weight: bold; + overflow: hidden; +} + +#guidedTourText1 { + display: inline-block; + margin: 10px; + padding: 5px; + padding-left: 10px; + padding-right: 10px; + line-height: 130%; + /* height adjusted in GuidedTour.js, 45% or 60% */ + height: 45%; + color: black; + background-color: ivory; + border: 1px solid rgb(90, 90, 90); + text-align: justify; + overflow: scroll; + pointer-events: auto; +} + +#guidedTourText2 { + display: none; + margin-top: 20px; + margin: 10px; + padding: 5px; + padding-left: 10px; + padding-right: 10px; + line-height: 130%; + height: 20%; + color: black; + background-color: ivory; + border: 1px solid rgb(90, 90, 90); + text-align: justify; + overflow: scroll; + pointer-events: auto; +} + +#guidedTourDocTitle { + display: inline-block; + margin-top: 10px; + color: white; + text-align: center; + font-weight: bold; + overflow: hidden; +} + +#guidedTourDocPreview { + height: 25%; + display: inline-block; + margin: 5%; +} + +#guidedTourDocPreviewImg { + width: 100%; /* or any custom size */ + height: 100%; + object-fit: contain; +} + +#guidedTourStartButton { + position: absolute; + bottom: 5px; + left: 0; + right: 0; + margin: auto; + border: 1px solid black; + background-color: white; + color: black; + height: 30px; + pointer-events: auto; +} + +#guidedTourNextTourButton { + position: absolute; + bottom: 5px; + right: 5px; + margin: auto; + font-size: 30px; + border: 1px solid black; + background-color: white; + color: black; + height: 40px; + pointer-events: auto; +} + +#guidedTourPreviousTourButton { + position: absolute; + bottom: 5px; + left: 5px; + margin: auto; + font-size: 30px; + border: 1px solid black; + background-color: white; + color: black; + height: 40px; + pointer-events: auto; +} + +#guidedTourNextStepButton { + position: absolute; + bottom: 5px; + right: 5px; + margin: auto; + font-size: 30px; + border: 1px solid black; + background-color: white; + color: black; + height: 40px; + pointer-events: auto; +} + +#guidedTourPreviousStepButton { + position: absolute; + bottom: 5px; + left: 5px; + margin: auto; + font-size: 30px; + border: 1px solid black; + background-color: white; + color: black; + height: 40px; + pointer-events: auto; +} + +#guidedTourExitButton { + position: absolute; + display: none; + bottom: 5px; + left: 0; + right: 0; + margin: auto; + border: 1px solid black; + background-color: white; + color: black; + height: 30px; + pointer-events: auto; +} + +#tourCpt { + position: absolute; + margin-top: 10px; + color: white; + left: 15px; + bottom: 100px; + font-size: 14px; + font-weight: bold; + overflow: hidden; } diff --git a/src/Widgets/GuidedTour/GuidedTour.js b/src/Widgets/GuidedTour/GuidedTour.js index 4698a9f09..de7c14d8b 100644 --- a/src/Widgets/GuidedTour/GuidedTour.js +++ b/src/Widgets/GuidedTour/GuidedTour.js @@ -1,8 +1,10 @@ +/** @format */ + //Components import { Window } from '../../Components/GUI/js/Window'; import '../../Components/GUI/css/window.css'; -import './GuidedTour.css' +import './GuidedTour.css'; /** * Class: GuidedTour @@ -15,9 +17,8 @@ import './GuidedTour.css' * //=============================================================================*/ export class GuidedTour extends Window { - constructor(guidedTourController) { - super('guidedTour', 'Guided Tour', false) + super('guidedTour', 'Guided Tour', false); this.guidedTourController = guidedTourController; this.tourIndex = 1; //current guided tour. Default is 1 (start) @@ -71,13 +72,16 @@ export class GuidedTour extends Window { // hide or show the guided tour window //============================================================================= - toggleGuidedTourWindow(){ - - document.getElementById('guidedTourWindow').style.display = - this.guidedTourWindowIsActive ? "block" : "none"; - this.guidedTourWindowIsActive = this.guidedTourWindowIsActive ? false : true; - - if(this.isStart){ + toggleGuidedTourWindow() { + document.getElementById('guidedTourWindow').style.display = this + .guidedTourWindowIsActive + ? 'block' + : 'none'; + this.guidedTourWindowIsActive = this.guidedTourWindowIsActive + ? false + : true; + + if (this.isStart) { this.startGuidedTourMode(); this.isStart = false; this.guidedTourController.toggleGuidedTourButtons(true); @@ -85,7 +89,7 @@ export class GuidedTour extends Window { } //get all available guided tour from the database - startGuidedTourMode(){ + startGuidedTourMode() { this.guidedTourController.getGuidedTours().then(() => { this.previewTour(); }); @@ -95,85 +99,90 @@ export class GuidedTour extends Window { * Initialize the preview of the guided tour */ //============================================================================= - previewTour(){ - document.getElementById('tourCpt').innerHTML = "Tour: " - + this.tourIndex + " out of " + this.guidedTourController.guidedTours.length; - document.getElementById("guidedTourPreviousTourButton").style.display = "block"; - document.getElementById("guidedTourNextTourButton").style.display = "block"; + previewTour() { + document.getElementById('tourCpt').innerHTML = + 'Tour: ' + + this.tourIndex + + ' out of ' + + this.guidedTourController.guidedTours.length; + document.getElementById('guidedTourPreviousTourButton').style.display = + 'block'; + document.getElementById('guidedTourNextTourButton').style.display = 'block'; // for the demo, until we have more than one finished guided tour // we can prevent user from changing tour by hiding the buttons - if(this.guidedTourController.preventUserFromChangingTour){ - document.getElementById("guidedTourPreviousTourButton").style.display = "none"; - document.getElementById("guidedTourNextTourButton").style.display = "none"; + if (this.guidedTourController.preventUserFromChangingTour) { + document.getElementById('guidedTourPreviousTourButton').style.display = + 'none'; + document.getElementById('guidedTourNextTourButton').style.display = + 'none'; } - document.getElementById("guidedTourPreviousStepButton").style.display = "none"; - document.getElementById("guidedTourNextStepButton").style.display = "none"; - document.getElementById("guidedTourExitButton").style.display = "none"; + document.getElementById('guidedTourPreviousStepButton').style.display = + 'none'; + document.getElementById('guidedTourNextStepButton').style.display = 'none'; + document.getElementById('guidedTourExitButton').style.display = 'none'; //document.getElementById("guidedTourText2").style.display = "none"; - document.getElementById("guidedTourStartButton").style.display = "block"; + document.getElementById('guidedTourStartButton').style.display = 'block'; let currentTour = this.guidedTourController.getCurrentTour(); - document.getElementById('guidedTourTitle').innerHTML = - currentTour ? currentTour.name - : 'No guided tour'; - document.getElementById('guidedTourText1').innerHTML = - currentTour ? currentTour.description - : 'Please add guided tours'; - document.getElementById("guidedTourText1").style.height = "45%"; - document.getElementById("guidedTourStepTitle").innerHTML = null; - + document.getElementById('guidedTourTitle').innerHTML = currentTour + ? currentTour.name + : 'No guided tour'; + document.getElementById('guidedTourText1').innerHTML = currentTour + ? currentTour.description + : 'Please add guided tours'; + document.getElementById('guidedTourText1').style.height = '45%'; + document.getElementById('guidedTourStepTitle').innerHTML = null; } - // update step with current step data //============================================================================= - updateStep(){ - + updateStep() { this.currentStep = this.guidedTourController.getCurrentStep(); this.documentBrowser.currentMetadata = - this.guidedTourController.getCurrentStep().document; - this.documentBrowser.currentDoc = this.guidedTourController.getCurrentStep().document; + this.guidedTourController.getCurrentStep().document; + this.documentBrowser.currentDoc = + this.guidedTourController.getCurrentStep().document; this.documentBrowser.updateBrowser(); - document.getElementById("guidedTourText1").innerHTML = this.currentStep.text1; - document.getElementById('guidedTourStepTitle').innerHTML = this.currentStep.title; + document.getElementById('guidedTourText1').innerHTML = + this.currentStep.text1; + document.getElementById('guidedTourStepTitle').innerHTML = + this.currentStep.title; this.documentBrowser.focusOnDoc(); } //start guided tour //============================================================================= - startGuidedTour(){ - - if(this.guidedTourController.getCurrentTour().extendedDocs.length > 0){ + startGuidedTour() { + if (this.guidedTourController.getCurrentTour().extendedDocs.length > 0) { this.tourIndex = 1; this.stepIndex = 1; this.updateStep(); // setup the display (hide & show elements) this.guidedTourController.toggleGuidedTourButtons(false); - document.getElementById("guidedTourDocPreviewImg").style.display = "none"; - document.getElementById("guidedTourText1").style.height = "60%"; - document.getElementById('tourCpt').style.display = "none"; - } - else { + document.getElementById('guidedTourDocPreviewImg').style.display = 'none'; + document.getElementById('guidedTourText1').style.height = '60%'; + document.getElementById('tourCpt').style.display = 'none'; + } else { alert('This guided tour is empty'); //should never happen. If a guided tour - //doesn't have steps, then it is not a guided tour + //doesn't have steps, then it is not a guided tour } - }; + } // Quit current guided tour //============================================================================= - exitGuidedTour(){ - this.guidedTourController.reset(); - }; + exitGuidedTour() { + this.guidedTourController.reset(); + } /** * Update guided tour preview by clicking on "guidedTourNextTourButton" button */ //============================================================================= - nextTour(){ - if(this.tourIndex < this.guidedTourController.guidedTours.length){ + nextTour() { + if (this.tourIndex < this.guidedTourController.guidedTours.length) { this.guidedTourController.getNextTour(); - this.tourIndex ++; + this.tourIndex++; this.previewTour(); } } @@ -182,10 +191,10 @@ export class GuidedTour extends Window { * Update guided tour preview by clicking on "guidedTourPreviousTourButton" button */ //============================================================================= - previousTour(){ + previousTour() { this.guidedTourController.getPreviousTour(); - if(this.tourIndex > 1 ){ - this.tourIndex --; + if (this.tourIndex > 1) { + this.tourIndex--; } this.previewTour(); } @@ -194,43 +203,48 @@ export class GuidedTour extends Window { * Update step by clicking on "guidedTourNextStepButton" button */ //============================================================================= - nextStep(){ - - if(this.stepIndex < this.guidedTourController.getCurrentTour().extendedDocs.length ){ - this.stepIndex ++; + nextStep() { + if ( + this.stepIndex < + this.guidedTourController.getCurrentTour().extendedDocs.length + ) { + this.stepIndex++; this.guidedTourController.getNextStep(); - this.updateStep(); + this.updateStep(); } - } /** * Update step by clicking on "guidedTourPreviousStepButton" button */ //============================================================================= - previousStep(){ - - if( this.stepIndex > 1 ){ + previousStep() { + if (this.stepIndex > 1) { this.guidedTourController.getPreviousStep(); - this.stepIndex --; + this.stepIndex--; this.updateStep(); } } // event listeners (buttons) initializeButtons() { - document.getElementById("guidedTourNextTourButton").addEventListener('mousedown', - this.nextTour.bind(this),false); - document.getElementById("guidedTourPreviousTourButton").addEventListener('mousedown', - this.previousTour.bind(this),false); - document.getElementById("guidedTourStartButton").addEventListener('mousedown', - this.startGuidedTour.bind(this),false); - document.getElementById("guidedTourNextStepButton").addEventListener('mousedown', - this.nextStep.bind(this),false); - document.getElementById("guidedTourPreviousStepButton").addEventListener('mousedown', - this.previousStep.bind(this),false); - document.getElementById("guidedTourExitButton").addEventListener('mousedown', - this.exitGuidedTour.bind(this),false); + document + .getElementById('guidedTourNextTourButton') + .addEventListener('mousedown', this.nextTour.bind(this), false); + document + .getElementById('guidedTourPreviousTourButton') + .addEventListener('mousedown', this.previousTour.bind(this), false); + document + .getElementById('guidedTourStartButton') + .addEventListener('mousedown', this.startGuidedTour.bind(this), false); + document + .getElementById('guidedTourNextStepButton') + .addEventListener('mousedown', this.nextStep.bind(this), false); + document + .getElementById('guidedTourPreviousStepButton') + .addEventListener('mousedown', this.previousStep.bind(this), false); + document + .getElementById('guidedTourExitButton') + .addEventListener('mousedown', this.exitGuidedTour.bind(this), false); } - } diff --git a/src/Widgets/GuidedTour/GuidedTourController.js b/src/Widgets/GuidedTour/GuidedTourController.js index b0fed6c47..2f2be96d7 100644 --- a/src/Widgets/GuidedTour/GuidedTourController.js +++ b/src/Widgets/GuidedTour/GuidedTourController.js @@ -1,20 +1,22 @@ +/** @format */ + //Components import { ModuleView } from '../../Components/ModuleView/ModuleView'; -import { RequestService } from "../../Components/Request/RequestService"; +import { RequestService } from '../../Components/Request/RequestService'; import './GuidedTour.css'; import { GuidedTour } from './GuidedTour.js'; import { DocumentModule } from '../Documents/DocumentModule'; /** -* Class: GuidedTourController -* Description : -* The GuidedTourController is an object handling the view, interracting with the -* server to get information and data (guided tours) -* It handles the display of guided tours in the guided tour window, and all the -* functionalities related to the guided tour (start, exit, next, previous...) -* GuidedTours are made of steps with properties : index, document, text1 and text2. -*/ + * Class: GuidedTourController + * Description : + * The GuidedTourController is an object handling the view, interracting with the + * server to get information and data (guided tours) + * It handles the display of guided tours in the guided tour window, and all the + * functionalities related to the guided tour (start, exit, next, previous...) + * GuidedTours are made of steps with properties : index, document, text1 and text2. + */ export class GuidedTourController extends ModuleView { /** * Constructor for GuidedTourController @@ -37,7 +39,7 @@ export class GuidedTourController extends ModuleView { constructor(documentModule, requestService, config) { super(); - this.guidedTourContainerId = "guidedTourContainer"; + this.guidedTourContainerId = 'guidedTourContainer'; this.documentModule = documentModule; //instance of DocumentModule @@ -65,8 +67,8 @@ export class GuidedTourController extends ModuleView { } /** - * initialize the controller - */ + * initialize the controller + */ //============================================================================= initialize() { this.guidedTour = new GuidedTour(this); @@ -76,11 +78,11 @@ export class GuidedTourController extends ModuleView { } /** - * Get all guided tour from a database */ + * Get all guided tour from a database */ //============================================================================= async getGuidedTours() { let req = await this.requestService.request('GET', this.url, { - authenticate: false + authenticate: false, }); this.guidedTours = JSON.parse(req.responseText); } @@ -92,8 +94,7 @@ export class GuidedTourController extends ModuleView { getCurrentTour() { if (this.guidedTours.length != 0) { return this.guidedTours[this.currentTourIndex]; - } - else { + } else { return null; } } @@ -107,7 +108,7 @@ export class GuidedTourController extends ModuleView { this.currentTourIndex++; } return this.getCurrentTour(); - }; + } /** * Sets the current guided tour to the previous guided tour and returns it. @@ -118,25 +119,24 @@ export class GuidedTourController extends ModuleView { this.currentTourIndex--; } return this.getCurrentTour(); - }; + } /** - * Returns the current tour step - */ + * Returns the current tour step + */ //============================================================================= getCurrentStep() { if (this.getCurrentTour().length != 0) { var steps = this.getCurrentTour().extendedDocs; return steps[this.currentStepIndex]; - } - else { + } else { return null; } } /** - * Sets the current step to the previous step and returns it. - */ + * Sets the current step to the previous step and returns it. + */ //============================================================================= getPreviousStep() { if (this.currentStepIndex > 0) { @@ -146,8 +146,8 @@ export class GuidedTourController extends ModuleView { } /** - * Sets the current step to the next step and returns it. - */ + * Sets the current step to the next step and returns it. + */ //============================================================================= getNextStep() { if (this.currentStepIndex < this.getCurrentTour().extendedDocs.length) { @@ -156,10 +156,9 @@ export class GuidedTourController extends ModuleView { return this.getCurrentStep(); } - /** - * Reset browser at the begining of the guided tours - */ + * Reset browser at the begining of the guided tours + */ //============================================================================= reset() { this.currentStepIndex = 0; @@ -167,19 +166,27 @@ export class GuidedTourController extends ModuleView { this.currentGuidedTour = this.guidedTours[this.currentTourIndex]; this.guidedTour.currentStep = this.getCurrentStep(); this.guidedTour.previewTour(); - } //Hide or show previous / next buttons in browser window //============================================================================= toggleGuidedTourButtons(active) { - document.getElementById("guidedTourPreviousTourButton").style.display = active ? "block" : "none"; - document.getElementById("guidedTourNextTourButton").style.display = active ? "block" : "none"; - document.getElementById("guidedTourPreviousStepButton").style.display = active ? "none" : "block"; - document.getElementById("guidedTourNextStepButton").style.display = active ? "none" : "block"; - document.getElementById('guidedTourStartButton').style.display = active ? "block" : "none"; - document.getElementById("guidedTourExitButton").style.display = active ? "none" : "block"; - + document.getElementById('guidedTourPreviousTourButton').style.display = + active ? 'block' : 'none'; + document.getElementById('guidedTourNextTourButton').style.display = active + ? 'block' + : 'none'; + document.getElementById('guidedTourPreviousStepButton').style.display = + active ? 'none' : 'block'; + document.getElementById('guidedTourNextStepButton').style.display = active + ? 'none' + : 'block'; + document.getElementById('guidedTourStartButton').style.display = active + ? 'block' + : 'none'; + document.getElementById('guidedTourExitButton').style.display = active + ? 'none' + : 'block'; } /////// MODULE MANAGEMENT FOR BASE DEMO @@ -191,5 +198,4 @@ export class GuidedTourController extends ModuleView { disableView() { this.guidedTour.dispose(); } - } diff --git a/src/Widgets/LayerChoice/views/LayerChoice.js b/src/Widgets/LayerChoice/views/LayerChoice.js index ef77d48be..6467deeb0 100644 --- a/src/Widgets/LayerChoice/views/LayerChoice.js +++ b/src/Widgets/LayerChoice/views/LayerChoice.js @@ -1,24 +1,26 @@ +/** @format */ + //Components -import { Window } from "../../../Components/GUI/js/Window"; -import { LayerManager } from "../../../Components/LayerManager/LayerManager"; +import { Window } from '../../../Components/GUI/js/Window'; +import { LayerManager } from '../../../Components/LayerManager/LayerManager'; export class LayerChoice extends Window { /** - * Creates the layer choice windows - * - * @param {LayerManager} layerManager + * Creates the layer choice windows + * + * @param {LayerManager} layerManager */ constructor(layerManager) { super('layer_choice', 'Layer', false); - /** + /** * the layerManager */ this.layerManager = layerManager; } get innerContentHtml() { - return /*html*/` + return /*html*/ `
      @@ -61,20 +63,31 @@ export class LayerChoice extends Window { let layers = this.layerManager.getColorLayers(); for (let i = 0; i < layers.length; i++) { let item = document.createElement('div'); - item.innerHTML = ` - Visible
      + item.innerHTML = ` + Visible
      - Opacity : ${layers[i].opacity} + Opacity : ${ + layers[i].opacity + }
      `; item.oninput = (event) => { - if (event.srcElement.id === "checkbox_" + i) { + if (event.srcElement.id === 'checkbox_' + i) { layers[i].visible = event.srcElement.checked; } - if (event.srcElement.id === "range_" + i) { - this.layerManager.updateOpacity(layers[i], event.srcElement.valueAsNumber); + if (event.srcElement.id === 'range_' + i) { + this.layerManager.updateOpacity( + layers[i], + event.srcElement.valueAsNumber + ); } - let span_opacity = document.getElementById("color_value_opacity_" + i); + let span_opacity = document.getElementById('color_value_opacity_' + i); span_opacity.innerHTML = `${layers[i].opacity}`; this.layerManager.notifyChange(); }; @@ -93,9 +106,14 @@ export class LayerChoice extends Window { Scale : ${layers[i].scale} `; item.oninput = (event) => { - this.layerManager.updateScale(layers[i], event.srcElement.valueAsNumber); + this.layerManager.updateScale( + layers[i], + event.srcElement.valueAsNumber + ); this.layerManager.notifyChange(); - let span_elevation = document.getElementById("elevation_value_scale_" + i); + let span_elevation = document.getElementById( + 'elevation_value_scale_' + i + ); span_elevation.innerHTML = `${layers[i].scale}`; }; list.appendChild(item); @@ -110,7 +128,9 @@ export class LayerChoice extends Window { let div = document.createElement('div'); div.innerHTML = ` - All Visible
      + All Visible
      `; div.onchange = (event) => { this.layerManager.changeVisibility(event.srcElement.checked); @@ -119,27 +139,46 @@ export class LayerChoice extends Window { list.append(div); for (let i = 0; i < layers.length; i++) { let item = document.createElement('div'); - item.innerHTML = ` - + item.innerHTML = ` +
      - Visible
      + Visible
      - Opacity : ${layers[i].opacity} + Opacity : ${ + layers[i].opacity + }
      `; item.oninput = (event) => { - if (event.srcElement.id === "checkbox_" + i) { + if (event.srcElement.id === 'checkbox_' + i) { layers[i].visible = event.srcElement.checked; } - if (event.srcElement.id === "range_" + i) { - this.layerManager.updateOpacity(layers[i], event.srcElement.valueAsNumber); + if (event.srcElement.id === 'range_' + i) { + this.layerManager.updateOpacity( + layers[i], + event.srcElement.valueAsNumber + ); } - let div_visible = document.getElementById("visible_" + i); - div_visible.innerHTML = `Visible
      `; - let span_opacity = document.getElementById("geometry_value_opacity_" + i); + let div_visible = document.getElementById('visible_' + i); + div_visible.innerHTML = `Visible
      `; + let span_opacity = document.getElementById( + 'geometry_value_opacity_' + i + ); span_opacity.innerHTML = `${layers[i].opacity}`; this.layerManager.notifyChange(); }; @@ -179,4 +218,4 @@ export class LayerChoice extends Window { get geometryLayerListElement() { return document.getElementById(this.geometryLayersId); } -} \ No newline at end of file +} diff --git a/src/Widgets/Links/LinkModule.js b/src/Widgets/Links/LinkModule.js index 001d55426..7950cecfb 100644 --- a/src/Widgets/Links/LinkModule.js +++ b/src/Widgets/Links/LinkModule.js @@ -1,12 +1,14 @@ +/** @format */ + //Components -import { RequestService } from "../../Components/Request/RequestService"; -import { Window } from "../../Components/GUI/js/Window"; +import { RequestService } from '../../Components/Request/RequestService'; +import { Window } from '../../Components/GUI/js/Window'; -import { LinkService } from "./Model/LinkService"; -import { DocumentModule } from "../Documents/DocumentModule"; -import { CityObjectModule } from "../CityObjects/CityObjectModule"; -import { LinkView } from "./View/LinkView"; -import { LinkProvider } from "./ViewModel/LinkProvider"; +import { LinkService } from './Model/LinkService'; +import { DocumentModule } from '../Documents/DocumentModule'; +import { CityObjectModule } from '../CityObjects/CityObjectModule'; +import { LinkView } from './View/LinkView'; +import { LinkProvider } from './ViewModel/LinkProvider'; /** * Manages the links between the city objects and the documents. This modules @@ -16,7 +18,7 @@ import { LinkProvider } from "./ViewModel/LinkProvider"; export class LinkModule { /** * Creates the link module. - * + * * @param {DocumentModule} documentModule The document module. * @param {CityObjectModule} cityObjectModule The city objects module. * @param {RequestService} requestService The request service. @@ -27,33 +29,51 @@ export class LinkModule { * @param {string} config.server.url The server URL. * @param {string} config.server.link The link route. */ - constructor(documentModule, cityObjectModule, requestService, itownsView, - cameraControls, config) { + constructor( + documentModule, + cityObjectModule, + requestService, + itownsView, + cameraControls, + config + ) { /** * The link service. - * + * * @type {LinkService} */ this.service = new LinkService(requestService, config); /** * The link provider. - * + * * @type {LinkProvider} */ - this.provider = new LinkProvider(documentModule.provider, cityObjectModule.provider, this.service, config); + this.provider = new LinkProvider( + documentModule.provider, + cityObjectModule.provider, + this.service, + config + ); this.provider.fetchLinks().then(() => { - this.view = new LinkView(documentModule, cityObjectModule, this.provider, - itownsView, cameraControls); + this.view = new LinkView( + documentModule, + cityObjectModule, + this.provider, + itownsView, + cameraControls + ); }); documentModule.view.addEventListener(Window.EVENT_DISABLED, () => { if (!cityObjectModule.provider.getLayer()) { return; } - if (cityObjectModule.provider.getLayer().filter.label === 'linkDisplayedDoc') { + if ( + cityObjectModule.provider.getLayer().filter.label === 'linkDisplayedDoc' + ) { cityObjectModule.provider.removeLayer(); } }); } -} \ No newline at end of file +} diff --git a/src/Widgets/Links/Model/Link.js b/src/Widgets/Links/Model/Link.js index 853d22c7f..59fea25b4 100644 --- a/src/Widgets/Links/Model/Link.js +++ b/src/Widgets/Links/Model/Link.js @@ -1,7 +1,10 @@ /** * Represents a link between a document and a target (in this example, the * only valid target types are city objects). + * + * @format */ + export class Link { /** * Constructs an empty link. @@ -9,21 +12,21 @@ export class Link { constructor() { /** * The ID of the link. - * + * * @type {number} */ this.id; /** * The source (document) ID. - * + * * @type {number} */ this.source_id; /** * The target ID. For the moment, the only targets are city objects. - * + * * @type {number} */ this.target_id; @@ -31,7 +34,7 @@ export class Link { /** * The X coordinate of the centroid. The centroid must be stored in the * in order to travel to the city object. - * + * * @type {number} */ this.centroid_x; @@ -39,7 +42,7 @@ export class Link { /** * The Y coordinate of the centroid. The centroid must be stored in the * in order to travel to the city object. - * + * * @type {number} */ this.centroid_y; @@ -47,9 +50,9 @@ export class Link { /** * The Z coordinate of the centroid. The centroid must be stored in the * in order to travel to the city object. - * + * * @type {number} */ this.centroid_z; } -} \ No newline at end of file +} diff --git a/src/Widgets/Links/Model/LinkService.js b/src/Widgets/Links/Model/LinkService.js index 8d188002b..b5bf88025 100644 --- a/src/Widgets/Links/Model/LinkService.js +++ b/src/Widgets/Links/Model/LinkService.js @@ -1,7 +1,9 @@ +/** @format */ + //Components -import { RequestService } from "../../../Components/Request/RequestService"; +import { RequestService } from '../../../Components/Request/RequestService'; -import { Link } from "./Link"; +import { Link } from './Link'; /** * This class is used to perform requests concerning links. @@ -9,7 +11,7 @@ import { Link } from "./Link"; export class LinkService { /** * Creates a link service Service. - * + * * @param {RequestService} requestService The request service. * @param {object} config The UD-Viz config. * @param {object} config.server The server configuration. @@ -23,22 +25,22 @@ export class LinkService { this.requestService = requestService; /** - * GET url to retrieve supported link types. - * GET url/ to retrieve links of this type. - * POST url/ to create a link of this type. + * GET url to retrieve supported link types. + * GET url/ to retrieve links of this type. + * POST url/ to create a link of this type. */ this.linkURL = `${config.server.url}${config.server.link}`; } /** * Return supported link types. - * + * * @returns {Promise>} An array containing the supported link * types. */ async getSupportedLinkTypes() { let req = await this.requestService.request('GET', this.linkURL, { - authenticate: false + authenticate: false, }); let types = JSON.parse(req.response); return types; @@ -46,19 +48,19 @@ export class LinkService { /** * Retrieves all links matching the given link type and filters. - * + * * @param {string} linkType A supported link type. * @param {FormData} [filters] Filtering criteria for the link. Possible filters * are `source_id` (which must be a document id) and `target_id` (an ID of * type `linkType`). - * + * * @returns {Promise>} An array of links. */ async getLinks(linkType, filters = null) { const url = `${this.linkURL}/${linkType}`; let req = await this.requestService.request('GET', url, { authenticate: false, - urlParameters: filters + urlParameters: filters, }); let links = JSON.parse(req.response); return links; @@ -66,7 +68,7 @@ export class LinkService { /** * Creates a new link with the given type. - * + * * @param {string} linkType A supported link type. * @param {FormData} formData Properties of the created link. It must include * `source_id` (the document id) and `target_id` (ID of the target of type @@ -76,7 +78,7 @@ export class LinkService { const url = `${this.linkURL}/${linkType}`; let req = await this.requestService.request('POST', url, { authenticate: false, - body: formData + body: formData, }); let created = JSON.parse(req.response); return created; @@ -84,14 +86,14 @@ export class LinkService { /** * Deletes a link of the given type with the given ID. - * + * * @param {string} linkType A supported link type. * @param {number} linkId ID of the link to delete. */ async deleteLink(linkType, linkId) { const url = `${this.linkURL}/${linkType}/${linkId}`; let req = await this.requestService.request('DELETE', url, { - authenticate: false + authenticate: false, }); let deleted = JSON.parse(req.response); return deleted; diff --git a/src/Widgets/Links/View/CityObjectLinkInterface.js b/src/Widgets/Links/View/CityObjectLinkInterface.js index b7542b7af..12d9ca96a 100644 --- a/src/Widgets/Links/View/CityObjectLinkInterface.js +++ b/src/Widgets/Links/View/CityObjectLinkInterface.js @@ -1,9 +1,11 @@ -import { LinkService } from "../Model/LinkService"; -import { CityObjectModule } from "../../CityObjects/CityObjectModule"; -import { CityObjectFilterSelector } from "../../CityObjects/View/CityObjectFilterSelector"; -import { LinkProvider } from "../ViewModel/LinkProvider"; -import { CityObjectProvider } from "../../CityObjects/ViewModel/CityObjectProvider"; -import { LinkView } from "./LinkView"; +/** @format */ + +import { LinkService } from '../Model/LinkService'; +import { CityObjectModule } from '../../CityObjects/CityObjectModule'; +import { CityObjectFilterSelector } from '../../CityObjects/View/CityObjectFilterSelector'; +import { LinkProvider } from '../ViewModel/LinkProvider'; +import { CityObjectProvider } from '../../CityObjects/ViewModel/CityObjectProvider'; +import { LinkView } from './LinkView'; /** * The interface extensions for the city object window. @@ -11,7 +13,7 @@ import { LinkView } from "./LinkView"; export class CityObjectLinkInterface { /** * Constructs the city object link interface. - * + * * @param {LinkView} linkView The link view. * @param {CityObjectModule} cityObjectModule The city object module. * @param {LinkProvider} linkProvider The link service. @@ -28,7 +30,7 @@ export class CityObjectLinkInterface { // to show them in the document navigator. cityObjectModule.addExtension('links', { type: 'div', - html: /*html*/` + html: /*html*/ `
      @@ -39,18 +41,20 @@ export class CityObjectLinkInterface { linkView.requestDisplayDocuments(); linkProvider.toggleLinkedDocumentsFilter(true); }; - } + }, }); /** * The link provider. - * + * * @type {LinkProvider} */ this.linkProvider = linkProvider; - this.linkProvider.addEventListener(CityObjectProvider.EVENT_CITY_OBJECT_SELECTED, - () => this._updateLinkList()); + this.linkProvider.addEventListener( + CityObjectProvider.EVENT_CITY_OBJECT_SELECTED, + () => this._updateLinkList() + ); } /** @@ -61,7 +65,7 @@ export class CityObjectLinkInterface { return; } let docs = this.linkProvider.getSelectedCityObjectLinkedDocuments(); - let listHtml = `

      ${docs.length} linked document(s)

      ` + let listHtml = `

      ${docs.length} linked document(s)

      `; if (docs.length > 0) { listHtml += `

        `; for (let doc of docs) { @@ -99,7 +103,7 @@ export class CityObjectLinkInterface { export class LinkCountFilterSelector extends CityObjectFilterSelector { /** * Creates the filter selector. - * + * * @param {LinkProvider} linkProvider The link provider. */ constructor(linkProvider) { @@ -112,7 +116,7 @@ export class LinkCountFilterSelector extends CityObjectFilterSelector { } get html() { - return /*html*/` + return /*html*/ ` `; @@ -121,4 +125,4 @@ export class LinkCountFilterSelector extends CityObjectFilterSelector { onSubmit(formData) { this.filter.requiredCount = Number(formData.get('requiredCount')) || 1; } -} \ No newline at end of file +} diff --git a/src/Widgets/Links/View/DocumentLinkInterface.js b/src/Widgets/Links/View/DocumentLinkInterface.js index 5a699d2f2..d3baac9ad 100644 --- a/src/Widgets/Links/View/DocumentLinkInterface.js +++ b/src/Widgets/Links/View/DocumentLinkInterface.js @@ -1,11 +1,13 @@ +/** @format */ + //Components -import { focusCameraOn } from "../../../Components/Camera/CameraUtils"; +import { focusCameraOn } from '../../../Components/Camera/CameraUtils'; -import { DocumentModule } from "../../Documents/DocumentModule"; +import { DocumentModule } from '../../Documents/DocumentModule'; import * as THREE from 'three'; -import { DocumentProvider } from "../../Documents/ViewModel/DocumentProvider"; -import { Link } from "../Model/Link"; -import { LinkProvider } from "../ViewModel/LinkProvider"; +import { DocumentProvider } from '../../Documents/ViewModel/DocumentProvider'; +import { Link } from '../Model/Link'; +import { LinkProvider } from '../ViewModel/LinkProvider'; /** * The interface extensions for the document windows. @@ -13,7 +15,7 @@ import { LinkProvider } from "../ViewModel/LinkProvider"; export class DocumentLinkInterface { /** * Constructs the document link interface. - * + * * @param {DocumentModule} documentModule The document module. * @param {LinkProvider} linkProvider The link provider. * @param {*} itownsView The iTowns view. @@ -22,14 +24,14 @@ export class DocumentLinkInterface { constructor(documentModule, linkProvider, itownsView, cameraControls) { /** * The link provider. - * + * * @type {LinkProvider} */ this.provider = linkProvider; /** * The list of links for the currently displayed document. - * + * * @type {Array} */ this.documentLinks = []; @@ -38,18 +40,18 @@ export class DocumentLinkInterface { * The itowns view. */ this.itownsView = itownsView; - + /** * The planar camera controls. */ this.cameraControls = cameraControls; // Adds the extension for the displayed documents. This extension shows the - // links and adds two buttons to highlight the linked city objects, and + // links and adds two buttons to highlight the linked city objects, and // create a new link. documentModule.addInspectorExtension('links', { type: 'div', - html: /*html*/` + html: /*html*/ `
        @@ -59,7 +61,7 @@ export class DocumentLinkInterface {
        `, - oncreated: () => this._init() + oncreated: () => this._init(), }); // Adds an extension in the navigator window to show the status of the @@ -68,18 +70,23 @@ export class DocumentLinkInterface { documentModule.addNavigatorExtension('linkFilter', { type: 'div', container: 'filter', - html: /*html*/` + html: /*html*/ ` `, oncreated: () => { - this.linkFilterElement.onchange = () => this.provider.toggleLinkedDocumentsFilter(); - } + this.linkFilterElement.onchange = () => + this.provider.toggleLinkedDocumentsFilter(); + }, }); - linkProvider.addEventListener(DocumentProvider.EVENT_FILTERED_DOCS_UPDATED, - () => this._updateLinkFilter()); + linkProvider.addEventListener( + DocumentProvider.EVENT_FILTERED_DOCS_UPDATED, + () => this._updateLinkFilter() + ); - linkProvider.addEventListener(DocumentProvider.EVENT_DISPLAYED_DOC_CHANGED, - () => this._updateLinkList()); + linkProvider.addEventListener( + DocumentProvider.EVENT_DISPLAYED_DOC_CHANGED, + () => this._updateLinkList() + ); } /** @@ -95,11 +102,16 @@ export class DocumentLinkInterface { if (!!this.provider.selectedCityObject) { let newLink = new Link(); newLink.source_id = this.provider.displayedDocument.id; - newLink.target_id = this.provider.selectedCityObject.props['cityobject.database_id']; + newLink.target_id = + this.provider.selectedCityObject.props['cityobject.database_id']; newLink.centroid_x = this.provider.selectedCityObject.centroid.x; newLink.centroid_y = this.provider.selectedCityObject.centroid.y; newLink.centroid_z = this.provider.selectedCityObject.centroid.z; - if (confirm('Are you sure you want to associate the document with this city object ?')) { + if ( + confirm( + 'Are you sure you want to associate the document with this city object ?' + ) + ) { try { await this.provider.createLink(newLink); } catch (e) { @@ -145,10 +157,14 @@ export class DocumentLinkInterface { for (let link of links) { newDivHtml += `
      • ID : ${link.target_id} - + travel - + delete
      • `; @@ -167,25 +183,28 @@ export class DocumentLinkInterface { } } - //////////////////// ///// LINK OPERATION /** * If the target is a city object, moves the camera to focus on its centroid. - * + * * @param {Link} link The link to travel to. */ async _travelToLink(link) { - let centroid = new THREE.Vector3(link.centroid_x, link.centroid_y, - link.centroid_z); - await focusCameraOn(this.itownsView, this.cameraControls, centroid, - {duration: 1}); + let centroid = new THREE.Vector3( + link.centroid_x, + link.centroid_y, + link.centroid_z + ); + await focusCameraOn(this.itownsView, this.cameraControls, centroid, { + duration: 1, + }); } /** * Deletes the link. - * + * * @param {Link} link The link to delete. */ async _deleteLink(link) { diff --git a/src/Widgets/Links/View/LinkView.js b/src/Widgets/Links/View/LinkView.js index 803be9b8b..57b9aaa17 100644 --- a/src/Widgets/Links/View/LinkView.js +++ b/src/Widgets/Links/View/LinkView.js @@ -1,12 +1,14 @@ -import { DocumentModule } from "../../Documents/DocumentModule"; -import { CityObjectModule } from "../../CityObjects/CityObjectModule"; -import { LinkService } from "../Model/LinkService"; -import { DocumentLinkInterface } from "./DocumentLinkInterface"; -import { CityObjectLinkInterface } from "./CityObjectLinkInterface"; -import { DocumentInspectorWindow } from "../../Documents/View/DocumentInspectorWindow"; -import { LinkProvider } from "../ViewModel/LinkProvider"; -import { DocumentView } from "../../Documents/View/DocumentView"; -import { CityObjectWindow } from "../../CityObjects/View/CityObjectWindow"; +/** @format */ + +import { DocumentModule } from '../../Documents/DocumentModule'; +import { CityObjectModule } from '../../CityObjects/CityObjectModule'; +import { LinkService } from '../Model/LinkService'; +import { DocumentLinkInterface } from './DocumentLinkInterface'; +import { CityObjectLinkInterface } from './CityObjectLinkInterface'; +import { DocumentInspectorWindow } from '../../Documents/View/DocumentInspectorWindow'; +import { LinkProvider } from '../ViewModel/LinkProvider'; +import { DocumentView } from '../../Documents/View/DocumentView'; +import { CityObjectWindow } from '../../CityObjects/View/CityObjectWindow'; /** * Represents the visual interface of the link module. This class contains @@ -16,45 +18,56 @@ import { CityObjectWindow } from "../../CityObjects/View/CityObjectWindow"; export class LinkView { /** * Constructs the link view. - * + * * @param {DocumentModule} documentModule The document module. * @param {CityObjectModule} cityObjectModule The city object module. * @param {LinkProvider} linkProvider The link service. * @param {*} itownsView The iTowns view. - * @param {*} cameraControls The planar camera controls + * @param {*} cameraControls The planar camera controls */ - constructor(documentModule, cityObjectModule, linkProvider, itownsView, - cameraControls) { - + constructor( + documentModule, + cityObjectModule, + linkProvider, + itownsView, + cameraControls + ) { /** * A reference to the document view. - * + * * @type {DocumentView} */ this.documentView = documentModule.view; /** * A reference to the city object window. - * + * * @type {CityObjectWindow} */ this.cityObjectView = cityObjectModule.view; /** * The interface extensions for the document module. - * + * * @type {DocumentLinkInterface} */ - this.documentInterface = new DocumentLinkInterface(documentModule, - linkProvider, itownsView, cameraControls); + this.documentInterface = new DocumentLinkInterface( + documentModule, + linkProvider, + itownsView, + cameraControls + ); /** * The interface extensions for the city object module. - * + * * @type {CityObjectLinkInterface} */ - this.cityObjectInterface = new CityObjectLinkInterface(this, - cityObjectModule, linkProvider); + this.cityObjectInterface = new CityObjectLinkInterface( + this, + cityObjectModule, + linkProvider + ); } /** @@ -70,4 +83,4 @@ export class LinkView { requestDisplayCityObjects() { this.cityObjectView.enable(); } -} \ No newline at end of file +} diff --git a/src/Widgets/Links/ViewModel/CityObjectLinkFilters.js b/src/Widgets/Links/ViewModel/CityObjectLinkFilters.js index 0aa4a7ac3..37aaf115d 100644 --- a/src/Widgets/Links/ViewModel/CityObjectLinkFilters.js +++ b/src/Widgets/Links/ViewModel/CityObjectLinkFilters.js @@ -1,8 +1,10 @@ +/** @format */ + //Components -import { CityObject } from "../../../Components/3DTiles/Model/CityObject"; +import { CityObject } from '../../../Components/3DTiles/Model/CityObject'; -import { CityObjectFilter } from "../../CityObjects/ViewModel/CityObjectFilter"; -import { LinkProvider } from "./LinkProvider"; +import { CityObjectFilter } from '../../CityObjects/ViewModel/CityObjectFilter'; +import { LinkProvider } from './LinkProvider'; /** * A filter for city objects based how many documents are linked to them. @@ -10,7 +12,7 @@ import { LinkProvider } from "./LinkProvider"; export class LinkCountFilter extends CityObjectFilter { /** * Instantiates the filter. - * + * * @param {LinkProvider} linkProvider The link provider. */ constructor(linkProvider) { @@ -23,7 +25,7 @@ export class LinkCountFilter extends CityObjectFilter { /** * The link provider - * + * * @type {LinkProvider} */ this.provider = linkProvider; @@ -32,8 +34,8 @@ export class LinkCountFilter extends CityObjectFilter { /** * Accepts city objects that have at least `this.requiredCount` linked * documents. - * - * @param {CityObject} cityObject + * + * @param {CityObject} cityObject */ accepts(cityObject) { let linkCount = this.provider.getLinksFromCityObject(cityObject).length; @@ -56,7 +58,7 @@ export class LinkCountFilter extends CityObjectFilter { export class LinkedWithDisplayedDocumentFilter extends CityObjectFilter { /** * Instantiates the filter. - * + * * @param {LinkProvider} linkProvider The link provider. */ constructor(linkProvider) { @@ -64,7 +66,7 @@ export class LinkedWithDisplayedDocumentFilter extends CityObjectFilter { /** * The link provider. - * + * * @type {LinkProvider} */ this.provider = linkProvider; @@ -72,12 +74,15 @@ export class LinkedWithDisplayedDocumentFilter extends CityObjectFilter { /** * Accepts city objects that are linked with the currently displayed document. - * - * @param {CityObject} cityObject + * + * @param {CityObject} cityObject */ accepts(cityObject) { - let found = this.provider.getDisplayedDocumentLinks().find((link) => - link.target_id == cityObject.props['cityobject.database_id']); + let found = this.provider + .getDisplayedDocumentLinks() + .find( + (link) => link.target_id == cityObject.props['cityobject.database_id'] + ); return !!found; } @@ -93,7 +98,7 @@ export class LinkedWithDisplayedDocumentFilter extends CityObjectFilter { export class LinkedWithFilteredDocumentsFilter extends CityObjectFilter { /** * Instantiates the filter. - * + * * @param {LinkProvider} linkProvider The link provider. */ constructor(linkProvider) { @@ -101,7 +106,7 @@ export class LinkedWithFilteredDocumentsFilter extends CityObjectFilter { /** * The link provider. - * + * * @type {LinkProvider} */ this.provider = linkProvider; @@ -109,16 +114,19 @@ export class LinkedWithFilteredDocumentsFilter extends CityObjectFilter { /** * Accepts city objects that are linked with the currently filtered documents. - * - * @param {CityObject} cityObject + * + * @param {CityObject} cityObject */ accepts(cityObject) { - let found = this.provider.getFilteredDocumentsLinks().find((link) => - link.target_id == cityObject.props['cityobject.database_id']); + let found = this.provider + .getFilteredDocumentsLinks() + .find( + (link) => link.target_id == cityObject.props['cityobject.database_id'] + ); return !!found; } toString() { return 'Linked to the filtered documents'; } -} \ No newline at end of file +} diff --git a/src/Widgets/Links/ViewModel/LinkProvider.js b/src/Widgets/Links/ViewModel/LinkProvider.js index 1a0d86a05..2e684b2c2 100644 --- a/src/Widgets/Links/ViewModel/LinkProvider.js +++ b/src/Widgets/Links/ViewModel/LinkProvider.js @@ -1,16 +1,21 @@ -//Components -import { CityObject } from "../../../Components/3DTiles/Model/CityObject"; -import { EventSender } from "../../../Components/Events/EventSender"; -import { CityObjectStyle } from "../../../Components/3DTiles/Model/CityObjectStyle"; - -import { LinkService } from "../Model/LinkService"; -import { DocumentProvider } from "../../Documents/ViewModel/DocumentProvider"; -import { CityObjectProvider } from "../../CityObjects/ViewModel/CityObjectProvider"; -import { Link } from "../Model/Link"; -import { Document } from "../../Documents/Model/Document"; -import { LinkCountFilter, LinkedWithDisplayedDocumentFilter, LinkedWithFilteredDocumentsFilter } from "./CityObjectLinkFilters"; -import { DocumentFilter } from "../../Documents/ViewModel/DocumentFilter"; +/** @format */ +//Components +import { CityObject } from '../../../Components/3DTiles/Model/CityObject'; +import { EventSender } from '../../../Components/Events/EventSender'; +import { CityObjectStyle } from '../../../Components/3DTiles/Model/CityObjectStyle'; + +import { LinkService } from '../Model/LinkService'; +import { DocumentProvider } from '../../Documents/ViewModel/DocumentProvider'; +import { CityObjectProvider } from '../../CityObjects/ViewModel/CityObjectProvider'; +import { Link } from '../Model/Link'; +import { Document } from '../../Documents/Model/Document'; +import { + LinkCountFilter, + LinkedWithDisplayedDocumentFilter, + LinkedWithFilteredDocumentsFilter, +} from './CityObjectLinkFilters'; +import { DocumentFilter } from '../../Documents/ViewModel/DocumentFilter'; /** * The link provider is responsible to manage links fetched from the server, @@ -21,7 +26,7 @@ import { DocumentFilter } from "../../Documents/ViewModel/DocumentFilter"; export class LinkProvider extends EventSender { /** * Constructs the link provider. - * + * * @param {DocumentProvider} documentProvider The document provider. * @param {CityObjectProvider} cityObjectProvider The city object provider. * @param {LinkService} linkService The link service. @@ -38,28 +43,28 @@ export class LinkProvider extends EventSender { /** * The link service. - * + * * @type {LinkService} */ this.linkService = linkService; /** * The document provider. - * + * * @type {DocumentProvider} */ this.documentProvider = documentProvider; /** * The city object provider. - * + * * @type {CityObjectProvider} */ this.cityObjectProvider = cityObjectProvider; /** * A filter for city objects based on their count of linked documents. - * + * * @type {LinkCountFilter} */ this.linkCountFilter = new LinkCountFilter(this); @@ -68,27 +73,32 @@ export class LinkProvider extends EventSender { /** * A filter for city objects based on wether they are linked with the * currently displayed document. - * + * * @type {LinkedWithDisplayedDocumentFilter} */ - this.linkedWithDisplayedDocFilter = new LinkedWithDisplayedDocumentFilter(this); + this.linkedWithDisplayedDocFilter = new LinkedWithDisplayedDocumentFilter( + this + ); this.cityObjectProvider.addFilter(this.linkedWithDisplayedDocFilter); /** * The style for city objects linked with the displayed document. - * + * * @type {CityObjectStyle} */ - this.linkDisplayedDocumentStyle = config.cityObjects.styles.linkedWithDisplayedDocument; + this.linkDisplayedDocumentStyle = + config.cityObjects.styles.linkedWithDisplayedDocument; /** * A filter for city objects based on wether they are linked with any of the * currently filtered documents (ie. the list of documents that appear in * the navigator). - * + * * @type {LinkedWithFilteredDocumentsFilter} */ - this.linkedWithFilteredDocsFilter = new LinkedWithFilteredDocumentsFilter(this); + this.linkedWithFilteredDocsFilter = new LinkedWithFilteredDocumentsFilter( + this + ); this.cityObjectProvider.addFilter(this.linkedWithFilteredDocsFilter); // The following adds a filter for documents, based on wether they are @@ -98,58 +108,62 @@ export class LinkProvider extends EventSender { * This value determines wether the filter is active. */ this.shouldFilterLinkedDocuments = false; - this.documentProvider.addFilter(new DocumentFilter((doc) => { - return !this.shouldFilterLinkedDocuments || - this.selectedCityObjectLinks.find(link => link.source_id === doc.id); - })); + this.documentProvider.addFilter( + new DocumentFilter((doc) => { + return ( + !this.shouldFilterLinkedDocuments || + this.selectedCityObjectLinks.find((link) => link.source_id === doc.id) + ); + }) + ); this.documentProvider.refreshDocumentList(); /** * The cached list of links. - * + * * @type {Array} */ this.links = []; /** * The currently displayed document. - * + * * @type {Document} */ this.displayedDocument = undefined; /** * The links of the currently displayed document. - * + * * @type {Array} */ this.displayedDocumentLinks = []; /** * The list of filtered documents. - * + * * @type {Array} */ this.filteredDocuments = []; /** * The links of the filtered documents. - * + * * @type {Array} */ this.filteredDocumentsLinks = []; /** * The currently selected city object. - * + * * @type {CityObject} */ this.selectedCityObject = undefined; /** * The links of the currently selected city object. - * + * * @type {Array} */ this.selectedCityObjectLinks = []; @@ -160,21 +174,27 @@ export class LinkProvider extends EventSender { this.registerEvent(DocumentProvider.EVENT_FILTERED_DOCS_UPDATED); this.registerEvent(CityObjectProvider.EVENT_CITY_OBJECT_SELECTED); - this.documentProvider.addEventListener(DocumentProvider.EVENT_DISPLAYED_DOC_CHANGED, - (doc) => this._onDisplayedDocumentChange(doc)); + this.documentProvider.addEventListener( + DocumentProvider.EVENT_DISPLAYED_DOC_CHANGED, + (doc) => this._onDisplayedDocumentChange(doc) + ); - this.documentProvider.addEventListener(DocumentProvider.EVENT_FILTERED_DOCS_UPDATED, - (docs) => this._onFilteredDocumentsUpdate(docs)); + this.documentProvider.addEventListener( + DocumentProvider.EVENT_FILTERED_DOCS_UPDATED, + (docs) => this._onFilteredDocumentsUpdate(docs) + ); - this.cityObjectProvider.addEventListener(CityObjectProvider.EVENT_CITY_OBJECT_SELECTED, - (co) => this._onCityObjectSelection(co)); + this.cityObjectProvider.addEventListener( + CityObjectProvider.EVENT_CITY_OBJECT_SELECTED, + (co) => this._onCityObjectSelection(co) + ); } /** * Triggers when the displayed document changed. Updates the displayed * document reference in the link provider and re-applies the styles for the * city objects. The event is propagated. - * + * * @param {Document} doc The newly displayed document. */ _onDisplayedDocumentChange(doc) { @@ -188,7 +208,7 @@ export class LinkProvider extends EventSender { * Triggers when the filtered documents change. Updates the filtered document * and their links in the provider, and re-applies the styles for the city * objects. The event is propagated. - * + * * @param {Array} docs The newly filtered documents. */ _onFilteredDocumentsUpdate(docs) { @@ -202,7 +222,7 @@ export class LinkProvider extends EventSender { * Triggers when a city object is selected. Updates the city object and its * links in the provider, and refreshes the list of documents. The event is * propagated. - * + * * @param {CityObject} co The newly selected city object. */ _onCityObjectSelection(co) { @@ -216,7 +236,7 @@ export class LinkProvider extends EventSender { /** * Fetches the links from the server. - * + * * @async */ async fetchLinks() { @@ -228,7 +248,7 @@ export class LinkProvider extends EventSender { /** * Deletes the link. - * + * * @async * @param {Link} link The link to delete. */ @@ -239,7 +259,7 @@ export class LinkProvider extends EventSender { /** * Creates a new link. - * + * * @param {Link} link The link to create. */ async createLink(link) { @@ -255,7 +275,7 @@ export class LinkProvider extends EventSender { /** * Returns the cached list of links. - * + * * @returns {Array} The cached list of links. */ getLinks() { @@ -264,27 +284,29 @@ export class LinkProvider extends EventSender { /** * Returns the links from a list of documents. - * + * * @param {Array} docs A list of documents. */ getLinksFromDocuments(docs) { - return this.links.filter((link) => - docs.find((doc) => doc.id == link.source_id) !== undefined); + return this.links.filter( + (link) => docs.find((doc) => doc.id == link.source_id) !== undefined + ); } /** * Returns the links from a city object. - * + * * @param {CityObject} cityObject The city object. */ getLinksFromCityObject(cityObject) { - return this.links.filter((link) => - link.target_id == cityObject.props['cityobject.database_id']); + return this.links.filter( + (link) => link.target_id == cityObject.props['cityobject.database_id'] + ); } /** * Returns the links from the displayed document. - * + * * @returns {Array} The list of links. */ getDisplayedDocumentLinks() { @@ -293,7 +315,7 @@ export class LinkProvider extends EventSender { /** * Returns the links from the filtered documents. - * + * * @returns {Array} The list of links. */ getFilteredDocumentsLinks() { @@ -302,7 +324,7 @@ export class LinkProvider extends EventSender { /** * Returns the links from the selected city object. - * + * * @returns {Array} The list of links. */ getSelectedCityObjectLinks() { @@ -311,19 +333,21 @@ export class LinkProvider extends EventSender { /** * Returns the list of documents linked to the selected city object. - * + * * @returns {Array} The list of linked documents. */ getSelectedCityObjectLinkedDocuments() { let allDocuments = this.documentProvider.getAllDocuments().slice(); - let docIdsToFind = this.selectedCityObjectLinks.map(link => link.source_id); - return allDocuments.filter(doc => docIdsToFind.includes(doc.id)); + let docIdsToFind = this.selectedCityObjectLinks.map( + (link) => link.source_id + ); + return allDocuments.filter((doc) => docIdsToFind.includes(doc.id)); } /** * Toggles the filter for the documents, based on wether they are linked with * the selected city object. - * + * * @param {Boolean} [toggle] The desired value (`true` activates the filter). * If not specified, the activation state of the filter is simply negated (ie. * if the filter was active, it is now inactive and vice-versa) @@ -340,13 +364,18 @@ export class LinkProvider extends EventSender { * Filters the city objects that are linked with the displayed document. */ highlightDisplayedDocumentLinks() { - this.cityObjectProvider.setLayer('linkDisplayedDoc', this.linkDisplayedDocumentStyle); + this.cityObjectProvider.setLayer( + 'linkDisplayedDoc', + this.linkDisplayedDocumentStyle + ); } /** * Filters the city objects that are linked with the filtered document. */ highlightFilteredDocumentsLinks() { - this.cityObjectProvider.setLayer('linkFilteredDocs', {materialProps: {color: 'blue'}}); + this.cityObjectProvider.setLayer('linkFilteredDocs', { + materialProps: { color: 'blue' }, + }); } -} \ No newline at end of file +} diff --git a/src/Widgets/Others/About.css b/src/Widgets/Others/About.css index f145d65e8..c9d65097b 100644 --- a/src/Widgets/Others/About.css +++ b/src/Widgets/Others/About.css @@ -1,30 +1,31 @@ +/** @format */ #aboutWindow { - position: absolute; - z-index: 11; - top: 10px; - width: 15%; - right : 22.5%; - color: white; - font-size: 75%; - padding: 0 1rem; - background-color: rgba(30,30,30,0.6); - border : 1px solid rgb(90,90,90); - pointer-events: auto; + position: absolute; + z-index: 11; + top: 10px; + width: 15%; + right: 22.5%; + color: white; + font-size: 75%; + padding: 0 1rem; + background-color: rgba(30, 30, 30, 0.6); + border: 1px solid rgb(90, 90, 90); + pointer-events: auto; } #aboutWindow > div > ul { - padding-left: 5px; + padding-left: 5px; } -#aboutCloseButton{ - position: absolute; - z-index: 40; - top: 0; - right: 3px; - margin : 3px; - border: 1px solid black; - background-color: white; - color: black; - pointer-events: auto; +#aboutCloseButton { + position: absolute; + z-index: 40; + top: 0; + right: 3px; + margin: 3px; + border: 1px solid black; + background-color: white; + color: black; + pointer-events: auto; } diff --git a/src/Widgets/Others/About.js b/src/Widgets/Others/About.js index fbb0be41b..265323ec4 100644 --- a/src/Widgets/Others/About.js +++ b/src/Widgets/Others/About.js @@ -1,3 +1,5 @@ +/** @format */ + //Components import { ModuleView } from '../../Components/ModuleView/ModuleView'; @@ -8,17 +10,16 @@ import './About.css'; * simply include this file in the html, no need to instanciate anything in main.js */ export class AboutWindow extends ModuleView { + constructor() { + super(); + // Create DOM element + let aboutDiv = document.createElement('div'); + aboutDiv.id = 'aboutWindow'; + document.getElementById('contentSection').append(aboutDiv); - constructor(options = {}) { - super(); - // Create DOM element - let aboutDiv = document.createElement("div"); - aboutDiv.id = 'aboutWindow'; - document.getElementById('contentSection').append(aboutDiv); - - // Create HMTL - document.getElementById("aboutWindow").innerHTML = - '
        \ + // Create HMTL + document.getElementById('aboutWindow').innerHTML = + '
        \
        \

        This UD-Viz-Core demo is part of the \ \

      • iTowns
      • \
      • Lyon Métropole Open\ Data
      • \ + href="https://data.grandlyon.com">Lyon Métropole Open Data\
      \

      \

      Legal and operational disclaimer: This demonstration\ @@ -75,19 +76,24 @@ export class AboutWindow extends ModuleView { \ '; - // Close the window...when close button is hit - document.getElementById("aboutCloseButton").addEventListener( - 'mousedown', () => { - this.disable(); - }, false); - } + // Close the window...when close button is hit + document.getElementById('aboutCloseButton').addEventListener( + 'mousedown', + () => { + this.disable(); + }, + false + ); + } - /////// MODULE VIEW MANAGEMENT - enableView() { - document.getElementById('aboutWindow').style.setProperty('display', 'block'); - } + /////// MODULE VIEW MANAGEMENT + enableView() { + document + .getElementById('aboutWindow') + .style.setProperty('display', 'block'); + } - disableView() { - document.getElementById('aboutWindow').style.setProperty('display', 'none'); - } + disableView() { + document.getElementById('aboutWindow').style.setProperty('display', 'none'); + } } diff --git a/src/Widgets/Others/Help.css b/src/Widgets/Others/Help.css index 0c84fa91a..01d0f5fa7 100644 --- a/src/Widgets/Others/Help.css +++ b/src/Widgets/Others/Help.css @@ -1,39 +1,41 @@ +/** @format */ + #helpWindow { - position: absolute; - z-index: 10; - width: 15%; - top: 10px; - left : 22.5%; - color: white; - font-size: 75%; - padding: 0 1rem; - background-color: rgba(30,30,30,0.6); - border : 1px solid rgb(90,90,90); - pointer-events: auto; + position: absolute; + z-index: 10; + width: 15%; + top: 10px; + left: 22.5%; + color: white; + font-size: 75%; + padding: 0 1rem; + background-color: rgba(30, 30, 30, 0.6); + border: 1px solid rgb(90, 90, 90); + pointer-events: auto; } #helpWindow > div > ul { - padding-left: 5px; + padding-left: 5px; } -#helpCloseButton{ - position: absolute; - z-index: 40; - top: 0; - right: 3px; - margin : 3px; - border: 1px solid black; - background-color: white; - color: black; - pointer-events: auto; +#helpCloseButton { + position: absolute; + z-index: 40; + top: 0; + right: 3px; + margin: 3px; + border: 1px solid black; + background-color: white; + color: black; + pointer-events: auto; } @media (max-width: 600px) { - #helpWindow { - display: none; - } + #helpWindow { + display: none; + } } hr { - color: white; + color: white; } diff --git a/src/Widgets/Others/Help.js b/src/Widgets/Others/Help.js index 729416bfa..3abf14592 100644 --- a/src/Widgets/Others/Help.js +++ b/src/Widgets/Others/Help.js @@ -1,24 +1,25 @@ +/** @format */ + //Components import { ModuleView } from '../../Components/ModuleView/ModuleView'; import './Help.css'; /** -* adds a "Help" window that can be open/closed with a button -* simply include this file in the html, no need to instanciate anything in main.js -*/ + * adds a "Help" window that can be open/closed with a button + * simply include this file in the html, no need to instanciate anything in main.js + */ export class HelpWindow extends ModuleView { - - constructor(options = {}) { + constructor() { super(); ///////////// Html elements - var helpDiv = document.createElement("div"); + var helpDiv = document.createElement('div'); helpDiv.id = 'helpWindow'; document.getElementById('contentSection').append(helpDiv); - document.getElementById("helpWindow").innerHTML = + document.getElementById('helpWindow').innerHTML = '

      \
      \

      { + document.getElementById('helpCloseButton').addEventListener( + 'mousedown', + () => { this.disable(); - }, false); + }, + false + ); } - /////// MODULE VIEW METHODS enableView() { diff --git a/src/Widgets/Temporal/Model/3DTemporalBatchTable.js b/src/Widgets/Temporal/Model/3DTemporalBatchTable.js index 57aa025ae..f965e8024 100644 --- a/src/Widgets/Temporal/Model/3DTemporalBatchTable.js +++ b/src/Widgets/Temporal/Model/3DTemporalBatchTable.js @@ -1,70 +1,90 @@ /** * Implements the batch table of the 3DTILES_temporal - * extension. See the spec in + * extension. See the spec in * ./jsonSchemas/3DTILES_temporal.batchTable.schema.json + * + * @format */ + export class $3DTemporalBatchTable { - /** - * Verifies the integrity and stores the data corresponding to the - * batch table part of the 3DTiles_temporal extension. - * @param {Object} json The json containing the 3DTiles_temporal - * extension batch table part for a given tile. - */ - constructor(json) { - // Poor verification that the handled json corresponds to the temporal - // extension spec. Should be done by comparing it with the JSON schema. - if (!json.startDates || !Array.isArray(json.startDates)) { - console.error("3D Tiles batch table temporal extension requires " + - "a startDates array. Refer to the spec."); - } - if (!json.endDates || !Array.isArray(json.endDates)) { - console.error("3D Tiles batch table temporal extension requires " + - "an endDates array. Refer to the spec."); - } - if (!json.featureIds || !Array.isArray(json.featureIds)) { - console.error("3D Tiles batch table temporal extension requires " + - "a featureIds array. Refer to the spec."); - } - if (json.startDates.length !== json.endDates.length || - json.startDates.length !== json.featureIds.length) { - console.error("3D Tiles temporal extensions arrays startDates " + - "(length: " + json.startDates.length + "), endDates (length: " + - json.endDates.length + ") and json.featureIds (length: " + - json.featureIds.length + ") must be the same length."); - } - - this.startDates = json.startDates; - this.endDates = json.endDates; - this.featureIds = json.featureIds; + /** + * Verifies the integrity and stores the data corresponding to the + * batch table part of the 3DTiles_temporal extension. + * @param {Object} json The json containing the 3DTiles_temporal + * extension batch table part for a given tile. + */ + constructor(json) { + // Poor verification that the handled json corresponds to the temporal + // extension spec. Should be done by comparing it with the JSON schema. + if (!json.startDates || !Array.isArray(json.startDates)) { + console.error( + '3D Tiles batch table temporal extension requires ' + + 'a startDates array. Refer to the spec.' + ); } - - /** - * Checks that the batch table temporal extension has values for a given - * identifier. - * @param {Number} batchId The identifier to check (identifier in the batch, - * i.e. position in the arrays). - */ - hasInfoForId(batchId) { - // The constructor ensures that the three arrays have the same size. - return !!this.startDates[batchId]; + if (!json.endDates || !Array.isArray(json.endDates)) { + console.error( + '3D Tiles batch table temporal extension requires ' + + 'an endDates array. Refer to the spec.' + ); + } + if (!json.featureIds || !Array.isArray(json.featureIds)) { + console.error( + '3D Tiles batch table temporal extension requires ' + + 'a featureIds array. Refer to the spec.' + ); } + if ( + json.startDates.length !== json.endDates.length || + json.startDates.length !== json.featureIds.length + ) { + console.error( + '3D Tiles temporal extensions arrays startDates ' + + '(length: ' + + json.startDates.length + + '), endDates (length: ' + + json.endDates.length + + ') and json.featureIds (length: ' + + json.featureIds.length + + ') must be the same length.' + ); + } + + this.startDates = json.startDates; + this.endDates = json.endDates; + this.featureIds = json.featureIds; + } + + /** + * Checks that the batch table temporal extension has values for a given + * identifier. + * @param {Number} batchId The identifier to check (identifier in the batch, + * i.e. position in the arrays). + */ + hasInfoForId(batchId) { + // The constructor ensures that the three arrays have the same size. + return !!this.startDates[batchId]; + } - /** - * Returns information for the given batchId. - * Can be used to display information associated with an object - * picked with the mouse for instance. - * @param {*} batchId The given identifier (identifier in the batch, - * i.e. position in the arrays). - */ - getInfoById(batchId) { - if (!this.hasInfoForId(batchId)) { - console.error("3D Tiles batch table temporal extension does not " + - "have information for batch ID " + batchId); - } - return { - 'featureId': this.featureIds[batchId], - 'startDate': this.startDates[batchId], - 'endDate': this.endDates[batchId] - }; + /** + * Returns information for the given batchId. + * Can be used to display information associated with an object + * picked with the mouse for instance. + * @param {*} batchId The given identifier (identifier in the batch, + * i.e. position in the arrays). + */ + getInfoById(batchId) { + if (!this.hasInfoForId(batchId)) { + console.error( + '3D Tiles batch table temporal extension does not ' + + 'have information for batch ID ' + + batchId + ); } -} \ No newline at end of file + return { + featureId: this.featureIds[batchId], + startDate: this.startDates[batchId], + endDate: this.endDates[batchId], + }; + } +} diff --git a/src/Widgets/Temporal/Model/3DTemporalBoundingVolume.js b/src/Widgets/Temporal/Model/3DTemporalBoundingVolume.js index a5d518c95..8b3c770a4 100644 --- a/src/Widgets/Temporal/Model/3DTemporalBoundingVolume.js +++ b/src/Widgets/Temporal/Model/3DTemporalBoundingVolume.js @@ -1,25 +1,32 @@ /** * Implements the bounding volume part of the 3DTILES_temporal - * extension. See the spec in + * extension. See the spec in * ./jsonSchemas/3DTILES_temporal.boundingVolume.schema.json + * + * @format */ + export class $3DTemporalBoundingVolume { - /** - * Verifies the integrity and stores the data corresponding to the - * bounding volume part of the 3DTiles_temporal extension. - * @param {Object} json The json containing the 3DTiles_temporal - * extension bounding volume part for a given tile. - */ - constructor(json) { - if (!json.startDate) { - console.error("3D Tiles bounding volume temporal extension " + - "requires a startDate. Refer to the spec."); - } - if (!json.endDate) { - console.error("3D Tiles bounding volume temporal extension " + - "requires an endDate. Refer to the spec."); - } - this.startDate = json.startDate; - this.endDate = json.endDate; + /** + * Verifies the integrity and stores the data corresponding to the + * bounding volume part of the 3DTiles_temporal extension. + * @param {Object} json The json containing the 3DTiles_temporal + * extension bounding volume part for a given tile. + */ + constructor(json) { + if (!json.startDate) { + console.error( + '3D Tiles bounding volume temporal extension ' + + 'requires a startDate. Refer to the spec.' + ); } + if (!json.endDate) { + console.error( + '3D Tiles bounding volume temporal extension ' + + 'requires an endDate. Refer to the spec.' + ); + } + this.startDate = json.startDate; + this.endDate = json.endDate; + } } diff --git a/src/Widgets/Temporal/Model/3DTemporalExtension.js b/src/Widgets/Temporal/Model/3DTemporalExtension.js index 5f22b94f6..f73fb46a5 100644 --- a/src/Widgets/Temporal/Model/3DTemporalExtension.js +++ b/src/Widgets/Temporal/Model/3DTemporalExtension.js @@ -1,135 +1,149 @@ +/** @format */ + import { $3DTemporalTileset } from './3DTemporalTileset.js'; /** - * Entrypoint of the temporal module model. + * Entrypoint of the temporal module model. * Stores all parts of the 3D Tiles temporal extension model */ export class $3DTemporalExtension { - constructor() { - this.extensionName = "3DTILES_temporal"; + constructor() { + this.extensionName = '3DTILES_temporal'; - /** - * A map with feature IDs as keys and transactions of these features - * as value. - */ - this.transactionsPerFeature = new Map(); + /** + * A map with feature IDs as keys and transactions of these features + * as value. + */ + this.transactionsPerFeature = new Map(); - /** - * A map of map with transactions as values and organized - * per tiles and per features. This structure is used for - * optimizing the temporal culling (to decide which features - * should be displayed and with which style depending on the time, - * see TemporalProvider.js for more information). It is structured - * as follows: - * { tileId : featureID : { - * asSource: transaction; - * asDestination: transaction; - * } - * } - * Note that currently only the first transaction where the feature - * is a source or where the feature is a destination is kept. - * NORMALLY a feature shouldn't be the source (reps. the - * destination) of multiple transaction, since in this case one - * should create aggregates. Otherwise it might represent - * concurrent evolutions which are not managed in this - * implementation. However, in practical terms there is cases where - * a feature is the source (resp. destination) of multiple - * transactions. These cases might need to be investigated in more - * depth.... - * @type {Map} - */ - this.transactionsPerTile = new Map(); + /** + * A map of map with transactions as values and organized + * per tiles and per features. This structure is used for + * optimizing the temporal culling (to decide which features + * should be displayed and with which style depending on the time, + * see TemporalProvider.js for more information). It is structured + * as follows: + * { tileId : featureID : { + * asSource: transaction; + * asDestination: transaction; + * } + * } + * Note that currently only the first transaction where the feature + * is a source or where the feature is a destination is kept. + * NORMALLY a feature shouldn't be the source (reps. the + * destination) of multiple transaction, since in this case one + * should create aggregates. Otherwise it might represent + * concurrent evolutions which are not managed in this + * implementation. However, in practical terms there is cases where + * a feature is the source (resp. destination) of multiple + * transactions. These cases might need to be investigated in more + * depth.... + * @type {Map} + */ + this.transactionsPerTile = new Map(); - /** - * The temporal extension part of the batch tables mapped to the tile - * IDs (keys of the map). - */ - this.temporalBatchTables = new Map(); + /** + * The temporal extension part of the batch tables mapped to the tile + * IDs (keys of the map). + */ + this.temporalBatchTables = new Map(); - /** - * The temporal extension part of the bounding volumes part mapped to - * the tile IDs (keys of the map). - */ - this.temporalBoundingVolumes = new Map(); + /** + * The temporal extension part of the bounding volumes part mapped to + * the tile IDs (keys of the map). + */ + this.temporalBoundingVolumes = new Map(); - // Events - // $3DTemporalTileset triggers an event when it is loaded - window.addEventListener( - $3DTemporalTileset.TEMPORAL_TILESET_LOADED, - this.temporalTilesetLoaded.bind(this)); + // Events + // $3DTemporalTileset triggers an event when it is loaded + window.addEventListener( + $3DTemporalTileset.TEMPORAL_TILESET_LOADED, + this.temporalTilesetLoaded.bind(this) + ); - // Another strategy is used for the batch table part and - // for the bounding volume part of the temporal extension - // since we need to know to which tile this batch table - // extension belongs to (that is not stored in the batch - // table extension part). Therefore, we use the - // TilesManager.EVENT_TILE_LOADED instead which is fired - // by the 3D Tiles itowns layer when a tile has been - // loaded. To avoid creating a dependency between this class - // and the tilesManager, we add this event listener in the - // TemporalCntroler which knows both this model and the tilesManager. - // This is not ideal but improving this would asks for more - // modifications in itowns, which is currently not possible. - } + // Another strategy is used for the batch table part and + // for the bounding volume part of the temporal extension + // since we need to know to which tile this batch table + // extension belongs to (that is not stored in the batch + // table extension part). Therefore, we use the + // TilesManager.EVENT_TILE_LOADED instead which is fired + // by the 3D Tiles itowns layer when a tile has been + // loaded. To avoid creating a dependency between this class + // and the tilesManager, we add this event listener in the + // TemporalCntroler which knows both this model and the tilesManager. + // This is not ideal but improving this would asks for more + // modifications in itowns, which is currently not possible. + } - /** - * Fills this.transactionsPerFeature map when the tileset has been loaded - * (all transactions are stored in the temporal extension part of the - * tileset). - * @param {*} event The evet triggered; holds the temporal part of the - * extension in event.detail - */ - temporalTilesetLoaded(event) { - const allTransactions = event.detail.temporalTileset.transactions; + /** + * Fills this.transactionsPerFeature map when the tileset has been loaded + * (all transactions are stored in the temporal extension part of the + * tileset). + * @param {*} event The evet triggered; holds the temporal part of the + * extension in event.detail + */ + temporalTilesetLoaded(event) { + const allTransactions = event.detail.temporalTileset.transactions; - for (let i = 0; i < allTransactions.length; i++) { - const transaction = allTransactions[i]; - for (let j = 0; j < transaction.source.length; j++) { - const source = transaction.source[j]; - if (this.transactionsPerFeature.get(source) === undefined) { - this.transactionsPerFeature.set(source, {}); - } - if (this.transactionsPerFeature.get(source).asSource === - undefined) { - this.transactionsPerFeature.get(source).asSource = - transaction; - } - } - for (let j = 0; j < transaction.destination.length; j++) { - const destination = transaction.destination[j]; - if (this.transactionsPerFeature.get(destination) === undefined) { - this.transactionsPerFeature.set(destination, {}); - } - if (this.transactionsPerFeature.get(destination).asDestination === - undefined) { - this.transactionsPerFeature.get(destination).asDestination = - transaction; - } - } + for (let i = 0; i < allTransactions.length; i++) { + const transaction = allTransactions[i]; + for (let j = 0; j < transaction.source.length; j++) { + const source = transaction.source[j]; + if (this.transactionsPerFeature.get(source) === undefined) { + this.transactionsPerFeature.set(source, {}); + } + if (this.transactionsPerFeature.get(source).asSource === undefined) { + this.transactionsPerFeature.get(source).asSource = transaction; + } + } + for (let j = 0; j < transaction.destination.length; j++) { + const destination = transaction.destination[j]; + if (this.transactionsPerFeature.get(destination) === undefined) { + this.transactionsPerFeature.set(destination, {}); } + if ( + this.transactionsPerFeature.get(destination).asDestination === + undefined + ) { + this.transactionsPerFeature.get(destination).asDestination = + transaction; + } + } } + } - /** - * Triggered when the content of a tile has been loaded. Fills - * this.transactionsPerTile list with the transaction of this tile. - * @param {*} tileContent - */ - updateTileExtensionModel(tileContent) { - this.temporalBoundingVolumes.set(tileContent.tileId, - tileContent.boundingVolume.extensions[this.extensionName]); + /** + * Triggered when the content of a tile has been loaded. Fills + * this.transactionsPerTile list with the transaction of this tile. + * @param {*} tileContent + */ + updateTileExtensionModel(tileContent) { + this.temporalBoundingVolumes.set( + tileContent.tileId, + tileContent.boundingVolume.extensions[this.extensionName] + ); - // The batch table is not mandatory (e.g. the root tile - // has no batch table) - if (tileContent.batchTable) { - this.temporalBatchTables.set(tileContent.tileId, - tileContent.batchTable.extensions[this.extensionName]); - if (! this.transactionsPerTile.has(tileContent.tileId)) { - this.transactionsPerTile.set(tileContent.tileId, new Map()); - } - for (let i = 0; i < this.temporalBatchTables.get(tileContent.tileId).featureIds.length; i++) { - const featureId = this.temporalBatchTables.get(tileContent.tileId).featureIds[i]; - this.transactionsPerTile.get(tileContent.tileId).set(featureId, this.transactionsPerFeature.get(featureId)); - } - } + // The batch table is not mandatory (e.g. the root tile + // has no batch table) + if (tileContent.batchTable) { + this.temporalBatchTables.set( + tileContent.tileId, + tileContent.batchTable.extensions[this.extensionName] + ); + if (!this.transactionsPerTile.has(tileContent.tileId)) { + this.transactionsPerTile.set(tileContent.tileId, new Map()); + } + for ( + let i = 0; + i < this.temporalBatchTables.get(tileContent.tileId).featureIds.length; + i++ + ) { + const featureId = this.temporalBatchTables.get(tileContent.tileId) + .featureIds[i]; + this.transactionsPerTile + .get(tileContent.tileId) + .set(featureId, this.transactionsPerFeature.get(featureId)); + } } + } } diff --git a/src/Widgets/Temporal/Model/3DTemporalPrimaryTransaction.js b/src/Widgets/Temporal/Model/3DTemporalPrimaryTransaction.js index 031ae35e2..2ff3a2d84 100644 --- a/src/Widgets/Temporal/Model/3DTemporalPrimaryTransaction.js +++ b/src/Widgets/Temporal/Model/3DTemporalPrimaryTransaction.js @@ -1,17 +1,19 @@ +/** @format */ + import { $3DTemporalTransaction } from './3DTemporalTransaction.js'; /** * Implements the primary transaction of the 3DTILES_temporal - * extension. See the spec in + * extension. See the spec in * ./jsonSchemas/3DTILES_temporal.primaryTransaction.schema.json */ export class $3DTemporalPrimaryTransaction extends $3DTemporalTransaction { - constructor(json) { - super(json); + constructor(json) { + super(json); - this.type = json.type; - // type testing is not reliable in javascript therefore we have to use - // booleans to do so... - this.isPrimary = true; - } + this.type = json.type; + // type testing is not reliable in javascript therefore we have to use + // booleans to do so... + this.isPrimary = true; + } } diff --git a/src/Widgets/Temporal/Model/3DTemporalTileset.js b/src/Widgets/Temporal/Model/3DTemporalTileset.js index 9dc6a31be..1f56a395b 100644 --- a/src/Widgets/Temporal/Model/3DTemporalTileset.js +++ b/src/Widgets/Temporal/Model/3DTemporalTileset.js @@ -1,53 +1,59 @@ +/** @format */ + import { $3DTemporalPrimaryTransaction } from '../Model/3DTemporalPrimaryTransaction.js'; import { $3DTemporalTransactionAggregate } from '../Model/3DTemporalTransactionAggregate.js'; import { $3DTemporalVersion } from './3DTemporalVersion.js'; /** * Implements the tileset part of the 3DTILES_temporal - * extension. See the spec in + * extension. See the spec in * ./jsonSchemas/3DTILES_temporal.tileset.schema.json */ export class $3DTemporalTileset { - constructor(json) { - this.startDate = json.startDate; - this.endDate = json.endDate; + constructor(json) { + this.startDate = json.startDate; + this.endDate = json.endDate; - this.transactions = []; - // Fill this.transactions - this.parseTransactions(json.transactions); + this.transactions = []; + // Fill this.transactions + this.parseTransactions(json.transactions); - this.temporalVersions = new $3DTemporalVersion(json.versions); - this.versionTransitions = json.versionTransitions; - - // Trapped by 3DTemporalExtension.js that stores this instance of - // $3DTemporalTileset - window.dispatchEvent(new CustomEvent( - $3DTemporalTileset.TEMPORAL_TILESET_LOADED, - {detail: { temporalTileset: this}})); - } + this.temporalVersions = new $3DTemporalVersion(json.versions); + this.versionTransitions = json.versionTransitions; - /** - * Parses transactions from a json file and creates primary and aggregated - * transactions. - * @param {Object} transactions The json holding the transactions. - */ - parseTransactions(transactions) { - for (let i = 0; i < transactions.length; i++) { - let parsedTransac; - if (transactions[i].type) { - // Transactions aggregates don't have a type attribute - parsedTransac = new $3DTemporalPrimaryTransaction(transactions[i]); - } else if (transactions[i].transactions) { - // Primary transactions don't have a transactions attribute - parsedTransac = new $3DTemporalTransactionAggregate(transactions[i]); - // Recursively parse the aggregated transactions. - parsedTransac.transactions = this.parseTransactions(transactions[i].transactions); - } - this.transactions.push(parsedTransac); - } - } + // Trapped by 3DTemporalExtension.js that stores this instance of + // $3DTemporalTileset + window.dispatchEvent( + new CustomEvent($3DTemporalTileset.TEMPORAL_TILESET_LOADED, { + detail: { temporalTileset: this }, + }) + ); + } - static get TEMPORAL_TILESET_LOADED() { - return 'TEMPORAL_TILESET_LOADED'; + /** + * Parses transactions from a json file and creates primary and aggregated + * transactions. + * @param {Object} transactions The json holding the transactions. + */ + parseTransactions(transactions) { + for (let i = 0; i < transactions.length; i++) { + let parsedTransac; + if (transactions[i].type) { + // Transactions aggregates don't have a type attribute + parsedTransac = new $3DTemporalPrimaryTransaction(transactions[i]); + } else if (transactions[i].transactions) { + // Primary transactions don't have a transactions attribute + parsedTransac = new $3DTemporalTransactionAggregate(transactions[i]); + // Recursively parse the aggregated transactions. + parsedTransac.transactions = this.parseTransactions( + transactions[i].transactions + ); } + this.transactions.push(parsedTransac); + } + } + + static get TEMPORAL_TILESET_LOADED() { + return 'TEMPORAL_TILESET_LOADED'; + } } diff --git a/src/Widgets/Temporal/Model/3DTemporalTransaction.js b/src/Widgets/Temporal/Model/3DTemporalTransaction.js index 406a42dec..8f092e0c4 100644 --- a/src/Widgets/Temporal/Model/3DTemporalTransaction.js +++ b/src/Widgets/Temporal/Model/3DTemporalTransaction.js @@ -1,15 +1,18 @@ /** * Implements the transaction concept of the 3DTILES_temporal - * extension. See the spec in + * extension. See the spec in * ./jsonSchemas/3DTILES_temporal.transaction.schema.json + * + * @format */ + export class $3DTemporalTransaction { - constructor(json) { - this.id = json.id; - this.startDate = json.startDate; - this.endDate = json.endDate; - this.source = json.source; - this.destination = json.destination; - this.tags = json.tags; - } + constructor(json) { + this.id = json.id; + this.startDate = json.startDate; + this.endDate = json.endDate; + this.source = json.source; + this.destination = json.destination; + this.tags = json.tags; + } } diff --git a/src/Widgets/Temporal/Model/3DTemporalTransactionAggregate.js b/src/Widgets/Temporal/Model/3DTemporalTransactionAggregate.js index eabcafd93..15af7d1c0 100644 --- a/src/Widgets/Temporal/Model/3DTemporalTransactionAggregate.js +++ b/src/Widgets/Temporal/Model/3DTemporalTransactionAggregate.js @@ -1,17 +1,19 @@ +/** @format */ + import { $3DTemporalTransaction } from './3DTemporalTransaction.js'; /** * Implements the aggregated transaction of the 3DTILES_temporal - * extension. See the spec in + * extension. See the spec in * ./jsonSchemas/3DTILES_temporal.transactionAggregate.schema.json */ export class $3DTemporalTransactionAggregate extends $3DTemporalTransaction { - constructor(json) { - super(json); + constructor(json) { + super(json); - this.transactions = {}; - // type testing is not reliable in javascript therefore we have to use - // booleans to do so... - this.isAggregate = true; - } + this.transactions = {}; + // type testing is not reliable in javascript therefore we have to use + // booleans to do so... + this.isAggregate = true; + } } diff --git a/src/Widgets/Temporal/Model/3DTemporalVersion.js b/src/Widgets/Temporal/Model/3DTemporalVersion.js index 814f1bf58..ead41e705 100644 --- a/src/Widgets/Temporal/Model/3DTemporalVersion.js +++ b/src/Widgets/Temporal/Model/3DTemporalVersion.js @@ -1,17 +1,20 @@ /** * Implements the version concept of the 3DTILES_temporal - * extension. See the spec in + * extension. See the spec in * ./jsonSchemas/3DTILES_temporal.version.schema.json + * + * @format */ + export class $3DTemporalVersion { - constructor(json) { - this.versions = json; - for (let i = 0; i < json.length; i++) { - // Add the fields missing for the graph window - this.versions[i].label = json[i].name; - this.versions[i].level = i; - this.versions[i].group = "consensusScenario"; // Needs to be changed if one wants multiple scenario - this.versions[i].title = json[i].description; - } - } -} \ No newline at end of file + constructor(json) { + this.versions = json; + for (let i = 0; i < json.length; i++) { + // Add the fields missing for the graph window + this.versions[i].label = json[i].name; + this.versions[i].level = i; + this.versions[i].group = 'consensusScenario'; // Needs to be changed if one wants multiple scenario + this.versions[i].title = json[i].description; + } + } +} diff --git a/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.batchTable.schema.json b/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.batchTable.schema.json index 307593267..8fa357703 100644 --- a/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.batchTable.schema.json +++ b/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.batchTable.schema.json @@ -24,7 +24,7 @@ "featuresIds": { "description": "Array of ids of the features. Used in versions and transactions to identify the features.", "type": "array", - "items": {"type": "string"} + "items": { "type": "string" } } } } diff --git a/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.primaryTransaction.json b/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.primaryTransaction.json index 7a1864eef..eac1b5377 100644 --- a/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.primaryTransaction.json +++ b/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.primaryTransaction.json @@ -3,15 +3,24 @@ "id": "3DTILES_temporal.primaryTransaction.schema.json", "title": "3DTILES_temporal_primaryTransaction extension", "type": "object", - "allOf" : [{ - "$ref" : "3DTILES_temporal.transaction.schema.json" - }, { - "properties" : { + "allOf": [ + { + "$ref": "3DTILES_temporal.transaction.schema.json" + }, + { + "properties": { "type": { "description": "Type of transaction", "type": "string", - "enum": ["creation", "demolition", "modification", "union", "division"] + "enum": [ + "creation", + "demolition", + "modification", + "union", + "division" + ] } } - }] + } + ] } diff --git a/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.tileset.schema.json b/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.tileset.schema.json index 2fb94c330..7b56a644c 100644 --- a/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.tileset.schema.json +++ b/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.tileset.schema.json @@ -18,20 +18,22 @@ "versions": { "description": "Versions of the city", "type": "array", - "items": {"$ref": "3DTILES_temporal.version.schema.json"} + "items": { "$ref": "3DTILES_temporal.version.schema.json" } }, "versionTransitions": { "description": "Transitions between versions of the city", "type": "array", - "items": {"$ref": "3DTILES_temporal.versionTransition.schema.json"} + "items": { "$ref": "3DTILES_temporal.versionTransition.schema.json" } }, "transactions": { "description": "Transactions between features", "type": "array", - "items": { "anyOf": [ - {"$ref": "3DTILES_temporal.primaryTransaction.schema.json"}, - {"$ref": "3DTILES_temporal.transactionAggregate.schema.json"} - ]} + "items": { + "anyOf": [ + { "$ref": "3DTILES_temporal.primaryTransaction.schema.json" }, + { "$ref": "3DTILES_temporal.transactionAggregate.schema.json" } + ] + } } } } diff --git a/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.transaction.schema.json b/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.transaction.schema.json index 7b603d6cf..d89ec67f4 100644 --- a/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.transaction.schema.json +++ b/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.transaction.schema.json @@ -21,17 +21,17 @@ "source": { "description": "Array of Features Ids (stored in the 3DTILES_temporal extension of the batch table) representing a state before the transaction", "type": "array", - "items": {"type": "string"} + "items": { "type": "string" } }, "destination": { "description": "Array of Features Ids (stored in the 3DTILES_temporal extension of the batch table) representing a state after the transaction", "type": "array", - "items": {"type": "string"} + "items": { "type": "string" } }, "tags": { "description": "tags of the transaction", "type": "array", - "items": {"type": "string"} + "items": { "type": "string" } } } } diff --git a/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.transactionAggregate.schema.json b/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.transactionAggregate.schema.json index 77c280382..332dc5fe5 100644 --- a/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.transactionAggregate.schema.json +++ b/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.transactionAggregate.schema.json @@ -3,18 +3,23 @@ "id": "3DTILES_temporal.transactionAggregate.schema.json", "title": "3DTILES_temporal_transactionAggregate extension", "type": "object", - "allOf" : [{ - "$ref" : "3DTILES_temporal.transaction.schema.json" - }, { - "properties" : { + "allOf": [ + { + "$ref": "3DTILES_temporal.transaction.schema.json" + }, + { + "properties": { "primaryTransactions": { "description": "Array of transactionAggregate or of primaryTransactions", "type": "array", - "items": { "anyOf": [ - {"$ref": "3DTILES_temporal.primaryTransaction.schema.json"}, - {"$ref": "3DTILES_temporal.transactionAggregate.schema.json"} - ]} + "items": { + "anyOf": [ + { "$ref": "3DTILES_temporal.primaryTransaction.schema.json" }, + { "$ref": "3DTILES_temporal.transactionAggregate.schema.json" } + ] + } } } - }] + } + ] } diff --git a/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.version.schema.schema.json b/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.version.schema.schema.json index de599adae..d04258e3b 100644 --- a/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.version.schema.schema.json +++ b/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.version.schema.schema.json @@ -28,12 +28,12 @@ }, "tags": { "type": "array", - "items": {"type": "string"} + "items": { "type": "string" } }, "featuresIds": { "description": "Array of Features Ids composing the version (stored in the 3DTILES_temporal extension of the batch table)", "type": "array", - "items": {"type": "string"} + "items": { "type": "string" } } } } diff --git a/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.versionTransition.schema.json b/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.versionTransition.schema.json index 7da39fee7..6dc924425 100644 --- a/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.versionTransition.schema.json +++ b/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.versionTransition.schema.json @@ -42,7 +42,7 @@ "transactionsIds": { "type": "array", "description": "ids of the transactions composing this VersionTransition", - "items": {"type": "string"} + "items": { "type": "string" } } } } diff --git a/src/Widgets/Temporal/TemporalModule.js b/src/Widgets/Temporal/TemporalModule.js index c00da400b..0b62d2f75 100644 --- a/src/Widgets/Temporal/TemporalModule.js +++ b/src/Widgets/Temporal/TemporalModule.js @@ -1,12 +1,14 @@ +/** @format */ + import { $3DTemporalExtension } from './Model/3DTemporalExtension.js'; import { TemporalProvider } from './ViewModel/TemporalProvider.js'; -import { TemporalView } from './View/TemporalView.js' +import { TemporalView } from './View/TemporalView.js'; /** * Entrypoint of the temporal module (that can be instanciated in the demos) */ export class TemporalModule { - /** + /** * Constructs a new temporal module. * * @param {TilesManager} tilesManager - The tiles manager associated with @@ -15,13 +17,15 @@ export class TemporalModule { * module. }; */ - constructor(tilesManager, temporalOptions) { - - this.model = new $3DTemporalExtension(); + constructor(tilesManager, temporalOptions) { + this.model = new $3DTemporalExtension(); - this.provider = new TemporalProvider(this.model, tilesManager, - temporalOptions.currentTime); + this.provider = new TemporalProvider( + this.model, + tilesManager, + temporalOptions.currentTime + ); - this.view = new TemporalView(this.provider, temporalOptions); - } -} \ No newline at end of file + this.view = new TemporalView(this.provider, temporalOptions); + } +} diff --git a/src/Widgets/Temporal/View/EnumWindows.js b/src/Widgets/Temporal/View/EnumWindows.js index e7a4538ec..374f8c093 100644 --- a/src/Widgets/Temporal/View/EnumWindows.js +++ b/src/Widgets/Temporal/View/EnumWindows.js @@ -1,8 +1,10 @@ +/** @format */ + export class EnumTemporalWindow { - static get SLIDERWINDOW(){ - return "SLIDERWINDOW"; - } - static get GRAPHWINDOW(){ - return "GRAPHWINDOW"; - } -} \ No newline at end of file + static get SLIDERWINDOW() { + return 'SLIDERWINDOW'; + } + static get GRAPHWINDOW() { + return 'GRAPHWINDOW'; + } +} diff --git a/src/Widgets/Temporal/View/NetworkManager.js b/src/Widgets/Temporal/View/NetworkManager.js index 96f0d6931..0b2e84fb3 100644 --- a/src/Widgets/Temporal/View/NetworkManager.js +++ b/src/Widgets/Temporal/View/NetworkManager.js @@ -1,11 +1,13 @@ -const Network = require('vis-network').Network +/** @format */ + +const Network = require('vis-network').Network; /** -* Manager for the graph -* It take care of all data needed by vis.js -*/ + * Manager for the graph + * It take care of all data needed by vis.js + */ export class NetworkManager { - /** + /** * Constructs a NetworkManager. * * @param {String} id_network - HTML id which will be the container of the graph @@ -30,69 +32,72 @@ export class NetworkManager { * * network {Vis.Network Object} - hold the network/graph instance created by viz.js */ - constructor(id_network="mynetwork", - data={"nodes": null, - "edges": null, - "groups": { - "id":0, - "label":"consensusScenario"} - }, - option=null){ - this.network = null; - this.data = data; - this.option = option; - this.id_network = id_network; - this.getAsynchronousData = null; - - } + constructor( + id_network = 'mynetwork', + data = { + nodes: null, + edges: null, + groups: { + id: 0, + label: 'consensusScenario', + }, + }, + option = null + ) { + this.network = null; + this.data = data; + this.option = option; + this.id_network = id_network; + this.getAsynchronousData = null; + } - /** - * Kill the simulation network - * When the graph is shown, a simulation is running. It allows dynamics interactions - * When killed, the graph disappear. - */ - destroy() { - if (this.network !== null) { - this.network.destroy(); - this.network = null; - } + /** + * Kill the simulation network + * When the graph is shown, a simulation is running. It allows dynamics interactions + * When killed, the graph disappear. + */ + destroy() { + if (this.network !== null) { + this.network.destroy(); + this.network = null; } + } - /** - * Initiate the vis.Network with the container (html), data (nodes & edges) and options (graphics) - * The data is got asynchronously. It's coming from tileset.json so we need to wait for it. - */ - init(){ - this.destroy(); + /** + * Initiate the vis.Network with the container (html), data (nodes & edges) and options (graphics) + * The data is got asynchronously. It's coming from tileset.json so we need to wait for it. + */ + init() { + this.destroy(); - this.data.nodes = this.getAsynchronousData()[0]; - this.data.edges = this.getAsynchronousData()[1]; - const container = document.getElementById(this.id_network); - this.network = new Network(container, this.data, this.option); - } + this.data.nodes = this.getAsynchronousData()[0]; + this.data.edges = this.getAsynchronousData()[1]; + const container = document.getElementById(this.id_network); + this.network = new Network(container, this.data, this.option); + } - /** - * Add callback to the graph - * Click on node = event - * Click on edge = event - * In both case, a date is passed - * @param : callback (function) ( the function to be call when the event is done) - */ - add_event(callback){ - this.network.on("selectNode", function (params) { - let nodeId = this.getNodeAt(params.pointer.DOM); - let node = this.body.nodes[nodeId]; - let time = node.options.name; - callback(time); - }); + /** + * Add callback to the graph + * Click on node = event + * Click on edge = event + * In both case, a date is passed + * @param : callback (function) ( the function to be call when the event is done) + */ + add_event(callback) { + this.network.on('selectNode', function (params) { + let nodeId = this.getNodeAt(params.pointer.DOM); + let node = this.body.nodes[nodeId]; + let time = node.options.name; + callback(time); + }); - this.network.on("selectEdge", function (params) { - let edgeId = this.getEdgeAt(params.pointer.DOM); - let connectedNodesId = this.getConnectedNodes(edgeId); - let from_time = this.body.nodes[connectedNodesId[0]].options.name; - let to_time = this.body.nodes[connectedNodesId[1]].options.name; - let time = (from_time/1 + to_time/1) / 2 ; - callback(time); - }); - } + this.network.on('selectEdge', function (params) { + let edgeId = this.getEdgeAt(params.pointer.DOM); + let connectedNodesId = this.getConnectedNodes(edgeId); + let from_time = this.body.nodes[connectedNodesId[0]].options.name; + let to_time = this.body.nodes[connectedNodesId[1]].options.name; + let time = (from_time / 1 + to_time / 1) / 2; + callback(time); + }); + } } diff --git a/src/Widgets/Temporal/View/TemporalGraphWindow.js b/src/Widgets/Temporal/View/TemporalGraphWindow.js index 0c1d5ab99..4fd949bb6 100644 --- a/src/Widgets/Temporal/View/TemporalGraphWindow.js +++ b/src/Widgets/Temporal/View/TemporalGraphWindow.js @@ -1,7 +1,9 @@ +/** @format */ + //Components -import { Window } from "../../../Components/GUI/js/Window"; +import { Window } from '../../../Components/GUI/js/Window'; -import { NetworkManager } from "./NetworkManager"; +import { NetworkManager } from './NetworkManager'; import './TemporalWindow.css'; /** @@ -16,55 +18,56 @@ import './TemporalWindow.css'; * @param options : optional parameters (min time, max time and current time) */ export class TemporalGraphWindow extends Window { - constructor(refreshCallback, options = {}) { + constructor(refreshCallback, options = {}) { // option : getAsynchronousData - super('temporal', 'Temporal Graph Navigation', false); + super('temporal', 'Temporal Graph Navigation', false); - this.refreshCallback = refreshCallback; + this.refreshCallback = refreshCallback; - // graph - this.networkManager = new NetworkManager(); - this.networkManager.option=options.viewOptions; - this.networkManager.getAsynchronousData = options.temporalWindow.getAsynchronousData; - } + // graph + this.networkManager = new NetworkManager(); + this.networkManager.option = options.viewOptions; + this.networkManager.getAsynchronousData = + options.temporalWindow.getAsynchronousData; + } - get innerContentHtml() { - return /*html*/` + get innerContentHtml() { + return /*html*/ `
      `; - } - - windowCreated() { - // Magical code to center an absolute positionned window - this.window.style.setProperty('left', '0'); - this.window.style.setProperty('right', '0'); - this.window.style.setProperty('margin-left', 'auto'); - this.window.style.setProperty('margin-right', 'auto'); - // Put it at the bottom of the page - this.window.style.setProperty('top', 'unset'); - this.window.style.setProperty('bottom', '0'); - this.window.style.setProperty('margin-bottom', 'auto'); - // Window size and center text - this.window.style.setProperty('width', '700px'); - this.window.style.setProperty('height', '215px'); -// this.window.style.setProperty('height', '115px'); - this.window.style.setProperty('text-align', 'center'); - - // Add graph - this.networkManager.init(); - this.networkManager.add_event((param)=>{this.changeTime(param)}); - } + } + windowCreated() { + // Magical code to center an absolute positionned window + this.window.style.setProperty('left', '0'); + this.window.style.setProperty('right', '0'); + this.window.style.setProperty('margin-left', 'auto'); + this.window.style.setProperty('margin-right', 'auto'); + // Put it at the bottom of the page + this.window.style.setProperty('top', 'unset'); + this.window.style.setProperty('bottom', '0'); + this.window.style.setProperty('margin-bottom', 'auto'); + // Window size and center text + this.window.style.setProperty('width', '700px'); + this.window.style.setProperty('height', '215px'); + // this.window.style.setProperty('height', '115px'); + this.window.style.setProperty('text-align', 'center'); - // change the current date and sync the temporal version to this new date - changeTime(time) { - this.currentTime = time; + // Add graph + this.networkManager.init(); + this.networkManager.add_event((param) => { + this.changeTime(param); + }); + } - // Eventually inform who it may concern (e.g. an associated iTowns layer) - // that the currentTime has changed: - this.refreshCallback(this.currentTime); - } + // change the current date and sync the temporal version to this new date + changeTime(time) { + this.currentTime = time; + // Eventually inform who it may concern (e.g. an associated iTowns layer) + // that the currentTime has changed: + this.refreshCallback(this.currentTime); + } } diff --git a/src/Widgets/Temporal/View/TemporalSliderWindow.js b/src/Widgets/Temporal/View/TemporalSliderWindow.js index 47b0da04b..27bd71894 100644 --- a/src/Widgets/Temporal/View/TemporalSliderWindow.js +++ b/src/Widgets/Temporal/View/TemporalSliderWindow.js @@ -1,10 +1,12 @@ +/** @format */ + //Components -import { Window } from "../../../Components/GUI/js/Window"; +import { Window } from '../../../Components/GUI/js/Window'; import './TemporalWindow.css'; /** - * Handles the GUI part enabling the user to specify the chosen "time" (year) + * Handles the GUI part enabling the user to specify the chosen "time" (year) * of observation for displayal of the (3D) scene. * Note that it is not the Temporal View's responsability to * alter/modify/update the scene according to the user specified moment (but @@ -13,25 +15,25 @@ import './TemporalWindow.css'; * @param options : optional parameters (min time, max time and current time) */ export class TemporalSliderWindow extends Window { - constructor(refreshCallback, options = {}) { - super('temporal', 'Temporal Navigation', false); + constructor(refreshCallback, options = {}) { + super('temporal', 'Temporal Navigation', false); - // Minimum and maximum times that can be displayed by this occurence - this.minTime = options.minTime || 2009; - this.maxTime = options.maxTime || 2015; + // Minimum and maximum times that can be displayed by this occurence + this.minTime = options.minTime || 2009; + this.maxTime = options.maxTime || 2015; - // The currently selected timestamp - this.currentTime = options.currentTime || 2009; + // The currently selected timestamp + this.currentTime = options.currentTime || 2009; - // The timestep used to increment or decrement time with the slide buttons. - // Note that timeStep is a "duration" as opposed to a timestamp. - this.timeStep = options.timeStep || 1; + // The timestep used to increment or decrement time with the slide buttons. + // Note that timeStep is a "duration" as opposed to a timestamp. + this.timeStep = options.timeStep || 1; - this.refreshCallback = refreshCallback; - } + this.refreshCallback = refreshCallback; + } - get innerContentHtml() { - return /*html*/` + get innerContentHtml() { + return /*html*/ `
      ${this.minTime}
      ${this.maxTime}
      @@ -40,45 +42,49 @@ export class TemporalSliderWindow extends Window { value=${this.currentTime} step=${this.timeStep}>
      `; - } + } - windowCreated() { - // Magical code to center an absolute positionned window - this.window.style.setProperty('left', '0'); - this.window.style.setProperty('right', '0'); - this.window.style.setProperty('margin-left', 'auto'); - this.window.style.setProperty('margin-right', 'auto'); - // Put it at the bottom of the page - this.window.style.setProperty('top', 'unset'); - this.window.style.setProperty('bottom', '10px'); - this.window.style.setProperty('margin-bottom', 'auto'); - // Window size and center text - this.window.style.setProperty('width', '700px'); - this.window.style.setProperty('height', '115px'); - this.window.style.setProperty('text-align', 'center'); + windowCreated() { + // Magical code to center an absolute positionned window + this.window.style.setProperty('left', '0'); + this.window.style.setProperty('right', '0'); + this.window.style.setProperty('margin-left', 'auto'); + this.window.style.setProperty('margin-right', 'auto'); + // Put it at the bottom of the page + this.window.style.setProperty('top', 'unset'); + this.window.style.setProperty('bottom', '10px'); + this.window.style.setProperty('margin-bottom', 'auto'); + // Window size and center text + this.window.style.setProperty('width', '700px'); + this.window.style.setProperty('height', '115px'); + this.window.style.setProperty('text-align', 'center'); - // Hook up the callbacks - document.getElementById('timeSliderValue').addEventListener( - 'input', this.timeSelection.bind(this), false); - document.getElementById('timeSlider').addEventListener( - 'input', this.timeSelectionSlider.bind(this), false); - } + // Hook up the callbacks + document + .getElementById('timeSliderValue') + .addEventListener('input', this.timeSelection.bind(this), false); + document + .getElementById('timeSlider') + .addEventListener('input', this.timeSelectionSlider.bind(this), false); + } - // Call back on new user input with the date selector - timeSelection() { - this.currentTime = document.getElementById('timeSliderValue').value.toString(); - document.getElementById('timeSlider').value = this.currentTime; - // Eventually inform who it may concern (e.g. an associated iTowns layer) - // that the currentTime has changed: - this.refreshCallback(this.currentTime); - } + // Call back on new user input with the date selector + timeSelection() { + this.currentTime = document + .getElementById('timeSliderValue') + .value.toString(); + document.getElementById('timeSlider').value = this.currentTime; + // Eventually inform who it may concern (e.g. an associated iTowns layer) + // that the currentTime has changed: + this.refreshCallback(this.currentTime); + } - // Call back on new user input with the time slider - timeSelectionSlider() { - this.currentTime = document.getElementById('timeSlider').value.toString(); - document.getElementById('timeSliderValue').value = this.currentTime; - // Eventually inform who it may concern (e.g. an associated iTowns layer) - // that the currentTime has changed: - this.refreshCallback(this.currentTime); - } + // Call back on new user input with the time slider + timeSelectionSlider() { + this.currentTime = document.getElementById('timeSlider').value.toString(); + document.getElementById('timeSliderValue').value = this.currentTime; + // Eventually inform who it may concern (e.g. an associated iTowns layer) + // that the currentTime has changed: + this.refreshCallback(this.currentTime); + } } diff --git a/src/Widgets/Temporal/View/TemporalView.js b/src/Widgets/Temporal/View/TemporalView.js index 794467aa4..532f70f03 100644 --- a/src/Widgets/Temporal/View/TemporalView.js +++ b/src/Widgets/Temporal/View/TemporalView.js @@ -1,3 +1,5 @@ +/** @format */ + //Components import { ModuleView } from '../../../Components/ModuleView/ModuleView.js'; @@ -21,30 +23,38 @@ export class TemporalView extends ModuleView { this.currentTime = temporalOptions.currentTime; function currentTimeUpdated(newDate) { - this.currentTime = Number(newDate); - this.provider.currentTime = this.currentTime; // TODO: verify that the - // flow is good with MVVM - this.provider.changeVisibleTilesStates(); + this.currentTime = Number(newDate); + this.provider.currentTime = this.currentTime; // TODO: verify that the + // flow is good with MVVM + this.provider.changeVisibleTilesStates(); } const refreshCallback = currentTimeUpdated.bind(this); // Callback to get data asynchronously from the tileset.json - function getAsynchronousData(){ - let versions = this.temporalExtension.temporal_tileset.temporalVersions.versions; - let versionTransitions = this.temporalExtension.temporal_tileset.versionTransitions; - return [versions, versionTransitions] - } + function getAsynchronousData() { + let versions = + this.temporalExtension.temporal_tileset.temporalVersions.versions; + let versionTransitions = + this.temporalExtension.temporal_tileset.versionTransitions; + return [versions, versionTransitions]; + } // Select the window type: switch (temporalOptions.view) { - case EnumTemporalWindow.SLIDERWINDOW : - this.temporalWindow = new TemporalSliderWindow(refreshCallback, temporalOptions); - break; - case EnumTemporalWindow.GRAPHWINDOW : - temporalOptions.getAsynchronousData = getAsynchronousData.bind(this); - this.temporalWindow = new TemporalGraphWindow(refreshCallback, temporalOptions); - break; - } + case EnumTemporalWindow.SLIDERWINDOW: + this.temporalWindow = new TemporalSliderWindow( + refreshCallback, + temporalOptions + ); + break; + case EnumTemporalWindow.GRAPHWINDOW: + temporalOptions.getAsynchronousData = getAsynchronousData.bind(this); + this.temporalWindow = new TemporalGraphWindow( + refreshCallback, + temporalOptions + ); + break; + } } ///////////////// @@ -56,4 +66,4 @@ export class TemporalView extends ModuleView { disableView() { this.temporalWindow.dispose(); } -} \ No newline at end of file +} diff --git a/src/Widgets/Temporal/View/TemporalWindow.css b/src/Widgets/Temporal/View/TemporalWindow.css index 8983a912f..e1c9c57c0 100644 --- a/src/Widgets/Temporal/View/TemporalWindow.css +++ b/src/Widgets/Temporal/View/TemporalWindow.css @@ -1,43 +1,45 @@ +/** @format */ + #temporalWindow { - position: absolute; - width: 100%; + position: absolute; + width: 100%; } #timeSliderMinDate { - position: absolute; - left : 10px; - top : 5px; - font: 28px 'Lucida Grande',sans-serif; - font-weight: bold; + position: absolute; + left: 10px; + top: 5px; + font: 28px 'Lucida Grande', sans-serif; + font-weight: bold; } #timeSliderMaxDate { - position: absolute; - right : 10px; - top : 5px; - font: 28px 'Lucida Grande',sans-serif; - font-weight: bold; + position: absolute; + right: 10px; + top: 5px; + font: 28px 'Lucida Grande', sans-serif; + font-weight: bold; } -#timeSliderValue{ - position: absolute; - text-align: center; - margin : auto; - color : black; - font: 28px 'Lucida Grande',sans-serif; - font-weight: bold; - top: 30px; - right : 0; - left : 0; - border: 1px solid black; - background-color: whitesmoke; - height: 40px; - width : 90px; +#timeSliderValue { + position: absolute; + text-align: center; + margin: auto; + color: black; + font: 28px 'Lucida Grande', sans-serif; + font-weight: bold; + top: 30px; + right: 0; + left: 0; + border: 1px solid black; + background-color: whitesmoke; + height: 40px; + width: 90px; } #timeSlider { - width: 65%; - position: absolute; - text-align: center; - margin : auto; - top: 10px; - left: 0; - right : 0; + width: 65%; + position: absolute; + text-align: center; + margin: auto; + top: 10px; + left: 0; + right: 0; } diff --git a/src/Widgets/Temporal/ViewModel/TemporalProvider.js b/src/Widgets/Temporal/ViewModel/TemporalProvider.js index 16f6494e9..622eed27c 100644 --- a/src/Widgets/Temporal/ViewModel/TemporalProvider.js +++ b/src/Widgets/Temporal/ViewModel/TemporalProvider.js @@ -1,224 +1,276 @@ +/** @format */ + //Components -import { TilesManager } from '../../../Components/3DTiles/TilesManager.js' +import { TilesManager } from '../../../Components/3DTiles/TilesManager.js'; import { getVisibleTiles } from '../../../Components/3DTiles/3DTilesUtils.js'; import { CityObjectStyle } from '../../../Components/3DTiles/Model/CityObjectStyle.js'; import { CityObjectID } from '../../../Components/3DTiles/Model/CityObject.js'; /** * The ViewModel of the temporal module. Contains intermediate data structures - * between the model and the view as well as the logic for city objects and + * between the model and the view as well as the logic for city objects and * transactions display. */ export class TemporalProvider { - /** - * Constructs a new temporal provider: initialize data structures - * used for the view (this.COStyles), initialize the possible - * city objects styles that displays transactions and set events. - * @param {$3DTemporalExtension} tempExtModel The model of the temporal - * module (i.e. holding data from the 3D Tiles temporal extension). - * @param {TilesManager} tilesManager The tiles manager associated - * with the itowns 3D Tiles layer holding the temporal extension. - * @param {Number} currentTime The current display time, updated by the - * TemporalView. - */ + /** + * Constructs a new temporal provider: initialize data structures + * used for the view (this.COStyles), initialize the possible + * city objects styles that displays transactions and set events. + * @param {$3DTemporalExtension} tempExtModel The model of the temporal + * module (i.e. holding data from the 3D Tiles temporal extension). + * @param {TilesManager} tilesManager The tiles manager associated + * with the itowns 3D Tiles layer holding the temporal extension. + * @param {Number} currentTime The current display time, updated by the + * TemporalView. + */ constructor(tempExtModel, tilesManager, currentTime) { - this.tempExtModel = tempExtModel; this.tilesManager = tilesManager; this.currentTime = currentTime; - /** Stores city objects (CO) styles per tile and per date - * to avoid computing it multiple times. It's actually a map + /** Stores city objects (CO) styles per tile and per date + * to avoid computing it multiple times. It's actually a map * of a map and its structure is: - * { date: tile : styles[] } } where the position in the styles + * { date: tile : styles[] } } where the position in the styles * array is the id of the city object - * */ + * */ this.COStyles = new Map(); this.initCOStyles(); // Initializes the model. One part of this model is filled when the - // temporal extension is loaded by iTowns; an other part is filled + // temporal extension is loaded by iTowns; an other part is filled // with the event declared below (when a tile is loaded). // See the comment at the end of the $3DTemporalExtension constructor // for more details. this.tilesManager.addEventListener( TilesManager.EVENT_TILE_LOADED, - this.tempExtModel.updateTileExtensionModel.bind( - this.tempExtModel)); + this.tempExtModel.updateTileExtensionModel.bind(this.tempExtModel) + ); // When a tile is loaded, we compute the state of its city objects (e.g. // should they be displayed or not and in which color, etc.) this.tilesManager.addEventListener( - TilesManager.EVENT_TILE_LOADED, - this.changeTileState.bind(this)); + TilesManager.EVENT_TILE_LOADED, + this.changeTileState.bind(this) + ); } /** - * Initializes the styles affected to city objects to represent + * Initializes the styles affected to city objects to represent * transactions (see 3DTiles_temporal extension for more information * on transactions). The names of the styles match transaction names, * except for 'noTransaction' dans 'hide'. */ initCOStyles() { - this.tilesManager.registerStyle('noTransaction', new CityObjectStyle({ - materialProps: { opacity: 1.0, color: 0xffffff } })); // white + this.tilesManager.registerStyle( + 'noTransaction', + new CityObjectStyle({ + materialProps: { opacity: 1.0, color: 0xffffff }, + }) + ); // white - this.tilesManager.registerStyle('creation', new CityObjectStyle({ - materialProps: { opacity: 0.6, color: 0x009900 } })); // green + this.tilesManager.registerStyle( + 'creation', + new CityObjectStyle({ + materialProps: { opacity: 0.6, color: 0x009900 }, + }) + ); // green - this.tilesManager.registerStyle('demolition', new CityObjectStyle({ - materialProps: { opacity: 0.6, color: 0xff0000 } })); // red + this.tilesManager.registerStyle( + 'demolition', + new CityObjectStyle({ + materialProps: { opacity: 0.6, color: 0xff0000 }, + }) + ); // red - this.tilesManager.registerStyle('modification', new CityObjectStyle({ - materialProps: { opacity: 0.6, color: 0xFFD700 } })); // yellow + this.tilesManager.registerStyle( + 'modification', + new CityObjectStyle({ + materialProps: { opacity: 0.6, color: 0xffd700 }, + }) + ); // yellow - this.tilesManager.registerStyle('hide', new CityObjectStyle({ - materialProps: { opacity: 0, color: 0xffffff, alphaTest: 0.3 } })); // hidden + this.tilesManager.registerStyle( + 'hide', + new CityObjectStyle({ + materialProps: { opacity: 0, color: 0xffffff, alphaTest: 0.3 }, + }) + ); // hidden } /** * Sets the style of a given city object in the tiles manager if this - * style has been registered in the tiles manager (e.g. in - * this.initCOStyles()). + * style has been registered in the tiles manager (e.g. in + * this.initCOStyles()). * @param {Number} tileId Id of the tile of the city object. * @param {Number} cityObjectId Id of the city object. * @param {String} styleName Name of the style to apply. */ setCityObjectStyle(tileId, cityObjectId, styleName) { - if(this.tilesManager.isStyleRegistered(styleName)) { - this.tilesManager.setStyle(new CityObjectID(tileId, cityObjectId), - styleName); + if (this.tilesManager.isStyleRegistered(styleName)) { + this.tilesManager.setStyle( + new CityObjectID(tileId, cityObjectId), + styleName + ); } else { - console.warn("Style " + styleName + " is not " + - "registered. Defaulting to style noTransaction.") - this.tilesManager.setStyle(new CityObjectID(tileId, cityObjectId), - 'noTransaction'); + console.warn( + 'Style ' + + styleName + + ' is not ' + + 'registered. Defaulting to style noTransaction.' + ); + this.tilesManager.setStyle( + new CityObjectID(tileId, cityObjectId), + 'noTransaction' + ); } } - /** - * Generates the style name of a transaction. This method is recursive - * for aggregated transactions that may have multiple nested transactions. - * The style name correspond to the one created in the - * initCOStyles method). - * - * @param {$3DTemporalTransaction} transaction The transaction - * to generate the style name from. - * - * @returns {string} If the transaction is a primary transaction, - * returns its type. If it is an aggregated transaction, it returns a - * concatenation of the primary transactions types aggregated in - * transaction, prefixed by 'aggregate'. Currently, no style are - * declared for transactions aggregates for a simpler visual - * rendering. We could also generate styles with random colors - * and add them to a legend and provide a user the possibility to - * update these colors and / or to disable them from the GUI. - */ - getTransactionStyleName(transaction, styleName) { - if (transaction.isPrimary) return transaction.type; - else if (transaction.isAggregate) { - if (styleName === '') styleName = 'aggregate'; // prefix - for (let i = 0 ; i < transaction.transactions.length ; i++) { - styleName = styleName + '-' + this.getTransactionStyleName( - transaction.transactions[i], styleName); - } - return styleName - } else { - console.warn('Transaction which is not a primary nor an aggregate.') - } + /** + * Generates the style name of a transaction. This method is recursive + * for aggregated transactions that may have multiple nested transactions. + * The style name correspond to the one created in the + * initCOStyles method). + * + * @param {$3DTemporalTransaction} transaction The transaction + * to generate the style name from. + * + * @returns {string} If the transaction is a primary transaction, + * returns its type. If it is an aggregated transaction, it returns a + * concatenation of the primary transactions types aggregated in + * transaction, prefixed by 'aggregate'. Currently, no style are + * declared for transactions aggregates for a simpler visual + * rendering. We could also generate styles with random colors + * and add them to a legend and provide a user the possibility to + * update these colors and / or to disable them from the GUI. + */ + getTransactionStyleName(transaction, styleName) { + if (transaction.isPrimary) return transaction.type; + else if (transaction.isAggregate) { + if (styleName === '') styleName = 'aggregate'; // prefix + for (let i = 0; i < transaction.transactions.length; i++) { + styleName = + styleName + + '-' + + this.getTransactionStyleName(transaction.transactions[i], styleName); + } + return styleName; + } else { + console.warn('Transaction which is not a primary nor an aggregate.'); } + } - /* *** Culling with transactions and colors management */ - // Rules for culling: - // * If the feature exists at the currentTime we display it in gray - // * If there is a transaction between the feature and another - // feature at the currentTime: - // * the displayed geometry is the one of the old feature for the - // first half duration of the transaction - // * the displayed geometry is the one of the new feature for the - // second half of the duration - // * the opacity is set to 0.6 - // * the color is set depending on the transaction type - // * else we hide the feature. - culling(BT, tileId, tileTransactions) { - const featuresDisplayStates = []; - for (let i = 0; i < BT.featureIds.length; i++) { - const featureId = BT.featureIds[i]; - if (this.currentTime >= BT.startDates[i] && this.currentTime <= - BT.endDates[i]) { - // ** FEATURE EXISTS - featuresDisplayStates.push('noTransaction'); - this.setCityObjectStyle(tileId, i, 'noTransaction'); - } else if (tileTransactions.has(featureId) && tileTransactions.get(featureId)) { - // ** TRANSACTION CASE - const featureTransactions = tileTransactions.get(featureId); - let hasTransac = false; - if (featureTransactions.asSource) { - const transacAsSource = featureTransactions.asSource - const transacAsSourceHalfDuration = (transacAsSource.endDate - - transacAsSource.startDate) / 2; - if (this.currentTime > transacAsSource.startDate && this.currentTime <= - transacAsSource.startDate + transacAsSourceHalfDuration) { - hasTransac = true; - const transactionStyleName = this.getTransactionStyleName(transacAsSource, ''); - featuresDisplayStates.push(transactionStyleName); - this.setCityObjectStyle(tileId, i, transactionStyleName); - } - } - if (featureTransactions.asDestination) { - const transacAsDest = featureTransactions.asDestination; - const transacAsDestHalfDuration = (transacAsDest.endDate - - transacAsDest.startDate) / 2; - if (this.currentTime > transacAsDest.startDate + - transacAsDestHalfDuration && this.currentTime <= - transacAsDest.endDate) { - hasTransac = true; - const transactionStyleName = this.getTransactionStyleName(transacAsDest, ''); - featuresDisplayStates.push(transactionStyleName); - this.setCityObjectStyle(tileId, i, transactionStyleName); - } - } + /* *** Culling with transactions and colors management */ + // Rules for culling: + // * If the feature exists at the currentTime we display it in gray + // * If there is a transaction between the feature and another + // feature at the currentTime: + // * the displayed geometry is the one of the old feature for the + // first half duration of the transaction + // * the displayed geometry is the one of the new feature for the + // second half of the duration + // * the opacity is set to 0.6 + // * the color is set depending on the transaction type + // * else we hide the feature. + culling(BT, tileId, tileTransactions) { + const featuresDisplayStates = []; + for (let i = 0; i < BT.featureIds.length; i++) { + const featureId = BT.featureIds[i]; + if ( + this.currentTime >= BT.startDates[i] && + this.currentTime <= BT.endDates[i] + ) { + // ** FEATURE EXISTS + featuresDisplayStates.push('noTransaction'); + this.setCityObjectStyle(tileId, i, 'noTransaction'); + } else if ( + tileTransactions.has(featureId) && + tileTransactions.get(featureId) + ) { + // ** TRANSACTION CASE + const featureTransactions = tileTransactions.get(featureId); + let hasTransac = false; + if (featureTransactions.asSource) { + const transacAsSource = featureTransactions.asSource; + const transacAsSourceHalfDuration = + (transacAsSource.endDate - transacAsSource.startDate) / 2; + if ( + this.currentTime > transacAsSource.startDate && + this.currentTime <= + transacAsSource.startDate + transacAsSourceHalfDuration + ) { + hasTransac = true; + const transactionStyleName = this.getTransactionStyleName( + transacAsSource, + '' + ); + featuresDisplayStates.push(transactionStyleName); + this.setCityObjectStyle(tileId, i, transactionStyleName); + } + } + if (featureTransactions.asDestination) { + const transacAsDest = featureTransactions.asDestination; + const transacAsDestHalfDuration = + (transacAsDest.endDate - transacAsDest.startDate) / 2; + if ( + this.currentTime > + transacAsDest.startDate + transacAsDestHalfDuration && + this.currentTime <= transacAsDest.endDate + ) { + hasTransac = true; + const transactionStyleName = this.getTransactionStyleName( + transacAsDest, + '' + ); + featuresDisplayStates.push(transactionStyleName); + this.setCityObjectStyle(tileId, i, transactionStyleName); + } + } - if (!hasTransac) { - // ** TRANSACTION NOT AT THE RIGHT DATE - featuresDisplayStates.push('hide'); - this.setCityObjectStyle(tileId, i, 'hide'); - } - } else { - // ** FEATURE DOES NOT EXIST AND THERE IS NO TRANSACTION + if (!hasTransac) { + // ** TRANSACTION NOT AT THE RIGHT DATE + featuresDisplayStates.push('hide'); + this.setCityObjectStyle(tileId, i, 'hide'); + } + } else { + // ** FEATURE DOES NOT EXIST AND THERE IS NO TRANSACTION - // ** MANAGE CREATIONS AND DEMOLITIONS (this step must be - // done because the creation and demolitions transactions - // are currently not in the tileset. However, the tileset - // should have them later on). - const halfVintage = 1.5; + // ** MANAGE CREATIONS AND DEMOLITIONS (this step must be + // done because the creation and demolitions transactions + // are currently not in the tileset. However, the tileset + // should have them later on). + const halfVintage = 1.5; - if (this.currentTime + halfVintage >= BT.startDates[i] && - this.currentTime < BT.startDates[i]) { - // ** CREATION - featuresDisplayStates.push('creation'); - this.setCityObjectStyle(tileId, i, 'creation'); - } else if (this.currentTime - halfVintage < BT.endDates[i] && - this.currentTime > BT.endDates[i]) { - // ** DEMOLITION - featuresDisplayStates.push('demolition'); - this.setCityObjectStyle(tileId, i, 'demolition'); - } else { - // ** FEATURE DOES NOT EXIST - featuresDisplayStates.push('hide'); - this.setCityObjectStyle(tileId, i, 'hide'); - } - } + if ( + this.currentTime + halfVintage >= BT.startDates[i] && + this.currentTime < BT.startDates[i] + ) { + // ** CREATION + featuresDisplayStates.push('creation'); + this.setCityObjectStyle(tileId, i, 'creation'); + } else if ( + this.currentTime - halfVintage < BT.endDates[i] && + this.currentTime > BT.endDates[i] + ) { + // ** DEMOLITION + featuresDisplayStates.push('demolition'); + this.setCityObjectStyle(tileId, i, 'demolition'); + } else { + // ** FEATURE DOES NOT EXIST + featuresDisplayStates.push('hide'); + this.setCityObjectStyle(tileId, i, 'hide'); + } } + } - return featuresDisplayStates; + return featuresDisplayStates; } /** - * Computes and sets the style of the features of a given tile. + * Computes and sets the style of the features of a given tile. * @param {Number} tileId The id of the given tile. */ computeTileState(tileId) { @@ -226,53 +278,63 @@ export class TemporalProvider { if (tileId === 0) return; // Skip the root tile which has no geometry // If it has already been computed, don't do it again - if (this.COStyles.has(this.currentTime) && - this.COStyles.get(this.currentTime).has(tileId)) { - const tileDisplayStates = this.COStyles.get(this.currentTime).get(tileId); - for (let i = 0 ; i < tileDisplayStates.length ; i++) { - this.setCityObjectStyle(tileId, i, tileDisplayStates[i]); - } + if ( + this.COStyles.has(this.currentTime) && + this.COStyles.get(this.currentTime).has(tileId) + ) { + const tileDisplayStates = this.COStyles.get(this.currentTime).get(tileId); + for (let i = 0; i < tileDisplayStates.length; i++) { + this.setCityObjectStyle(tileId, i, tileDisplayStates[i]); + } } else { - if (this.tempExtModel.temporalBatchTables.has(tileId)) { - const tileTemporalBT = this.tempExtModel.temporalBatchTables.get(tileId); - if (! this.COStyles.has(this.currentTime)) { - this.COStyles.set(this.currentTime, new Map()); - } - this.COStyles.get(this.currentTime).set(tileId, this.culling(tileTemporalBT, tileId, this.tempExtModel.transactionsPerTile.get(tileId))); - } else { + if (this.tempExtModel.temporalBatchTables.has(tileId)) { + const tileTemporalBT = + this.tempExtModel.temporalBatchTables.get(tileId); + if (!this.COStyles.has(this.currentTime)) { + this.COStyles.set(this.currentTime, new Map()); + } + this.COStyles.get(this.currentTime).set( + tileId, + this.culling( + tileTemporalBT, + tileId, + this.tempExtModel.transactionsPerTile.get(tileId) + ) + ); + } else { console.warn(`Cannot compute features states for tile ${tileId} since the temporal extension of the batch table has not yet been loaded for this tile`); return; - } + } } } /** * Computes and applies the display state of a tile. This method - * is triggered by an event (TilesManager.EVENT_TILE_LOADED) - * indicating that a new tile content has been loaded (e.g. because it + * is triggered by an event (TilesManager.EVENT_TILE_LOADED) + * indicating that a new tile content has been loaded (e.g. because it * becomes visible by the camera) * @param {Object} tileContent The tile content loaded. */ changeTileState(tileContent) { - this.computeTileState(tileContent.tileId); - this.tilesManager.applyStyleToTile(tileContent.tileId, - { updateView: false }); - } + this.computeTileState(tileContent.tileId); + this.tilesManager.applyStyleToTile(tileContent.tileId, { + updateView: false, + }); + } /** - * Computes and applies the display state of currently visible tiles - * (i.e. those in the camera field of view and having features - * at the current display time). This method is triggered by the + * Computes and applies the display state of currently visible tiles + * (i.e. those in the camera field of view and having features + * at the current display time). This method is triggered by the * TemporalView when the time of the view is updated. */ changeVisibleTilesStates() { - const tiles = getVisibleTiles(this.tilesManager.layer); - for (let i = 0; i < tiles.length; i++) { - this.computeTileState(tiles[i].tileId); - } - this.tilesManager.applyStyles(); + const tiles = getVisibleTiles(this.tilesManager.layer); + for (let i = 0; i < tiles.length; i++) { + this.computeTileState(tiles[i].tileId); + } + this.tilesManager.applyStyles(); } - -} \ No newline at end of file +} From c6fc54f476cba16a922854d8e557889a51fc5381 Mon Sep 17 00:00:00 2001 From: valentinMachado Date: Tue, 8 Jun 2021 11:10:10 +0200 Subject: [PATCH 38/68] eslint return no error --- .eslintrc.js | 1 + .travis.yml | 11 +- package.json | 3 +- src/Components/3DTiles/3DTilesUtils.js | 20 +- src/Components/3DTiles/Model/CityObject.js | 2 +- .../3DTiles/Model/CityObjectStyle.js | 4 +- src/Components/3DTiles/StyleManager.js | 14 +- src/Components/3DTiles/TilesManager.js | 60 +-- src/Components/Camera/CameraUtils.js | 17 +- src/Components/Camera/PositionerWindow.js | 4 +- .../DataProcessing/DataProcessing.js | 36 +- src/Components/Events/EventSender.js | 96 ++--- src/Components/GUI/js/Draggable.js | 70 ++-- src/Components/GUI/js/Window.js | 396 +++++++++--------- src/Components/GUI/js/WindowExtension.js | 8 +- src/Components/GUI/js/WindowManager.js | 2 +- src/Components/LayerManager/LayerManager.js | 254 +++++------ src/Components/ModuleView/ModuleView.js | 84 ++-- src/Components/Request/RequestService.js | 132 +++--- src/Game/Components/AssetsManager.js | 22 +- .../Shared/GameObject/Components/Collider.js | 50 ++- src/Game/Shared/GameObject/GameObject.js | 9 - src/Game/Shared/WorldState.js | 2 +- src/Game/UDVDebugger/UDVDebugger.js | 18 - .../View/CityObjectFilterWindow.js | 4 +- .../CityObjects/View/CityObjectWindow.js | 6 +- .../CityObjects/ViewModel/AttributeFilter.js | 6 +- .../ViewModel/CityObjectProvider.js | 6 +- .../Documents/View/DocumentNavigatorWindow.js | 16 +- .../3DTilesDebug/views/3DTilesDebugWindow.js | 4 +- .../Contribute/View/DocumentCreationWindow.js | 2 +- .../views/DocumentCommentsWindow.js | 8 +- .../Geocoding/services/GeocodingService.js | 4 +- .../Geocoding/views/GeocodingView.js | 4 +- .../GuidedTour/GuidedTourController.js | 4 +- src/Widgets/LayerChoice/views/LayerChoice.js | 36 +- .../Links/View/CityObjectLinkInterface.js | 7 +- .../Links/View/DocumentLinkInterface.js | 12 +- 38 files changed, 715 insertions(+), 719 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 00b804fc4..6b41370fc 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -19,5 +19,6 @@ module.exports = { 'linebreak-style': ['error', 'unix'], quotes: ['error', 'single'], semi: ['error', 'always'], + 'no-unused-vars': 'off', }, }; diff --git a/.travis.yml b/.travis.yml index fcaa6727f..3683952db 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,10 +18,9 @@ install: jobs: include: - - stage: test + - stage: build script: - - npm run test - # - stage: lint - # script: - # - ./node_modules/eslint/bin/eslint.js --version - # - npm run lint + - npm run build + - stage: eslint + script: + - npm run eslint diff --git a/package.json b/package.json index 28ac51c2e..f9a72ec1b 100644 --- a/package.json +++ b/package.json @@ -4,8 +4,7 @@ "description": "A collection of itowns plugins", "main": "src", "scripts": { - "eslint": "./node_modules/.bin/eslint ./src", - "test": "npm run build", + "eslint": "./node_modules/.bin/eslint ./src --fix", "build": "cross-env NODE_ENV=production webpack", "build-debug": "cross-env NODE_ENV=development webpack", "debug": "nodemon --verbose --watch src --delay 2500ms ./bin/debug.js -e js,css,html" diff --git a/src/Components/3DTiles/3DTilesUtils.js b/src/Components/3DTiles/3DTilesUtils.js index 97f192b35..4d49d5235 100644 --- a/src/Components/3DTiles/3DTilesUtils.js +++ b/src/Components/3DTiles/3DTilesUtils.js @@ -9,9 +9,9 @@ import { objectEquals } from '../DataProcessing/DataProcessing.js'; * @param {*} tile A 3DTiles tile object from THREE.js. */ export function getBatchTableFromTile(tile) { - if (!!tile.batchTable) { + if (tile.batchTable) { return tile.batchTable; - } else if (!!tile.parent) { + } else if (tile.parent) { return getBatchTableFromTile(tile.parent); } return undefined; @@ -66,11 +66,11 @@ export function getVisibleTiles(layer) { let rootTile = layer.object3d.children[0]; let tiles = []; let exploreTree = (node) => { - if (!!node) { - if (!!node.batchTable) { + if (node) { + if (node.batchTable) { // It's an actual tile tiles.push(node); - }; + } for (let childIndex = 0; childIndex < node.children.length; childIndex++) { let child = node.children[childIndex]; if (child.type === 'Object3D') { @@ -157,8 +157,8 @@ export function setTileVerticesColor(tile, newColor, indexArray = null) { if (!!indexArray && (lowerBound > i || upperBound < i)) { //If i is not one of the selected indexes, we keep the previous color let previousColor = (tile.geometry.attributes.color) ? - tile.geometry.attributes.color.array.slice(i * 3, i * 3 + 3) : - tile.material.color.toArray(); + tile.geometry.attributes.color.array.slice(i * 3, i * 3 + 3) : + tile.material.color.toArray(); vertexColor = previousColor; } @@ -215,8 +215,8 @@ export function createTileGroups(tile, materialsProps, ranges) { let mesh = getMeshFromTile(tile); let defaultMaterial = Array.isArray(mesh.material) ? - mesh.material[0] : - mesh.material; + mesh.material[0] : + mesh.material; // Reset the materials mesh.material = [ defaultMaterial ]; @@ -335,7 +335,7 @@ export function createTileGroupsFromBatchIDs(tile, groups) { if (materialIndex < 0) { // If the material is new, push it materialIndex = materials.length; - materials.push(group.material) + materials.push(group.material); } // Push the batch IDs and remember their material diff --git a/src/Components/3DTiles/Model/CityObject.js b/src/Components/3DTiles/Model/CityObject.js index 2cf7a218e..b50305560 100644 --- a/src/Components/3DTiles/Model/CityObject.js +++ b/src/Components/3DTiles/Model/CityObject.js @@ -1,4 +1,4 @@ -import { Tile } from "./Tile.js"; +import { Tile } from './Tile.js'; import * as THREE from 'three'; /** diff --git a/src/Components/3DTiles/Model/CityObjectStyle.js b/src/Components/3DTiles/Model/CityObjectStyle.js index 0ee07dff1..7c3c4c509 100644 --- a/src/Components/3DTiles/Model/CityObjectStyle.js +++ b/src/Components/3DTiles/Model/CityObjectStyle.js @@ -1,4 +1,4 @@ -import * as THREE from "three"; +import * as THREE from 'three'; /** * Represents the style of a tile part. Accepted parameters are : @@ -14,7 +14,7 @@ export class CityObjectStyle { */ this.materialProps = null; - if (typeof(params) !== "object") { + if (typeof(params) !== 'object') { throw 'TilePartStyle require parameters in its constructor'; } diff --git a/src/Components/3DTiles/StyleManager.js b/src/Components/3DTiles/StyleManager.js index c72c513eb..5f668076e 100644 --- a/src/Components/3DTiles/StyleManager.js +++ b/src/Components/3DTiles/StyleManager.js @@ -1,7 +1,7 @@ -import { CityObjectStyle } from "./Model/CityObjectStyle.js"; -import { CityObjectID } from "./Model/CityObject.js"; -import { createTileGroups } from "./3DTilesUtils.js"; -import { Tile } from "./Model/Tile.js"; +import { CityObjectStyle } from './Model/CityObjectStyle.js'; +import { CityObjectID } from './Model/CityObject.js'; +import { createTileGroups } from './3DTilesUtils.js'; +import { Tile } from './Model/Tile.js'; /** * Class used to manage the styles of city objects. @@ -115,9 +115,9 @@ export class StyleManager { * @returns {CityObjectStyle} */ getStyle(identifier) { - if (typeof(identifier) === "string") { + if (typeof(identifier) === 'string') { return this.registeredStyles[identifier]; - } else if (typeof(identifier) === "number") { + } else if (typeof(identifier) === 'number') { return this.anonymousStyles[identifier]; } throw 'Style identifier must be a string or a number'; @@ -197,7 +197,7 @@ export class StyleManager { this._registerUsage(styleIdentifier, cityObjectId); } else if (Array.isArray(cityObjectId)) { cityObjectId.sort((idA, idB) => { - return idA.tileId - idB.tileId + return idA.tileId - idB.tileId; }); for (let id of cityObjectId) { if (this.styleTable[id.tileId] === undefined) { diff --git a/src/Components/3DTiles/TilesManager.js b/src/Components/3DTiles/TilesManager.js index 792e03d0c..12b645fa5 100644 --- a/src/Components/3DTiles/TilesManager.js +++ b/src/Components/3DTiles/TilesManager.js @@ -1,9 +1,9 @@ -import { Tile } from "./Model/Tile.js"; -import { getVisibleTiles, updateITownsView } from "./3DTilesUtils.js"; -import { CityObjectID, CityObject, createCityObjectID } from "./Model/CityObject.js"; -import { CityObjectStyle } from "./Model/CityObjectStyle.js"; -import { StyleManager } from "./StyleManager.js"; -import { EventSender } from "../Events/EventSender.js"; +import { Tile } from './Model/Tile.js'; +import { getVisibleTiles, updateITownsView } from './3DTilesUtils.js'; +import { CityObjectID, CityObject, createCityObjectID } from './Model/CityObject.js'; +import { CityObjectStyle } from './Model/CityObjectStyle.js'; +import { StyleManager } from './StyleManager.js'; +import { EventSender } from '../Events/EventSender.js'; /** * Manages the tiles and the style for city objects. @@ -54,15 +54,15 @@ export class TilesManager extends EventSender { this.tiles = []; if (this.totalTileCount !== 0) { - // Load existing tiles - const tiles = getVisibleTiles(this.layer); - for (let tile of tiles) { - if (this.tiles[tile.tileId] === undefined) { - this.tiles[tile.tileId] = new Tile(this.layer, tile.tileId); - this.tiles[tile.tileId].loadCityObjects(); - this.loadedTileCount += 1; - } + // Load existing tiles + const tiles = getVisibleTiles(this.layer); + for (let tile of tiles) { + if (this.tiles[tile.tileId] === undefined) { + this.tiles[tile.tileId] = new Tile(this.layer, tile.tileId); + this.tiles[tile.tileId].loadCityObjects(); + this.loadedTileCount += 1; } + } } ///// EVENTS @@ -93,22 +93,22 @@ export class TilesManager extends EventSender { } loadTile(tile) { - // Update the totalTileCount. - // TODO: this should be managed with an event: when the tileset is - // loaded (i.e. tileIndex filled), then totalTileCount should be set. - this.totalTileCount = this.layer.tileset.tiles.length; - // Verifies that the tile has not been already added (might be removed - // when tile unloading will be managed) - if (this.tiles[tile.tileId] === undefined) { - this.tiles[tile.tileId] = new Tile(this.layer, tile.tileId); - this.tiles[tile.tileId].loadCityObjects(); - this.loadedTileCount += 1; - } - // Callback when a tile is loaded. - // TODO: Les tuiles d'iTowns devraient etre rendues invisibles plutot - // que d'etre déchargées et rechargées. A ce moment là, ce callback - // pourra etre dans le if ci dessus - this.sendEvent(TilesManager.EVENT_TILE_LOADED, tile); + // Update the totalTileCount. + // TODO: this should be managed with an event: when the tileset is + // loaded (i.e. tileIndex filled), then totalTileCount should be set. + this.totalTileCount = this.layer.tileset.tiles.length; + // Verifies that the tile has not been already added (might be removed + // when tile unloading will be managed) + if (this.tiles[tile.tileId] === undefined) { + this.tiles[tile.tileId] = new Tile(this.layer, tile.tileId); + this.tiles[tile.tileId].loadCityObjects(); + this.loadedTileCount += 1; + } + // Callback when a tile is loaded. + // TODO: Les tuiles d'iTowns devraient etre rendues invisibles plutot + // que d'etre déchargées et rechargées. A ce moment là, ce callback + // pourra etre dans le if ci dessus + this.sendEvent(TilesManager.EVENT_TILE_LOADED, tile); } /** diff --git a/src/Components/Camera/CameraUtils.js b/src/Components/Camera/CameraUtils.js index 74d5815b5..f5cb1794e 100644 --- a/src/Components/Camera/CameraUtils.js +++ b/src/Components/Camera/CameraUtils.js @@ -1,6 +1,10 @@ +/** @format */ + +const THREE = require('three'); + /** * Makes the camera move to focus on the target position. - * + * * @param {itowns.View} view The iTowns view. * @param {itowns.PlanarControls} controls The camera controls. * @param {THREE.Vector3} targetPos The target position. @@ -23,10 +27,11 @@ export function focusCameraOn(view, controls, targetPos, options = {}) { const horizontalDist = options.horizontalDistance || 1000; let cameraPos = view.camera.camera3D.position.clone(); - const direction = (new THREE.Vector3()).subVectors(targetPos, cameraPos); - const currentDist = Math.sqrt(direction.x * direction.x + - direction.y * direction.y); - cameraPos.addScaledVector(direction, (1 - horizontalDist / currentDist)); + const direction = new THREE.Vector3().subVectors(targetPos, cameraPos); + const currentDist = Math.sqrt( + direction.x * direction.x + direction.y * direction.y + ); + cameraPos.addScaledVector(direction, 1 - horizontalDist / currentDist); cameraPos.z = targetPos.z + verticalDist; const travelDuration = duration ? duration : 'auto'; const timeoutDuration = duration ? duration * 1000 : 0; @@ -36,4 +41,4 @@ export function focusCameraOn(view, controls, targetPos, options = {}) { reject(e); } }); -} \ No newline at end of file +} diff --git a/src/Components/Camera/PositionerWindow.js b/src/Components/Camera/PositionerWindow.js index 81ad9ecef..fc2c3eed3 100644 --- a/src/Components/Camera/PositionerWindow.js +++ b/src/Components/Camera/PositionerWindow.js @@ -1,4 +1,4 @@ -import { Window } from "../GUI/js/Window"; +import { Window } from '../GUI/js/Window'; import { MAIN_LOOP_EVENTS } from 'itowns'; import * as THREE from 'three'; @@ -60,7 +60,7 @@ export class PositionerWindow extends Window { this.buttonValidateElement.onclick = () => { this._validate(); - } + }; } ///////////////////////// diff --git a/src/Components/DataProcessing/DataProcessing.js b/src/Components/DataProcessing/DataProcessing.js index c0c6f0baa..4da11ed30 100644 --- a/src/Components/DataProcessing/DataProcessing.js +++ b/src/Components/DataProcessing/DataProcessing.js @@ -3,14 +3,17 @@ * would update those fields to an empty string if they were sent in the * body. To check if a value is empty, this function just convert it into * a boolean. + * + * @format * @param {FormData} formData The form data. * @returns The same data, without the fields containing an empty value. */ + export function removeEmptyValues(formData) { let emptyKeys = []; formData.forEach((value, key) => { if (!value) { - emptyKeys.push(key) + emptyKeys.push(key); } }); emptyKeys.forEach((key) => { @@ -24,7 +27,7 @@ export function removeEmptyValues(formData) { * on a file) to a data URI. This is required, for example, to display images * fetched from the server. As we need authentication headers to retrieve some * protected files, we get the raw data dynamically and need to convert it to - * a data URI do display it. + * a data URI do display it. * The basic scheme of the URI is defined in the * [RFC 2397](https://tools.ietf.org/html/rfc2397), with the mediaType set to * `mimeType` and the raw data converted to base64. @@ -45,12 +48,13 @@ export function imageToDataURI(arrayBuffer, mimeType, chunkSize = 8 * 1024) { // String.fromCharCode), we need to split it into chunks let responseAsString = ''; for (let i = 0; i < responseArray.length / chunkSize; i++) { - responseAsString += String.fromCharCode.apply(null, - responseArray.slice(i * chunkSize, (i + 1) * chunkSize)); + responseAsString += String.fromCharCode.apply( + null, + responseArray.slice(i * chunkSize, (i + 1) * chunkSize) + ); } - let b64data = 'data:' + mimeType - + ';base64,' + btoa(responseAsString); + let b64data = 'data:' + mimeType + ';base64,' + btoa(responseAsString); return b64data; } @@ -58,11 +62,11 @@ export function imageToDataURI(arrayBuffer, mimeType, chunkSize = 8 * 1024) { * Gets an attribute of an object from the given path. To get nested attributes, * the path qualifiers must be separated by dots ('.'). If the path is not * nested (does not contain any dot), the function is equivalent to `obj[path]`. - * - * - * @param {object} obj - * @param {string} path - * + * + * + * @param {object} obj + * @param {string} path + * * @example * const obj = {test: {msg: "Hello world !"}}; * console.log(getAttributeByPath(obj, "test.msg")); // prints "Hello world !"; @@ -83,7 +87,7 @@ export function getAttributeByPath(obj, path) { /** * Checks the equality of two objects by their properties. For two objects to * be equal, they must have the same keys and the same values. - * + * * @param {any} a An object. * @param {any} b An object. */ @@ -91,16 +95,16 @@ export function objectEquals(a, b) { // Set of a's keys let keys = new Set(Object.keys(a)); for (let key of Object.keys(b)) { - if (!keys.has(key)) { + if (!keys.has(key)) { // If b has a key unknown to a, they aren't equal - return false; + return false; } } for (let key of keys) { // For each key of a, b must also have the key and the values must be equal if (b[key] === undefined || a[key] !== b[key]) { - return false; + return false; } } return true; -}; \ No newline at end of file +} diff --git a/src/Components/Events/EventSender.js b/src/Components/Events/EventSender.js index 212c1a9e5..78fe89c43 100644 --- a/src/Components/Events/EventSender.js +++ b/src/Components/Events/EventSender.js @@ -4,98 +4,98 @@ * specific events, or to all events. */ export class EventSender { - constructor() { - /** + constructor() { + /** * The listeners attached to a specific event. * * @type {Object. any>>} */ - this.eventListeners = {}; - /** + this.eventListeners = {}; + /** * The listeners attached to no particular event. They will receive * all notifications. * * @type {Array<(data: any) => any>} */ - this.allEventsListeners = []; - } + this.allEventsListeners = []; + } - /** + /** * Registers an event. Should be called by the implementing class to * specify its own events. * @param event The event to register. Can be of any type. The class will be * able to send only the events that it has registered. */ - registerEvent(event) { - this.eventListeners[event] = []; - } + registerEvent(event) { + this.eventListeners[event] = []; + } - /** + /** * Registers an event listener attached to a specific event. The `action` * function will be called only when `event` is fired. * * @param event The event to listen to. * @param {(data: any)} action The function to call. */ - addEventListener(event, action) { - if (this.eventListeners[event]) { - this.eventListeners[event].push(action); - } else { - throw `This event is not defined by this listener : ${event}`; - } + addEventListener(event, action) { + if (this.eventListeners[event]) { + this.eventListeners[event].push(action); + } else { + throw `This event is not defined by this listener : ${event}`; } + } - /** + /** * Registers an event listener attached to no specific event. The `action` * function will be called when any event is fired. * * @param {(event: any, data: any)} action The function to call. */ - addListener(action) { - if (typeof(action) !== 'function') { - throw 'A listener must be a function'; - } - this.allEventsListeners.push(action); + addListener(action) { + if (typeof(action) !== 'function') { + throw 'A listener must be a function'; } + this.allEventsListeners.push(action); + } - /** + /** * Sends an event to the listeners. `event` must be first registers through the `registerEvent` * method. An argument can be passed but is optional. * * @param event The event to fire. Must be first registered. * @param data The optional data to pass as parameter. */ - async sendEvent(event, data = null) { - let listeners = this.eventListeners[event]; - if (!!listeners) { - for (let action of listeners) { - action(data); - } - for (let action of this.allEventsListeners) { - action(event, data); - } - } else { - throw `This event must be registered before being sent : ${event}`; - } + async sendEvent(event, data = null) { + let listeners = this.eventListeners[event]; + if (listeners) { + for (let action of listeners) { + action(data); + } + for (let action of this.allEventsListeners) { + action(event, data); + } + } else { + throw `This event must be registered before being sent : ${event}`; } + } - /** + /** * Removes a specific event listener. * * @param {(data: any) => any} action The event listener to remove. This * should be the same reference that was used to register it. */ - removeEventListener(action) { - for (let eventListeners of Object.values(this.eventListeners)) { - let index = eventListeners.findIndex((list) => action === list); - if (index >= 0) { - eventListeners.splice(index, 1); - } - } + removeEventListener(action) { + for (let eventListeners of Object.values(this.eventListeners)) { + let index = eventListeners.findIndex((list) => action === list); + if (index >= 0) { + eventListeners.splice(index, 1); + } + } - let index = this.allEventsListeners.findIndex((list) => action === list); - if (index >= 0) { - this.allEventsListeners.splice(index, 1); - } + let index = this.allEventsListeners.findIndex((list) => action === list); + if (index >= 0) { + this.allEventsListeners.splice(index, 1); } + } } \ No newline at end of file diff --git a/src/Components/GUI/js/Draggable.js b/src/Components/GUI/js/Draggable.js index fe4149478..7ae2bef9e 100644 --- a/src/Components/GUI/js/Draggable.js +++ b/src/Components/GUI/js/Draggable.js @@ -1,44 +1,44 @@ // Code from https://www.w3schools.com/howto/howto_js_draggable.asp // Make the DIV element draggable: export function dragElement(elmnt, dragelmnt) { - var pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0; + var pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0; - dragelmnt.onmousedown = dragMouseDown; + dragelmnt.onmousedown = dragMouseDown; - function dragMouseDown(e) { - e = e || window.event; - // get the mouse cursor position at startup: - pos3 = e.clientX; - pos4 = e.clientY; - document.onmouseup = closeDragElement; - // call a function whenever the cursor moves: - document.onmousemove = elementDrag; - } + function dragMouseDown(e) { + e = e || window.event; + // get the mouse cursor position at startup: + pos3 = e.clientX; + pos4 = e.clientY; + document.onmouseup = closeDragElement; + // call a function whenever the cursor moves: + document.onmousemove = elementDrag; + } - function elementDrag(e) { - e = e || window.event; - e.preventDefault(); - // calculate the new cursor position: - pos1 = pos3 - e.clientX; - pos2 = pos4 - e.clientY; - pos3 = e.clientX; - pos4 = e.clientY; - // set the element's new position: - let newTop = (elmnt.offsetTop - pos2); - if (newTop < 0) { - newTop = 0; - } - let newLeft = (elmnt.offsetLeft - pos1); - if (newLeft < 0) { - newLeft = 0; - } - elmnt.style.top = newTop + "px"; - elmnt.style.left = newLeft + "px"; + function elementDrag(e) { + e = e || window.event; + e.preventDefault(); + // calculate the new cursor position: + pos1 = pos3 - e.clientX; + pos2 = pos4 - e.clientY; + pos3 = e.clientX; + pos4 = e.clientY; + // set the element's new position: + let newTop = (elmnt.offsetTop - pos2); + if (newTop < 0) { + newTop = 0; } - - function closeDragElement() { - // stop moving when mouse button is released: - document.onmouseup = null; - document.onmousemove = null; + let newLeft = (elmnt.offsetLeft - pos1); + if (newLeft < 0) { + newLeft = 0; } + elmnt.style.top = newTop + 'px'; + elmnt.style.left = newLeft + 'px'; + } + + function closeDragElement() { + // stop moving when mouse button is released: + document.onmouseup = null; + document.onmousemove = null; + } } \ No newline at end of file diff --git a/src/Components/GUI/js/Window.js b/src/Components/GUI/js/Window.js index 229bccd08..47d92c3b7 100644 --- a/src/Components/GUI/js/Window.js +++ b/src/Components/GUI/js/Window.js @@ -1,6 +1,6 @@ import { dragElement } from './Draggable.js'; import { ModuleView } from '../../ModuleView/ModuleView.js'; -import { windowManager } from "./WindowManager.js"; +import { windowManager } from './WindowManager.js'; import { WindowExtension } from './WindowExtension.js'; // Documentation is on the Wiki @@ -12,7 +12,7 @@ import { WindowExtension } from './WindowExtension.js'; * @extends ModuleView */ export class Window extends ModuleView { - /** + /** * Creates a window. * * @param {string} uniqueName The name used to generate HTML ids. @@ -21,160 +21,160 @@ export class Window extends ModuleView { * the 'close' button is hit. If set to true, the window will `hide`. If set * to false, the window will `dispose`. */ - constructor(uniqueName, title, hideOnClose = true) { - super(); + constructor(uniqueName, title, hideOnClose = true) { + super(); - /** + /** * Name of the window. Used to generate unique ids. * * @member {string} */ - this.name = uniqueName; - /** + this.name = uniqueName; + /** * Title displayed on the window. * * @member {string} */ - this.title = title; - /** + this.title = title; + /** * Behaviour of the window when the 'close' button is hit. If set to * true, the window will `hide`. If set to false, the window will * `dispose`. * * @member {boolean} */ - this.hideOnClose = hideOnClose; + this.hideOnClose = hideOnClose; - /** + /** * Defines if the window has its default style. If set to false, you * should override the `html` getter and set the `windowDisplayWhenVisible` * property. * * @type {true} */ - this.defaultStyle = true; + this.defaultStyle = true; - /** + /** * Define the css `display` property when the window is visible. * * @type {string} */ - this.windowDisplayWhenVisible = 'grid'; + this.windowDisplayWhenVisible = 'grid'; - /** + /** * The list of extensions for this window. * * @type {Array} */ - this.windowExtensions = []; + this.windowExtensions = []; - this.registerEvent(Window.EVENT_CREATED); - this.registerEvent(Window.EVENT_DESTROYED); - this.registerEvent(Window.EVENT_SHOWN); - this.registerEvent(Window.EVENT_HIDDEN); + this.registerEvent(Window.EVENT_CREATED); + this.registerEvent(Window.EVENT_DESTROYED); + this.registerEvent(Window.EVENT_SHOWN); + this.registerEvent(Window.EVENT_HIDDEN); - windowManager.registerWindow(this); - } + windowManager.registerWindow(this); + } - //////////// Methods to override - //////////////////////////////// + //////////// Methods to override + //////////////////////////////// - /** + /** * HTML string representing the inner content of the window. * * @abstract */ - get innerContentHtml() { - return null; - }; + get innerContentHtml() { + return null; + } - /** + /** * Method called when the window is created. During and after the call, * all HTML properties are not null. * * @abstract */ - windowCreated() { + windowCreated() { - }; + } - /** + /** * Method called when the window is destroyed. * * @abstract */ - windowDestroyed() { + windowDestroyed() { - }; + } - //////////// Do NOT override these methods - ////////////////////////////////////////// + //////////// Do NOT override these methods + ////////////////////////////////////////// - /** + /** * Creates the HTML elements of the window and add them to the given parent * node. Calls the `windowCreated` hook method and sends two events, * `EVENT_CREATED` and `EVENT_SHOWN`. * * @param {HTMLElement} htmlElement */ - appendTo(htmlElement) { - if (!this.isCreated) { - this.parentElement = htmlElement; - let windowDiv = document.createElement('div'); - windowDiv.innerHTML = this.html; - windowDiv.id = this.windowId; - htmlElement.appendChild(windowDiv); - if (this.defaultStyle) { - windowDiv.className = "window"; - dragElement(windowDiv, this.header); - this.headerCloseButton.onclick = this.disable.bind(this); - } - - for (let extension of this.windowExtensions) { - extension.appendTo(this.window); - } - - this.windowCreated(); - this.sendEvent(Window.EVENT_CREATED); - this.sendEvent(Window.EVENT_SHOWN); - } + appendTo(htmlElement) { + if (!this.isCreated) { + this.parentElement = htmlElement; + let windowDiv = document.createElement('div'); + windowDiv.innerHTML = this.html; + windowDiv.id = this.windowId; + htmlElement.appendChild(windowDiv); + if (this.defaultStyle) { + windowDiv.className = 'window'; + dragElement(windowDiv, this.header); + this.headerCloseButton.onclick = this.disable.bind(this); + } + + for (let extension of this.windowExtensions) { + extension.appendTo(this.window); + } + + this.windowCreated(); + this.sendEvent(Window.EVENT_CREATED); + this.sendEvent(Window.EVENT_SHOWN); } + } - /** + /** * Destroys the window. Calls the `windowDestroyed` hook method and sends an * `EVENT_DESTROYED` event. */ - dispose() { - if (this.isCreated) { - this.parentElement.removeChild(this.window); + dispose() { + if (this.isCreated) { + this.parentElement.removeChild(this.window); - this.windowDestroyed(); - this.sendEvent(Window.EVENT_DESTROYED); - } + this.windowDestroyed(); + this.sendEvent(Window.EVENT_DESTROYED); } + } - /** + /** * Shows the window. Sends an `EVENT_SHOWN` event. */ - show() { - if (this.isCreated && !this.isVisible) { - this.window.style.setProperty('display', this.windowDisplayWhenVisible); - this.sendEvent(Window.EVENT_SHOWN); - } + show() { + if (this.isCreated && !this.isVisible) { + this.window.style.setProperty('display', this.windowDisplayWhenVisible); + this.sendEvent(Window.EVENT_SHOWN); } + } - /** + /** * Hides the window. Sends an `EVENT_DESTROYED` event. */ - hide() { - if (this.isVisible) { - this.window.style.setProperty('display', 'none'); - this.sendEvent(Window.EVENT_HIDDEN); - } + hide() { + if (this.isVisible) { + this.window.style.setProperty('display', 'none'); + this.sendEvent(Window.EVENT_HIDDEN); } + } - get html() { - return ` + get html() { + return `

      ${this.title}

      @@ -185,12 +185,12 @@ export class Window extends ModuleView {

      `; - } + } - //////////// Extensions management - ////////////////////////////////// + //////////// Extensions management + ////////////////////////////////// - /** + /** * Adds a new extension in the window. * * @param {string} label The unique label for the extension. @@ -206,138 +206,138 @@ export class Window extends ModuleView { * @param {function} [options.callback] The callback to call when the user * clicks on a `button` extension. This has no effects on `div` extensions. */ - addExtension(label, options) { - options.id = `${this.windowId}__extensions_${label.toLowerCase().replace(/ +/, '_')}`; - let extension = new WindowExtension(label, options); - if (!!this.windowExtensions.find(ext => ext.label === label)) { - throw 'Extension already exist : ' + label; - } - this.windowExtensions.push(extension); - - if (this.isCreated) { - extension.appendTo(this.window); - } + addExtension(label, options) { + options.id = `${this.windowId}__extensions_${label.toLowerCase().replace(/ +/, '_')}`; + let extension = new WindowExtension(label, options); + if (this.windowExtensions.find(ext => ext.label === label)) { + throw 'Extension already exist : ' + label; } + this.windowExtensions.push(extension); - /** + if (this.isCreated) { + extension.appendTo(this.window); + } + } + + /** * Removes an existing extension from the window. * * @param {string} label The label identifying the extension to remove. */ - removeExtension(label) { - let index = this.windowExtensions.findIndex(ext => ext.label === label); - if (index < 0) { - throw 'Extension does not exist : ' + label; - } - - let extension = this.windowExtensions[index]; - if (this.isCreated) { - let extensionElement = document.getElementById(extension.id); - extensionElement.parentElement.removeChild(extensionElement); - } - - this.windowExtensions.splice(index, 1); + removeExtension(label) { + let index = this.windowExtensions.findIndex(ext => ext.label === label); + if (index < 0) { + throw 'Extension does not exist : ' + label; } - //////////// Module view overrides - ////////////////////////////////// + let extension = this.windowExtensions[index]; + if (this.isCreated) { + let extensionElement = document.getElementById(extension.id); + extensionElement.parentElement.removeChild(extensionElement); + } - /** + this.windowExtensions.splice(index, 1); + } + + //////////// Module view overrides + ////////////////////////////////// + + /** * Creates and show the window. * * @override */ - async enableView() { - this.appendTo(this.parentElement); - this.show(); - } + async enableView() { + this.appendTo(this.parentElement); + this.show(); + } - /** + /** * If `hideOnClose` is `true`, hides the window. Else, destroys it. * * @override */ - async disableView() { - if (this.hideOnClose) { - this.hide(); - } else { - this.dispose(); - } - } - - //////////// IDs, HTML and other getters - //////////////////////////////////////// - - get isCreated() { - let windowDiv = this.window; - return windowDiv !== null && windowDiv !== undefined; - } - - get isVisible() { - return this.isCreated && window.getComputedStyle(this.window).getPropertyValue('display') === this.windowDisplayWhenVisible; - } - - get windowId() { - return `_window_${this.name}`; - } - - get window() { - return document.getElementById(this.windowId); - } - - get headerId() { - return `_window_header_${this.name}`; - } - - get header() { - return document.getElementById(this.headerId); - } - - get headerTitleId() { - return `_window_header_title_${this.name}`; - } - - get headerTitle() { - return document.getElementById(this.headerTitleId); - } - - get headerCloseButtonId() { - return `_window_header_close_button_${this.name}`; - } - - get headerCloseButton() { - return document.getElementById(this.headerCloseButtonId); - } - - get contentId() { - return `_window_content_${this.name}`; - } - - get content() { - return document.getElementById(this.contentId); - } - - get innerContentId() { - return `_window_inner_content_${this.name}`; - } - - get innerContent() { - return document.getElementById(this.innerContentId); - } - - //////////// Events - /////////////////// - - static get EVENT_CREATED() { - return 'WINDOW_CREATED'; - } - static get EVENT_DESTROYED() { - return 'WINDOW_DESTROYED'; - } - static get EVENT_HIDDEN() { - return 'WINDOW_HIDDEN'; - } - static get EVENT_SHOWN() { - return 'WINDOW_SHOWN'; + async disableView() { + if (this.hideOnClose) { + this.hide(); + } else { + this.dispose(); } + } + + //////////// IDs, HTML and other getters + //////////////////////////////////////// + + get isCreated() { + let windowDiv = this.window; + return windowDiv !== null && windowDiv !== undefined; + } + + get isVisible() { + return this.isCreated && window.getComputedStyle(this.window).getPropertyValue('display') === this.windowDisplayWhenVisible; + } + + get windowId() { + return `_window_${this.name}`; + } + + get window() { + return document.getElementById(this.windowId); + } + + get headerId() { + return `_window_header_${this.name}`; + } + + get header() { + return document.getElementById(this.headerId); + } + + get headerTitleId() { + return `_window_header_title_${this.name}`; + } + + get headerTitle() { + return document.getElementById(this.headerTitleId); + } + + get headerCloseButtonId() { + return `_window_header_close_button_${this.name}`; + } + + get headerCloseButton() { + return document.getElementById(this.headerCloseButtonId); + } + + get contentId() { + return `_window_content_${this.name}`; + } + + get content() { + return document.getElementById(this.contentId); + } + + get innerContentId() { + return `_window_inner_content_${this.name}`; + } + + get innerContent() { + return document.getElementById(this.innerContentId); + } + + //////////// Events + /////////////////// + + static get EVENT_CREATED() { + return 'WINDOW_CREATED'; + } + static get EVENT_DESTROYED() { + return 'WINDOW_DESTROYED'; + } + static get EVENT_HIDDEN() { + return 'WINDOW_HIDDEN'; + } + static get EVENT_SHOWN() { + return 'WINDOW_SHOWN'; + } } \ No newline at end of file diff --git a/src/Components/GUI/js/WindowExtension.js b/src/Components/GUI/js/WindowExtension.js index 8a95604ef..71b9e9201 100644 --- a/src/Components/GUI/js/WindowExtension.js +++ b/src/Components/GUI/js/WindowExtension.js @@ -105,17 +105,17 @@ export class WindowExtension { */ findContainer(htmlRoot) { let queries = []; - if (!!this.container) { + if (this.container) { queries.push(`[data-ext-container="${this.type}-${this.container}"]`); queries.push(`[data-ext-container="${this.container}"]`); } - queries.push(`[data-ext-container="${this.type}"]`) - queries.push(`[data-ext-container-default="${this.type}"]`) + queries.push(`[data-ext-container="${this.type}"]`); + queries.push(`[data-ext-container-default="${this.type}"]`); let container; for (let query of queries) { container = htmlRoot.querySelector(query); - if (!!container) { + if (container) { break; } } diff --git a/src/Components/GUI/js/WindowManager.js b/src/Components/GUI/js/WindowManager.js index 5456ce52e..b57112f77 100644 --- a/src/Components/GUI/js/WindowManager.js +++ b/src/Components/GUI/js/WindowManager.js @@ -1,4 +1,4 @@ -import { Window } from "./Window.js"; +import { Window } from './Window.js'; const BASE_Z_INDEX = 100; diff --git a/src/Components/LayerManager/LayerManager.js b/src/Components/LayerManager/LayerManager.js index 3b15de9d0..d1435421c 100644 --- a/src/Components/LayerManager/LayerManager.js +++ b/src/Components/LayerManager/LayerManager.js @@ -1,247 +1,247 @@ -import { getFirstTileIntersection, getBatchIdFromIntersection, getObject3DFromTile, getVisibleTileCount } from "../3DTiles/3DTilesUtils.js"; +import { getFirstTileIntersection, getBatchIdFromIntersection, getObject3DFromTile, getVisibleTileCount } from '../3DTiles/3DTilesUtils.js'; export class LayerManager { - /** + /** * Creates a new TilesManager from an iTowns view and the 3DTiles layer. * * @param {*} view The iTowns view. */ - constructor(view) { - /** + constructor(view) { + /** * The iTowns view. */ - this.view = view; + this.view = view; - /** + /** * The set of tiles Manager that have been loaded. * @type {Array} */ - this.tilesManagers = []; - } + this.tilesManagers = []; + } - /** + /** * Register a new or modify an existing registered style for all tilesManager. * * @param {string} name A name to identify the style. * @param {CityObjectStyle} style The style to register. */ - registerStyle(name, style) { - this.tilesManagers.forEach(function(tilesManager){ - tilesManager.registerStyle(name, style); - }); - } + registerStyle(name, style) { + this.tilesManagers.forEach(function(tilesManager){ + tilesManager.registerStyle(name, style); + }); + } - /** + /** * Removes all styles currently registered. */ - removeAll3DTilesStyles() { - this.tilesManagers.forEach(function(tilesManager){ - tilesManager.removeAllStyles(); - }); - } + removeAll3DTilesStyles() { + this.tilesManagers.forEach(function(tilesManager){ + tilesManager.removeAllStyles(); + }); + } - /** + /** * Applies the current styles added with `setStyle` or `addStyle`. * * @param {object} options Options of the method. * @param {() => any} [options.updateFunction] The function used to update the * view. Default is `udpateITownsView(view, layer)`. */ - applyAll3DTilesStyles(options = {}) { - this.tilesManagers.forEach(function(tilesManager){ - tilesManager.applyStyles(options); - }); - } + applyAll3DTilesStyles(options = {}) { + this.tilesManagers.forEach(function(tilesManager){ + tilesManager.applyStyles(options); + }); + } - /** + /** * Check if at least one 3DTiles layer is visible * * @returns {boolean} */ - isOneLayerVisible() { - for (let i = 0; i < this.tilesManagers.length; i++) { - if (this.tilesManagers[i].layer.visible) { - return true; - } - } - return false; + isOneLayerVisible() { + for (let i = 0; i < this.tilesManagers.length; i++) { + if (this.tilesManagers[i].layer.visible) { + return true; + } } + return false; + } - /** + /** * Change the visibilty of all 3DTiles layers * */ - changeVisibility(bool) { - this.tilesManagers.forEach(function(tilesManager){ - tilesManager.layer.visible = bool ; - }); - } + changeVisibility(bool) { + this.tilesManagers.forEach(function(tilesManager){ + tilesManager.layer.visible = bool ; + }); + } - /** + /** * Update the scale of the given layer * @param {itowns.Layer} layer one layer loaded. * @param {float} scale Value of the new scale */ - updateScale(layer, scale) { - layer.scale = scale; - this.notifyChange(); - } + updateScale(layer, scale) { + layer.scale = scale; + this.notifyChange(); + } - /** + /** * Update the opacity of the given layer * @param {itowns.Layer} layer one layer loaded. * @param {float} opacity Value of the new scale */ - updateOpacity(layer, opacity) { - layer.opacity = opacity; - this.notifyChange(); - } - /** + updateOpacity(layer, opacity) { + layer.opacity = opacity; + this.notifyChange(); + } + /** * Update the view when called. Must be called when a change have been made * The view.camera.camera3D is passed to actualize all of the layer, but the * the documentation of notifyChange says taht it should not be needed */ - notifyChange() { - this.view.notifyChange(this.view.camera.camera3D); - } + notifyChange() { + this.view.notifyChange(this.view.camera.camera3D); + } - /** + /** * Returns the city object under the mouse cursor. * * @param {MouseEvent} event The mouse event. * * @returns {CityObject | undefined} */ - pickCityObject(event) { - /** + pickCityObject(event) { + /** * Make sure the event is captured by a click listener attached * to the div#viewerDiv, which contains the iTowns canvas. All click * listeners should be instantiated this way as of iTowns 2.24.0 */ - if (event.currentTarget.id.toUpperCase() === 'VIEWERDIV') { - // Get the intersecting objects where our mouse pointer is - let intersections = []; - //As the current pickObjectsAt on all layer is not working, we need - //to call pickObjectsAt() for each layer. - for (let i = 0; i < this.tilesManagers.length; i++) { - intersections = intersections.concat(this.view.pickObjectsAt( - event, - 5, - this.tilesManagers[i].layer - )); - } - let firstInter = getFirstTileIntersection(intersections); - if (!!firstInter) { - let tilesManager = this.getTilesManagerByLayerID(firstInter.layer.id); - let batchId = getBatchIdFromIntersection(firstInter); - let tileId = getObject3DFromTile(firstInter.object).tileId; - return tilesManager.tiles[tileId].cityObjects[batchId]; - } - } - return undefined; - } - - /** + if (event.currentTarget.id.toUpperCase() === 'VIEWERDIV') { + // Get the intersecting objects where our mouse pointer is + let intersections = []; + //As the current pickObjectsAt on all layer is not working, we need + //to call pickObjectsAt() for each layer. + for (let i = 0; i < this.tilesManagers.length; i++) { + intersections = intersections.concat(this.view.pickObjectsAt( + event, + 5, + this.tilesManagers[i].layer + )); + } + let firstInter = getFirstTileIntersection(intersections); + if (firstInter) { + let tilesManager = this.getTilesManagerByLayerID(firstInter.layer.id); + let batchId = getBatchIdFromIntersection(firstInter); + let tileId = getObject3DFromTile(firstInter.object).tileId; + return tilesManager.tiles[tileId].cityObjects[batchId]; + } + } + return undefined; + } + + /** * Returns a tilesManager given a layer ID. * * @param {string} id the layer ID. * * @returns {TilesManager} */ - getTilesManagerByLayerID(id) { - for (let i = 0; i < this.tilesManagers.length; i++) { - if (this.tilesManagers[i].layer.id === id) - return this.tilesManagers[i]; - } + getTilesManagerByLayerID(id) { + for (let i = 0; i < this.tilesManagers.length; i++) { + if (this.tilesManagers[i].layer.id === id) + return this.tilesManagers[i]; } + } - /** + /** * Get all Layers loaded in the view. */ - getLayers() { - return this.view.getLayers(); - } + getLayers() { + return this.view.getLayers(); + } - /** + /** * Get the number of tiles that have been loaded, across all the tileset that * have been loaded * * @returns {int} */ - getLoaded3DTilesTileCount() { - let loadedTileCount = 0; - for (let i = 0; i < this.tilesManagers.length; i++) { - loadedTileCount += this.tilesManagers[i].loadedTileCount; - } - return loadedTileCount; + getLoaded3DTilesTileCount() { + let loadedTileCount = 0; + for (let i = 0; i < this.tilesManagers.length; i++) { + loadedTileCount += this.tilesManagers[i].loadedTileCount; } + return loadedTileCount; + } - /** + /** * Get the number of tiles across all the tileset * * @returns {int} */ - getTotal3DTilesTileCount() { - let totalTileCount = 0; - for (let i = 0; i < this.tilesManagers.length; i++) { - totalTileCount += this.tilesManagers[i].totalTileCount; - } - return totalTileCount; + getTotal3DTilesTileCount() { + let totalTileCount = 0; + for (let i = 0; i < this.tilesManagers.length; i++) { + totalTileCount += this.tilesManagers[i].totalTileCount; } + return totalTileCount; + } - /** + /** * Get the number of tiles visible, across all the tileset that * have been loaded * * @returns {int} */ - getVisible3DTilesTileCountFromLayers() { - let visibleTileCount = 0; - for (let i = 0; i < this.tilesManagers.length; i++) { - visibleTileCount += getVisibleTileCount(this.tilesManagers[i].layer); - } - return visibleTileCount; + getVisible3DTilesTileCountFromLayers() { + let visibleTileCount = 0; + for (let i = 0; i < this.tilesManagers.length; i++) { + visibleTileCount += getVisibleTileCount(this.tilesManagers[i].layer); } + return visibleTileCount; + } - /** + /** * Get Color layers in the view * * @returns {Array} */ - getColorLayers() { - return this.view.getLayers(layer => layer.isColorLayer); - } + getColorLayers() { + return this.view.getLayers(layer => layer.isColorLayer); + } - /** + /** * Get Elevation layers in the view * * @returns {Array} */ - getElevationLayers() { - return this.view.getLayers(layer => layer.isElevationLayer); - } + getElevationLayers() { + return this.view.getLayers(layer => layer.isElevationLayer); + } - /** + /** * Get Geometry layers in the view * * @returns {Array} */ - getGeometryLayers() { - return this.view.getLayers(layer => layer.isGeometryLayer); - } + getGeometryLayers() { + return this.view.getLayers(layer => layer.isGeometryLayer); + } - /** + /** * Get Geometry layers in the view, without the planar one * * @returns {Array} */ - getGeometryLayersWithoutPlanar() { - return this.view.getLayers(layer => layer.id !== "planar" + getGeometryLayersWithoutPlanar() { + return this.view.getLayers(layer => layer.id !== 'planar' && layer.isGeometryLayer); - } + } } diff --git a/src/Components/ModuleView/ModuleView.js b/src/Components/ModuleView/ModuleView.js index de1e4847b..77e4f819c 100644 --- a/src/Components/ModuleView/ModuleView.js +++ b/src/Components/ModuleView/ModuleView.js @@ -5,82 +5,82 @@ import { EventSender } from '../Events/EventSender.js'; * a module, but is strongly advised as it simplifies the integration is demos. */ export class ModuleView extends EventSender { - /** + /** * Creates a new ModuleView. */ - constructor() { - super(); + constructor() { + super(); - /** + /** * Represents the parent HTML element of this view. Must be defined * by the user of the view * * @member {HTMLElement} */ - this.parentElement = null; + this.parentElement = null; - this.registerEvent(ModuleView.EVENT_ENABLED); - this.registerEvent(ModuleView.EVENT_DISABLED); - } + this.registerEvent(ModuleView.EVENT_ENABLED); + this.registerEvent(ModuleView.EVENT_DISABLED); + } - ///////// Overideable methods - // These methods should be overriden by the implementing class - // By default, they do nothing. They are supposed to enable - // or disable the view. (Can be done by destroying / creating, or - // by hiding, showing). - // These methods should never be called manually as they do not - // send appropriate events. - /** + ///////// Overideable methods + // These methods should be overriden by the implementing class + // By default, they do nothing. They are supposed to enable + // or disable the view. (Can be done by destroying / creating, or + // by hiding, showing). + // These methods should never be called manually as they do not + // send appropriate events. + /** * Must be overriden by the implementing class. Supposedly enables the view. * @abstract */ - async enableView() { } - /** + async enableView() { } + /** * Must be overriden by the implementing class. Supposedly disables the view. * @abstract */ - async disableView() { } + async disableView() { } - ///////// Do not override - // These methods are the public methods called to destroy or - // create the view. - /** + ///////// Do not override + // These methods are the public methods called to destroy or + // create the view. + /** * Enables the view (depends on the implementation). * * Sends a EVENT_ENABLED event once the view is enabled. * * @async */ - async enable() { - await this.enableView(); - this.sendEvent(ModuleView.EVENT_ENABLED); - } + async enable() { + await this.enableView(); + this.sendEvent(ModuleView.EVENT_ENABLED); + } - /** + /** * Disables the view (depends on the implementation). * * Sends a EVENT_DISABLED event once the view is disabled. * * @async */ - async disable() { - await this.disableView(); - this.sendEvent(ModuleView.EVENT_DISABLED); - } + async disable() { + await this.disableView(); + this.sendEvent(ModuleView.EVENT_DISABLED); + } - ///////// Events - // Events called when enabling / disabling the view - /** + ///////// Events + // Events called when enabling / disabling the view + /** * Event sent when the view is enabled */ - static get EVENT_ENABLED() { - return 'MODULE_VIEW_ENABLED'; - } + static get EVENT_ENABLED() { + return 'MODULE_VIEW_ENABLED'; + } - /** + /** * Event sent when the view is disabled */ - static get EVENT_DISABLED() { - return 'MODULE_VIEW_DISABLED'; - } + static get EVENT_DISABLED() { + return 'MODULE_VIEW_DISABLED'; + } } \ No newline at end of file diff --git a/src/Components/Request/RequestService.js b/src/Components/Request/RequestService.js index c11472fa6..6b39fe2cb 100644 --- a/src/Components/Request/RequestService.js +++ b/src/Components/Request/RequestService.js @@ -1,30 +1,30 @@ // Service used to make HTTP requests and manage authentication // Wiki : https://github.com/MEPP-team/UD-Viz/wiki/Request-Service#request-service export function RequestService() { - // eslint-disable-next-line no-unused-expressions - this.authenticationService; - this.useAuthentication = false; + // eslint-disable-next-line no-unused-expressions + this.authenticationService; + this.useAuthentication = false; - // eslint-disable-next-line func-names - this.initialize = function () { + // eslint-disable-next-line func-names + this.initialize = function () { - }; + }; - /** + /** * @deprecated Prefer using `RequestService.request` instead. * // eslint-disable-next-line valid-jsdoc */ - // eslint-disable-next-line func-names - this.send = function (method, url, body = '', authenticate = true) { - return this.request(method, url, { - // eslint-disable-next-line object-shorthand - body: body, - // eslint-disable-next-line object-shorthand - authenticate: authenticate, - }); - }; + // eslint-disable-next-line func-names + this.send = function (method, url, body = '', authenticate = true) { + return this.request(method, url, { + // eslint-disable-next-line object-shorthand + body: body, + // eslint-disable-next-line object-shorthand + authenticate: authenticate, + }); + }; - /** + /** * Performs an HTTP request. * * @async @@ -43,64 +43,64 @@ export function RequestService() { * * @returns {Promise} */ - this.request = (method, url, options = {}) => { - const args = options || {}; - const body = args.body || ''; - let authenticate = (args.authenticate !== null + this.request = (method, url, options = {}) => { + const args = options || {}; + const body = args.body || ''; + let authenticate = (args.authenticate !== null && args.authenticate !== undefined) ? - args.authenticate : true; - if (authenticate === 'auto') { - authenticate = !!window.sessionStorage.getItem('user.token'); + args.authenticate : true; + if (authenticate === 'auto') { + authenticate = !!window.sessionStorage.getItem('user.token'); + } + const responseType = args.responseType || null; + const urlParameters = args.urlParameters || null; + return new Promise((resolve, reject) => { + const req = new XMLHttpRequest(); + if (!!urlParameters) { // eslint-disable-line no-extra-boolean-cast + url += '?'; + for (const [paramKey, paramValue] of Object.entries(urlParameters)) { + url += `${encodeURIComponent(paramKey)}=${encodeURIComponent(paramValue)}&`; } - const responseType = args.responseType || null; - const urlParameters = args.urlParameters || null; - return new Promise((resolve, reject) => { - const req = new XMLHttpRequest(); - if (!!urlParameters) { // eslint-disable-line no-extra-boolean-cast - url += '?'; - for (const [paramKey, paramValue] of Object.entries(urlParameters)) { - url += `${encodeURIComponent(paramKey)}=${encodeURIComponent(paramValue)}&`; - } - } - req.open(method, url, true); + } + req.open(method, url, true); - if (this.useAuthentication && authenticate) { - const token = window.sessionStorage.getItem('user.token'); - if (token === null) { - reject(new AuthNeededError()); - return; - } - req.setRequestHeader('Authorization', `Bearer ${token}`); - } + if (this.useAuthentication && authenticate) { + const token = window.sessionStorage.getItem('user.token'); + if (token === null) { + reject(new AuthNeededError()); + return; + } + req.setRequestHeader('Authorization', `Bearer ${token}`); + } - if (!!responseType) { // eslint-disable-line no-extra-boolean-cast - req.responseType = responseType; - } + if (!!responseType) { // eslint-disable-line no-extra-boolean-cast + req.responseType = responseType; + } - req.send(body); + req.send(body); - req.onload = () => { - if (req.status >= 200 && req.status < 300) { - resolve(req); - } else { - reject(req.responseText); - } - }; - }); - }; + req.onload = () => { + if (req.status >= 200 && req.status < 300) { + resolve(req); + } else { + reject(req.responseText); + } + }; + }); + }; - // eslint-disable-next-line func-names - this.setAuthenticationService = function (authenticationService) { - this.authenticationService = authenticationService; - this.useAuthentication = true; - }; + // eslint-disable-next-line func-names + this.setAuthenticationService = function (authenticationService) { + this.authenticationService = authenticationService; + this.useAuthentication = true; + }; - this.initialize(); + this.initialize(); } export class AuthNeededError extends Error { - constructor() { - super('Login needed for this request'); - this.name = 'AuthNeededError'; - } + constructor() { + super('Login needed for this request'); + this.name = 'AuthNeededError'; + } } diff --git a/src/Game/Components/AssetsManager.js b/src/Game/Components/AssetsManager.js index 73901e897..5df2acd3a 100644 --- a/src/Game/Components/AssetsManager.js +++ b/src/Game/Components/AssetsManager.js @@ -277,19 +277,27 @@ export class AssetsManager { const parent = new THREE.Object3D(); switch (anchor) { case 'center': - let center = bbox.min.lerp(bbox.max, 0.5); - obj.position.sub(center); + { + let center = bbox.min.lerp(bbox.max, 0.5); + obj.position.sub(center); + } break; case 'max': - obj.position.sub(bbox.max); + { + obj.position.sub(bbox.max); + } break; case 'min': - obj.position.sub(bbox.min); + { + obj.position.sub(bbox.min); + } break; case 'center_min': - let centerMin = bbox.min.clone().lerp(bbox.max, 0.5); - centerMin.z = bbox.min.z; - obj.position.sub(centerMin); + { + let centerMin = bbox.min.clone().lerp(bbox.max, 0.5); + centerMin.z = bbox.min.z; + obj.position.sub(centerMin); + } break; default: } diff --git a/src/Game/Shared/GameObject/Components/Collider.js b/src/Game/Shared/GameObject/Components/Collider.js index 2f15cda5b..f1f0661e3 100644 --- a/src/Game/Shared/GameObject/Components/Collider.js +++ b/src/Game/Shared/GameObject/Components/Collider.js @@ -93,37 +93,41 @@ class ShapeWrapper { initFromJSON(json) { switch (json.type) { case 'Circle': - const circle = new Circle(json.center.x, json.center.y, json.radius); + { + const circle = new Circle(json.center.x, json.center.y, json.radius); - this.update = function (worldtransform) { - const wp = worldtransform.getPosition(); - circle.x = json.center.x + wp.x; - circle.y = json.center.y + wp.y; - }; + this.update = function (worldtransform) { + const wp = worldtransform.getPosition(); + circle.x = json.center.x + wp.x; + circle.y = json.center.y + wp.y; + }; - this.shape = circle; + this.shape = circle; + } break; case 'Polygon': - const points = []; - json.points.forEach(function (p) { - points.push([p.x, p.y]); - }); - - const polygon = new Polygon(0, 0, points); - - //attach userData to perform update - this.update = function (worldtransform) { + { const points = []; json.points.forEach(function (p) { - const wp = worldtransform.getPosition(); - const point = [p.x + wp.x, p.y + wp.y]; - points.push(point); - //TODO handle rotation + points.push([p.x, p.y]); }); - polygon.setPoints(points); - }; - this.shape = polygon; + const polygon = new Polygon(0, 0, points); + + //attach userData to perform update + this.update = function (worldtransform) { + const points = []; + json.points.forEach(function (p) { + const wp = worldtransform.getPosition(); + const point = [p.x + wp.x, p.y + wp.y]; + points.push(point); + //TODO handle rotation + }); + polygon.setPoints(points); + }; + + this.shape = polygon; + } break; default: } diff --git a/src/Game/Shared/GameObject/GameObject.js b/src/Game/Shared/GameObject/GameObject.js index 0285a6e2c..aaa84509d 100644 --- a/src/Game/Shared/GameObject/GameObject.js +++ b/src/Game/Shared/GameObject/GameObject.js @@ -10,7 +10,6 @@ const THREE = require('three'); const RenderComponent = require('./Components/Render'); const ColliderComponent = require('./Components/Collider'); const WorldScriptComponent = require('./Components/WorldScript'); -const JSONUtils = require('../../../Components/SystemUtils/JSONUtils'); const LocalScriptModule = require('./Components/LocalScript'); const THREEUtils = require('../Components/THREEUtils'); @@ -290,14 +289,6 @@ const GameObjectModule = class GameObject { return obj; } - getTransform() { - return this.transform; - } - - setTransform(transform) { - this.transform = transform; - } - clone() { return new GameObject(this.toJSON(true)); } diff --git a/src/Game/Shared/WorldState.js b/src/Game/Shared/WorldState.js index 5acc1a471..879011021 100644 --- a/src/Game/Shared/WorldState.js +++ b/src/Game/Shared/WorldState.js @@ -63,7 +63,7 @@ const WorldStateModule = class WorldState { if (uuidGO.includes(uuid)) count++; }); if (uuidGO.length != count) { - debugger; + throw new Error('count of go error'); } const result = new WorldState({ diff --git a/src/Game/UDVDebugger/UDVDebugger.js b/src/Game/UDVDebugger/UDVDebugger.js index f3a731399..04c68bc7d 100644 --- a/src/Game/UDVDebugger/UDVDebugger.js +++ b/src/Game/UDVDebugger/UDVDebugger.js @@ -125,22 +125,4 @@ export class UDVDebugger { this.root.style.width = w + 'px'; this.root.style.height = h + 'px'; } - - //TODO used twice put it in a UTILS - async loadConfigFile(filePath, cb) { - return new Promise((resolve, reject) => { - $.ajax({ - type: 'GET', - url: filePath, - datatype: 'json', - success: (data) => { - resolve(data); - }, - error: (e) => { - console.error(e); - reject(); - }, - }); - }); - } } diff --git a/src/Widgets/CityObjects/View/CityObjectFilterWindow.js b/src/Widgets/CityObjects/View/CityObjectFilterWindow.js index e9b018a86..180524de2 100644 --- a/src/Widgets/CityObjects/View/CityObjectFilterWindow.js +++ b/src/Widgets/CityObjects/View/CityObjectFilterWindow.js @@ -67,7 +67,7 @@ export class CityObjectFilterWindow extends Window { * add. */ addFilterSelector(filterSelector) { - if (!!this.getFilterSelector(filterSelector.filterLabel)) { + if (this.getFilterSelector(filterSelector.filterLabel)) { throw ( 'A filter selector with the same filter label already exist: ' + filterSelector.filterLabel @@ -119,7 +119,7 @@ export class CityObjectFilterWindow extends Window { _onFilterSelection() { this.filterSectionElement.innerHTML = ''; let selector = this._getCurrentSelector(); - if (!!selector) { + if (selector) { selector.appendFormFieldsTo(this.filterSectionElement); } } diff --git a/src/Widgets/CityObjects/View/CityObjectWindow.js b/src/Widgets/CityObjects/View/CityObjectWindow.js index 5359230a6..fdbf9c113 100644 --- a/src/Widgets/CityObjects/View/CityObjectWindow.js +++ b/src/Widgets/CityObjects/View/CityObjectWindow.js @@ -1,5 +1,7 @@ /** @format */ +const THREE = require('three'); + //Components import { Window } from '../../../Components/GUI/js/Window'; import { CityObjectStyle } from '../../../Components/3DTiles/Model/CityObjectStyle'; @@ -168,7 +170,7 @@ export class CityObjectWindow extends Window { _updateLayerDescription() { if (this.isCreated) { let layer = this.provider.getLayer(); - if (!!layer) { + if (layer) { this.selectedFilterElement.innerText = layer.filter.toString(); this.layerColorIndicatorElement.style.display = ''; this.layerColorIndicatorElement.style.background = @@ -200,7 +202,7 @@ export class CityObjectWindow extends Window { * @param {string} filterLabel The selected filter label. */ _onFilterSelected(filterLabel) { - if (!!filterLabel) { + if (filterLabel) { this.provider.setLayer(filterLabel, this.defaultLayerStyle); } else { this.provider.removeLayer(); diff --git a/src/Widgets/CityObjects/ViewModel/AttributeFilter.js b/src/Widgets/CityObjects/ViewModel/AttributeFilter.js index 3b8a3c056..8ba36058f 100644 --- a/src/Widgets/CityObjects/ViewModel/AttributeFilter.js +++ b/src/Widgets/CityObjects/ViewModel/AttributeFilter.js @@ -73,16 +73,16 @@ export class AttributeFilter extends CityObjectFilter { let result = ''; let attributes = []; - if (!!this.tileId) { + if (this.tileId) { attributes.push(['tileId', this.tileId]); } - if (!!this.batchId) { + if (this.batchId) { attributes.push(['batchId', this.batchId]); } for (let entry of Object.entries(this.props)) { - if (!!entry[1]) { + if (entry[1]) { attributes.push([entry[0], entry[1]]); } } diff --git a/src/Widgets/CityObjects/ViewModel/CityObjectProvider.js b/src/Widgets/CityObjects/ViewModel/CityObjectProvider.js index 99b40e6a5..ee839dfc4 100644 --- a/src/Widgets/CityObjects/ViewModel/CityObjectProvider.js +++ b/src/Widgets/CityObjects/ViewModel/CityObjectProvider.js @@ -85,7 +85,7 @@ export class CityObjectProvider extends EventSender { */ selectCityObject(mouseEvent) { let cityObject = this.layerManager.pickCityObject(mouseEvent); - if (!!cityObject) { + if (cityObject) { this.selectedCityObject = cityObject; this.removeLayer(); this.sendEvent(CityObjectProvider.EVENT_CITY_OBJECT_SELECTED, cityObject); @@ -160,7 +160,7 @@ export class CityObjectProvider extends EventSender { let filter = this.filters[filterLabel]; if (filter === undefined) { - throw 'No filter found with the label : ' + label; + throw 'No filter found with the label : ' + filterLabel; } this.cityOjectLayer = new CityObjectLayer(filter, style); @@ -198,7 +198,7 @@ export class CityObjectProvider extends EventSender { */ _updateTilesManager() { this.layerManager.removeAll3DTilesStyles(); - if (!!this.selectedCityObject) { + if (this.selectedCityObject) { let tileManager = this.layerManager.getTilesManagerByLayerID( this.selectedCityObject.tile.layer.id ); diff --git a/src/Widgets/Documents/View/DocumentNavigatorWindow.js b/src/Widgets/Documents/View/DocumentNavigatorWindow.js index 12897b158..a2becb139 100644 --- a/src/Widgets/Documents/View/DocumentNavigatorWindow.js +++ b/src/Widgets/Documents/View/DocumentNavigatorWindow.js @@ -145,8 +145,8 @@ export class DocumentNavigatorWindow extends AbstractDocumentWindow { item.innerHTML = /*html*/ `
      ${doc.title}
      Refering ${new Date( - doc.refDate - ).toLocaleDateString()}
      + doc.refDate + ).toLocaleDateString()}
      `; item.classList.add('navigator-result-doc'); item.onclick = () => { @@ -170,10 +170,10 @@ export class DocumentNavigatorWindow extends AbstractDocumentWindow { } let previouslySelected = this.documentListElement.querySelector('.document-selected'); - if (!!previouslySelected) { + if (previouslySelected) { previouslySelected.classList.remove('document-selected'); } - if (!!document) { + if (document) { let newIndex = this.provider.getDisplayedDocumentIndex(); let newSelected = this.documentListElement.querySelector( `li:nth-child(${newIndex + 1})` @@ -203,22 +203,22 @@ export class DocumentNavigatorWindow extends AbstractDocumentWindow { rightsHolder !== '' ? rightsHolder : undefined; let pubStartDate = this.inputPubDateStartElement.value; - this.searchFilter.pubStartDate = !!pubStartDate + this.searchFilter.pubStartDate = pubStartDate ? new Date(pubStartDate) : undefined; let pubEndDate = this.inputPubDateEndElement.value; - this.searchFilter.pubEndDate = !!pubEndDate + this.searchFilter.pubEndDate = pubEndDate ? new Date(pubEndDate) : undefined; let refStartDate = this.inputRefDateStartElement.value; - this.searchFilter.refStartDate = !!refStartDate + this.searchFilter.refStartDate = refStartDate ? new Date(refStartDate) : undefined; let refEndDate = this.inputRefDateEndElement.value; - this.searchFilter.refEndDate = !!refEndDate + this.searchFilter.refEndDate = refEndDate ? new Date(refEndDate) : undefined; diff --git a/src/Widgets/Extensions/3DTilesDebug/views/3DTilesDebugWindow.js b/src/Widgets/Extensions/3DTilesDebug/views/3DTilesDebugWindow.js index 0fac2b999..d618741c1 100644 --- a/src/Widgets/Extensions/3DTilesDebug/views/3DTilesDebugWindow.js +++ b/src/Widgets/Extensions/3DTilesDebug/views/3DTilesDebugWindow.js @@ -1,5 +1,7 @@ /** @format */ +const THREE = require('three'); + //Components import { Window } from '../../../../Components/GUI/js/Window'; import { CityObjectStyle } from '../../../../Components/3DTiles/Model/CityObjectStyle'; @@ -154,7 +156,7 @@ export class Debug3DTilesWindow extends Window { this.clickDivElement.innerHTML += `
      ${key} : ${value}`; } - if (!!this.selectedCityObject) { + if (this.selectedCityObject) { this.selectedTilesManager.removeStyle( this.selectedCityObject.cityObjectId ); diff --git a/src/Widgets/Extensions/Contribute/View/DocumentCreationWindow.js b/src/Widgets/Extensions/Contribute/View/DocumentCreationWindow.js index 4b06675d8..f8c7d77a2 100644 --- a/src/Widgets/Extensions/Contribute/View/DocumentCreationWindow.js +++ b/src/Widgets/Extensions/Contribute/View/DocumentCreationWindow.js @@ -266,7 +266,7 @@ export class DocumentCreationWindow extends AbstractDocumentWindow { * @private */ _updateFormButtons() { - if (!!this.docImageElement.value) { + if (this.docImageElement.value) { this.buttonPositionElement.disabled = false; } else { this.buttonPositionElement.disabled = true; diff --git a/src/Widgets/Extensions/DocumentComments/views/DocumentCommentsWindow.js b/src/Widgets/Extensions/DocumentComments/views/DocumentCommentsWindow.js index 8b4f957a3..b295541d9 100644 --- a/src/Widgets/Extensions/DocumentComments/views/DocumentCommentsWindow.js +++ b/src/Widgets/Extensions/DocumentComments/views/DocumentCommentsWindow.js @@ -80,12 +80,12 @@ export class DocumentCommentsWindow extends AbstractDocumentWindow { div.innerHTML = `

      ${comment.author.firstName} ${ - comment.author.lastName - }

      + comment.author.lastName +}

      ${text}

      ${new Date( - comment.date - ).toLocaleString()}

      + comment.date + ).toLocaleString()}

      `; document.getElementById('documentComments_left').appendChild(div); diff --git a/src/Widgets/Extensions/Geocoding/services/GeocodingService.js b/src/Widgets/Extensions/Geocoding/services/GeocodingService.js index 1e25f87d4..29b50f89d 100644 --- a/src/Widgets/Extensions/Geocoding/services/GeocodingService.js +++ b/src/Widgets/Extensions/Geocoding/services/GeocodingService.js @@ -63,7 +63,7 @@ export class GeocodingService { authenticate: false, }); const response = JSON.parse(req.response); - const results = (!!this.basePath ? response[this.basePath] : response).map( + const results = (this.basePath ? response[this.basePath] : response).map( (res) => { return { lat: Number(getAttributeByPath(res, this.latPath)), @@ -72,7 +72,7 @@ export class GeocodingService { } ); - if (!!this.requestTimeIntervalMs) { + if (this.requestTimeIntervalMs) { this.canDoRequest = false; setTimeout(() => { this.canDoRequest = true; diff --git a/src/Widgets/Extensions/Geocoding/views/GeocodingView.js b/src/Widgets/Extensions/Geocoding/views/GeocodingView.js index dec63944f..d57b9dff0 100644 --- a/src/Widgets/Extensions/Geocoding/views/GeocodingView.js +++ b/src/Widgets/Extensions/Geocoding/views/GeocodingView.js @@ -110,7 +110,7 @@ export class GeocodingView extends ModuleView { let i = 0; //step 1 : convert the lat/lng to coordinates used by itowns let targetPos = this.getWorldCoordinates(lat, lng); - if (!!targetPos.z) { + if (targetPos.z) { //if we could convert the coords (ie. they are on the map) //step 2 : add a mesh representing a pin this.addPin(targetPos); @@ -141,7 +141,7 @@ export class GeocodingView extends ModuleView { this.planarView.tileLayer, coords ); - const targetZ = !!elevation ? elevation : undefined; + const targetZ = elevation ? elevation : undefined; return new THREE.Vector3(targetX, targetY, targetZ); } diff --git a/src/Widgets/GuidedTour/GuidedTourController.js b/src/Widgets/GuidedTour/GuidedTourController.js index 2f2be96d7..fc464dc80 100644 --- a/src/Widgets/GuidedTour/GuidedTourController.js +++ b/src/Widgets/GuidedTour/GuidedTourController.js @@ -21,9 +21,9 @@ export class GuidedTourController extends ModuleView { /** * Constructor for GuidedTourController * The controller reads data from a database to build one or more guided tours - * Each guided tour is a succession of "steps" + * Each guided tour is a succession of "steps" * Each step has a document + tour text + doc text (steps are instances of - * the TourStep class) + * the TourStep class) * Multiple guided tours are supported (only one tour is finished for the demo) * For the demo : options.preventUserFromChangingTour allows to hide the buttons for changing tour * diff --git a/src/Widgets/LayerChoice/views/LayerChoice.js b/src/Widgets/LayerChoice/views/LayerChoice.js index 6467deeb0..aaa68e565 100644 --- a/src/Widgets/LayerChoice/views/LayerChoice.js +++ b/src/Widgets/LayerChoice/views/LayerChoice.js @@ -67,14 +67,14 @@ export class LayerChoice extends Window { layers[i].id }-spoiler" class="section-title">${layers[i].id} Visible
      + layers[i].visible ? 'checked' : '' +}>
      Opacity : ${ - layers[i].opacity - } + layers[i].opacity +}
      `; item.oninput = (event) => { @@ -129,8 +129,8 @@ export class LayerChoice extends Window { let div = document.createElement('div'); div.innerHTML = ` All Visible
      + this.layerManager.isOneLayerVisible() ? 'checked' : '' +}>
      `; div.onchange = (event) => { this.layerManager.changeVisibility(event.srcElement.checked); @@ -143,22 +143,22 @@ export class LayerChoice extends Window { layers[i].id }-spoiler"> + layers[i].id +}-spoiler" class="subsection-title">${ + layers[i].id +}
      Visible
      + layers[i].visible ? 'checked' : '' +}>
      Opacity : ${ - layers[i].opacity - } + layers[i].opacity +}
      `; diff --git a/src/Widgets/Links/View/CityObjectLinkInterface.js b/src/Widgets/Links/View/CityObjectLinkInterface.js index 12d9ca96a..70a61f20f 100644 --- a/src/Widgets/Links/View/CityObjectLinkInterface.js +++ b/src/Widgets/Links/View/CityObjectLinkInterface.js @@ -1,6 +1,5 @@ /** @format */ -import { LinkService } from '../Model/LinkService'; import { CityObjectModule } from '../../CityObjects/CityObjectModule'; import { CityObjectFilterSelector } from '../../CityObjects/View/CityObjectFilterSelector'; import { LinkProvider } from '../ViewModel/LinkProvider'; @@ -67,7 +66,7 @@ export class CityObjectLinkInterface { let docs = this.linkProvider.getSelectedCityObjectLinkedDocuments(); let listHtml = `

      ${docs.length} linked document(s)

      `; if (docs.length > 0) { - listHtml += `

        `; + listHtml += '

          '; for (let doc of docs) { listHtml += `
        • ${doc.title}
        • `; } @@ -80,7 +79,7 @@ export class CityObjectLinkInterface { ////// GETTERS get linkListId() { - return `city_objects_link_list`; + return 'city_objects_link_list'; } get linkListElement() { @@ -88,7 +87,7 @@ export class CityObjectLinkInterface { } get showDocsButtonId() { - return `city_objects_link_show_doc`; + return 'city_objects_link_show_doc'; } get showDocsButtonElement() { diff --git a/src/Widgets/Links/View/DocumentLinkInterface.js b/src/Widgets/Links/View/DocumentLinkInterface.js index d3baac9ad..4822c1831 100644 --- a/src/Widgets/Links/View/DocumentLinkInterface.js +++ b/src/Widgets/Links/View/DocumentLinkInterface.js @@ -99,7 +99,7 @@ export class DocumentLinkInterface { }; this.createLinkButtonElement.onclick = async () => { - if (!!this.provider.selectedCityObject) { + if (this.provider.selectedCityObject) { let newLink = new Link(); newLink.source_id = this.provider.displayedDocument.id; newLink.target_id = @@ -158,13 +158,13 @@ export class DocumentLinkInterface { newDivHtml += `
        • ID : ${link.target_id} + link + )}" class="clickable-text"> travel + link + )}" class="clickable-text"> delete
        • `; @@ -229,7 +229,7 @@ export class DocumentLinkInterface { } get linkFilterId() { - return `city_object_link_filter`; + return 'city_object_link_filter'; } get linkFilterElement() { From 7f8d1d9f7430a16bdc57961f0fc86c496c09b1ee Mon Sep 17 00:00:00 2001 From: valentinMachado Date: Tue, 8 Jun 2021 11:14:37 +0200 Subject: [PATCH 39/68] modify travis test (without --fix) --- .travis.yml | 7 ++----- package.json | 1 + 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 3683952db..e0d536338 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,9 +18,6 @@ install: jobs: include: - - stage: build + - stage: travis script: - - npm run build - - stage: eslint - script: - - npm run eslint + - npm run travis diff --git a/package.json b/package.json index f9a72ec1b..13b159cda 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,7 @@ "description": "A collection of itowns plugins", "main": "src", "scripts": { + "travis": "./node_modules/.bin/eslint ./src && npm run build", "eslint": "./node_modules/.bin/eslint ./src --fix", "build": "cross-env NODE_ENV=production webpack", "build-debug": "cross-env NODE_ENV=development webpack", From b9eb1871e3d53750eea712165d3dcb5481ab1b01 Mon Sep 17 00:00:00 2001 From: valentinMachado Date: Tue, 8 Jun 2021 11:56:04 +0200 Subject: [PATCH 40/68] remove --fix from script npm --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 13b159cda..c9c75c6e6 100644 --- a/package.json +++ b/package.json @@ -4,8 +4,8 @@ "description": "A collection of itowns plugins", "main": "src", "scripts": { - "travis": "./node_modules/.bin/eslint ./src && npm run build", - "eslint": "./node_modules/.bin/eslint ./src --fix", + "travis": "npm run eslint && npm run build", + "eslint": "./node_modules/.bin/eslint ./src", "build": "cross-env NODE_ENV=production webpack", "build-debug": "cross-env NODE_ENV=development webpack", "debug": "nodemon --verbose --watch src --delay 2500ms ./bin/debug.js -e js,css,html" From 0bd77ac87f141e590a1f904a46944d25ce9da478 Mon Sep 17 00:00:00 2001 From: valentinMachado Date: Tue, 1 Jun 2021 10:23:05 +0200 Subject: [PATCH 41/68] data nudefined => null --- src/Game/Shared/Command.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Game/Shared/Command.js b/src/Game/Shared/Command.js index 1d95f67bb..1253e1b81 100644 --- a/src/Game/Shared/Command.js +++ b/src/Game/Shared/Command.js @@ -10,7 +10,7 @@ const CommandModule = class Command { this.type = json.type; this.userID = json.userID; this.avatarID = json.avatarID; - this.data = json.data; + this.data = json.data || null; } getData() { @@ -38,7 +38,6 @@ const CommandModule = class Command { } toJSON() { - return { type: this.type, avatarID: this.avatarID, From e3bb90ceba6a8a64f750d53484ad35335791d7f9 Mon Sep 17 00:00:00 2001 From: valentinMachado Date: Thu, 3 Jun 2021 10:48:23 +0200 Subject: [PATCH 42/68] add getter gameview --- src/Game/GameView/GameView.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/Game/GameView/GameView.js b/src/Game/GameView/GameView.js index a0f89cf7d..d6968417b 100644 --- a/src/Game/GameView/GameView.js +++ b/src/Game/GameView/GameView.js @@ -314,6 +314,18 @@ export class GameView { cameraShadow.updateProjectionMatrix(); } + getWorldStateInterpolator() { + return this.worldStateInterpolator; + } + + getLastState() { + return this.lastState; + } + + getInputManager() { + return this.inputManager; + } + updateViewServer(dt) { //TODO itowns BUG if (!isNaN(dt)) { From 14e2b0d3f15e48183d1c5a5dcfe00c493c64038f Mon Sep 17 00:00:00 2001 From: valentinMachado Date: Thu, 3 Jun 2021 10:56:03 +0200 Subject: [PATCH 43/68] remove debug --- src/Game/GameView/GameView.js | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/Game/GameView/GameView.js b/src/Game/GameView/GameView.js index d6968417b..ab750e29f 100644 --- a/src/Game/GameView/GameView.js +++ b/src/Game/GameView/GameView.js @@ -21,15 +21,9 @@ import { isFunction } from 'jquery'; const udvShared = require('../Shared/Shared'); const Command = udvShared.Command; const WorldState = udvShared.WorldState; -const Data = udvShared.Data; - -//DEBUG -let id = 0; export class GameView { constructor(params) { - this.id = id; - id++; params.htmlParent = params.htmlParent || document.body; From c709d06af83931e4d9895d58b725a2ab272d7458 Mon Sep 17 00:00:00 2001 From: valentinMachado Date: Thu, 3 Jun 2021 16:49:31 +0200 Subject: [PATCH 44/68] rename quat parse --- src/Game/Components/AssetsManager.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Game/Components/AssetsManager.js b/src/Game/Components/AssetsManager.js index e9a3fc3af..1b174cf70 100644 --- a/src/Game/Components/AssetsManager.js +++ b/src/Game/Components/AssetsManager.js @@ -260,10 +260,10 @@ export class AssetsManager { const noShadow = modelData.noShadow || false; //rotation - const quatTHREE2UDV = new THREE.Quaternion().setFromEuler( + const quatYUP2ZUP = new THREE.Quaternion().setFromEuler( new THREE.Euler(-Math.PI * 0.5, 0, Math.PI) ); - obj.applyQuaternion(quatTHREE2UDV); + obj.applyQuaternion(quatYUP2ZUP); const bbox = new THREE.Box3().setFromObject(obj); const parent = new THREE.Object3D(); @@ -277,6 +277,7 @@ export class AssetsManager { break; case 'min': obj.position.sub(bbox.min); + console.log(id, bbox.min); break; case 'center_min': let centerMin = bbox.min.clone().lerp(bbox.max, 0.5); @@ -284,7 +285,6 @@ export class AssetsManager { obj.position.sub(centerMin); break; default: - throw new Error('no anchor'); } //scale From d24b4192d9690a5b3f0429e17930a041938a7322 Mon Sep 17 00:00:00 2001 From: valentinMachado Date: Thu, 3 Jun 2021 18:10:11 +0200 Subject: [PATCH 45/68] remove log --- src/Game/Components/AssetsManager.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Game/Components/AssetsManager.js b/src/Game/Components/AssetsManager.js index 1b174cf70..86ef40dd1 100644 --- a/src/Game/Components/AssetsManager.js +++ b/src/Game/Components/AssetsManager.js @@ -277,7 +277,6 @@ export class AssetsManager { break; case 'min': obj.position.sub(bbox.min); - console.log(id, bbox.min); break; case 'center_min': let centerMin = bbox.min.clone().lerp(bbox.max, 0.5); From eebc69194d69304f79f6258233bb8e35f0161735 Mon Sep 17 00:00:00 2001 From: valentinMachado Date: Fri, 4 Jun 2021 10:59:13 +0200 Subject: [PATCH 46/68] add outdated setter --- src/Game/Shared/GameObject/GameObject.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Game/Shared/GameObject/GameObject.js b/src/Game/Shared/GameObject/GameObject.js index 598744107..b99191bed 100644 --- a/src/Game/Shared/GameObject/GameObject.js +++ b/src/Game/Shared/GameObject/GameObject.js @@ -58,8 +58,6 @@ const GameObjectModule = class GameObject { //assets has been initialized this.initialized = false; - - //TODO remove me //default object3d this.object3D = new THREE.Object3D(); this.object3D.name = this.name + '_object3D'; @@ -207,6 +205,10 @@ const GameObjectModule = class GameObject { return this.outdated; } + setOutdated(value) { + this.outdated = value; + } + executeScripts(event, params) { const script = this.getComponent(WorldScriptComponent.TYPE); if (!script) return null; From 5e9a1a57bdc96cd666a87df459e090e3b7646053 Mon Sep 17 00:00:00 2001 From: valentinMachado Date: Fri, 4 Jun 2021 12:25:19 +0200 Subject: [PATCH 47/68] refacto --- src/Game/{ => Shared}/Components/THREEUtils.js | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/Game/{ => Shared}/Components/THREEUtils.js (100%) diff --git a/src/Game/Components/THREEUtils.js b/src/Game/Shared/Components/THREEUtils.js similarity index 100% rename from src/Game/Components/THREEUtils.js rename to src/Game/Shared/Components/THREEUtils.js From 80d66b8b279d3d87a51867fbb7aac03cd3f2c1f9 Mon Sep 17 00:00:00 2001 From: valentinMachado Date: Fri, 4 Jun 2021 12:25:29 +0200 Subject: [PATCH 48/68] refacto bis --- src/Game/Components/AssetsManager.js | 2 +- src/Game/Components/Components.js | 2 +- src/Game/GameView/GameView.js | 5 +---- src/Game/Shared/Components/Components.js | 2 ++ src/Game/Shared/Components/THREEUtils.js | 12 ++++++++---- src/Game/Shared/GameObject/GameObject.js | 25 +++++++++++++----------- 6 files changed, 27 insertions(+), 21 deletions(-) diff --git a/src/Game/Components/AssetsManager.js b/src/Game/Components/AssetsManager.js index 86ef40dd1..34e2b632d 100644 --- a/src/Game/Components/AssetsManager.js +++ b/src/Game/Components/AssetsManager.js @@ -4,7 +4,7 @@ import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'; import * as THREE from 'three'; import * as jquery from 'jquery'; import GameObjectModule from '../Shared/GameObject/GameObject'; -import { THREEUtils } from '../Components/THREEUtils'; +const THREEUtils = require('../Shared/Components/THREEUtils'); const DEFAULT_MATERIAL = new THREE.MeshLambertMaterial({ color: 0x00ff00 }); diff --git a/src/Game/Components/Components.js b/src/Game/Components/Components.js index 1abd65a66..d65691aab 100644 --- a/src/Game/Components/Components.js +++ b/src/Game/Components/Components.js @@ -4,4 +4,4 @@ export { WebSocketService } from './WebSocketService'; export { WorldStateInterpolator } from './WorldStateInterpolator'; export { AssetsManager } from './AssetsManager'; export { InputManager } from './InputManager'; -export { THREEUtils } from './THREEUtils'; + diff --git a/src/Game/GameView/GameView.js b/src/Game/GameView/GameView.js index ab750e29f..5d8c41a7b 100644 --- a/src/Game/GameView/GameView.js +++ b/src/Game/GameView/GameView.js @@ -7,8 +7,6 @@ import { AssetsManager } from '../Components/AssetsManager'; import { InputManager } from '../Components/InputManager'; import { Cameraman, Routine } from '../Components/Cameraman'; -import { THREEUtils } from '../Components/THREEUtils'; - import * as THREE from 'three'; import * as proj4 from 'proj4'; import * as itowns from 'itowns'; @@ -16,15 +14,14 @@ import * as itowns from 'itowns'; import './GameView.css'; import LocalScript from '../Shared/GameObject/Components/LocalScript'; import Render from '../Shared/GameObject/Components/Render'; -import { isFunction } from 'jquery'; const udvShared = require('../Shared/Shared'); const Command = udvShared.Command; const WorldState = udvShared.WorldState; +const THREEUtils = udvShared.Components.THREEUtils; export class GameView { constructor(params) { - params.htmlParent = params.htmlParent || document.body; //html diff --git a/src/Game/Shared/Components/Components.js b/src/Game/Shared/Components/Components.js index 919edc2bd..c4d0d74e4 100644 --- a/src/Game/Shared/Components/Components.js +++ b/src/Game/Shared/Components/Components.js @@ -2,8 +2,10 @@ const commonJsData = require('./Data'); const commonJsPrefabUtils = require('./PrefabUtils'); +const commonJsTHREEUtils = require('./THREEUtils'); module.exports = { Data: commonJsData, PrefabUtils: commonJsPrefabUtils, + THREEUtils: commonJsTHREEUtils, }; diff --git a/src/Game/Shared/Components/THREEUtils.js b/src/Game/Shared/Components/THREEUtils.js index 8ed2f06b0..759049a1c 100644 --- a/src/Game/Shared/Components/THREEUtils.js +++ b/src/Game/Shared/Components/THREEUtils.js @@ -1,10 +1,10 @@ /** @format */ -import * as THREE from 'three'; +const THREE = require('three'); //TODO create an object Transform with a clone method -const THREEUtils = { +module.exports = { textureEncoding: THREE.RGBDEncoding, addLights(scene) { @@ -37,6 +37,10 @@ const THREEUtils = { // renderer.toneMapping = THREE.ReinhardToneMapping; // renderer.toneMappingExposure = 1; }, -}; -export { THREEUtils }; + Transform: class { + constructor() { + console.log('new transform'); + } + }, +}; diff --git a/src/Game/Shared/GameObject/GameObject.js b/src/Game/Shared/GameObject/GameObject.js index b99191bed..f337c1131 100644 --- a/src/Game/Shared/GameObject/GameObject.js +++ b/src/Game/Shared/GameObject/GameObject.js @@ -12,6 +12,7 @@ const ColliderComponent = require('./Components/Collider'); const WorldScriptComponent = require('./Components/WorldScript'); const JSONUtils = require('../../../Components/SystemUtils/JSONUtils'); const LocalScriptModule = require('./Components/LocalScript'); +const THREEUtils = require('../Components/THREEUtils'); const GameObjectModule = class GameObject { constructor(json, parent) { @@ -29,6 +30,7 @@ const GameObjectModule = class GameObject { //name this.name = json.name || 'none'; + //TODO remove me //prefabId this.prefabId = json.prefabId || null; @@ -61,6 +63,9 @@ const GameObjectModule = class GameObject { //default object3d this.object3D = new THREE.Object3D(); this.object3D.name = this.name + '_object3D'; + + //buffer + this.eulerBuffer = new THREE.Euler(0, 0, 0, 'ZXY'); //to avoid new THREE.Euler on fetchObject3D } updateNoStaticFromGO(go, assetsManager) { @@ -279,20 +284,18 @@ const GameObjectModule = class GameObject { if (!obj) obj = this.object3D; } - //transform + //position obj.position.copy(this.getPosition()); - //TODO rotation n'est plus un THREE VEctor3 mais un euler - obj.rotation.copy( - new THREE.Euler( - this.transform.rotation.x, - this.transform.rotation.y, - this.transform.rotation.z, - 'ZXY' - ) - ); + //rot + const rot = this.getRotation(); + this.eulerBuffer.x = rot.x; + this.eulerBuffer.y = rot.y; + this.eulerBuffer.z = rot.z; + obj.rotation.copy(this.eulerBuffer); + //scale obj.scale.copy(this.getScale()); - //reset + //add children if recursive if (recursive) { this.children.forEach(function (child) { const childObj = child.fetchObject3D(); From db7a52faf56865b3774c6c9b03b9dda05b36f7e8 Mon Sep 17 00:00:00 2001 From: valentinMachado Date: Fri, 4 Jun 2021 13:17:37 +0200 Subject: [PATCH 49/68] rename --- src/Game/Shared/GameObject/Components/Render.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Game/Shared/GameObject/Components/Render.js b/src/Game/Shared/GameObject/Components/Render.js index d3eee94fb..aea94fcd0 100644 --- a/src/Game/Shared/GameObject/Components/Render.js +++ b/src/Game/Shared/GameObject/Components/Render.js @@ -92,7 +92,7 @@ const RenderModule = class Render { //stock data in userData this.object3D.userData = { - uuid: this.parent.getUUID(), + gameObjectUUID: this.parent.getUUID(), }; //get the 3D model From 4baabe32613bb1eb52c70a56aff99dbe2380fe05 Mon Sep 17 00:00:00 2001 From: valentinMachado Date: Fri, 4 Jun 2021 14:19:05 +0200 Subject: [PATCH 50/68] transform class --- src/Game/Shared/Components/THREEUtils.js | 62 ++++++++++++++++++++++-- 1 file changed, 59 insertions(+), 3 deletions(-) diff --git a/src/Game/Shared/Components/THREEUtils.js b/src/Game/Shared/Components/THREEUtils.js index 759049a1c..992b9ac27 100644 --- a/src/Game/Shared/Components/THREEUtils.js +++ b/src/Game/Shared/Components/THREEUtils.js @@ -38,9 +38,65 @@ module.exports = { // renderer.toneMappingExposure = 1; }, - Transform: class { - constructor() { - console.log('new transform'); + Transform: class Transform { + constructor(position, rotation, scale) { + this.position = position || new THREE.Vector3(); + this.rotation = rotation || new THREE.Vector3(); + this.scale = scale || new THREE.Vector3(1, 1, 1); + } + + getPosition() { + return this.position; + } + + setPosition(position) { + this.position = position; + } + + getRotation() { + return this.rotation; + } + + setRotation(rotation) { + this.rotation = rotation; + } + + getScale() { + return this.scale; + } + + setScale(scale) { + this.scale = scale; + } + + clone() { + return new Transform( + this.position.clone(), + this.rotation.clone(), + this.scale.clone() + ); + } + + setFromJSON(json) { + if (json) { + if (json.position) { + this.position.x = json.position.x; + this.position.y = json.position.y; + this.position.z = json.position.z; + } + + if (json.rotation) { + this.rotation.x = json.rotation.x; + this.rotation.y = json.rotation.y; + this.rotation.z = json.rotation.z; + } + + if (json.scale) { + this.scale.x = json.scale.x; + this.scale.y = json.scale.y; + this.scale.z = json.scale.z; + } + } } }, }; From 05e7fa57bc6471bf100f8b8fc7b8864ab8bdd09f Mon Sep 17 00:00:00 2001 From: valentinMachado Date: Fri, 4 Jun 2021 15:27:06 +0200 Subject: [PATCH 51/68] transform refacto --- src/Game/Components/Cameraman.js | 1 + src/Game/Shared/Components/THREEUtils.js | 28 +++-- .../Shared/GameObject/Components/Collider.js | 11 +- src/Game/Shared/GameObject/GameObject.js | 103 +++++------------- src/Game/UDVDebugger/UDVDebugger.js | 4 +- 5 files changed, 53 insertions(+), 94 deletions(-) diff --git a/src/Game/Components/Cameraman.js b/src/Game/Components/Cameraman.js index 327beed0a..76cc75bd3 100644 --- a/src/Game/Components/Cameraman.js +++ b/src/Game/Components/Cameraman.js @@ -111,6 +111,7 @@ export class Cameraman { quaternion.multiply(quaternionCam); quaternion.multiply(quaternionAngle); + //this is not a transform of THREEUtils.Transform return { position: position, quaternion: quaternion }; } diff --git a/src/Game/Shared/Components/THREEUtils.js b/src/Game/Shared/Components/THREEUtils.js index 992b9ac27..520ec4d96 100644 --- a/src/Game/Shared/Components/THREEUtils.js +++ b/src/Game/Shared/Components/THREEUtils.js @@ -2,8 +2,6 @@ const THREE = require('three'); -//TODO create an object Transform with a clone method - module.exports = { textureEncoding: THREE.RGBDEncoding, @@ -77,24 +75,32 @@ module.exports = { ); } + lerp(transform, ratio) { + this.position.lerp(transform.getPosition(), ratio); + this.rotation.lerp(transform.getRotation(), ratio); + this.scale.lerp(transform.getScale(), ratio); + } + + toJSON() { + return { + position: this.position.toArray(), + rotation: this.rotation.toArray(), + scale: this.scale.toArray(), + }; + } + setFromJSON(json) { if (json) { if (json.position) { - this.position.x = json.position.x; - this.position.y = json.position.y; - this.position.z = json.position.z; + this.position.fromArray(json.position); } if (json.rotation) { - this.rotation.x = json.rotation.x; - this.rotation.y = json.rotation.y; - this.rotation.z = json.rotation.z; + this.rotation.fromArray(json.rotation); } if (json.scale) { - this.scale.x = json.scale.x; - this.scale.y = json.scale.y; - this.scale.z = json.scale.z; + this.scale.fromArray(json.scale); } } } diff --git a/src/Game/Shared/GameObject/Components/Collider.js b/src/Game/Shared/GameObject/Components/Collider.js index 585a0f87a..2f15cda5b 100644 --- a/src/Game/Shared/GameObject/Components/Collider.js +++ b/src/Game/Shared/GameObject/Components/Collider.js @@ -96,8 +96,9 @@ class ShapeWrapper { const circle = new Circle(json.center.x, json.center.y, json.radius); this.update = function (worldtransform) { - circle.x = json.center.x + worldtransform.position.x; - circle.y = json.center.y + worldtransform.position.y; + const wp = worldtransform.getPosition(); + circle.x = json.center.x + wp.x; + circle.y = json.center.y + wp.y; }; this.shape = circle; @@ -114,10 +115,8 @@ class ShapeWrapper { this.update = function (worldtransform) { const points = []; json.points.forEach(function (p) { - const point = [ - p.x + worldtransform.position.x, - p.y + worldtransform.position.y, - ]; + const wp = worldtransform.getPosition(); + const point = [p.x + wp.x, p.y + wp.y]; points.push(point); //TODO handle rotation }); diff --git a/src/Game/Shared/GameObject/GameObject.js b/src/Game/Shared/GameObject/GameObject.js index f337c1131..a75d20fec 100644 --- a/src/Game/Shared/GameObject/GameObject.js +++ b/src/Game/Shared/GameObject/GameObject.js @@ -35,7 +35,8 @@ const GameObjectModule = class GameObject { this.prefabId = json.prefabId || null; //transform - this.setTransformFromJSON(json.transform); + this.transform = new THREEUtils.Transform(); + this.transform.setFromJSON(json.transform); //static this.static = json.static || false; @@ -84,7 +85,7 @@ const GameObjectModule = class GameObject { setFromJSON(json) { this.components = {}; //clear this.setComponentsFromJSON(json); - this.setTransformFromJSON(json.transform); + this.transform.setFromJSON(json.transform); this.name = json.name; this.static = json.static; @@ -112,17 +113,13 @@ const GameObjectModule = class GameObject { } computeWorldTransform() { - const result = { - position: new THREE.Vector3(), - rotation: new THREE.Vector3(), - scale: new THREE.Vector3(1, 1, 1), - }; + const result = new THREEUtils.Transform(); let current = this; do { - result.position.add(current.getPosition()); - result.rotation.add(current.getRotation()); - result.scale.multiply(current.getScale()); + result.getPosition().add(current.getPosition()); + result.getRotation().add(current.getRotation()); + result.getScale().multiply(current.getScale()); current = current.parent; } while (current); @@ -131,21 +128,19 @@ const GameObjectModule = class GameObject { } move(vector) { - this.transform.position.add(vector); + this.transform.getPosition().add(vector); this.outdated = true; } clampRotation() { - this.transform.rotation.x = - (Math.PI * 2 + this.transform.rotation.x) % (Math.PI * 2); - this.transform.rotation.y = - (Math.PI * 2 + this.transform.rotation.y) % (Math.PI * 2); - this.transform.rotation.z = - (Math.PI * 2 + this.transform.rotation.z) % (Math.PI * 2); + const r = this.transform.getRotation(); + r.x = (Math.PI * 2 + r.x) % (Math.PI * 2); + r.y = (Math.PI * 2 + r.y) % (Math.PI * 2); + r.z = (Math.PI * 2 + r.z) % (Math.PI * 2); } rotate(vector) { - this.transform.rotation.add(vector); + this.transform.getRotation().add(vector); this.clampRotation(); this.outdated = true; } @@ -166,12 +161,9 @@ const GameObjectModule = class GameObject { } computeForwardVector() { + const r = this.transform.getRotation(); const quaternion = new THREE.Quaternion().setFromEuler( - new THREE.Euler( - this.transform.rotation.x, - this.transform.rotation.y, - this.transform.rotation.z - ) + new THREE.Euler(r.x, r.y, r.z) ); const result = this.getDefaultForward().applyQuaternion(quaternion); return result; @@ -306,35 +298,12 @@ const GameObjectModule = class GameObject { return obj; } - setTransformFromJSON(json) { - if (!this.transform) { - const defaultTransform = { - position: new THREE.Vector3(), - rotation: new THREE.Vector3(), - scale: new THREE.Vector3(1, 1, 1), - }; - this.transform = defaultTransform; - } - - if (json) { - if (json.position) { - this.transform.position.x = json.position.x; - this.transform.position.y = json.position.y; - this.transform.position.z = json.position.z; - } - - if (json.rotation) { - this.transform.rotation.x = json.rotation.x; - this.transform.rotation.y = json.rotation.y; - this.transform.rotation.z = json.rotation.z; - } + getTransform() { + return this.transform; + } - if (json.scale) { - this.transform.scale.x = json.scale.x; - this.transform.scale.y = json.scale.y; - this.transform.scale.z = json.scale.z; - } - } + setTransform(transform) { + this.transform = transform; } clone() { @@ -406,31 +375,31 @@ const GameObjectModule = class GameObject { } getRotation() { - return this.transform.rotation; + return this.transform.getRotation(); } setRotation(vector) { - this.transform.rotation.set(vector.x, vector.y, vector.z); + this.transform.getRotation().set(vector.x, vector.y, vector.z); this.clampRotation(); this.outdated = true; } setPosition(vector) { - this.transform.position.set(vector.x, vector.y, vector.z); + this.transform.getPosition().set(vector.x, vector.y, vector.z); this.outdated = true; } getPosition() { - return this.transform.position; + return this.transform.getPosition(); } setScale(vector) { - this.transform.scale.set(vector.x, vector.y, vector.z); + this.transform.getScale().set(vector.x, vector.y, vector.z); this.outdated = true; } getScale() { - return this.transform.scale; + return this.transform.getScale(); } getName() { @@ -453,10 +422,6 @@ const GameObjectModule = class GameObject { children.push(child.toJSON(withServerComponent)); }); - const position = this.transform.position; - const rot = this.transform.rotation; - const scale = this.transform.scale; - const components = {}; for (let type in this.components) { const c = this.components[type]; @@ -465,11 +430,6 @@ const GameObjectModule = class GameObject { } } - //TODO not declare here or use THREE.Vector3.toJSON - const V2JSON = function (vector) { - return { x: vector.x, y: vector.y, z: vector.z }; - }; - return { name: this.name, type: GameObjectModule.TYPE, @@ -479,11 +439,7 @@ const GameObjectModule = class GameObject { parentUUID: this.parentUUID, components: components, children: children, - transform: { - position: V2JSON(position), - rotation: V2JSON(rot), - scale: V2JSON(scale), - }, + transform: this.transform.toJSON(), }; } }; @@ -492,10 +448,7 @@ GameObjectModule.TYPE = 'GameObject'; GameObjectModule.interpolateInPlace = function (g1, g2, ratio) { //modify g1 transform - g1.transform.position.lerp(g2.transform.position, ratio); - g1.transform.rotation.lerp(g2.transform.rotation, ratio); - g1.transform.scale.lerp(g2.transform.scale, ratio); - + g1.getTransform().lerp(g2.getTransform(), ratio); return g1; }; diff --git a/src/Game/UDVDebugger/UDVDebugger.js b/src/Game/UDVDebugger/UDVDebugger.js index e2b195daa..f3a731399 100644 --- a/src/Game/UDVDebugger/UDVDebugger.js +++ b/src/Game/UDVDebugger/UDVDebugger.js @@ -102,8 +102,8 @@ export class UDVDebugger { }; const loc = { - x: avatarGO.transform.position.x / pixelWorldUnit.width, - y: avatarGO.transform.position.y / pixelWorldUnit.height, + x: avatarGO.getPosition().x / pixelWorldUnit.width, + y: avatarGO.getPosition().y / pixelWorldUnit.height, }; // console.log(loc); From 1e013b5c486e25115880ed865fce6c1460666ead Mon Sep 17 00:00:00 2001 From: valentinMachado Date: Mon, 7 Jun 2021 09:07:30 +0200 Subject: [PATCH 52/68] remove prefabId --- src/Game/Shared/Components/Components.js | 2 -- src/Game/Shared/Components/Data.js | 2 +- src/Game/Shared/Components/PrefabUtils.js | 28 ----------------------- src/Game/Shared/GameObject/GameObject.js | 10 +------- 4 files changed, 2 insertions(+), 40 deletions(-) delete mode 100644 src/Game/Shared/Components/PrefabUtils.js diff --git a/src/Game/Shared/Components/Components.js b/src/Game/Shared/Components/Components.js index c4d0d74e4..94608c1f0 100644 --- a/src/Game/Shared/Components/Components.js +++ b/src/Game/Shared/Components/Components.js @@ -1,11 +1,9 @@ /** @format */ const commonJsData = require('./Data'); -const commonJsPrefabUtils = require('./PrefabUtils'); const commonJsTHREEUtils = require('./THREEUtils'); module.exports = { Data: commonJsData, - PrefabUtils: commonJsPrefabUtils, THREEUtils: commonJsTHREEUtils, }; diff --git a/src/Game/Shared/Components/Data.js b/src/Game/Shared/Components/Data.js index 3b4343102..373abdc4c 100644 --- a/src/Game/Shared/Components/Data.js +++ b/src/Game/Shared/Components/Data.js @@ -17,7 +17,7 @@ module.exports = Object.freeze({ }, }, - //THREAD + //THREAD TODO move this to worldthread and rename this file Constants pack(obj) { let OString = JSON.stringify(obj); diff --git a/src/Game/Shared/Components/PrefabUtils.js b/src/Game/Shared/Components/PrefabUtils.js deleted file mode 100644 index 2c6352b77..000000000 --- a/src/Game/Shared/Components/PrefabUtils.js +++ /dev/null @@ -1,28 +0,0 @@ -/** @format */ - -const JSONUtils = require('../../../Components/SystemUtils/JSONUtils'); - -module.exports = { - parsePrefab(goJSON, manager) { - console.warn('deprecated ?'); - const parse = function (json, cb) { - if (json.children instanceof Object) { - for (let key in json.children) { - cb(json.children, key); - } - } - }; - - parse(goJSON, function (json, key) { - const value = json[key]; - - if (value.prefabId != undefined) { - const prefabJSON = manager.fetchPrefabJSON(value.prefabId); - JSONUtils.overWrite(prefabJSON, json); - json[key] = prefabJSON; - } - }); - - return goJSON; - }, -}; diff --git a/src/Game/Shared/GameObject/GameObject.js b/src/Game/Shared/GameObject/GameObject.js index a75d20fec..0285a6e2c 100644 --- a/src/Game/Shared/GameObject/GameObject.js +++ b/src/Game/Shared/GameObject/GameObject.js @@ -30,10 +30,6 @@ const GameObjectModule = class GameObject { //name this.name = json.name || 'none'; - //TODO remove me - //prefabId - this.prefabId = json.prefabId || null; - //transform this.transform = new THREEUtils.Transform(); this.transform.setFromJSON(json.transform); @@ -90,14 +86,10 @@ const GameObjectModule = class GameObject { this.static = json.static; //TODO recursive call for children + if (this.children.length) console.warn('children not set from ', json); } initAssetsComponents(manager, udvShared, isServerSide = false) { - if (this.prefabId) { - const json = manager.fetchPrefabJSON(this.prefabId); - JSONUtils.overWrite(json, this.json); - this.setFromJSON(json); - } if (!this.initialized) { this.initialized = true; From 4e86069ced52d18937b226c453ff6d254c4e3b3e Mon Sep 17 00:00:00 2001 From: valentinMachado Date: Mon, 7 Jun 2021 09:29:47 +0200 Subject: [PATCH 53/68] move function in utils --- src/Components/SystemUtils/File.js | 16 +++++++++++++++ src/Components/SystemUtils/JSONUtils.js | 27 +++++++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/src/Components/SystemUtils/File.js b/src/Components/SystemUtils/File.js index 43afe413f..2e076ba55 100644 --- a/src/Components/SystemUtils/File.js +++ b/src/Components/SystemUtils/File.js @@ -14,6 +14,7 @@ module.exports = { downloadAnchorNode.click(); downloadAnchorNode.remove(); }, + loadJSON(filePath) { return new Promise((resolve, reject) => { jquery.ajax({ @@ -30,4 +31,19 @@ module.exports = { }); }); }, + + readSingleFile(e, onLoad) { + try { + const file = e.target.files[0]; + if (!file) { + return; + } + const _this = this; + const reader = new FileReader(); + reader.onload = onLoad; + reader.readAsText(file); + } catch (e) { + throw new Error(e); + } + }, }; diff --git a/src/Components/SystemUtils/JSONUtils.js b/src/Components/SystemUtils/JSONUtils.js index 918af82a0..cddb0cd94 100644 --- a/src/Components/SystemUtils/JSONUtils.js +++ b/src/Components/SystemUtils/JSONUtils.js @@ -38,4 +38,31 @@ module.exports = { } }); }, + + separator: '&', + + pack(jsonArray) { + let result = ''; + for (let key in jsonArray) { + result += JSON.stringify(jsonArray[key]); + result += this.separator; + } + + //remove seprator at the end + if (result.endsWith(this.separator)) { + result = result.slice(0, result.length - this.separator.length); + } + return result; + }, + + unpack(string) { + const prefabs = string.split(this.separator); + const result = {}; + prefabs.forEach(function (p) { + const json = JSON.parse(p); + result[json.name] = json; + }); + + return result; + }, }; From 803fc92788baefa99dcb3239b5a93c33a43f07ab Mon Sep 17 00:00:00 2001 From: valentinMachado Date: Mon, 7 Jun 2021 09:43:09 +0200 Subject: [PATCH 54/68] static func bind --- src/Game/Shared/GameObject/Components/Render.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/Game/Shared/GameObject/Components/Render.js b/src/Game/Shared/GameObject/Components/Render.js index aea94fcd0..3ccd4e19a 100644 --- a/src/Game/Shared/GameObject/Components/Render.js +++ b/src/Game/Shared/GameObject/Components/Render.js @@ -155,4 +155,20 @@ const RenderModule = class Render { RenderModule.TYPE = 'Render'; +RenderModule.bindName = function (goJSON, name) { + try { + goJSON.components.Render.name = name; + } catch (e) { + throw new Error(e); + } +}; + +RenderModule.bindColor = function (goJSON, color) { + try { + goJSON.components.Render.color = color; + } catch (e) { + throw new Error(e); + } +}; + module.exports = RenderModule; From 49e4d32d1f2155820032d175b12b535cb392b04f Mon Sep 17 00:00:00 2001 From: valentinMachado Date: Mon, 7 Jun 2021 10:57:21 +0200 Subject: [PATCH 55/68] add TODO --- src/Game/Components/AssetsManager.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Game/Components/AssetsManager.js b/src/Game/Components/AssetsManager.js index 34e2b632d..b60062e6b 100644 --- a/src/Game/Components/AssetsManager.js +++ b/src/Game/Components/AssetsManager.js @@ -201,6 +201,7 @@ export class AssetsManager { return frame; } + //TODO assetManager load video with config a return video with id createVideo(path, w = 1, h = 1, size) { const video = document.createElement('video'); video.src = path; From 20a3c40d454bee1763266cd261cd019e0ab5881d Mon Sep 17 00:00:00 2001 From: valentinMachado Date: Mon, 7 Jun 2021 13:58:16 +0200 Subject: [PATCH 56/68] video are now localscript --- src/Game/Components/AssetsManager.js | 9 +++++++++ src/Game/GameView/GameView.js | 8 +++----- src/Game/Shared/GameObject/Components/Render.js | 16 +++++----------- 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/src/Game/Components/AssetsManager.js b/src/Game/Components/AssetsManager.js index b60062e6b..73901e897 100644 --- a/src/Game/Components/AssetsManager.js +++ b/src/Game/Components/AssetsManager.js @@ -10,6 +10,8 @@ const DEFAULT_MATERIAL = new THREE.MeshLambertMaterial({ color: 0x00ff00 }); export class AssetsManager { constructor() { + this.conf = null; + //manager to load scripts this.prefabs = {}; this.worldScripts = {}; @@ -47,6 +49,11 @@ export class AssetsManager { return new GameObjectModule(this.prefabs[idprefab]); } + fetchVideoPath(idVideo) { + if (!this.conf.videos[idVideo]) console.error('no video with id ', idVideo); + return this.conf.videos[idVideo].path; + } + fetchPrefabJSON(idprefab) { if (!this.prefabs[idprefab]) console.error('no prefab with id ', idprefab); return JSON.parse(JSON.stringify(this.prefabs[idprefab])); @@ -323,6 +330,8 @@ export class AssetsManager { } loadFromConfig(config) { + this.conf = config; + //load config file const _this = this; const loader = new GLTFLoader(); diff --git a/src/Game/GameView/GameView.js b/src/Game/GameView/GameView.js index 5d8c41a7b..4a440d0d1 100644 --- a/src/Game/GameView/GameView.js +++ b/src/Game/GameView/GameView.js @@ -404,11 +404,9 @@ export class GameView { if (!_this.isLocal) g.initAssetsComponents(_this.assetsManager, udvShared); - g.traverse(function (child) { - const scriptComponent = child.getComponent(LocalScript.TYPE); - if (scriptComponent) - scriptComponent.execute(LocalScript.EVENT.INIT, [ctx]); - }); + const scriptComponent = g.getComponent(LocalScript.TYPE); + if (scriptComponent) + scriptComponent.execute(LocalScript.EVENT.INIT, [ctx]); //add static object to obstacle if (g.isStatic()) { diff --git a/src/Game/Shared/GameObject/Components/Render.js b/src/Game/Shared/GameObject/Components/Render.js index 3ccd4e19a..3f5440965 100644 --- a/src/Game/Shared/GameObject/Components/Render.js +++ b/src/Game/Shared/GameObject/Components/Render.js @@ -86,6 +86,11 @@ const RenderModule = class Render { } } + addObject3D(obj) { + this.object3D.add(obj); + this.originalObject3D = this.object3D.clone(); + } + initAssets(assetsManager) { this.object3D = new THREE.Object3D(); this.object3D.name = 'Render Object3D ' + this.parent.getName(); @@ -129,17 +134,6 @@ const RenderModule = class Render { ); this.object3D.add(mediaImg); } - - if (this.media.video) { - const result = assetsManager.createVideo( - this.media.video.path, - this.media.video.width, - this.media.video.height, - this.media.video.size - ); - this.tickCb.push(result.tick); - this.object3D.add(result.frame); - } } const color = this.color; From 008af373a6c066ab37626931a32648a858a2a74b Mon Sep 17 00:00:00 2001 From: valentinMachado Date: Mon, 7 Jun 2021 16:13:39 +0200 Subject: [PATCH 57/68] export transform control --- src/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/index.js b/src/index.js index 1f076ff5e..c396989d3 100644 --- a/src/index.js +++ b/src/index.js @@ -27,8 +27,8 @@ export { jquery }; //three import * as THREE from 'three'; import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'; -import { PointerLockControls } from 'three/examples/jsm/controls/PointerLockControls'; -export { THREE, OrbitControls, PointerLockControls }; +import { TransformControls } from 'three/examples/jsm/controls/TransformControls'; +export { THREE, OrbitControls, TransformControls }; //proj4 import * as proj4 from 'proj4'; From 5fdca3ae9ddc569e372b6088e9c9b9f363fc61c8 Mon Sep 17 00:00:00 2001 From: valentinMachado Date: Tue, 8 Jun 2021 10:35:59 +0200 Subject: [PATCH 58/68] format with prettier widgets sources --- .eslintrc.js | 23 + package.json | 2 + .../3DTiles/3DTilesBuildingUtils.js | 17 +- .../View/CameraPositionerView.js | 15 +- src/Widgets/CityObjects/CityObjectModule.js | 24 +- .../View/AttributeFilterSelector.js | 20 +- .../View/CityObjectFilterSelector.js | 27 +- .../View/CityObjectFilterWindow.js | 35 +- .../CityObjects/View/CityObjectWindow.css | 6 +- .../CityObjects/View/CityObjectWindow.js | 84 ++-- .../CityObjects/ViewModel/AttributeFilter.js | 22 +- .../CityObjects/ViewModel/CityObjectFilter.js | 16 +- .../CityObjects/ViewModel/CityObjectLayer.js | 14 +- .../ViewModel/CityObjectProvider.js | 61 ++- .../View/DocumentVisualizer.css | 6 +- .../View/DocumentVisualizerWindow.js | 73 +-- src/Widgets/Documents/DocumentModule.js | 12 +- src/Widgets/Documents/Model/Document.js | 25 +- .../Documents/Model/DocumentService.js | 86 ++-- .../Documents/View/AbstractDocumentWindow.js | 37 +- .../Documents/View/DocumentInspectorWindow.js | 38 +- .../Documents/View/DocumentNavigatorWindow.js | 80 ++-- src/Widgets/Documents/View/DocumentView.js | 47 +- src/Widgets/Documents/View/DocumentWindow.css | 10 +- .../Documents/ViewModel/DocumentFilter.js | 14 +- .../Documents/ViewModel/DocumentProvider.js | 97 ++-- .../ViewModel/DocumentSearchFilter.js | 46 +- .../3DTilesDebug/views/3DTilesDebugWindow.js | 68 ++- .../services/AuthenticationService.js | 291 ++++++------ .../views/AuthenticationView.css | 182 ++++---- .../views/AuthenticationView.js | 263 +++++------ .../Extensions/Contribute/ContributeModule.js | 48 +- .../Contribute/Service/ContributeService.js | 16 +- .../Extensions/Contribute/View/Contribute.css | 14 +- .../Contribute/View/DocumentCreationWindow.js | 95 ++-- .../View/DocumentDeletionInterface.js | 20 +- .../Contribute/View/DocumentUpdateWindow.js | 40 +- .../DocumentCommentsModule.js | 20 +- .../services/DocumentCommentsService.js | 97 ++-- .../views/DocumentCommentsStyle.css | 132 +++--- .../views/DocumentCommentsWindow.js | 139 +++--- .../DocumentValidationModule.js | 23 +- .../Service/DocumentsInValidationSource.js | 8 +- .../Service/ValidationService.js | 16 +- .../DocumentValidation/View/ValidationView.js | 105 +++-- src/Widgets/Extensions/Extensions.js | 2 - .../Geocoding/services/GeocodingService.js | 40 +- .../Geocoding/views/GeocodingStyle.css | 18 +- .../Geocoding/views/GeocodingView.js | 43 +- src/Widgets/GuidedTour/GuidedTour.css | 370 +++++++-------- src/Widgets/GuidedTour/GuidedTour.js | 176 +++---- .../GuidedTour/GuidedTourController.js | 82 ++-- src/Widgets/LayerChoice/views/LayerChoice.js | 95 ++-- src/Widgets/Links/LinkModule.js | 54 ++- src/Widgets/Links/Model/Link.js | 17 +- src/Widgets/Links/Model/LinkService.js | 32 +- .../Links/View/CityObjectLinkInterface.js | 36 +- .../Links/View/DocumentLinkInterface.js | 79 ++-- src/Widgets/Links/View/LinkView.js | 59 ++- .../Links/ViewModel/CityObjectLinkFilters.js | 48 +- src/Widgets/Links/ViewModel/LinkProvider.js | 155 ++++--- src/Widgets/Others/About.css | 45 +- src/Widgets/Others/About.js | 54 ++- src/Widgets/Others/Help.css | 54 +-- src/Widgets/Others/Help.js | 25 +- .../Temporal/Model/3DTemporalBatchTable.js | 142 +++--- .../Model/3DTemporalBoundingVolume.js | 43 +- .../Temporal/Model/3DTemporalExtension.js | 244 +++++----- .../Model/3DTemporalPrimaryTransaction.js | 18 +- .../Temporal/Model/3DTemporalTileset.js | 82 ++-- .../Temporal/Model/3DTemporalTransaction.js | 21 +- .../Model/3DTemporalTransactionAggregate.js | 18 +- .../Temporal/Model/3DTemporalVersion.js | 27 +- .../3DTILES_temporal.batchTable.schema.json | 2 +- .../3DTILES_temporal.primaryTransaction.json | 21 +- .../3DTILES_temporal.tileset.schema.json | 14 +- .../3DTILES_temporal.transaction.schema.json | 6 +- ..._temporal.transactionAggregate.schema.json | 23 +- ...DTILES_temporal.version.schema.schema.json | 4 +- ...LES_temporal.versionTransition.schema.json | 2 +- src/Widgets/Temporal/TemporalModule.js | 24 +- src/Widgets/Temporal/View/EnumWindows.js | 16 +- src/Widgets/Temporal/View/NetworkManager.js | 133 +++--- .../Temporal/View/TemporalGraphWindow.js | 85 ++-- .../Temporal/View/TemporalSliderWindow.js | 112 ++--- src/Widgets/Temporal/View/TemporalView.js | 46 +- src/Widgets/Temporal/View/TemporalWindow.css | 68 +-- .../Temporal/ViewModel/TemporalProvider.js | 428 ++++++++++-------- 88 files changed, 3115 insertions(+), 2462 deletions(-) create mode 100644 .eslintrc.js diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 000000000..00b804fc4 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,23 @@ +/** @format */ + +module.exports = { + env: { + browser: true, + es2021: true, + node: true, + }, + extends: 'eslint:recommended', + parserOptions: { + ecmaVersion: 2020, + sourceType: 'module', + ecmaFeatures: { + jsx: true, + }, + }, + rules: { + indent: [2, 2, { SwitchCase: 1 }], + 'linebreak-style': ['error', 'unix'], + quotes: ['error', 'single'], + semi: ['error', 'always'], + }, +}; diff --git a/package.json b/package.json index 3b689cd3b..28ac51c2e 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,7 @@ "description": "A collection of itowns plugins", "main": "src", "scripts": { + "eslint": "./node_modules/.bin/eslint ./src", "test": "npm run build", "build": "cross-env NODE_ENV=production webpack", "build-debug": "cross-env NODE_ENV=development webpack", @@ -36,6 +37,7 @@ "child-process-promise": "^2.2.1", "cross-env": "^7.0.3", "css-loader": "^0.28.10", + "eslint": "^7.28.0", "nodemon": "^2.0.7", "style-loader": "^0.20.3", "url-loader": "^1.0.1", diff --git a/src/Components/3DTiles/3DTilesBuildingUtils.js b/src/Components/3DTiles/3DTilesBuildingUtils.js index fdc61ab5f..086c003b0 100644 --- a/src/Components/3DTiles/3DTilesBuildingUtils.js +++ b/src/Components/3DTiles/3DTilesBuildingUtils.js @@ -1,11 +1,16 @@ -import { setTileVerticesColor, getBatchIdFromIntersection, - getBatchTableFromTile, - getTileInLayer} from "./3DTilesUtils"; +/** @format */ + +import { + setTileVerticesColor, + getBatchIdFromIntersection, + getBatchTableFromTile, + getTileInLayer, +} from './3DTilesUtils'; /** * Gets a building ID from an intersection. The intersecting object must * be a "Mesh" object with a batch id. - * + * * @param {*} inter An intersection */ export function getBuildingIdFromIntersection(inter) { @@ -28,7 +33,7 @@ export function getBuildingInfoFromBuildingId(tilesInfo, buildingId) { /** * Sets the color of one building in the scene. - * + * * @param {*} layer The 3DTiles layer. * @param {*} buildingInfo The building info. * @param {Array} color The color. @@ -39,4 +44,4 @@ export function colorBuilding(layer, buildingInfo, color) { throw 'Building not in the view - tile is not loaded'; } setTileVerticesColor(tile, color, buildingInfo.arrayIndexes); -} \ No newline at end of file +} diff --git a/src/Widgets/CameraPositioner/View/CameraPositionerView.js b/src/Widgets/CameraPositioner/View/CameraPositionerView.js index 095105b5c..7dd3ff773 100644 --- a/src/Widgets/CameraPositioner/View/CameraPositionerView.js +++ b/src/Widgets/CameraPositioner/View/CameraPositionerView.js @@ -1,7 +1,9 @@ +/** @format */ + //Components -import { ModuleView } from "../../../Components/ModuleView/ModuleView"; -import { PositionerWindow } from "../../../Components/Camera/PositionerWindow"; -import { Window } from "../../../Components/GUI/js/Window"; +import { ModuleView } from '../../../Components/ModuleView/ModuleView'; +import { PositionerWindow } from '../../../Components/Camera/PositionerWindow'; +import { Window } from '../../../Components/GUI/js/Window'; export class CameraPositionerView extends ModuleView { constructor(itownsView, cameraControls) { @@ -9,8 +11,9 @@ export class CameraPositionerView extends ModuleView { this.positionerWindow = new PositionerWindow(itownsView, cameraControls); - this.positionerWindow.addEventListener(Window.EVENT_DISABLED, - () => this.disable()); + this.positionerWindow.addEventListener(Window.EVENT_DISABLED, () => + this.disable() + ); } enableView() { @@ -20,4 +23,4 @@ export class CameraPositionerView extends ModuleView { disableView() { this.positionerWindow.dispose(); } -} \ No newline at end of file +} diff --git a/src/Widgets/CityObjects/CityObjectModule.js b/src/Widgets/CityObjects/CityObjectModule.js index e32169f93..678b45085 100644 --- a/src/Widgets/CityObjects/CityObjectModule.js +++ b/src/Widgets/CityObjects/CityObjectModule.js @@ -1,8 +1,10 @@ +/** @format */ + //Components -import { CityObjectStyle } from "../../Components/3DTiles/Model/CityObjectStyle"; +import { CityObjectStyle } from '../../Components/3DTiles/Model/CityObjectStyle'; -import { CityObjectProvider } from "./ViewModel/CityObjectProvider"; -import { CityObjectWindow } from "./View/CityObjectWindow"; +import { CityObjectProvider } from './ViewModel/CityObjectProvider'; +import { CityObjectWindow } from './View/CityObjectWindow'; /** * Manages the city objects and allows the user to visualize them with @@ -14,7 +16,7 @@ export class CityObjectModule { * Manages the city objects and allows the user to visualize them with * filters. Other modules can extend the functionnalities of the city object * module by adding filters. - * + * * @param {LayerManager} layerManager The layer manager. * @param {object} config The UDV configuration. * @param {object} config.cityObjects The city objects config. @@ -43,7 +45,7 @@ export class CityObjectModule { /** * Adds an event listener to the city object provider. - * + * * @param {string} event The event of the city object provider. * @param {(data: any) => any} action The listener method. */ @@ -53,7 +55,7 @@ export class CityObjectModule { /** * Removes the event listener from the city object provider. - * + * * @param {(data: any) => any} action The listener to remove. */ removeEventListener(action) { @@ -61,9 +63,9 @@ export class CityObjectModule { } /** - * Creates a new extension for the city object window. An extension is + * Creates a new extension for the city object window. An extension is * a piece of HTML identified by a label. - * + * * @param {string} label The extension label. * @param {object} options The options for the extension. * @param {string} options.type The type of the extension. Can either be @@ -83,7 +85,7 @@ export class CityObjectModule { /** * Removes an existing extension in the city object window. - * + * * @param {string} label The extension label. */ removeExtension(label) { @@ -92,11 +94,11 @@ export class CityObjectModule { /** * Adds a filter selector in the city object filter window. - * + * * @param {CityObjectFilterSelector} filterSelector The filter selector to * add. */ addFilterSelector(filterSelector) { this.view.addFilterSelector(filterSelector); } -} \ No newline at end of file +} diff --git a/src/Widgets/CityObjects/View/AttributeFilterSelector.js b/src/Widgets/CityObjects/View/AttributeFilterSelector.js index 90064ea1f..1a8757afe 100644 --- a/src/Widgets/CityObjects/View/AttributeFilterSelector.js +++ b/src/Widgets/CityObjects/View/AttributeFilterSelector.js @@ -1,6 +1,8 @@ -import { CityObjectFilterSelector } from "./CityObjectFilterSelector"; -import { CityObjectProvider } from "../ViewModel/CityObjectProvider"; -import { AttributeFilter } from "../ViewModel/AttributeFilter"; +/** @format */ + +import { CityObjectFilterSelector } from './CityObjectFilterSelector'; +import { CityObjectProvider } from '../ViewModel/CityObjectProvider'; +import { AttributeFilter } from '../ViewModel/AttributeFilter'; /** * A filter selector for the `AttributeFilter` filter. It allows the user to @@ -11,7 +13,7 @@ import { AttributeFilter } from "../ViewModel/AttributeFilter"; export class AttributeFilterSelector extends CityObjectFilterSelector { /** * Constructs the attribute filter selector from the provider. - * + * * @param {CityObjectProvider} provider The city object provider. */ constructor(provider) { @@ -19,7 +21,7 @@ export class AttributeFilterSelector extends CityObjectFilterSelector { /** * The associated attribute filter. - * + * * @type {AttributeFilter} */ this.filter = new AttributeFilter(); @@ -29,7 +31,7 @@ export class AttributeFilterSelector extends CityObjectFilterSelector { } get html() { - return /*html*/` + return /*html*/ ` @@ -42,9 +44,9 @@ export class AttributeFilterSelector extends CityObjectFilterSelector { /** * Sets the `tileId`, `batchId` and `props` attributes of the attribut filter * from the given form data. - * + * * @override - * + * * @param {FormData} formData */ onSubmit(formData) { @@ -56,4 +58,4 @@ export class AttributeFilterSelector extends CityObjectFilterSelector { } } } -} \ No newline at end of file +} diff --git a/src/Widgets/CityObjects/View/CityObjectFilterSelector.js b/src/Widgets/CityObjects/View/CityObjectFilterSelector.js index 34dd96dde..1ba6f26eb 100644 --- a/src/Widgets/CityObjects/View/CityObjectFilterSelector.js +++ b/src/Widgets/CityObjects/View/CityObjectFilterSelector.js @@ -2,26 +2,29 @@ * Represents an option in the list of filters the user can select. It also * stores additional HTML that can be put in a form if the filter accepts * parameters. + * + * @format */ + export class CityObjectFilterSelector { /** * Constructs a filter selector from the associated filter label and a * display name. - * + * * @param {string} filterLabel The associated filter. * @param {string} displayName The displayed name in the `select` tag. */ - constructor(filterLabel, displayName) { + constructor(filterLabel, displayName) { /** * The label of the corresponding filter. - * + * * @type {string} */ this.filterLabel = filterLabel; /** * The displayed name of the filter. - * + * * @type {string} */ this.displayName = displayName; @@ -29,7 +32,7 @@ export class CityObjectFilterSelector { /** * The HTML that will be put in the filter form. - * + * * @returns {string} */ get html() { @@ -40,29 +43,25 @@ export class CityObjectFilterSelector { /** * Triggers when the HTML elements are created. */ - onCreated() { - - } + onCreated() {} /** * Triggers when the form is submitted. - * + * * @param {FormData} formData The form data corresponding to the filter * selector form. */ - onSubmit(formData) { - - } + onSubmit(formData) {} /** * Adds the HTML content of the filter selector in the given HTLM element. * This element should be a form, or part of a form. Calls the `onCreated` * hook. - * + * * @param {HTMLElement} parentElement The parent element to add the fields. */ appendFormFieldsTo(parentElement) { parentElement.innerHTML = this.html; this.onCreated(); } -} \ No newline at end of file +} diff --git a/src/Widgets/CityObjects/View/CityObjectFilterWindow.js b/src/Widgets/CityObjects/View/CityObjectFilterWindow.js index 7de85fa85..e9b018a86 100644 --- a/src/Widgets/CityObjects/View/CityObjectFilterWindow.js +++ b/src/Widgets/CityObjects/View/CityObjectFilterWindow.js @@ -1,7 +1,9 @@ +/** @format */ + //Components -import { Window } from "../../../Components/GUI/js/Window"; +import { Window } from '../../../Components/GUI/js/Window'; -import { CityObjectFilterSelector } from "./CityObjectFilterSelector"; +import { CityObjectFilterSelector } from './CityObjectFilterSelector'; /** * The filter selection window. This window allows the user to pick a filter @@ -17,7 +19,7 @@ export class CityObjectFilterWindow extends Window { /** * The list of filter selectors. - * + * * @type {Array} */ this.filterSelectors = []; @@ -27,7 +29,7 @@ export class CityObjectFilterWindow extends Window { } get innerContentHtml() { - return /*html*/` + return /*html*/ `

          Filter selection

          @@ -55,19 +57,21 @@ export class CityObjectFilterWindow extends Window { this.filterFormElement.onsubmit = () => { this._onSubmit(); return false; - } + }; } /** * Adds a filter selector in the filter selectos list. - * + * * @param {CityObjectFilterSelector} filterSelector The filter selector to * add. */ addFilterSelector(filterSelector) { if (!!this.getFilterSelector(filterSelector.filterLabel)) { - throw 'A filter selector with the same filter label already exist: ' - + filterSelector.filterLabel; + throw ( + 'A filter selector with the same filter label already exist: ' + + filterSelector.filterLabel + ); } this.filterSelectors.push(filterSelector); this._createFilterSelect(); @@ -75,7 +79,7 @@ export class CityObjectFilterWindow extends Window { /** * Returns the filter selector corresponding to the given filter label. - * + * * @param {string} filterLabel The label of the filter. */ getFilterSelector(filterLabel) { @@ -125,12 +129,14 @@ export class CityObjectFilterWindow extends Window { * selected the 'No filter' option. */ _getCurrentSelector() { - let selected = this.filterSelectElement.options[this.filterSelectElement.selectedIndex].label; + let selected = + this.filterSelectElement.options[this.filterSelectElement.selectedIndex] + .label; if (selected === 'no-filter') { return undefined; } - + let selector = this.getFilterSelector(selected); if (selector === undefined) { @@ -154,7 +160,10 @@ export class CityObjectFilterWindow extends Window { let formData = new FormData(this.filterFormElement); selector.onSubmit(formData); - this.sendEvent(CityObjectFilterWindow.EVENT_FILTER_SELECTED, selector.filterLabel); + this.sendEvent( + CityObjectFilterWindow.EVENT_FILTER_SELECTED, + selector.filterLabel + ); this.disable(); } @@ -191,4 +200,4 @@ export class CityObjectFilterWindow extends Window { static get EVENT_FILTER_SELECTED() { return 'EVENT_FILTER_SELECTED'; } -} \ No newline at end of file +} diff --git a/src/Widgets/CityObjects/View/CityObjectWindow.css b/src/Widgets/CityObjects/View/CityObjectWindow.css index a5d4c1d4a..9f403a2a0 100644 --- a/src/Widgets/CityObjects/View/CityObjectWindow.css +++ b/src/Widgets/CityObjects/View/CityObjectWindow.css @@ -1,3 +1,5 @@ +/** @format */ + .city-object-title { margin: 5px 0 5px 0; font-weight: bold; @@ -13,7 +15,7 @@ margin: 10px; } -.city-object-filter-section input[type="text"] { +.city-object-filter-section input[type='text'] { width: 100%; box-sizing: border-box; } @@ -27,4 +29,4 @@ border: 1px solid #f2f2f2; margin: 2px; margin-left: 10px; -} \ No newline at end of file +} diff --git a/src/Widgets/CityObjects/View/CityObjectWindow.js b/src/Widgets/CityObjects/View/CityObjectWindow.js index d9940dbae..5359230a6 100644 --- a/src/Widgets/CityObjects/View/CityObjectWindow.js +++ b/src/Widgets/CityObjects/View/CityObjectWindow.js @@ -1,11 +1,13 @@ +/** @format */ + //Components -import { Window } from "../../../Components/GUI/js/Window"; -import { CityObjectStyle } from "../../../Components/3DTiles/Model/CityObjectStyle"; +import { Window } from '../../../Components/GUI/js/Window'; +import { CityObjectStyle } from '../../../Components/3DTiles/Model/CityObjectStyle'; -import { CityObjectProvider } from "../ViewModel/CityObjectProvider"; -import { CityObjectFilterSelector } from "./CityObjectFilterSelector"; -import { CityObjectFilterWindow } from "./CityObjectFilterWindow"; -import { AttributeFilterSelector } from "./AttributeFilterSelector"; +import { CityObjectProvider } from '../ViewModel/CityObjectProvider'; +import { CityObjectFilterSelector } from './CityObjectFilterSelector'; +import { CityObjectFilterWindow } from './CityObjectFilterWindow'; +import { AttributeFilterSelector } from './AttributeFilterSelector'; import './CityObjectWindow.css'; @@ -17,7 +19,7 @@ import './CityObjectWindow.css'; export class CityObjectWindow extends Window { /** * Constructs the window from the provider. - * + * * @param {CityObjectProvider} provider The city object provider. */ constructor(provider) { @@ -25,35 +27,35 @@ export class CityObjectWindow extends Window { /** * The city object provider. - * + * * @type {CityObjectProvider} */ this.provider = provider; /** * The window for selected filters. - * + * * @type {CityObjectFilterWindow} */ this.filterWindow = new CityObjectFilterWindow(); /** * The style for the layer chosen by the user, through the filter window. - * + * * @type {CityObjectStyle | string} */ - this.defaultLayerStyle = {materialProps: {color: 0xffa14f}}; + this.defaultLayerStyle = { materialProps: { color: 0xffa14f } }; /** * Wether the use is currently selecting a city object. - * + * * @type {boolean} */ this.isSelectingCityObject = false; /** * The list of extensions - * + * * @type {Array<{html: string, label: string, id: string}>} */ this.extensions = []; @@ -61,7 +63,7 @@ export class CityObjectWindow extends Window { let viewerDiv = document.getElementById('viewerDiv'); /** * The event listener for mouse clicks. - * + * * @type {(event: MouseEvent) => any} */ this.mouseClickListener = (event) => { @@ -77,29 +79,34 @@ export class CityObjectWindow extends Window { viewerDiv.removeEventListener('mousedown', this.mouseClickListener); }); - // Adding a filter selector for the attribute filter - this.filterWindow.addFilterSelector(new AttributeFilterSelector(this.provider)); + this.filterWindow.addFilterSelector( + new AttributeFilterSelector(this.provider) + ); // The event listener for filter selection (in the filter window). Updates // the layer in the provider. this.filterWindow.addEventListener( CityObjectFilterWindow.EVENT_FILTER_SELECTED, - (filterLabel) => this._onFilterSelected(filterLabel)); + (filterLabel) => this._onFilterSelected(filterLabel) + ); // The event listener for the layer change. Updates the layer description. - this.provider.addEventListener(CityObjectProvider.EVENT_LAYER_CHANGED, - () => this._updateLayerDescription()); + this.provider.addEventListener(CityObjectProvider.EVENT_LAYER_CHANGED, () => + this._updateLayerDescription() + ); // Event listener for city object selection - this.provider.addEventListener(CityObjectProvider.EVENT_CITY_OBJECT_SELECTED, - (cityObject) => this._updateSelectedCityObjectDescription(cityObject)); + this.provider.addEventListener( + CityObjectProvider.EVENT_CITY_OBJECT_SELECTED, + (cityObject) => this._updateSelectedCityObjectDescription(cityObject) + ); this._updateLayerDescription(); this._updateSelectedCityObjectDescription(); } get innerContentHtml() { - return /*html*/` + return /*html*/ `

          Filter

          @@ -140,14 +147,12 @@ export class CityObjectWindow extends Window { this._createExtensionElement(extension); } - this.selectFilterButtonElement.onclick = - () => this.filterWindow.enable(); + this.selectFilterButtonElement.onclick = () => this.filterWindow.enable(); - this.clearFilterButtonElement.onclick = - () => this.provider.removeLayer(); + this.clearFilterButtonElement.onclick = () => this.provider.removeLayer(); - this.clearSelectionButtonElement.onclick = - () => this._clearCityObjectSelection(); + this.clearSelectionButtonElement.onclick = () => + this._clearCityObjectSelection(); this.clearSelectionButtonElement.disabled = true; @@ -167,7 +172,7 @@ export class CityObjectWindow extends Window { this.selectedFilterElement.innerText = layer.filter.toString(); this.layerColorIndicatorElement.style.display = ''; this.layerColorIndicatorElement.style.background = - '#' + (new THREE.Color(layer.style.materialProps.color)).getHexString(); + '#' + new THREE.Color(layer.style.materialProps.color).getHexString(); } else { this.selectedFilterElement.innerText = ''; this.layerColorIndicatorElement.style.display = 'none'; @@ -180,7 +185,7 @@ export class CityObjectWindow extends Window { /** * Adds a filter selector in the city object filter window. - * + * * @param {CityObjectFilterSelector} filterSelector The filter selector to * add. */ @@ -191,7 +196,7 @@ export class CityObjectWindow extends Window { /** * Triggered when the user selects a filter in the filter selection window. * Sets the correct layer in the provider. - * + * * @param {string} filterLabel The selected filter label. */ _onFilterSelected(filterLabel) { @@ -205,7 +210,7 @@ export class CityObjectWindow extends Window { /** * Sets the default style for the layer defined by the user (through the * filter selection window). - * + * * @param {CityObjectStyle | string} style The default style for the layer. */ setDefaultLayerStyle(style) { @@ -225,7 +230,7 @@ export class CityObjectWindow extends Window { /** * Updates the description for the selected city object. - * + * * @param {CityObject} cityObject The selected city object. */ _updateSelectedCityObjectDescription(cityObject) { @@ -233,8 +238,11 @@ export class CityObjectWindow extends Window { return; } - this.selectionColorIndicatorElement.style.background = '#' + - (new THREE.Color(this.provider.defaultSelectionStyle.materialProps.color)).getHexString(); + this.selectionColorIndicatorElement.style.background = + '#' + + new THREE.Color( + this.provider.defaultSelectionStyle.materialProps.color + ).getHexString(); if (!cityObject) { this.selectedCityObjectElement.innerHTML = ''; @@ -244,7 +252,7 @@ export class CityObjectWindow extends Window { this.clearSelectionButtonElement.disabled = false; - let html = /*html*/` + let html = /*html*/ `

          Attributes

          Tile ID : ${cityObject.tile.tileId}
          @@ -252,7 +260,7 @@ export class CityObjectWindow extends Window { Layer : ${cityObject.tile.layer.name} `; for (let prop of Object.entries(cityObject.props)) { - html += /*html*/` + html += /*html*/ `
          ${prop[0]} : ${prop[1]} `; } @@ -318,4 +326,4 @@ export class CityObjectWindow extends Window { get selectionColorIndicatorElement() { return document.getElementById(this.selectionColorIndicatorId); } -} \ No newline at end of file +} diff --git a/src/Widgets/CityObjects/ViewModel/AttributeFilter.js b/src/Widgets/CityObjects/ViewModel/AttributeFilter.js index a429f4ec9..3b8a3c056 100644 --- a/src/Widgets/CityObjects/ViewModel/AttributeFilter.js +++ b/src/Widgets/CityObjects/ViewModel/AttributeFilter.js @@ -1,7 +1,9 @@ +/** @format */ + //Components -import { CityObject } from "../../../Components/3DTiles/Model/CityObject"; +import { CityObject } from '../../../Components/3DTiles/Model/CityObject'; -import { CityObjectFilter } from "./CityObjectFilter"; +import { CityObjectFilter } from './CityObjectFilter'; /** * A specialization of `CityObjectFilter` to filter the city objects from @@ -37,9 +39,9 @@ export class AttributeFilter extends CityObjectFilter { * Accepts city objects according to their attributes. For each attribute in * this filter that evaluates to `true` (ie. neither undefined, null nor an * empty string), equality is tested with the city object. - * + * * @param {CityObject} cityObject The city object to evaluate. - * + * * @returns {boolean} Wether the city object is acceptable. */ accepts(cityObject) { @@ -52,8 +54,10 @@ export class AttributeFilter extends CityObjectFilter { } for (let key of Object.keys(this.props)) { - if (!cityObject.props[key] || - (!!this.props[key] && this.props[key] != cityObject.props[key])) { + if ( + !cityObject.props[key] || + (!!this.props[key] && this.props[key] != cityObject.props[key]) + ) { return false; } } @@ -92,11 +96,11 @@ export class AttributeFilter extends CityObjectFilter { result += ', '; } } - result += ')' + result += ')'; } else { - result += 'All city objects' + result += 'All city objects'; } return result; } -} \ No newline at end of file +} diff --git a/src/Widgets/CityObjects/ViewModel/CityObjectFilter.js b/src/Widgets/CityObjects/ViewModel/CityObjectFilter.js index a10f47931..aebddc3a5 100644 --- a/src/Widgets/CityObjects/ViewModel/CityObjectFilter.js +++ b/src/Widgets/CityObjects/ViewModel/CityObjectFilter.js @@ -1,5 +1,7 @@ +/** @format */ + //Components -import { CityObject } from "../../../Components/3DTiles/Model/CityObject"; +import { CityObject } from '../../../Components/3DTiles/Model/CityObject'; /** * Represents a filter for city objects. It is basically a function that takes @@ -9,7 +11,7 @@ export class CityObjectFilter { /** * Constructs a new city object filter, from an acceptation function. If no * acceptation function was provided, the filter accepts all city objects. - * + * * @param {string} label The unique label identifying the filter. * @param {(CityObject) => boolean} [accepts] The function responsible to * filter the city objects. It must evaluate wether a city object is @@ -18,12 +20,12 @@ export class CityObjectFilter { constructor(label, accepts) { /** * The unique identifier of the filter. - * + * * @type {string} */ this.label = label; - if (typeof(accepts) === 'function') { + if (typeof accepts === 'function') { this.accepts = accepts; } else { // Necessary if inheritance is used, I'm not sure why though @@ -34,9 +36,9 @@ export class CityObjectFilter { /** * The function responsible to filter the city objects. It evaluates wether * a city object is acceptable according to the filter. - * + * * @param {CityObject} cityObject The city object to evaluate. - * + * * @returns {boolean} Wether the city object is acceptable. */ accepts(cityObject) { @@ -50,4 +52,4 @@ export class CityObjectFilter { toString() { return this.label; } -} \ No newline at end of file +} diff --git a/src/Widgets/CityObjects/ViewModel/CityObjectLayer.js b/src/Widgets/CityObjects/ViewModel/CityObjectLayer.js index fd258568c..9d2a59f63 100644 --- a/src/Widgets/CityObjects/ViewModel/CityObjectLayer.js +++ b/src/Widgets/CityObjects/ViewModel/CityObjectLayer.js @@ -1,7 +1,9 @@ +/** @format */ + //Components -import { CityObjectStyle } from "../../../Components/3DTiles/Model/CityObjectStyle"; +import { CityObjectStyle } from '../../../Components/3DTiles/Model/CityObjectStyle'; -import { CityObjectFilter } from "./CityObjectFilter"; +import { CityObjectFilter } from './CityObjectFilter'; /** * A layer represents an association between a set of city objects and a style. @@ -10,7 +12,7 @@ import { CityObjectFilter } from "./CityObjectFilter"; export class CityObjectLayer { /** * Constructs a layer from a filter and a style. - * + * * @param {CityObjectFilter} filter The filter associated with the layer. * @param {CityObjectStyle | string} style The style associated with the * layer. @@ -22,16 +24,16 @@ export class CityObjectLayer { /** * The filter associated with the layer. - * + * * @type {CityObjectFilter} */ this.filter = filter; /** * The style associated with the layer. - * + * * @type {CityObjectStyle | string} */ this.style = style; } -} \ No newline at end of file +} diff --git a/src/Widgets/CityObjects/ViewModel/CityObjectProvider.js b/src/Widgets/CityObjects/ViewModel/CityObjectProvider.js index e130e6dd4..99b40e6a5 100644 --- a/src/Widgets/CityObjects/ViewModel/CityObjectProvider.js +++ b/src/Widgets/CityObjects/ViewModel/CityObjectProvider.js @@ -1,11 +1,16 @@ +/** @format */ + //Components -import { CityObjectStyle } from "../../../Components/3DTiles/Model/CityObjectStyle"; -import { CityObjectID, CityObject } from "../../../Components/3DTiles/Model/CityObject"; -import { EventSender } from "../../../Components/Events/EventSender"; -import { LayerManager } from "../../../Components/LayerManager/LayerManager"; +import { CityObjectStyle } from '../../../Components/3DTiles/Model/CityObjectStyle'; +import { + CityObjectID, + CityObject, +} from '../../../Components/3DTiles/Model/CityObject'; +import { EventSender } from '../../../Components/Events/EventSender'; +import { LayerManager } from '../../../Components/LayerManager/LayerManager'; -import { CityObjectFilter } from "./CityObjectFilter"; -import { CityObjectLayer } from "./CityObjectLayer"; +import { CityObjectFilter } from './CityObjectFilter'; +import { CityObjectLayer } from './CityObjectLayer'; /** * The city object provider manages the city object by organizing them in two @@ -16,49 +21,49 @@ import { CityObjectLayer } from "./CityObjectLayer"; export class CityObjectProvider extends EventSender { /** * Constructs a city object provider, using a layer manager. - * + * * @param {LayerManager} layerManager The layer manager. */ constructor(layerManager) { super(); /** * The tiles manager. - * + * * @type {LayerManager} */ this.layerManager = layerManager; /** * The available filters. - * + * * @type {Object.} */ this.filters = {}; /** * The current highlighted layer. - * + * * @type {CityObjectLayer} */ this.cityOjectLayer = undefined; /** * The array of city objects in the layer. - * + * * @type {Array} */ this.layerCityObjectIds = []; /** * The selected city object. - * + * * @type {CityObject} */ this.selectedCityObject = undefined; /** * The style applied to the selected city object. - * + * * @type {CityObjectStyle | string} */ this.defaultSelectionStyle = { materialProps: { color: 0x13ddef } }; @@ -75,7 +80,7 @@ export class CityObjectProvider extends EventSender { /** * Selects a city object from a mouse event. If a city object is actually * under the mouse, the `EVENT_CITY_OBJECT_SELECTED` event is sent. - * + * * @param {MouseEvent} mouseEvent The mouse click event. */ selectCityObject(mouseEvent) { @@ -101,7 +106,7 @@ export class CityObjectProvider extends EventSender { /** * Sets the style for the selected city object. - * + * * @param {CityObjectStyle | string} style The style. */ setSelectionStyle(style) { @@ -115,7 +120,7 @@ export class CityObjectProvider extends EventSender { * Adds a filter to the dictionnary of available filters. The key shall be * the `label` attribute of the filter. After that, the * `EVENT_FILTERS_UPDATED` event is sent. - * + * * @param {CityObjectFilter} cityObjectFilter The filter to add. */ addFilter(cityObjectFilter) { @@ -132,7 +137,7 @@ export class CityObjectProvider extends EventSender { /** * Returns the currently available filters. - * + * * @return {Array} The currently available filters. */ getFilters() { @@ -145,7 +150,7 @@ export class CityObjectProvider extends EventSender { /** * Sets the current layer. The layer is defined by a filter (ie. a set * of city objects) and a style. Sends the `EVENT_LAYER_CHANGED` event. - * + * * @param {string} filterLabel Label of the filter that defines the layer. * The filter must first be registered using `addFilter`. * @param {CityObjectStyle | string} style The style to associate to the @@ -169,7 +174,7 @@ export class CityObjectProvider extends EventSender { /** * Returns the current layer. - * + * * @returns {CityObjectLayer} The current layer. */ getLayer() { @@ -188,13 +193,15 @@ export class CityObjectProvider extends EventSender { /** * Updates the tiles manager so that it has the correct styles associated with * the right city objects. - * + * * @private */ _updateTilesManager() { this.layerManager.removeAll3DTilesStyles(); if (!!this.selectedCityObject) { - let tileManager = this.layerManager.getTilesManagerByLayerID(this.selectedCityObject.tile.layer.id); + let tileManager = this.layerManager.getTilesManagerByLayerID( + this.selectedCityObject.tile.layer.id + ); if (this.cityOjectLayer === undefined) { this.layerCityObjectIds = []; @@ -203,10 +210,16 @@ export class CityObjectProvider extends EventSender { .findAllCityObjects(this.cityOjectLayer.filter.accepts) .map((co) => co.cityObjectId); - tileManager.setStyle(this.layerCityObjectIds, this.cityOjectLayer.style); + tileManager.setStyle( + this.layerCityObjectIds, + this.cityOjectLayer.style + ); } - tileManager.setStyle(this.selectedCityObject.cityObjectId, this.defaultSelectionStyle); + tileManager.setStyle( + this.selectedCityObject.cityObjectId, + this.defaultSelectionStyle + ); } } @@ -234,4 +247,4 @@ export class CityObjectProvider extends EventSender { static get EVENT_CITY_OBJECT_SELECTED() { return 'EVENT_CITY_OBJECT_SELECTED'; } -} \ No newline at end of file +} diff --git a/src/Widgets/DocumentVisualizer/View/DocumentVisualizer.css b/src/Widgets/DocumentVisualizer/View/DocumentVisualizer.css index 54c94e584..5318063d5 100644 --- a/src/Widgets/DocumentVisualizer/View/DocumentVisualizer.css +++ b/src/Widgets/DocumentVisualizer/View/DocumentVisualizer.css @@ -1,3 +1,5 @@ +/** @format */ + .orienter-box { width: 55%; height: 55%; @@ -18,7 +20,7 @@ .orienter-box .controls-panel { width: 80%; max-width: 500px; - background: rgba(30,30,30,.6); + background: rgba(30, 30, 30, 0.6); border: 1px solid #000; padding: 5px; color: white; @@ -41,4 +43,4 @@ .orienter-box .controls-panel .slider-container input { width: 100%; -} \ No newline at end of file +} diff --git a/src/Widgets/DocumentVisualizer/View/DocumentVisualizerWindow.js b/src/Widgets/DocumentVisualizer/View/DocumentVisualizerWindow.js index 1eba8039d..0f6018ca0 100644 --- a/src/Widgets/DocumentVisualizer/View/DocumentVisualizerWindow.js +++ b/src/Widgets/DocumentVisualizer/View/DocumentVisualizerWindow.js @@ -1,9 +1,11 @@ -import { AbstractDocumentWindow } from "../../Documents/View/AbstractDocumentWindow"; -import * as THREE from "three"; +/** @format */ + +import { AbstractDocumentWindow } from '../../Documents/View/AbstractDocumentWindow'; +import * as THREE from 'three'; import './DocumentVisualizer.css'; -import { DocumentProvider } from "../../Documents/ViewModel/DocumentProvider"; -import { DocumentModule } from "../../Documents/DocumentModule"; +import { DocumentProvider } from '../../Documents/ViewModel/DocumentProvider'; +import { DocumentModule } from '../../Documents/DocumentModule'; /** * Represents the document visualizer, under the form of an oriented image. It @@ -13,7 +15,7 @@ import { DocumentModule } from "../../Documents/DocumentModule"; export class DocumentVisualizerWindow extends AbstractDocumentWindow { /** * Creates a new document image orienter. - * + * * @param {DocumentModule} documentModule The document module. * @param {*} itownsView The iTowns view. * @param {*} cameraControls The planar camera controls. @@ -34,40 +36,40 @@ export class DocumentVisualizerWindow extends AbstractDocumentWindow { this.disable(); await this.startTravelToDisplayedDocument(); this.requestDisplay(); - } + }, }); /** * The iTowns view. - * + * * @type {any} */ this.itownsView = itownsView; /** * The camera controls. - * + * * @type {any} */ this.cameraControls = cameraControls; /** * The visualization camera position. - * + * * @type {THREE.Vector3} */ this.position = undefined; /** * The visualization camera orientation. - * + * * @type {THREE.Quaternion} */ this.quaternion = undefined; } get html() { - return /*html*/` + return /*html*/ `

          @@ -84,7 +86,7 @@ export class DocumentVisualizerWindow extends AbstractDocumentWindow { windowCreated() { this.hide(); - this.window.classList.add("orienter-box"); + this.window.classList.add('orienter-box'); this.window.style.position = 'absolute'; this.closeButtonElement.onclick = () => { @@ -98,8 +100,10 @@ export class DocumentVisualizerWindow extends AbstractDocumentWindow { documentWindowReady() { // Dispose the window when the displayed document change - this.provider.addEventListener(DocumentProvider.EVENT_DISPLAYED_DOC_CHANGED, - () => this.disable()); + this.provider.addEventListener( + DocumentProvider.EVENT_DISPLAYED_DOC_CHANGED, + () => this.disable() + ); } ////////////////////// @@ -108,7 +112,7 @@ export class DocumentVisualizerWindow extends AbstractDocumentWindow { /** * Triggered when the opacity of the slider changes. This method apply the * change on the image and the output element. - * + * * @private */ _onOpacityChange() { @@ -120,7 +124,7 @@ export class DocumentVisualizerWindow extends AbstractDocumentWindow { /** * Sets the orientation for the camera. `startTravel` should be called after * this method to apply the new position. - * + * * @param {THREE.Vector3} position The visualization camera position. */ setTargetPosition(position) { @@ -130,7 +134,7 @@ export class DocumentVisualizerWindow extends AbstractDocumentWindow { /** * Sets the orientation for the camera. `startTravel` should be called after * this method to apply the new orientation. - * + * * @param {THREE.Quaternion} position The visualization camera orientation. */ setTargetQuaternion(quaternion) { @@ -139,7 +143,7 @@ export class DocumentVisualizerWindow extends AbstractDocumentWindow { /** * Sets the image source. - * + * * @param {string} newSrc The image source. */ setImageSrc(newSrc) { @@ -149,7 +153,7 @@ export class DocumentVisualizerWindow extends AbstractDocumentWindow { /** * Retrieve the displayed document and start a travel to its visualization * location. - * + * * @async */ async startTravelToDisplayedDocument() { @@ -161,9 +165,11 @@ export class DocumentVisualizerWindow extends AbstractDocumentWindow { let imageSrc = await this.provider.getDisplayedDocumentImage(); - if (isNaN(currentDoc.visualization.positionX) || - isNaN(currentDoc.visualization.quaternionX)) { - return; + if ( + isNaN(currentDoc.visualization.positionX) || + isNaN(currentDoc.visualization.quaternionX) + ) { + return; } var docViewPos = new THREE.Vector3(); @@ -187,10 +193,10 @@ export class DocumentVisualizerWindow extends AbstractDocumentWindow { /** * Starts the document orientation. The processes first assign the correct src * to the image, then sets the opacity to 0. After the travel is finished, - * the opacity is gradually restored. + * the opacity is gradually restored. * To call this function, the `position`, `quaternion` and `imageSrc` * attributes must all have been set beforehand. - * + * * @async */ startTravel() { @@ -198,8 +204,7 @@ export class DocumentVisualizerWindow extends AbstractDocumentWindow { this.opacitySliderElement.value = 0; this.opacityElement.value = 0; - this.cameraControls.initiateTravel(this.position, 2, - this.quaternion, true); + this.cameraControls.initiateTravel(this.position, 2, this.quaternion, true); this.itownsView.notifyChange(); return new Promise((resolve, reject) => { @@ -212,14 +217,14 @@ export class DocumentVisualizerWindow extends AbstractDocumentWindow { this._onOpacityChange(); if (nextValue >= 1) { nextValue = 1; - clearInterval(intervalHandle) + clearInterval(intervalHandle); } }; intervalHandle = setInterval(increaseOpacity, 15); resolve(); }, 2000); } catch (e) { - reject(e); + reject(e); } }); } @@ -228,7 +233,7 @@ export class DocumentVisualizerWindow extends AbstractDocumentWindow { ///// GETTERS get closeButtonId() { - return `${this.windowId}_close_button` + return `${this.windowId}_close_button`; } get closeButtonElement() { @@ -236,15 +241,15 @@ export class DocumentVisualizerWindow extends AbstractDocumentWindow { } get opacitySliderId() { - return `${this.windowId}_opacity_slider` + return `${this.windowId}_opacity_slider`; } get opacitySliderElement() { return document.getElementById(this.opacitySliderId); } - + get opacityId() { - return `${this.windowId}_opacity` + return `${this.windowId}_opacity`; } get opacityElement() { @@ -252,10 +257,10 @@ export class DocumentVisualizerWindow extends AbstractDocumentWindow { } get imageId() { - return `${this.windowId}_image` + return `${this.windowId}_image`; } get imageElement() { return document.getElementById(this.imageId); } -} \ No newline at end of file +} diff --git a/src/Widgets/Documents/DocumentModule.js b/src/Widgets/Documents/DocumentModule.js index 5dc2fe8a5..1ef144c04 100644 --- a/src/Widgets/Documents/DocumentModule.js +++ b/src/Widgets/Documents/DocumentModule.js @@ -1,9 +1,11 @@ +/** @format */ + //Components -import { RequestService } from "../../Components/Request/RequestService"; +import { RequestService } from '../../Components/Request/RequestService'; -import { DocumentService, DocumentSource } from "./Model/DocumentService"; -import { DocumentProvider } from "./ViewModel/DocumentProvider"; -import { DocumentView } from "./View/DocumentView"; +import { DocumentService, DocumentSource } from './Model/DocumentService'; +import { DocumentProvider } from './ViewModel/DocumentProvider'; +import { DocumentView } from './View/DocumentView'; /** * The entry point of the documents module. @@ -74,7 +76,7 @@ export class DocumentModule { * for a button. */ addInspectorExtension(label, options) { - this.view.inspectorWindow.addExtension(label, options) + this.view.inspectorWindow.addExtension(label, options); } /** diff --git a/src/Widgets/Documents/Model/Document.js b/src/Widgets/Documents/Model/Document.js index 3b0d85a86..73931814e 100644 --- a/src/Widgets/Documents/Model/Document.js +++ b/src/Widgets/Documents/Model/Document.js @@ -1,6 +1,9 @@ /** * Represents a document. + * + * @format */ + export class Document { /** * Creates a new document. @@ -8,70 +11,70 @@ export class Document { constructor() { /** * The ID of the document. - * + * * @type {number} */ this.id; /** * The title of the document. - * + * * @type {string} */ this.title; /** * The source of the document. - * + * * @type {string} */ this.source; /** * The holder of the rights for the document. - * + * * @type {string} */ this.rightsHolder; /** * The description of the document. - * + * * @type {string} */ this.description; /** * The reference data, in an ISO 8601 format. - * + * * @type {string} */ this.refDate; /** * The publication data, in an ISO 8601 format. - * + * * @type {string} */ this.publicationDate; /** * The creator id. - * + * * @type {number} */ this.user_id; /** * The validation status information. - * + * * @type {{status: string}} */ this.validationStatus; /** * Visualization information. - * + * * @type {{ * positionX: number, * positionY: number, @@ -84,4 +87,4 @@ export class Document { */ this.visualization; } -} \ No newline at end of file +} diff --git a/src/Widgets/Documents/Model/DocumentService.js b/src/Widgets/Documents/Model/DocumentService.js index 780dcccf2..1c6b3f05f 100644 --- a/src/Widgets/Documents/Model/DocumentService.js +++ b/src/Widgets/Documents/Model/DocumentService.js @@ -1,8 +1,10 @@ +/** @format */ + //Components -import { RequestService } from "../../../Components/Request/RequestService"; -import { imageToDataURI } from "../../../Components/DataProcessing/DataProcessing"; +import { RequestService } from '../../../Components/Request/RequestService'; +import { imageToDataURI } from '../../../Components/DataProcessing/DataProcessing'; -import { Document } from "./Document"; +import { Document } from './Document'; /** * This class is responsible of fetching the documents from the server. It is @@ -11,7 +13,7 @@ import { Document } from "./Document"; export class DocumentService { /** * Constructs a new document service. - * + * * @param {RequestService} requestService The request service. * @param {object} config The configuration of UD-Viz. * @param {object} config.server The server configuration. @@ -24,14 +26,14 @@ export class DocumentService { constructor(requestService, config) { /** * The request service. - * + * * @type {RequestService} */ this.requestService = requestService; - + /** * If authentication should be used for the request. - * + * * @type {boolean} */ this.authenticate = false; @@ -41,14 +43,14 @@ export class DocumentService { /** * The object that defines the server URLs to fetch documents. - * + * * @type {DocumentSource} */ this.source = new DefaultDocumentSource(config); /** * The list of documents. - * + * * @type {Array} */ this.documents = []; @@ -56,15 +58,15 @@ export class DocumentService { /** * Sets the source of documents. - * + * * @param {DocumentSource} docSource The document source. * @param {boolean} [authenticate] Specifies if authentication should be used * to fetch documents. - * + * * @returns {DocumentSource} The previous source. */ setSource(docSource, authenticate = false) { - if (! (docSource instanceof DocumentSource)) { + if (!(docSource instanceof DocumentSource)) { throw 'The document source must be an instance of DocumentSource'; } @@ -77,14 +79,17 @@ export class DocumentService { /** * Fetches the documents from the server and return them in an array. - * + * * @async - * + * * @returns {Promise>} */ async fetchDocuments() { - let req = await this.requestService.request('GET', - this.source.getDocumentUrl(), { authenticate: this.authenticate }); + let req = await this.requestService.request( + 'GET', + this.source.getDocumentUrl(), + { authenticate: this.authenticate } + ); if (req.status !== 200) { throw 'Could not fetch the documents: ' + req.statusText; @@ -97,20 +102,22 @@ export class DocumentService { /** * Fetches the image corresponding to the given document. - * + * * @param {Document} doc The document to fetch the image. - * + * * @returns {string} The data string of the image. */ async fetchDocumentImage(doc) { let imgUrl = this.source.getImageUrl(doc); let req = await this.requestService.request('GET', imgUrl, { responseType: 'arraybuffer', - authenticate: this.authenticate + authenticate: this.authenticate, }); if (req.status >= 200 && req.status < 300) { - return imageToDataURI(req.response, - req.getResponseHeader('Content-Type')); + return imageToDataURI( + req.response, + req.getResponseHeader('Content-Type') + ); } throw 'Could not get the file'; } @@ -120,15 +127,13 @@ export class DocumentService { * An object that holds and returns the URLs for documents. */ export class DocumentSource { - constructor() { - - } + constructor() {} /** * Returns the URL to retrieve the documents. - * + * * @abstract - * + * * @returns {string} */ getDocumentUrl() { @@ -137,11 +142,11 @@ export class DocumentSource { /** * Returns the URL to retrieve the image of the document. - * + * * @param {Document} doc The document. - * + * * @abstract - * + * * @returns {string} */ getImageUrl(doc) { @@ -154,7 +159,7 @@ export class DocumentSource { */ class DefaultDocumentSource extends DocumentSource { /** - * + * * @param {object} config The configuration of UD-Viz. * @param {object} config.server The server configuration. * @param {string} config.server.url The server url. @@ -166,23 +171,28 @@ class DefaultDocumentSource extends DocumentSource { /** * The URL to fetch the documents. - * + * * @type {string} */ this.documentUrl; /** * The route to fetch the document images. - * + * * @type {string} */ this.fileRoute; - if (!!config && !!config.server && !!config.server.url && - !!config.server.document && !!config.server.file) { + if ( + !!config && + !!config.server && + !!config.server.url && + !!config.server.document && + !!config.server.file + ) { this.documentUrl = config.server.url; - if (this.documentUrl.slice(-1) !== "/") { - this.documentUrl += "/"; + if (this.documentUrl.slice(-1) !== '/') { + this.documentUrl += '/'; } this.documentUrl += config.server.document; this.fileRoute = config.server.file; @@ -197,10 +207,10 @@ class DefaultDocumentSource extends DocumentSource { /** * @override - * + * * @param {Document} doc The document. */ getImageUrl(doc) { return this.documentUrl + '/' + doc.id + '/' + this.fileRoute; } -} \ No newline at end of file +} diff --git a/src/Widgets/Documents/View/AbstractDocumentWindow.js b/src/Widgets/Documents/View/AbstractDocumentWindow.js index a6187e726..971eb235e 100644 --- a/src/Widgets/Documents/View/AbstractDocumentWindow.js +++ b/src/Widgets/Documents/View/AbstractDocumentWindow.js @@ -1,51 +1,54 @@ +/** @format */ + //Components -import { Window } from "../../../Components/GUI/js/Window"; +import { Window } from '../../../Components/GUI/js/Window'; -import { DocumentProvider } from "../ViewModel/DocumentProvider"; -import { DocumentView } from "./DocumentView"; +import { DocumentProvider } from '../ViewModel/DocumentProvider'; +import { DocumentView } from './DocumentView'; -import './DocumentWindow.css' +import './DocumentWindow.css'; export class AbstractDocumentWindow extends Window { /** * Constructs an abstract document window from a name. - * + * * @param {string} name The name of the window. */ constructor(name) { - super(`document2-${name.replace(/ +/, "-").toLowerCase()}`, - `Document - ${name}`, true); + super( + `document2-${name.replace(/ +/, '-').toLowerCase()}`, + `Document - ${name}`, + true + ); /** * The document provider. - * + * * @type {DocumentProvider} */ this.provider = undefined; /** * The document view. - * + * * @type {DocumentView} */ this.view = undefined; } - + /** * Function called when the document provider and the view have been set up. * Operations that depends on them can be performed in this function. - * + * * @override */ - documentWindowReady() { - - } + documentWindowReady() {} /** * Sets the provider and the view. Should be called by `DocumentView`. Once * this is done, the window is actually usable ; this triggers the * `documentWindowReady` method. - * + * * @param {DocumentView} view The document view. * @param {DocumentProvider} provider The document provider. */ @@ -58,11 +61,11 @@ export class AbstractDocumentWindow extends Window { /** * Request to show a this document window. - * + * * @param {boolean} [hideOtherWindows] Set to `true` to hide other document * windows. */ requestDisplay(hideOtherWindows = false) { this.view.requestWindowDisplay(this, hideOtherWindows); } -} \ No newline at end of file +} diff --git a/src/Widgets/Documents/View/DocumentInspectorWindow.js b/src/Widgets/Documents/View/DocumentInspectorWindow.js index 49a1fd4a3..030fcc07a 100644 --- a/src/Widgets/Documents/View/DocumentInspectorWindow.js +++ b/src/Widgets/Documents/View/DocumentInspectorWindow.js @@ -1,6 +1,8 @@ -import { DocumentProvider } from "../ViewModel/DocumentProvider"; -import { Document } from "../Model/Document"; -import { AbstractDocumentWindow } from "./AbstractDocumentWindow"; +/** @format */ + +import { DocumentProvider } from '../ViewModel/DocumentProvider'; +import { Document } from '../Model/Document'; +import { AbstractDocumentWindow } from './AbstractDocumentWindow'; /** * The window responsible for displaying the currently displayed document, as @@ -31,7 +33,7 @@ export class DocumentInspectorWindow extends AbstractDocumentWindow { } get innerContentHtml() { - return /*html*/` + return /*html*/ `

          Title:

          @@ -86,8 +88,10 @@ export class DocumentInspectorWindow extends AbstractDocumentWindow { } documentWindowReady() { - this.provider.addEventListener(DocumentProvider.EVENT_DISPLAYED_DOC_CHANGED, - (doc) => this.onDisplayedDocumentChange(doc)); + this.provider.addEventListener( + DocumentProvider.EVENT_DISPLAYED_DOC_CHANGED, + (doc) => this.onDisplayedDocumentChange(doc) + ); } /////////////////////// @@ -133,10 +137,12 @@ export class DocumentInspectorWindow extends AbstractDocumentWindow { this.docDescriptionElement.innerText = newDocument.description; this.docSourceElement.innerText = newDocument.source; this.docRightsHolderElement.innerText = newDocument.rightsHolder; - this.docPubDateElement.innerText = - (new Date(newDocument.publicationDate)).toLocaleDateString(); - this.docRefDateElement.innerText = - (new Date(newDocument.refDate)).toLocaleDateString(); + this.docPubDateElement.innerText = new Date( + newDocument.publicationDate + ).toLocaleDateString(); + this.docRefDateElement.innerText = new Date( + newDocument.refDate + ).toLocaleDateString(); this.docImageElement.src = await this.provider.getDisplayedDocumentImage(); } @@ -144,7 +150,7 @@ export class DocumentInspectorWindow extends AbstractDocumentWindow { ///// GETTERS get docTitleId() { - return `${this.windowId}_title` + return `${this.windowId}_title`; } get docTitleElement() { @@ -152,7 +158,7 @@ export class DocumentInspectorWindow extends AbstractDocumentWindow { } get docDescriptionId() { - return `${this.windowId}_desc` + return `${this.windowId}_desc`; } get docDescriptionElement() { @@ -160,7 +166,7 @@ export class DocumentInspectorWindow extends AbstractDocumentWindow { } get docSourceId() { - return `${this.windowId}_source` + return `${this.windowId}_source`; } get docSourceElement() { @@ -168,7 +174,7 @@ export class DocumentInspectorWindow extends AbstractDocumentWindow { } get docRightsHolderId() { - return `${this.windowId}_rights_holder` + return `${this.windowId}_rights_holder`; } get docRightsHolderElement() { @@ -176,7 +182,7 @@ export class DocumentInspectorWindow extends AbstractDocumentWindow { } get docPubDateId() { - return `${this.windowId}_pub_date` + return `${this.windowId}_pub_date`; } get docPubDateElement() { @@ -184,7 +190,7 @@ export class DocumentInspectorWindow extends AbstractDocumentWindow { } get docRefDateId() { - return `${this.windowId}_ref_date` + return `${this.windowId}_ref_date`; } get docRefDateElement() { diff --git a/src/Widgets/Documents/View/DocumentNavigatorWindow.js b/src/Widgets/Documents/View/DocumentNavigatorWindow.js index c73d11943..12897b158 100644 --- a/src/Widgets/Documents/View/DocumentNavigatorWindow.js +++ b/src/Widgets/Documents/View/DocumentNavigatorWindow.js @@ -1,7 +1,9 @@ -import { DocumentProvider } from "../ViewModel/DocumentProvider"; -import { Document } from "../Model/Document"; -import { DocumentSearchFilter } from "../ViewModel/DocumentSearchFilter"; -import { AbstractDocumentWindow } from "./AbstractDocumentWindow"; +/** @format */ + +import { DocumentProvider } from '../ViewModel/DocumentProvider'; +import { Document } from '../Model/Document'; +import { DocumentSearchFilter } from '../ViewModel/DocumentSearchFilter'; +import { AbstractDocumentWindow } from './AbstractDocumentWindow'; /** * Represents the navigator window for the documents. It contains the filters on @@ -26,18 +28,18 @@ export class DocumentNavigatorWindow extends AbstractDocumentWindow { * a panel. * * @type {Object. any, - * html: string - * }>} - */ - this.extensions = {}; + * type: 'button' | 'panel', + * label: string, + * id: string, + * callback?: (doc: Document[]) => any, + * html: string + * }>} + */ + this.extensions = {}; } get innerContentHtml() { - return /*html*/` + return /*html*/ `

          Document(s) @@ -111,10 +113,14 @@ export class DocumentNavigatorWindow extends AbstractDocumentWindow { documentWindowReady() { this.provider.addFilter(this.searchFilter); - this.provider.addEventListener(DocumentProvider.EVENT_FILTERED_DOCS_UPDATED, - (documents) => this._onFilteredDocumentsUpdate(documents)); - this.provider.addEventListener(DocumentProvider.EVENT_DISPLAYED_DOC_CHANGED, - (doc) => this._onDisplayedDocumentChange(doc)); + this.provider.addEventListener( + DocumentProvider.EVENT_FILTERED_DOCS_UPDATED, + (documents) => this._onFilteredDocumentsUpdate(documents) + ); + this.provider.addEventListener( + DocumentProvider.EVENT_DISPLAYED_DOC_CHANGED, + (doc) => this._onDisplayedDocumentChange(doc) + ); } ////////////////////////////// @@ -136,11 +142,13 @@ export class DocumentNavigatorWindow extends AbstractDocumentWindow { list.innerHTML = ''; for (let doc of documents) { let item = document.createElement('li'); - item.innerHTML = /*html*/` + item.innerHTML = /*html*/ `
          ${doc.title}
          -
          Refering ${(new Date(doc.refDate)).toLocaleDateString()}
          +
          Refering ${new Date( + doc.refDate + ).toLocaleDateString()}
          `; - item.classList.add('navigator-result-doc') + item.classList.add('navigator-result-doc'); item.onclick = () => { this.provider.setDisplayedDocument(doc); }; @@ -167,13 +175,13 @@ export class DocumentNavigatorWindow extends AbstractDocumentWindow { } if (!!document) { let newIndex = this.provider.getDisplayedDocumentIndex(); - let newSelected = this.documentListElement - .querySelector(`li:nth-child(${newIndex + 1})`); + let newSelected = this.documentListElement.querySelector( + `li:nth-child(${newIndex + 1})` + ); newSelected.classList.add('document-selected'); } } - //////////////////////// ///// SEARCH AND FILTERS @@ -181,31 +189,37 @@ export class DocumentNavigatorWindow extends AbstractDocumentWindow { * Event on the 'search' button click. */ async search() { - let keywords = this.inputKeywordsElement.value.split(/[ ,;]/) - .filter((k) => k !== "").map((k) => k.toLowerCase()); + let keywords = this.inputKeywordsElement.value + .split(/[ ,;]/) + .filter((k) => k !== '') + .map((k) => k.toLowerCase()); this.searchFilter.keywords = keywords; let source = this.inputSourceElement.value.toLowerCase(); - this.searchFilter.source = (source !== "") ? source : undefined; + this.searchFilter.source = source !== '' ? source : undefined; let rightsHolder = this.inputRightsHolderElement.value.toLowerCase(); - this.searchFilter.rightsHolder = (rightsHolder !== "") ? rightsHolder - : undefined; + this.searchFilter.rightsHolder = + rightsHolder !== '' ? rightsHolder : undefined; let pubStartDate = this.inputPubDateStartElement.value; - this.searchFilter.pubStartDate = (!!pubStartDate) ? new Date(pubStartDate) + this.searchFilter.pubStartDate = !!pubStartDate + ? new Date(pubStartDate) : undefined; let pubEndDate = this.inputPubDateEndElement.value; - this.searchFilter.pubEndDate = (!!pubEndDate) ? new Date(pubEndDate) + this.searchFilter.pubEndDate = !!pubEndDate + ? new Date(pubEndDate) : undefined; let refStartDate = this.inputRefDateStartElement.value; - this.searchFilter.refStartDate = (!!refStartDate) ? new Date(refStartDate) + this.searchFilter.refStartDate = !!refStartDate + ? new Date(refStartDate) : undefined; let refEndDate = this.inputRefDateEndElement.value; - this.searchFilter.refEndDate = (!!refEndDate) ? new Date(refEndDate) + this.searchFilter.refEndDate = !!refEndDate + ? new Date(refEndDate) : undefined; this.provider.refreshDocumentList(); @@ -269,7 +283,7 @@ export class DocumentNavigatorWindow extends AbstractDocumentWindow { } get inputRightsHolderId() { - return `${this.windowId}_rights_holder` + return `${this.windowId}_rights_holder`; } get inputRightsHolderElement() { diff --git a/src/Widgets/Documents/View/DocumentView.js b/src/Widgets/Documents/View/DocumentView.js index 2083334e3..cd1b66b86 100644 --- a/src/Widgets/Documents/View/DocumentView.js +++ b/src/Widgets/Documents/View/DocumentView.js @@ -1,11 +1,13 @@ +/** @format */ + //Components -import { ModuleView } from "../../../Components/ModuleView/ModuleView"; -import { Window } from "../../../Components/GUI/js/Window"; +import { ModuleView } from '../../../Components/ModuleView/ModuleView'; +import { Window } from '../../../Components/GUI/js/Window'; -import { DocumentProvider } from "../ViewModel/DocumentProvider"; -import { DocumentNavigatorWindow } from "./DocumentNavigatorWindow"; -import { DocumentInspectorWindow } from "./DocumentInspectorWindow"; -import { AbstractDocumentWindow } from "./AbstractDocumentWindow"; +import { DocumentProvider } from '../ViewModel/DocumentProvider'; +import { DocumentNavigatorWindow } from './DocumentNavigatorWindow'; +import { DocumentInspectorWindow } from './DocumentInspectorWindow'; +import { AbstractDocumentWindow } from './AbstractDocumentWindow'; /** * The entry point of the document view. It holds the two main windows, inspector @@ -15,7 +17,7 @@ import { AbstractDocumentWindow } from "./AbstractDocumentWindow"; export class DocumentView extends ModuleView { /** * Creates a document view. - * + * * @param {DocumentProvider} provider The document provider. */ constructor(provider) { @@ -23,35 +25,35 @@ export class DocumentView extends ModuleView { /** * The document provider. - * + * * @type {DocumentProvider} */ this.provider = provider; /** * The search window. - * + * * @type {DocumentNavigatorWindow} */ this.navigatorWindow = new DocumentNavigatorWindow(); /** * The inspector window. - * + * * @type {DocumentInspectorWindow} */ this.inspectorWindow = new DocumentInspectorWindow(); /** * The different windows of the view. - * + * * @type {Array} */ - this.windows = [] + this.windows = []; /** * The windows that have been temporarily hidden. - * + * * @type {Array} */ this.hiddenWindows = []; @@ -70,13 +72,15 @@ export class DocumentView extends ModuleView { /** * Adds a new window to display information about documents. The document * provider is passed as parameter in this function. - * + * * @param {AbstractDocumentWindow} newWindow The window to add. */ addDocumentWindow(newWindow) { - if (! (newWindow instanceof AbstractDocumentWindow)) { - throw 'Only instances of AbstractDocumentWindow can be added to the ' + - 'document view'; + if (!(newWindow instanceof AbstractDocumentWindow)) { + throw ( + 'Only instances of AbstractDocumentWindow can be added to the ' + + 'document view' + ); } this.windows.push(newWindow); @@ -85,14 +89,15 @@ export class DocumentView extends ModuleView { /** * Request to show a specific document window. - * + * * @param {AbstractDocumentWindow} windowToDisplay The window to show. * @param {boolean} [hideOtherWindows] Set to `true` to hide other document * windows. */ requestWindowDisplay(windowToDisplay, hideOtherWindows = false) { - let found = this.windows - .findIndex(w => w.windowId === windowToDisplay.windowId) >= 0; + let found = + this.windows.findIndex((w) => w.windowId === windowToDisplay.windowId) >= + 0; if (!found) { throw 'Window must be registered first'; } @@ -135,4 +140,4 @@ export class DocumentView extends ModuleView { window.dispose(); } } -} \ No newline at end of file +} diff --git a/src/Widgets/Documents/View/DocumentWindow.css b/src/Widgets/Documents/View/DocumentWindow.css index 44b9f6c50..9c73225e9 100644 --- a/src/Widgets/Documents/View/DocumentWindow.css +++ b/src/Widgets/Documents/View/DocumentWindow.css @@ -1,6 +1,8 @@ -/* Generic for document windows */ - - +/** + * /* Generic for document windows + * + * @format + */ /* Search window */ @@ -9,7 +11,7 @@ margin-top: 5px; } -.search-form input[type="text"], +.search-form input[type='text'], .search-form select { box-sizing: border-box; width: 100%; diff --git a/src/Widgets/Documents/ViewModel/DocumentFilter.js b/src/Widgets/Documents/ViewModel/DocumentFilter.js index 71e5fdaf8..c7d60f9e6 100644 --- a/src/Widgets/Documents/ViewModel/DocumentFilter.js +++ b/src/Widgets/Documents/ViewModel/DocumentFilter.js @@ -1,4 +1,6 @@ -import { Document } from "../Model/Document"; +/** @format */ + +import { Document } from '../Model/Document'; /** * A filter for documents. It is essentially a function that determines if a @@ -7,7 +9,7 @@ import { Document } from "../Model/Document"; export class DocumentFilter { /** * Constructs a new document filter, from an acceptation function. - * + * * @param {(Document) => boolean} accepts The function responsible to filter * the documents. It must evaluate wether a document is acceptable according * to the filter. @@ -16,7 +18,7 @@ export class DocumentFilter { /** * The function responsible to filter the documents. It must evaluate wether * a document is acceptable according to the filter. - * + * * @type {(Document) => boolean} */ this.accepts = accepts; @@ -24,13 +26,13 @@ export class DocumentFilter { /** * Applies the filter to the documents. - * + * * @param {Array} documents The documents to filter. - * + * * @returns {Array} */ apply(documents) { let filtered = documents.filter(this.accepts); return filtered; } -} \ No newline at end of file +} diff --git a/src/Widgets/Documents/ViewModel/DocumentProvider.js b/src/Widgets/Documents/ViewModel/DocumentProvider.js index addd47825..41f171072 100644 --- a/src/Widgets/Documents/ViewModel/DocumentProvider.js +++ b/src/Widgets/Documents/ViewModel/DocumentProvider.js @@ -1,9 +1,11 @@ +/** @format */ + //Components -import { EventSender } from "../../../Components/Events/EventSender"; +import { EventSender } from '../../../Components/Events/EventSender'; -import { DocumentService } from "../Model/DocumentService"; -import { Document } from "../Model/Document"; -import { DocumentFilter } from "./DocumentFilter"; +import { DocumentService } from '../Model/DocumentService'; +import { Document } from '../Model/Document'; +import { DocumentFilter } from './DocumentFilter'; /** * Represents the set of documents that is displayed in the view. This includes @@ -15,7 +17,7 @@ import { DocumentFilter } from "./DocumentFilter"; export class DocumentProvider extends EventSender { /** * Constructs a new documents provider. - * + * * @param {DocumentService} service The document service. */ constructor(service) { @@ -23,35 +25,35 @@ export class DocumentProvider extends EventSender { /** * The document service. - * + * * @type {DocumentService} */ this.service = service; /** * The list of filters. - * + * * @type {Array} */ this.filters = []; /** * The list of all documents. - * + * * @type {Array} */ this.allDocuments = []; /** * The list of filtered documents. - * + * * @type {Array} */ this.filteredDocuments = []; /** * The currently displayed document. - * + * * @type {number} */ this.displayedDocumentIndex = undefined; @@ -77,28 +79,33 @@ export class DocumentProvider extends EventSender { if (this.filteredDocuments.length > 0) { if (previousDocument) { let previousDisplayedId = previousDocument.id; - let newIndex = this.filteredDocuments.findIndex(doc => - doc.id === previousDisplayedId); - this.displayedDocumentIndex = (newIndex >= 0) ? newIndex : 0; + let newIndex = this.filteredDocuments.findIndex( + (doc) => doc.id === previousDisplayedId + ); + this.displayedDocumentIndex = newIndex >= 0 ? newIndex : 0; } else { this.displayedDocumentIndex = 0; } } else { this.displayedDocumentIndex = undefined; } - await this.sendEvent(DocumentProvider.EVENT_FILTERED_DOCS_UPDATED, - this.getFilteredDocuments()); - await this.sendEvent(DocumentProvider.EVENT_DISPLAYED_DOC_CHANGED, - this.getDisplayedDocument()); + await this.sendEvent( + DocumentProvider.EVENT_FILTERED_DOCS_UPDATED, + this.getFilteredDocuments() + ); + await this.sendEvent( + DocumentProvider.EVENT_DISPLAYED_DOC_CHANGED, + this.getDisplayedDocument() + ); } /** * Adds a filter to the filtering pipeline. - * + * * @param {DocumentFilter} newFilter The new filter to add. */ addFilter(newFilter) { - if (! (newFilter instanceof DocumentFilter)) { + if (!(newFilter instanceof DocumentFilter)) { throw 'addFilter() expects a DocumentFilter parameter'; } this.filters.push(newFilter); @@ -106,12 +113,13 @@ export class DocumentProvider extends EventSender { /** * Sets the given document as the displayed one. - * + * * @param {Document} doc The document. */ setDisplayedDocument(doc) { - let index = this.filteredDocuments.findIndex((filteredDoc) => - doc.id === filteredDoc.id); + let index = this.filteredDocuments.findIndex( + (filteredDoc) => doc.id === filteredDoc.id + ); if (index < 0) { throw 'Document not found.'; @@ -123,12 +131,14 @@ export class DocumentProvider extends EventSender { /** * Change the displayed document index. Sends a `DISPLAYED_DOCUMENT_CHANGED` * event. - * + * * @param {number} index The new document index. */ setDisplayedDocumentIndex(index) { if (this.displayedDocumentIndex === undefined) { - console.warn('Cannot change displayed document if no document is present'); + console.warn( + 'Cannot change displayed document if no document is present' + ); return; } @@ -137,34 +147,41 @@ export class DocumentProvider extends EventSender { } this.displayedDocumentIndex = index; - this.sendEvent(DocumentProvider.EVENT_DISPLAYED_DOC_CHANGED, - this.getDisplayedDocument()); + this.sendEvent( + DocumentProvider.EVENT_DISPLAYED_DOC_CHANGED, + this.getDisplayedDocument() + ); } /** * Shift the displayed document index. The filtered array is treated as * cyclical. Sends a `DISPLAYED_DOCUMENT_CHANGED` event. - * + * * @param {number} offset The offset that will be applied to the current * index. */ shiftDisplayedDocumentIndex(offset) { if (this.displayedDocumentIndex === undefined) { - console.warn('Cannot change displayed document if no document is present'); + console.warn( + 'Cannot change displayed document if no document is present' + ); return; } offset = offset % this.filteredDocuments.length; - this.displayedDocumentIndex = (this.filteredDocuments.length + - this.displayedDocumentIndex + offset) % this.filteredDocuments.length; - - this.sendEvent(DocumentProvider.EVENT_DISPLAYED_DOC_CHANGED, - this.getDisplayedDocument()); + this.displayedDocumentIndex = + (this.filteredDocuments.length + this.displayedDocumentIndex + offset) % + this.filteredDocuments.length; + + this.sendEvent( + DocumentProvider.EVENT_DISPLAYED_DOC_CHANGED, + this.getDisplayedDocument() + ); } /** * Returns the list of all documents. - * + * * @returns {Array} */ getAllDocuments() { @@ -173,7 +190,7 @@ export class DocumentProvider extends EventSender { /** * Returns the filtered list of documents. - * + * * @returns {Array} */ getFilteredDocuments() { @@ -182,7 +199,7 @@ export class DocumentProvider extends EventSender { /** * Returns the currently displayed document. - * + * * @returns {Document | undefined} */ getDisplayedDocument() { @@ -195,7 +212,7 @@ export class DocumentProvider extends EventSender { /** * Returns the displayed document index. - * + * * @returns {number | undefined} */ getDisplayedDocumentIndex() { @@ -206,9 +223,9 @@ export class DocumentProvider extends EventSender { * Returns the image corresponding to the displayed document. It is a string * that can be put into the `src` attribute of an `img` tag (so either an * URL or a base64 encoded file). - * + * * @async - * + * * @returns {Promise} */ async getDisplayedDocumentImage() { @@ -229,4 +246,4 @@ export class DocumentProvider extends EventSender { static get EVENT_DISPLAYED_DOC_CHANGED() { return 'EVENT_DISPLAYED_DOC_CHANGED'; } -} \ No newline at end of file +} diff --git a/src/Widgets/Documents/ViewModel/DocumentSearchFilter.js b/src/Widgets/Documents/ViewModel/DocumentSearchFilter.js index 2c6444523..9d9087262 100644 --- a/src/Widgets/Documents/ViewModel/DocumentSearchFilter.js +++ b/src/Widgets/Documents/ViewModel/DocumentSearchFilter.js @@ -1,5 +1,7 @@ -import { DocumentFilter } from "./DocumentFilter"; -import { Document } from "../Model/Document"; +/** @format */ + +import { DocumentFilter } from './DocumentFilter'; +import { Document } from '../Model/Document'; /** * A document filter to use with the search window. It filters the documents @@ -17,14 +19,14 @@ export class DocumentSearchFilter extends DocumentFilter { /** * A list of keywords to search in the title or the description of the * document. These keywords should be in lowercase. - * + * * @type {Array} */ this.keywords = []; /** * A string representing the source. Should be in lowercase. - * + * * @type {string} */ this.source = undefined; @@ -36,28 +38,28 @@ export class DocumentSearchFilter extends DocumentFilter { /** * The lower bound of the publication date. - * + * * @type {Date} */ this.pubStartDate = undefined; /** * The upper bound of the publication date. - * + * * @type {Date} */ this.pubEndDate = undefined; /** * The lower bound of the refering date. - * + * * @type {Date} */ this.refStartDate = undefined; /** * The upper bound of the refering date. - * + * * @type {Date} */ this.refEndDate = undefined; @@ -65,14 +67,16 @@ export class DocumentSearchFilter extends DocumentFilter { /** * The function to filter the documents. - * + * * @param {Document} doc The document to filter. */ filterDocument(doc) { if (this.keywords.length > 0) { for (let keyword of this.keywords) { - if (!doc.title.toLowerCase().includes(keyword) && - !doc.description.toLowerCase().includes(keyword)) { + if ( + !doc.title.toLowerCase().includes(keyword) && + !doc.description.toLowerCase().includes(keyword) + ) { return false; } } @@ -82,16 +86,24 @@ export class DocumentSearchFilter extends DocumentFilter { return false; } - if (!!this.rightsHolder && - !doc.rightsHolder.toLowerCase().includes(this.rightsHolder)) { + if ( + !!this.rightsHolder && + !doc.rightsHolder.toLowerCase().includes(this.rightsHolder) + ) { return false; } - if (!!this.pubStartDate && !(this.pubStartDate <= new Date(doc.publicationDate))) { + if ( + !!this.pubStartDate && + !(this.pubStartDate <= new Date(doc.publicationDate)) + ) { return false; } - if (!!this.pubEndDate && !(this.pubEndDate >= new Date(doc.publicationDate))) { + if ( + !!this.pubEndDate && + !(this.pubEndDate >= new Date(doc.publicationDate)) + ) { return false; } @@ -102,7 +114,7 @@ export class DocumentSearchFilter extends DocumentFilter { if (!!this.refEndDate && !(this.refEndDate >= new Date(doc.refDate))) { return false; } - + return true; } @@ -118,4 +130,4 @@ export class DocumentSearchFilter extends DocumentFilter { this.refStartDate = undefined; this.refEndDate = undefined; } -} \ No newline at end of file +} diff --git a/src/Widgets/Extensions/3DTilesDebug/views/3DTilesDebugWindow.js b/src/Widgets/Extensions/3DTilesDebug/views/3DTilesDebugWindow.js index e9b59eb72..0fac2b999 100644 --- a/src/Widgets/Extensions/3DTilesDebug/views/3DTilesDebugWindow.js +++ b/src/Widgets/Extensions/3DTilesDebug/views/3DTilesDebugWindow.js @@ -1,13 +1,15 @@ +/** @format */ + //Components -import { Window } from "../../../../Components/GUI/js/Window"; -import { CityObjectStyle } from "../../../../Components/3DTiles/Model/CityObjectStyle"; -import { CityObjectID } from "../../../../Components/3DTiles/Model/CityObject"; -import { TilesManager } from "../../../../Components/3DTiles/TilesManager"; +import { Window } from '../../../../Components/GUI/js/Window'; +import { CityObjectStyle } from '../../../../Components/3DTiles/Model/CityObjectStyle'; +import { CityObjectID } from '../../../../Components/3DTiles/Model/CityObject'; +import { TilesManager } from '../../../../Components/3DTiles/TilesManager'; export class Debug3DTilesWindow extends Window { /** * Creates the debug window. - * + * * @param {layer} layerManager The tiles manager. */ constructor(layerManager) { @@ -15,17 +17,20 @@ export class Debug3DTilesWindow extends Window { /** * The tiles manager. - * + * * @type {layerManager} */ this.layerManager = layerManager; // Selection - this.layerManager.registerStyle('selected', new CityObjectStyle({ - materialProps: { color: 0x00ff00 } - })); + this.layerManager.registerStyle( + 'selected', + new CityObjectStyle({ + materialProps: { color: 0x00ff00 }, + }) + ); this.selectedCityObject = undefined; this.selectedTilesManager = undefined; - + let viewerDiv = document.getElementById('viewerDiv'); let clickListener = (event) => { this.onMouseClick(event); @@ -50,7 +55,7 @@ export class Debug3DTilesWindow extends Window { } get innerContentHtml() { - return /*html*/` + return /*html*/ `

          0 / ? tiles loaded.

          0 tiles visible.

          @@ -94,7 +99,10 @@ export class Debug3DTilesWindow extends Window { // Sets the number of loaded tiles and add an event for dynamic change of this value. this.updateTBIInfoParagraphElement(); for (let i = 0; i < this.layerManager.tilesManagers.length; i++) { - this.layerManager.tilesManagers[i].addEventListener(TilesManager.EVENT_TILE_LOADED, (tile) => this.updateTBIInfoParagraphElement(tile)); + this.layerManager.tilesManagers[i].addEventListener( + TilesManager.EVENT_TILE_LOADED, + (tile) => this.updateTBIInfoParagraphElement(tile) + ); } this.groupColorOpacityInputElement.oninput = () => { this.groupColorOpacitySpanElement.innerText = @@ -127,7 +135,8 @@ export class Debug3DTilesWindow extends Window { */ onMouseMove(event) { // Update the current visible tile count - let visibleTileCount = this.layerManager.getVisible3DTilesTileCountFromLayers(); + let visibleTileCount = + this.layerManager.getVisible3DTilesTileCountFromLayers(); this.visibleTilesParagraphElement.innerText = `${visibleTileCount} tiles visible.`; } @@ -135,30 +144,37 @@ export class Debug3DTilesWindow extends Window { * If the user is currently hovering a building, fetches the building info * and colors the building. If a building was already selected, it returns to * its original coloring. - * + * * @param {MouseEvent} event The mouse event. */ onMouseClick(event) { let cityObject = this.layerManager.pickCityObject(event); if (cityObject !== undefined) { - for (let [key, value] of Object.entries(cityObject.props)) { this.clickDivElement.innerHTML += `
          ${key} : ${value}`; } if (!!this.selectedCityObject) { - this.selectedTilesManager.removeStyle(this.selectedCityObject.cityObjectId); + this.selectedTilesManager.removeStyle( + this.selectedCityObject.cityObjectId + ); this.selectedTilesManager.applyStyles(); } this.selectedCityObject = cityObject; - this.selectedTilesManager = this.layerManager.getTilesManagerByLayerID(this.selectedCityObject.tile.layer.id); - this.selectedTilesManager.setStyle(this.selectedCityObject.cityObjectId, 'selected'); + this.selectedTilesManager = this.layerManager.getTilesManagerByLayerID( + this.selectedCityObject.tile.layer.id + ); + this.selectedTilesManager.setStyle( + this.selectedCityObject.cityObjectId, + 'selected' + ); this.selectedTilesManager.applyStyles({ - updateFunction: - this.selectedTilesManager.view.notifyChange.bind(this.selectedTilesManager.view) + updateFunction: this.selectedTilesManager.view.notifyChange.bind( + this.selectedTilesManager.view + ), }); - this.clickDivElement.innerHTML = /*html*/` + this.clickDivElement.innerHTML = /*html*/ ` 3D Tiles : ${this.selectedTilesManager.layer.name}
          Vertex indexes : ${cityObject.indexStart} to ${cityObject.indexEnd} (${cityObject.indexCount})
          @@ -174,11 +190,15 @@ export class Debug3DTilesWindow extends Window { submitStyleForm() { try { let tileId = Number.parseInt(this.groupColorTileInputElement.value); - let batchIds = JSON.parse('[' + this.groupColorBatchInputElement.value + ']'); + let batchIds = JSON.parse( + '[' + this.groupColorBatchInputElement.value + ']' + ); let color = new THREE.Color(this.groupColorColorInputElement.value); let opacity = Number.parseFloat(this.groupColorOpacityInputElement.value); - this.layerManager.tilesManagers[0].setStyle(new CityObjectID(tileId, batchIds), - { materialProps: { color, opacity } }); + this.layerManager.tilesManagers[0].setStyle( + new CityObjectID(tileId, batchIds), + { materialProps: { color, opacity } } + ); this.layerManager.tilesManagers[0].applyStyles(); } catch (e) { alert(e); diff --git a/src/Widgets/Extensions/Authentication/services/AuthenticationService.js b/src/Widgets/Extensions/Authentication/services/AuthenticationService.js index ea5ba7c1c..bb912024e 100644 --- a/src/Widgets/Extensions/Authentication/services/AuthenticationService.js +++ b/src/Widgets/Extensions/Authentication/services/AuthenticationService.js @@ -1,148 +1,161 @@ -import {RequestService} from "../../../../Components/Request/RequestService" +/** @format */ + +import { RequestService } from '../../../../Components/Request/RequestService'; export function AuthenticationService(requestService, config) { - this.observers = []; - this.config = config; - this.loginUrl = `${config.server.url}${config.server.login}`; - //route to manage users (register) - this.userUrl = `${config.server.url}${config.server.user}`; - //route to get personal information - this.userMeUrl = `${config.server.url}${config.server.userMe}`; - this.requestService = new RequestService(); - this.loginRequiredKeys = ['username', 'password']; - this.registerRequiredKeys = ['username', 'firstName', 'lastName', 'password', 'email']; - this.storageKeys = { - token: 'user.token', - firstname: 'user.firstname', - lastname: 'user.lastname', - username: 'user.username', - email: 'user.email' - }; - - this.requestService = requestService; - - this.initialize = function initialize() { - this.requestService.setAuthenticationService(this); - }; - - this.login = async function login(formData) { - if (!this.formCheck(formData, this.loginRequiredKeys)) { - throw 'Invalid form'; - } - - if (this.isUserLoggedIn()) { - throw 'Already logged in'; - } - - const result = (await this.requestService.send('POST', this.loginUrl, formData, false)).response; - const resultJson = JSON.parse(result); - if (!resultJson) { - throw 'Username or password is incorrect' - } - const jwt = resultJson.token; - if (jwt !== undefined && jwt !== null) { - this.storeToken(jwt); - let response = JSON.parse((await this.requestService.send('GET', this.userMeUrl)).response); - const user = { - firstname: response.firstName, - lastname: response.lastName, - username: response.username, - email: response.email - }; - - this.storeUser(user); - - this.notifyObservers(); - } else { - throw 'Username or password is incorrect'; - } - }; - - this.logout = function logout() { - if (!this.isUserLoggedIn()) { - throw 'Not logged in'; - } - this.removeUserFromSession(); - - this.notifyObservers(); - }; - - this.register = async function register(formData) { - if (!this.formCheck(formData, this.registerRequiredKeys)) { - throw 'Invalid form'; - } - if (this.isUserLoggedIn()) { - throw 'Already logged in'; - } - const result = (await this.requestService.send('POST', this.userUrl, formData, false)).response; - const obj = JSON.parse(result); - - this.notifyObservers(); - }; - - this.formCheck = function formCheck(formData, requiredKeys) { - for (var key of requiredKeys) { - if (formData.get(key) === null) { - console.error(`Missing key in form : ${key}`) - return false; - } - } - return true; - }; - - this.removeUserFromSession = function removeUserFromSession() { - window.sessionStorage.removeItem(this.storageKeys.token); - window.sessionStorage.removeItem(this.storageKeys.firstname); - window.sessionStorage.removeItem(this.storageKeys.lastname); - window.sessionStorage.removeItem(this.storageKeys.username); - window.sessionStorage.removeItem(this.storageKeys.email); - }; - - this.storeToken = function (token) { - window.sessionStorage.setItem(this.storageKeys.token, token); + this.observers = []; + this.config = config; + this.loginUrl = `${config.server.url}${config.server.login}`; + //route to manage users (register) + this.userUrl = `${config.server.url}${config.server.user}`; + //route to get personal information + this.userMeUrl = `${config.server.url}${config.server.userMe}`; + this.requestService = new RequestService(); + this.loginRequiredKeys = ['username', 'password']; + this.registerRequiredKeys = [ + 'username', + 'firstName', + 'lastName', + 'password', + 'email', + ]; + this.storageKeys = { + token: 'user.token', + firstname: 'user.firstname', + lastname: 'user.lastname', + username: 'user.username', + email: 'user.email', + }; + + this.requestService = requestService; + + this.initialize = function initialize() { + this.requestService.setAuthenticationService(this); + }; + + this.login = async function login(formData) { + if (!this.formCheck(formData, this.loginRequiredKeys)) { + throw 'Invalid form'; + } + + if (this.isUserLoggedIn()) { + throw 'Already logged in'; } - this.storeUser = function storeUser(user) { - window.sessionStorage.setItem(this.storageKeys.firstname, user.firstname); - window.sessionStorage.setItem(this.storageKeys.lastname, user.lastname); - window.sessionStorage.setItem(this.storageKeys.username, user.username); - window.sessionStorage.setItem(this.storageKeys.email, user.email); - }; - - this.getUser = function getUser() { - let user = {}; - user.token = window.sessionStorage.getItem(this.storageKeys.token); - if (user.token === null || user.token === undefined) { - return null; - } - user.firstname = window.sessionStorage.getItem(this.storageKeys.firstname); - user.lastname = window.sessionStorage.getItem(this.storageKeys.lastname); - user.username = window.sessionStorage.getItem(this.storageKeys.username); - user.email = window.sessionStorage.getItem(this.storageKeys.email); - return user; - }; - - this.isUserLoggedIn = function isUserLoggedIn() { - try { - let user = this.getUser(); - return user !== null && user !== undefined; - } catch (e) { - console.error(e); - return false; - } - }; - - // Observers - this.addObserver = function (observerFunction) { - this.observers.push(observerFunction); + const result = ( + await this.requestService.send('POST', this.loginUrl, formData, false) + ).response; + const resultJson = JSON.parse(result); + if (!resultJson) { + throw 'Username or password is incorrect'; + } + const jwt = resultJson.token; + if (jwt !== undefined && jwt !== null) { + this.storeToken(jwt); + let response = JSON.parse( + (await this.requestService.send('GET', this.userMeUrl)).response + ); + const user = { + firstname: response.firstName, + lastname: response.lastName, + username: response.username, + email: response.email, + }; + + this.storeUser(user); + + this.notifyObservers(); + } else { + throw 'Username or password is incorrect'; } + }; - this.notifyObservers = function () { - for (let observer of this.observers) { - observer(); - } + this.logout = function logout() { + if (!this.isUserLoggedIn()) { + throw 'Not logged in'; } + this.removeUserFromSession(); + this.notifyObservers(); + }; + + this.register = async function register(formData) { + if (!this.formCheck(formData, this.registerRequiredKeys)) { + throw 'Invalid form'; + } + if (this.isUserLoggedIn()) { + throw 'Already logged in'; + } + const result = ( + await this.requestService.send('POST', this.userUrl, formData, false) + ).response; + const obj = JSON.parse(result); + + this.notifyObservers(); + }; + + this.formCheck = function formCheck(formData, requiredKeys) { + for (var key of requiredKeys) { + if (formData.get(key) === null) { + console.error(`Missing key in form : ${key}`); + return false; + } + } + return true; + }; + + this.removeUserFromSession = function removeUserFromSession() { + window.sessionStorage.removeItem(this.storageKeys.token); + window.sessionStorage.removeItem(this.storageKeys.firstname); + window.sessionStorage.removeItem(this.storageKeys.lastname); + window.sessionStorage.removeItem(this.storageKeys.username); + window.sessionStorage.removeItem(this.storageKeys.email); + }; + + this.storeToken = function (token) { + window.sessionStorage.setItem(this.storageKeys.token, token); + }; + + this.storeUser = function storeUser(user) { + window.sessionStorage.setItem(this.storageKeys.firstname, user.firstname); + window.sessionStorage.setItem(this.storageKeys.lastname, user.lastname); + window.sessionStorage.setItem(this.storageKeys.username, user.username); + window.sessionStorage.setItem(this.storageKeys.email, user.email); + }; + + this.getUser = function getUser() { + let user = {}; + user.token = window.sessionStorage.getItem(this.storageKeys.token); + if (user.token === null || user.token === undefined) { + return null; + } + user.firstname = window.sessionStorage.getItem(this.storageKeys.firstname); + user.lastname = window.sessionStorage.getItem(this.storageKeys.lastname); + user.username = window.sessionStorage.getItem(this.storageKeys.username); + user.email = window.sessionStorage.getItem(this.storageKeys.email); + return user; + }; + + this.isUserLoggedIn = function isUserLoggedIn() { + try { + let user = this.getUser(); + return user !== null && user !== undefined; + } catch (e) { + console.error(e); + return false; + } + }; + + // Observers + this.addObserver = function (observerFunction) { + this.observers.push(observerFunction); + }; + + this.notifyObservers = function () { + for (let observer of this.observers) { + observer(); + } + }; - this.initialize(); -} \ No newline at end of file + this.initialize(); +} diff --git a/src/Widgets/Extensions/Authentication/views/AuthenticationView.css b/src/Widgets/Extensions/Authentication/views/AuthenticationView.css index 7730f89eb..519e1b38b 100644 --- a/src/Widgets/Extensions/Authentication/views/AuthenticationView.css +++ b/src/Widgets/Extensions/Authentication/views/AuthenticationView.css @@ -1,147 +1,149 @@ +/** @format */ + #loginRegistrationWindow * { - box-sizing: border-box; + box-sizing: border-box; } #loginRegistrationWindow { - grid-template-columns: 1fr 1fr; - box-sizing: border-box; - position: absolute; - top: 0; - height: 100%; - width: 100%; - color: black; - font-size: 75%; - background-color: rgba(30, 30, 30, 0.3); - border: 1px solid rgb(90, 90, 90); - pointer-events: auto; - display: grid; - z-index: 50000; + grid-template-columns: 1fr 1fr; + box-sizing: border-box; + position: absolute; + top: 0; + height: 100%; + width: 100%; + color: black; + font-size: 75%; + background-color: rgba(30, 30, 30, 0.3); + border: 1px solid rgb(90, 90, 90); + pointer-events: auto; + display: grid; + z-index: 50000; } #loginRegistrationWindow > div > ul { - padding-left: 5px; + padding-left: 5px; } #loginRegistrationCloseButton { - margin-top: 2.2vw; - margin-left: 24.8vw; - grid-column: 2; - grid-row: 1; - height: 2vw; - width: 5vw; + margin-top: 2.2vw; + margin-left: 24.8vw; + grid-column: 2; + grid-row: 1; + height: 2vw; + width: 5vw; } #RegistrationForm { - margin: 2vw 0 auto auto; - display: grid; - grid-row: 1; - grid-column: 1; - width: 30vw; - height: 42vw; - padding: 1.5vw 6%; - color: white; - background-color: rgba(45, 52, 54, 0.9); - border: 0.15vw solid #2c2c2c; + margin: 2vw 0 auto auto; + display: grid; + grid-row: 1; + grid-column: 1; + width: 30vw; + height: 42vw; + padding: 1.5vw 6%; + color: white; + background-color: rgba(45, 52, 54, 0.9); + border: 0.15vw solid #2c2c2c; } #LoginForm { - margin: 2vw auto auto 0; - width: 30vw; - height: 42vw; - display: grid; - grid-row: 1; - grid-column: 2; - padding: 1.5vw 6%; - grid-template-rows: 5vw 2.5vw repeat(2, 5vw 3.5vw) 7vw 1fr; - color: white; - background-color: rgba(45, 52, 54, 0.9); - border: 0.15vw solid #2c2c2c; + margin: 2vw auto auto 0; + width: 30vw; + height: 42vw; + display: grid; + grid-row: 1; + grid-column: 2; + padding: 1.5vw 6%; + grid-template-rows: 5vw 2.5vw repeat(2, 5vw 3.5vw) 7vw 1fr; + color: white; + background-color: rgba(45, 52, 54, 0.9); + border: 0.15vw solid #2c2c2c; } #loginRegistrationWindow h2 { - text-align: center; - font-size: 3vw; - margin: 0; - font-weight: 700; + text-align: center; + font-size: 3vw; + margin: 0; + font-weight: 700; } -#LoginButton, #RegisterButton { - font-size: 2vw; - height: 4vw; - padding: 0 20%; - border-radius: 0.5vw; - color: white; - background-color: #1aaa55; - border: 0.2vw solid #168f48; +#LoginButton, +#RegisterButton { + font-size: 2vw; + height: 4vw; + padding: 0 20%; + border-radius: 0.5vw; + color: white; + background-color: #1aaa55; + border: 0.2vw solid #168f48; } -#LoginButton:hover, #RegisterButton:hover { - background-color: #168f48; +#LoginButton:hover, +#RegisterButton:hover { + background-color: #168f48; } #RegistrationForm label { - font-size: 1vw; - margin: auto 0 1% 1% ; + font-size: 1vw; + margin: auto 0 1% 1%; } #RegistrationForm label::after { - content: "*"; - color: red; - margin-left: 0.2vw; + content: '*'; + color: red; + margin-left: 0.2vw; } #RegistrationForm input { - font-size: 1.5vw; - padding: 2%; - background-color: #eeeeef; - border: 0.05vw solid black; + font-size: 1.5vw; + padding: 2%; + background-color: #eeeeef; + border: 0.05vw solid black; } #RegistrationForm button { - margin: 1.5vw auto auto; + margin: 1.5vw auto auto; } #LoginForm label { - font-size: 2.5vw; - margin: auto 0 1% 1% ; + font-size: 2.5vw; + margin: auto 0 1% 1%; } #LoginForm input { - font-size: 1.5vw; - padding: 2%; - background-color: #eeeeef; - border: 0.05vw solid black; + font-size: 1.5vw; + padding: 2%; + background-color: #eeeeef; + border: 0.05vw solid black; } #LoginForm div { - font-size: 2vw; - margin: 2vw auto; + font-size: 2vw; + margin: 2vw auto; } #LoginForm button { - margin: 3vw auto auto; + margin: 3vw auto auto; } .ErrorBox { - color: red; - font-weight: bold; - text-align: center; + color: red; + font-weight: bold; + text-align: center; } - -#loginRegistrationWindow label -{ - display: block; - width: 200px; - float: left; +#loginRegistrationWindow label { + display: block; + width: 200px; + float: left; } #profileMenu label { - display: block; - float: left; + display: block; + float: left; } -.SuccessBox{ - color: green; - text-align: center; -} \ No newline at end of file +.SuccessBox { + color: green; + text-align: center; +} diff --git a/src/Widgets/Extensions/Authentication/views/AuthenticationView.js b/src/Widgets/Extensions/Authentication/views/AuthenticationView.js index 31a5f4177..f423710f1 100644 --- a/src/Widgets/Extensions/Authentication/views/AuthenticationView.js +++ b/src/Widgets/Extensions/Authentication/views/AuthenticationView.js @@ -1,17 +1,18 @@ +/** @format */ + //Components import { ModuleView } from '../../../../Components/ModuleView/ModuleView'; import './AuthenticationView.css'; export class AuthenticationView extends ModuleView { + constructor(authenticationService) { + super(); + this.authenticationService = authenticationService; + } - constructor(authenticationService) { - super(); - this.authenticationService = authenticationService; - } - - html() { - return ` + html() { + return ` \

          Registration

          \

          @@ -43,139 +44,139 @@ export class AuthenticationView extends ModuleView { \ \ `; - } - - appendToElement(htmlElement) { - let div = document.createElement('div'); - div.innerHTML = this.html(); - div.id = "loginRegistrationWindow"; - htmlElement.appendChild(div); - document.getElementById('loginRegistrationCloseButton').onclick = () => { - this.disable() - }; - document.getElementById('LoginButton').onclick = () => { - this.logInFunction() - }; - document.getElementById('RegisterButton').onclick = () => { - this.registerFunction() - }; - document.getElementById('PasswordRegistration').onkeypress = () => { - if ((event.key) == "Enter") this.registerFunction() - }; - document.getElementById('PasswordLogin').onkeypress = () => { - if ((event.key) == "Enter") this.logInFunction() - }; - } - - - dispose() { - let div = document.getElementById('loginRegistrationWindow'); - return div.parentNode.removeChild(div); - } - - displayRegisterError(msg) { - let errorField = document.getElementById('RegisterInfo'); - errorField.className = "ErrorBox" - errorField.innerHTML = msg; + } + + appendToElement(htmlElement) { + let div = document.createElement('div'); + div.innerHTML = this.html(); + div.id = 'loginRegistrationWindow'; + htmlElement.appendChild(div); + document.getElementById('loginRegistrationCloseButton').onclick = () => { + this.disable(); }; - - displayLoginError(msg) { - let errorField = document.getElementById('LoginInfo'); - errorField.innerHTML = msg; + document.getElementById('LoginButton').onclick = () => { + this.logInFunction(); }; - - displayRegisterSuccess(msg) { - let successField = document.getElementById('RegisterInfo'); - successField.className = "SuccessBox"; - successField.innerHTML = msg; - } - - isVisible() { - let div = document.getElementById('loginRegistrationWindow'); - return div !== undefined && div !== null; + document.getElementById('RegisterButton').onclick = () => { + this.registerFunction(); + }; + document.getElementById('PasswordRegistration').onkeypress = () => { + if (event.key == 'Enter') this.registerFunction(); + }; + document.getElementById('PasswordLogin').onkeypress = () => { + if (event.key == 'Enter') this.logInFunction(); + }; + } + + dispose() { + let div = document.getElementById('loginRegistrationWindow'); + return div.parentNode.removeChild(div); + } + + displayRegisterError(msg) { + let errorField = document.getElementById('RegisterInfo'); + errorField.className = 'ErrorBox'; + errorField.innerHTML = msg; + } + + displayLoginError(msg) { + let errorField = document.getElementById('LoginInfo'); + errorField.innerHTML = msg; + } + + displayRegisterSuccess(msg) { + let successField = document.getElementById('RegisterInfo'); + successField.className = 'SuccessBox'; + successField.innerHTML = msg; + } + + isVisible() { + let div = document.getElementById('loginRegistrationWindow'); + return div !== undefined && div !== null; + } + verifyNotEmptyValuesForm(formIds) { + var validate = true; + for (var id in formIds) { + let element = document.getElementById(formIds[id]); + element.setAttribute('style', ''); + if (element.value == '') { + element.setAttribute('style', ' border: 3px solid red'); + validate = false; + } } - verifyNotEmptyValuesForm(formIds) { - var validate = true; - for (var id in formIds) { - let element = document.getElementById(formIds[id]); - element.setAttribute("style", ""); - if (element.value == "") { - element.setAttribute("style", " border: 3px solid red"); - validate = false; - } - } - return validate; + return validate; + } + deleteValuesForm(formIds) { + for (var id in formIds) { + let element = document.getElementById(formIds[id]); + element.value = ''; } - deleteValuesForm(formIds) { - for (var id in formIds) { - let element = document.getElementById(formIds[id]); - element.value = ""; - } + } + verifymail() { + // This regular expression checks an email in the form of 'name@example.com' + let RegularExpression = + /^(([^<>()[]\.,;:s@]+(.[^<>()[]\.,;:s@]+)*)|(.+))@(([[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}])|(([a-zA-Z-0-9]+.)+[a-zA-Z]{2,}))$/; + let element = document.getElementById('Email'); + if (RegularExpression.test(element.value)) { + element.setAttribute('style', ''); + this.displayRegisterError(''); + return true; + } else { + element.setAttribute('style', ' border: 3px solid red'); + this.displayRegisterError('Please insert a valid mail'); + return false; } - verifymail() { - // This regular expression checks an email in the form of 'name@example.com' - let RegularExpression = /^(([^<>()[]\.,;:s@]+(.[^<>()[]\.,;:s@]+)*)|(.+))@(([[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}])|(([a-zA-Z-0-9]+.)+[a-zA-Z]{2,}))$/; - let element = document.getElementById("Email"); - if (RegularExpression.test(element.value)) { - element.setAttribute("style", ""); - this.displayRegisterError(""); - return true; - } - else { - element.setAttribute("style", " border: 3px solid red"); - this.displayRegisterError("Please insert a valid mail"); - return false; + } + + async logInFunction() { + this.displayLoginError(''); + const loginForm = document.getElementById('LoginForm'); + const formData = new FormData(loginForm); + var formIds = ['login', 'PasswordLogin']; + if (this.verifyNotEmptyValuesForm(formIds)) { + try { + await this.authenticationService.login(formData); + this.disable(); + } catch (e) { + if (e.status === 401) { + this.displayLoginError('Login or password invalid'); } + } } - - async logInFunction() { - this.displayLoginError(''); - const loginForm = document.getElementById('LoginForm'); - const formData = new FormData(loginForm); - var formIds = ['login', 'PasswordLogin']; - if (this.verifyNotEmptyValuesForm(formIds)) { - try { - await this.authenticationService.login(formData); - this.disable(); - } catch (e) { - if (e.status === 401) { - this.displayLoginError("Login or password invalid"); - } - - } + } + + async registerFunction() { + this.displayRegisterError(''); + const registerForm = document.getElementById('RegistrationForm'); + const formData = new FormData(registerForm); + var formIds = [ + 'Firstname', + 'Lastname', + 'Username', + 'Email', + 'PasswordRegistration', + ]; + if (this.verifyNotEmptyValuesForm(formIds) & this.verifymail()) { + try { + await this.authenticationService.register(formData); + this.deleteValuesForm(formIds); + this.displayRegisterSuccess('Your registration succeed'); + } catch (e) { + if (e.status == '422') { + this.displayRegisterError('The user already exist'); + } else { + this.displayRegisterError(e.response); } + } } + } + /////// MODULE MANAGEMENT FOR BASE DEMO - async registerFunction() { - this.displayRegisterError(''); - const registerForm = document.getElementById('RegistrationForm'); - const formData = new FormData(registerForm); - var formIds = ['Firstname', 'Lastname', 'Username', 'Email', 'PasswordRegistration']; - if (this.verifyNotEmptyValuesForm(formIds) & this.verifymail()) { - try { - await this.authenticationService.register(formData); - this.deleteValuesForm(formIds); - this.displayRegisterSuccess("Your registration succeed"); + enableView() { + this.appendToElement(this.parentElement); + } - } catch (e) { - if (e.status == '422') { - this.displayRegisterError('The user already exist'); - } - else { - this.displayRegisterError(e.response); - } - } - } - - - }; - /////// MODULE MANAGEMENT FOR BASE DEMO - - enableView() { - this.appendToElement(this.parentElement); - } - - disableView() { - this.dispose(); - } + disableView() { + this.dispose(); + } } diff --git a/src/Widgets/Extensions/Contribute/ContributeModule.js b/src/Widgets/Extensions/Contribute/ContributeModule.js index 49a80d6c2..9f9e7a963 100644 --- a/src/Widgets/Extensions/Contribute/ContributeModule.js +++ b/src/Widgets/Extensions/Contribute/ContributeModule.js @@ -1,13 +1,15 @@ +/** @format */ + //Widgets -import { DocumentModule } from "../../Documents/DocumentModule"; +import { DocumentModule } from '../../Documents/DocumentModule'; //Components -import { RequestService } from "../../../Components/Request/RequestService"; +import { RequestService } from '../../../Components/Request/RequestService'; -import { DocumentCreationWindow } from "./View/DocumentCreationWindow"; -import { DocumentUpdateWindow } from "./View/DocumentUpdateWindow"; -import { ContributeService } from "./Service/ContributeService"; -import { DocumentDeletionInterface } from "./View/DocumentDeletionInterface"; +import { DocumentCreationWindow } from './View/DocumentCreationWindow'; +import { DocumentUpdateWindow } from './View/DocumentUpdateWindow'; +import { ContributeService } from './Service/ContributeService'; +import { DocumentDeletionInterface } from './View/DocumentDeletionInterface'; /** * This module is used to manage the update, deletion and creation of documents. @@ -17,7 +19,7 @@ import { DocumentDeletionInterface } from "./View/DocumentDeletionInterface"; export class ContributeModule { /** * Constructs a new contribute module. - * + * * @param {DocumentModule} documentModule The document module. * @param {DocumentImageOrienter} documentImageOrienter The document image * orienter module. @@ -29,17 +31,33 @@ export class ContributeModule { * @param {string} config.server.url The server url. * @param {string} config.server.document The base route for documents. */ - constructor(documentModule, documentImageOrienter, requestService, itownsView, cameraControls, config) { - this.contributeService = new ContributeService(requestService, - documentModule.provider, config) + constructor( + documentModule, + documentImageOrienter, + requestService, + itownsView, + cameraControls, + config + ) { + this.contributeService = new ContributeService( + requestService, + documentModule.provider, + config + ); - this.creationWindow = new DocumentCreationWindow(this.contributeService, - itownsView, cameraControls, documentImageOrienter); - this.updateWindow = new DocumentUpdateWindow(this.contributeService, - documentModule); + this.creationWindow = new DocumentCreationWindow( + this.contributeService, + itownsView, + cameraControls, + documentImageOrienter + ); + this.updateWindow = new DocumentUpdateWindow( + this.contributeService, + documentModule + ); new DocumentDeletionInterface(documentModule, this.contributeService); documentModule.addDocumentWindow(this.creationWindow); documentModule.addDocumentWindow(this.updateWindow); } -} \ No newline at end of file +} diff --git a/src/Widgets/Extensions/Contribute/Service/ContributeService.js b/src/Widgets/Extensions/Contribute/Service/ContributeService.js index 14703380a..22e1a28f0 100644 --- a/src/Widgets/Extensions/Contribute/Service/ContributeService.js +++ b/src/Widgets/Extensions/Contribute/Service/ContributeService.js @@ -1,9 +1,11 @@ +/** @format */ + //Widgets -import { DocumentProvider } from "../../../Documents/ViewModel/DocumentProvider"; -import { Document } from "../../../Documents/Model/Document"; +import { DocumentProvider } from '../../../Documents/ViewModel/DocumentProvider'; +import { Document } from '../../../Documents/Model/Document'; //Components -import { RequestService } from "../../../../Components/Request/RequestService"; +import { RequestService } from '../../../../Components/Request/RequestService'; /** * This class performs the requests on the server to update and create @@ -74,7 +76,7 @@ export class ContributeService { let url = this.documentUrl + '/' + id; let response = await this.requestService.request('PUT', url, { - body: updatedData + body: updatedData, }); if (response.status >= 200 && response.status < 300) { @@ -95,9 +97,9 @@ export class ContributeService { * @returns {Document} The created document. */ async createDocument(creationData) { - let response = await (this.requestService.request('POST', this.documentUrl, { - body: creationData - })); + let response = await this.requestService.request('POST', this.documentUrl, { + body: creationData, + }); if (response.status >= 200 && response.status < 300) { let created = JSON.parse(response.responseText); diff --git a/src/Widgets/Extensions/Contribute/View/Contribute.css b/src/Widgets/Extensions/Contribute/View/Contribute.css index e46ed1231..1def77c2b 100644 --- a/src/Widgets/Extensions/Contribute/View/Contribute.css +++ b/src/Widgets/Extensions/Contribute/View/Contribute.css @@ -1,12 +1,16 @@ -/* forms */ +/** + * /* forms + * + * @format + */ -.doc-update-creation-form input[type="date"], -.doc-update-creation-form input[type="text"], -.doc-update-creation-form input[type="file"], +.doc-update-creation-form input[type='date'], +.doc-update-creation-form input[type='text'], +.doc-update-creation-form input[type='file'], .doc-update-creation-form textarea, .doc-update-creation-form select { display: block; width: 100%; max-width: 100%; box-sizing: border-box; -} \ No newline at end of file +} diff --git a/src/Widgets/Extensions/Contribute/View/DocumentCreationWindow.js b/src/Widgets/Extensions/Contribute/View/DocumentCreationWindow.js index dadf8b750..4b06675d8 100644 --- a/src/Widgets/Extensions/Contribute/View/DocumentCreationWindow.js +++ b/src/Widgets/Extensions/Contribute/View/DocumentCreationWindow.js @@ -1,71 +1,80 @@ +/** @format */ + import * as THREE from 'three'; //Widgets -import { DocumentVisualizerWindow } from "../../../DocumentVisualizer/View/DocumentVisualizerWindow"; -import { AbstractDocumentWindow } from "../../../Documents/View/AbstractDocumentWindow"; +import { DocumentVisualizerWindow } from '../../../DocumentVisualizer/View/DocumentVisualizerWindow'; +import { AbstractDocumentWindow } from '../../../Documents/View/AbstractDocumentWindow'; //Components -import { Window } from "../../../../Components/GUI/js/Window"; -import { PositionerWindow } from "../../../../Components/Camera/PositionerWindow"; +import { Window } from '../../../../Components/GUI/js/Window'; +import { PositionerWindow } from '../../../../Components/Camera/PositionerWindow'; -import { ContributeService } from "../Service/ContributeService"; +import { ContributeService } from '../Service/ContributeService'; export class DocumentCreationWindow extends AbstractDocumentWindow { /** * Creates a new document creation window. - * + * * @param {ContributeService} contributeService The contribute service to * perform requests. * @param {*} itownsView The iTowns view. * @param {*} cameraControls The planar camera controls. * @param {DocumentVisualizerWindow} documentImageOrienter The document image orienter module. */ - constructor(contributeService, itownsView, cameraControls, documentImageOrienter) { + constructor( + contributeService, + itownsView, + cameraControls, + documentImageOrienter + ) { super('Creation'); - /** * The contribute service to perform requests. - * + * * @type {ContributeService} */ this.contributeService = contributeService; /** * The camera positioner utility tool. - * + * * @type {PositionerWindow} */ this.positioner = new PositionerWindow(itownsView, cameraControls); - this.positioner.addEventListener(PositionerWindow.EVENT_POSITION_SUBMITTED, - (data) => this._registerPositionAndQuaternion(data)); - this.addEventListener(Window.EVENT_DISABLED, - () => this.positioner.disable()); + this.positioner.addEventListener( + PositionerWindow.EVENT_POSITION_SUBMITTED, + (data) => this._registerPositionAndQuaternion(data) + ); + this.addEventListener(Window.EVENT_DISABLED, () => + this.positioner.disable() + ); /** * The camera controls - * + * * @type {*} */ this.controls = cameraControls; /** * The registered camera position for the document visualization. - * + * * @type {THREE.Vector3} */ this.cameraPosition = undefined; /** * The registered camera orientation for the document visualization. - * + * * @type {THREE.Quaternion} */ this.cameraQuaternion = undefined; /** * The document image orienter module. - * + * * @type {DocumentVisualizerWindow} */ this.documentImageOrienter = documentImageOrienter; @@ -73,18 +82,20 @@ export class DocumentCreationWindow extends AbstractDocumentWindow { // same time. this.documentImageOrienter.addEventListener(Window.EVENT_DISABLED, () => { if (this.positioner.isVisible) { - this.positioner.disable() - }}); + this.positioner.disable(); + } + }); this.positioner.addEventListener(Window.EVENT_DISABLED, () => { this._exitEditMode(); if (this.documentImageOrienter.isVisible) { - this.documentImageOrienter.disable() - }}); + this.documentImageOrienter.disable(); + } + }); /** * The settings for an accurate movement of the camera. These settings * should be used in the `PlanarControls` class. - * + * * @type {{rotateSpeed: number, zoomInFactor: number, zoomOutFactor: number, * maxPanSpeed: number, minPanSpeed: number}} */ @@ -93,16 +104,16 @@ export class DocumentCreationWindow extends AbstractDocumentWindow { zoomInFactor: 0.04, zoomOutFactor: 0.04, maxPanSpeed: 5.0, - minPanSpeed: 0.01 + minPanSpeed: 0.01, }; /** * The saved state of the planar controls settings. This is used to restore * the default settings when needed. - * + * * @type {{rotateSpeed: number, zoomInFactor: number, zoomOutFactor: number, - * maxPanSpeed: number, minPanSpeed: number}} - */ + * maxPanSpeed: number, minPanSpeed: number}} + */ this.savedControlsSettings = {}; for (let key of Object.keys(this.accurateControlsSettings)) { this.savedControlsSettings[key] = this.controls[key]; @@ -110,7 +121,7 @@ export class DocumentCreationWindow extends AbstractDocumentWindow { } get innerContentHtml() { - return /*html*/` + return /*html*/ `

          Document data

          @@ -161,7 +172,7 @@ export class DocumentCreationWindow extends AbstractDocumentWindow { this.view.navigatorWindow.addExtension('Create', { type: 'button', html: 'Create a new document', - callback: () => this.view.requestWindowDisplay(this, true) + callback: () => this.view.requestWindowDisplay(this, true), }); } @@ -171,7 +182,7 @@ export class DocumentCreationWindow extends AbstractDocumentWindow { /** * Displays the document positioning interfaces : the window positioner and * the document image orienter. - * + * * @private */ _startPositioningDocument() { @@ -214,7 +225,7 @@ export class DocumentCreationWindow extends AbstractDocumentWindow { /** * Sets the initial values for the form. - * + * * @private */ _initForm() { @@ -231,13 +242,13 @@ export class DocumentCreationWindow extends AbstractDocumentWindow { /** * Checks if the form is ready to be validated. Every entry must have a * non-empty value, and the camera position / orientation must have been set. - * + * * @private */ _formValidation() { let data = new FormData(this.formElement); for (let entry of data.entries()) { - if (!entry[1] || entry[1] === "") { + if (!entry[1] || entry[1] === '') { return false; } } @@ -251,7 +262,7 @@ export class DocumentCreationWindow extends AbstractDocumentWindow { * Update the form buttons depending on the current form state. If the * document have been chosen, we can position it. If the form is valid, * we can create the document. - * + * * @private */ _updateFormButtons() { @@ -270,11 +281,11 @@ export class DocumentCreationWindow extends AbstractDocumentWindow { /** * Registers the camera position and orientation. - * + * * @param {{ * position: THREE.Vector3, * quaternion: THREE.Quaternion - * }} cameraState Position and orientation of the camera. + * }} cameraState Position and orientation of the camera. */ _registerPositionAndQuaternion(cameraState) { this.cameraPosition = cameraState.position; @@ -284,7 +295,7 @@ export class DocumentCreationWindow extends AbstractDocumentWindow { /** * Proceeds to create the document from the form data. - * + * * @private */ async _submitCreation() { @@ -300,7 +311,7 @@ export class DocumentCreationWindow extends AbstractDocumentWindow { data.append('quaternionY', this.cameraQuaternion.y); data.append('quaternionZ', this.cameraQuaternion.z); data.append('quaternionW', this.cameraQuaternion.w); - + try { await this.contributeService.createDocument(data); this.disable(); @@ -343,11 +354,11 @@ export class DocumentCreationWindow extends AbstractDocumentWindow { get docTitleElement() { return document.getElementById(this.docTitleId); } - + get docImageId() { return `${this.windowId}_image`; } - + get docImageElement() { return document.getElementById(this.docImageId); } @@ -361,7 +372,7 @@ export class DocumentCreationWindow extends AbstractDocumentWindow { } get docRightsHolderId() { - return `${this.windowId}_rights_holder` + return `${this.windowId}_rights_holder`; } get docRightsHolderElement() { @@ -391,4 +402,4 @@ export class DocumentCreationWindow extends AbstractDocumentWindow { get refDateElement() { return document.getElementById(this.refDateId); } -} \ No newline at end of file +} diff --git a/src/Widgets/Extensions/Contribute/View/DocumentDeletionInterface.js b/src/Widgets/Extensions/Contribute/View/DocumentDeletionInterface.js index 0740599a7..4f3a9f135 100644 --- a/src/Widgets/Extensions/Contribute/View/DocumentDeletionInterface.js +++ b/src/Widgets/Extensions/Contribute/View/DocumentDeletionInterface.js @@ -1,7 +1,9 @@ +/** @format */ + //Widgets -import { DocumentModule } from "../../../Documents/DocumentModule"; +import { DocumentModule } from '../../../Documents/DocumentModule'; -import { ContributeService } from "../Service/ContributeService"; +import { ContributeService } from '../Service/ContributeService'; /** * Represents a really simple interface to delete a document. It is just a @@ -11,7 +13,7 @@ import { ContributeService } from "../Service/ContributeService"; export class DocumentDeletionInterface { /** * Creates a button in the document browser to perform the deletion. - * + * * @param {DocumentModule} documentModule The document module. * @param {ContributeService} contributeService The contribute service. */ @@ -21,8 +23,12 @@ export class DocumentDeletionInterface { container: 'right', html: 'Delete', callback: async () => { - if (!confirm('You are going to delete the document. This operation ' + - 'is irreversible. Do you want to continue ?')) { + if ( + !confirm( + 'You are going to delete the document. This operation ' + + 'is irreversible. Do you want to continue ?' + ) + ) { return; } try { @@ -30,7 +36,7 @@ export class DocumentDeletionInterface { } catch (e) { alert(e); } - } + }, }); } -} \ No newline at end of file +} diff --git a/src/Widgets/Extensions/Contribute/View/DocumentUpdateWindow.js b/src/Widgets/Extensions/Contribute/View/DocumentUpdateWindow.js index 97635bdb4..0d87516b5 100644 --- a/src/Widgets/Extensions/Contribute/View/DocumentUpdateWindow.js +++ b/src/Widgets/Extensions/Contribute/View/DocumentUpdateWindow.js @@ -1,12 +1,13 @@ -//Widgets -import { AbstractDocumentWindow } from "../../../Documents/View/AbstractDocumentWindow"; -import { DocumentProvider } from "../../../Documents/ViewModel/DocumentProvider"; -import { DocumentModule } from "../../../Documents/DocumentModule"; +/** @format */ -import { ContributeService } from "../Service/ContributeService"; +//Widgets +import { AbstractDocumentWindow } from '../../../Documents/View/AbstractDocumentWindow'; +import { DocumentProvider } from '../../../Documents/ViewModel/DocumentProvider'; +import { DocumentModule } from '../../../Documents/DocumentModule'; -import "./Contribute.css"; +import { ContributeService } from '../Service/ContributeService'; +import './Contribute.css'; /** * This window is used to update a document. It contains a form that allows to @@ -34,12 +35,12 @@ export class DocumentUpdateWindow extends AbstractDocumentWindow { type: 'button', container: 'right', html: 'Update', - callback: () => this._initWindow() + callback: () => this._initWindow(), }); } get innerContentHtml() { - return /*html*/` + return /*html*/ `

          @@ -75,12 +76,14 @@ export class DocumentUpdateWindow extends AbstractDocumentWindow { this.cancelButtonElement.onclick = () => { this.disable(); - } + }; } documentWindowReady() { - this.provider.addEventListener(DocumentProvider.EVENT_DISPLAYED_DOC_CHANGED, - () => this.disable()); + this.provider.addEventListener( + DocumentProvider.EVENT_DISPLAYED_DOC_CHANGED, + () => this.disable() + ); } /////////////////////// @@ -114,15 +117,16 @@ export class DocumentUpdateWindow extends AbstractDocumentWindow { } this.docTitleElement.innerText = doc.title; - this.docImageElement.src = - await this.provider.getDisplayedDocumentImage(); + this.docImageElement.src = await this.provider.getDisplayedDocumentImage(); this.sourceElement.value = doc.source; this.docRightsHolderElement.value = doc.rightsHolder; this.descriptionElement.value = doc.description; - this.pubDateElement.value = (new Date(doc.publicationDate)) - .toISOString().substring(0, 10); - this.refDateElement.value = (new Date(doc.refDate)) - .toISOString().substring(0, 10); + this.pubDateElement.value = new Date(doc.publicationDate) + .toISOString() + .substring(0, 10); + this.refDateElement.value = new Date(doc.refDate) + .toISOString() + .substring(0, 10); } ///////////////// @@ -186,7 +190,7 @@ export class DocumentUpdateWindow extends AbstractDocumentWindow { } get docRightsHolderId() { - return `${this.windowId}_rights_holder` + return `${this.windowId}_rights_holder`; } get docRightsHolderElement() { diff --git a/src/Widgets/Extensions/DocumentComments/DocumentCommentsModule.js b/src/Widgets/Extensions/DocumentComments/DocumentCommentsModule.js index 5a59342d3..5d578b5fb 100644 --- a/src/Widgets/Extensions/DocumentComments/DocumentCommentsModule.js +++ b/src/Widgets/Extensions/DocumentComments/DocumentCommentsModule.js @@ -1,10 +1,12 @@ -import { DocumentModule } from "../../Documents/DocumentModule"; +/** @format */ + +import { DocumentModule } from '../../Documents/DocumentModule'; //Components -import { RequestService } from "../../../Components/Request/RequestService"; +import { RequestService } from '../../../Components/Request/RequestService'; -import { DocumentCommentsService } from "./services/DocumentCommentsService"; -import { DocumentCommentsWindow } from "./views/DocumentCommentsWindow"; +import { DocumentCommentsService } from './services/DocumentCommentsService'; +import { DocumentCommentsWindow } from './views/DocumentCommentsWindow'; /** * The class that represents the document comments module. It contains a @@ -15,7 +17,7 @@ export class DocumentCommentsModule { /** * Creates the document comments module. Creates a service and a comments * window. - * + * * @param {DocumentModule} documentModule The document module. * @param {RequestService} requestService The request service. * @param {object} config The UDV config. @@ -26,10 +28,14 @@ export class DocumentCommentsModule { * @param {string} config.server.user The route for users. */ constructor(documentModule, requestService, config) { - this.service = new DocumentCommentsService(documentModule.provider, requestService, config); + this.service = new DocumentCommentsService( + documentModule.provider, + requestService, + config + ); this.commentsWindow = new DocumentCommentsWindow(this.service); documentModule.addDocumentWindow(this.commentsWindow); } -} \ No newline at end of file +} diff --git a/src/Widgets/Extensions/DocumentComments/services/DocumentCommentsService.js b/src/Widgets/Extensions/DocumentComments/services/DocumentCommentsService.js index acb130033..809919ab9 100644 --- a/src/Widgets/Extensions/DocumentComments/services/DocumentCommentsService.js +++ b/src/Widgets/Extensions/DocumentComments/services/DocumentCommentsService.js @@ -1,56 +1,67 @@ +/** @format */ + //Components -import { RequestService } from "../../../../Components/Request/RequestService"; +import { RequestService } from '../../../../Components/Request/RequestService'; -import { DocumentProvider } from "../../../Documents/ViewModel/DocumentProvider"; +import { DocumentProvider } from '../../../Documents/ViewModel/DocumentProvider'; /** * The service that performs the requests for document comments. This include * retrieve and create operations. */ export class DocumentCommentsService { - /** - * Creates a document comments service. - * - * @param {DocumentProvider} documentProvider The document provider. - * @param {RequestService} requestService The request service. - * @param {object} config The UD-Viz config. - * @param {object} config.server The server access config. - * @param {string} config.server.url The server URL. - * @param {string} config.server.document The route for documents. - * @param {string} config.server.comment The route for comments. - * @param {string} config.server.user The route for users. - */ - constructor (documentProvider, requestService, config) { - this.documentProvider = documentProvider; + /** + * Creates a document comments service. + * + * @param {DocumentProvider} documentProvider The document provider. + * @param {RequestService} requestService The request service. + * @param {object} config The UD-Viz config. + * @param {object} config.server The server access config. + * @param {string} config.server.url The server URL. + * @param {string} config.server.document The route for documents. + * @param {string} config.server.comment The route for comments. + * @param {string} config.server.user The route for users. + */ + constructor(documentProvider, requestService, config) { + this.documentProvider = documentProvider; - this.requestService = requestService; - - this.documentUrl = `${config.server.url}${config.server.document}`; - this.commentRoute = config.server.comment; - this.authorUrl = `${config.server.url}${config.server.user}`; - } + this.requestService = requestService; + + this.documentUrl = `${config.server.url}${config.server.document}`; + this.commentRoute = config.server.comment; + this.authorUrl = `${config.server.url}${config.server.user}`; + } - async getComments() { - let currentDocument = this.documentProvider.getDisplayedDocument(); - if (currentDocument !== null && currentDocument !== undefined) { - let url = this.documentUrl + "/" + currentDocument.id + "/" + this.commentRoute; - let response = (await this.requestService.request('GET', url, {authenticate: 'auto'})).response; - let jsonResponse = JSON.parse(response); - for (let element of jsonResponse) { - let url = this.authorUrl + "/" + element.user_id; - let responseAuthor = (await this.requestService.request('GET', url, {authenticate: 'auto'})).response; - element.author = JSON.parse(responseAuthor); - } - return jsonResponse; - } - return []; + async getComments() { + let currentDocument = this.documentProvider.getDisplayedDocument(); + if (currentDocument !== null && currentDocument !== undefined) { + let url = + this.documentUrl + '/' + currentDocument.id + '/' + this.commentRoute; + let response = ( + await this.requestService.request('GET', url, { authenticate: 'auto' }) + ).response; + let jsonResponse = JSON.parse(response); + for (let element of jsonResponse) { + let url = this.authorUrl + '/' + element.user_id; + let responseAuthor = ( + await this.requestService.request('GET', url, { + authenticate: 'auto', + }) + ).response; + element.author = JSON.parse(responseAuthor); + } + return jsonResponse; } + return []; + } - async publishComment(formData) { - let currentDocument = this.documentProvider.getDisplayedDocument(); - if (currentDocument !== null && currentDocument !== undefined) { - let url = this.documentUrl + "/" + currentDocument.id + "/" + this.commentRoute; - let response = (await this.requestService.send('POST', url, formData)).response; - } + async publishComment(formData) { + let currentDocument = this.documentProvider.getDisplayedDocument(); + if (currentDocument !== null && currentDocument !== undefined) { + let url = + this.documentUrl + '/' + currentDocument.id + '/' + this.commentRoute; + let response = (await this.requestService.send('POST', url, formData)) + .response; } -} \ No newline at end of file + } +} diff --git a/src/Widgets/Extensions/DocumentComments/views/DocumentCommentsStyle.css b/src/Widgets/Extensions/DocumentComments/views/DocumentCommentsStyle.css index 549729463..2e3d8cd59 100644 --- a/src/Widgets/Extensions/DocumentComments/views/DocumentCommentsStyle.css +++ b/src/Widgets/Extensions/DocumentComments/views/DocumentCommentsStyle.css @@ -1,76 +1,78 @@ +/** @format */ + #documentComments_innerWindow { - width: 100%; - height: 100%; - padding : 0; - margin: 0; - vertical-align:top; - display: grid; - grid-template-columns: 55% 45%; - } + width: 100%; + height: 100%; + padding: 0; + margin: 0; + vertical-align: top; + display: grid; + grid-template-columns: 55% 45%; +} - #documentComments_left{ - vertical-align:top; - overflow-y: auto; - } +#documentComments_left { + vertical-align: top; + overflow-y: auto; +} - #documentComments_right{ - vertical-align:top; - } +#documentComments_right { + vertical-align: top; +} - #documentComments_inputComment{ - height: 150px; - width: 90%; - margin: auto; - border-radius: 3px; - resize: none; - margin-top: 5px; - font-size: 10pt; - } +#documentComments_inputComment { + height: 150px; + width: 90%; + margin: auto; + border-radius: 3px; + resize: none; + margin-top: 5px; + font-size: 10pt; +} - #documentComments_inputButton{ - margin: 10%; - width: 70%; - } +#documentComments_inputButton { + margin: 10%; + width: 70%; +} - .commentRow { - width: 100%; - text-align: center; - } +.commentRow { + width: 100%; + text-align: center; +} - .talk-bubble { - margin: 3%; - position: relative; - width: 95%; - background-color: #e3dfff; - border-radius: 5px; - margin: 5px; - } +.talk-bubble { + margin: 3%; + position: relative; + width: 95%; + background-color: #e3dfff; + border-radius: 5px; + margin: 5px; +} - .talktext{ - padding: 0.3em; - text-align: left; - line-height: 0.9em; - } +.talktext { + padding: 0.3em; + text-align: left; + line-height: 0.9em; +} - .talktext-comment { - /* remove webkit p margins */ - color: #2f2d2e; - padding-left: 10px; - padding-right: 10px; - font-size: 100%; - } +.talktext-comment { + /* remove webkit p margins */ + color: #2f2d2e; + padding-left: 10px; + padding-right: 10px; + font-size: 100%; +} - .talktext-author { - border-bottom: 1px solid rgba(0, 0, 0, 0.3); - margin-top: 0; - padding: 5px; - font-weight: bold; - color: #41292c; - } +.talktext-author { + border-bottom: 1px solid rgba(0, 0, 0, 0.3); + margin-top: 0; + padding: 5px; + font-weight: bold; + color: #41292c; +} - .talktext-date { - color: #7d7d7d; - margin-bottom: 0; - text-align: right; - font-size: 90%; - } +.talktext-date { + color: #7d7d7d; + margin-bottom: 0; + text-align: right; + font-size: 90%; +} diff --git a/src/Widgets/Extensions/DocumentComments/views/DocumentCommentsWindow.js b/src/Widgets/Extensions/DocumentComments/views/DocumentCommentsWindow.js index 9ec060ff7..8b4f957a3 100644 --- a/src/Widgets/Extensions/DocumentComments/views/DocumentCommentsWindow.js +++ b/src/Widgets/Extensions/DocumentComments/views/DocumentCommentsWindow.js @@ -1,3 +1,5 @@ +/** @format */ + import { AbstractDocumentWindow } from '../../../Documents/View/AbstractDocumentWindow'; import { DocumentCommentsService } from '../services/DocumentCommentsService'; @@ -8,20 +10,19 @@ import './DocumentCommentsStyle.css'; * a comments creation interface. */ export class DocumentCommentsWindow extends AbstractDocumentWindow { + /** + * Creates a document comments window to add in the document browser. + * + * @param {DocumentCommentsService} documentCommentsService The document comments + * service. + */ + constructor(documentCommentsService) { + super('Comments'); + this.documentCommentsService = documentCommentsService; + } - /** - * Creates a document comments window to add in the document browser. - * - * @param {DocumentCommentsService} documentCommentsService The document comments - * service. - */ - constructor(documentCommentsService) { - super('Comments'); - this.documentCommentsService = documentCommentsService; - } - - get innerContentHtml() { - return /*html*/` + get innerContentHtml() { + return /*html*/ `
          @@ -38,65 +39,75 @@ export class DocumentCommentsWindow extends AbstractDocumentWindow {
          `; - } + } - windowCreated() { - this.hide(); + windowCreated() { + this.hide(); - this.window.style.width = '500px'; - this.window.style.height = '500px'; - this.window.style.left = '290px'; - this.window.style.top = '10px'; - this.innerContent.style.height = '100%'; - document.getElementById('documentComments_inputButton').onclick = this.publishComment.bind(this); - this.getComments(); - } + this.window.style.width = '500px'; + this.window.style.height = '500px'; + this.window.style.left = '290px'; + this.window.style.top = '10px'; + this.innerContent.style.height = '100%'; + document.getElementById('documentComments_inputButton').onclick = + this.publishComment.bind(this); + this.getComments(); + } - documentWindowReady() { - this.view.inspectorWindow.addExtension('Comments', { - type: 'button', - container: 'left', - html: 'Comments', - callback: () => { - this.view.requestWindowDisplay(this); - this.getComments(); - } - }); - } + documentWindowReady() { + this.view.inspectorWindow.addExtension('Comments', { + type: 'button', + container: 'left', + html: 'Comments', + callback: () => { + this.view.requestWindowDisplay(this); + this.getComments(); + }, + }); + } - getComments() { - this.documentCommentsService.getComments().then((comments) => { - document.getElementById('documentComments_left').innerHTML = ''; - for (let comment of comments) { - let text = (typeof comment.description === 'string') ? comment.description.replace(/(?:\r\n|\r|\n)/g, '
          ') : ''; - let div = document.createElement('div'); - div.className = 'talk-bubble'; - div.innerHTML = ` + getComments() { + this.documentCommentsService.getComments().then( + (comments) => { + document.getElementById('documentComments_left').innerHTML = ''; + for (let comment of comments) { + let text = + typeof comment.description === 'string' + ? comment.description.replace(/(?:\r\n|\r|\n)/g, '
          ') + : ''; + let div = document.createElement('div'); + div.className = 'talk-bubble'; + div.innerHTML = `
          -

          ${comment.author.firstName} ${comment.author.lastName}

          +

          ${comment.author.firstName} ${ + comment.author.lastName + }

          ${text}

          -

          ${(new Date(comment.date)).toLocaleString()}

          +

          ${new Date( + comment.date + ).toLocaleString()}

          `; - document.getElementById('documentComments_left').appendChild(div); - } - }, (reason) => { - alert(reason); - this.disable(); - }); - } - - - async publishComment() { - let form = document.getElementById('documentComments_inputForm'); - let form_data = new FormData(form); - try { - await this.documentCommentsService.publishComment(form_data).then(() => { - document.getElementById('documentComments_inputComment').value = ''; - this.getComments(); - }); - } catch (e) { - alert(e); + document.getElementById('documentComments_left').appendChild(div); } + }, + (reason) => { + alert(reason); + this.disable(); + } + ); + } + + async publishComment() { + let form = document.getElementById('documentComments_inputForm'); + let form_data = new FormData(form); + try { + await this.documentCommentsService.publishComment(form_data).then(() => { + document.getElementById('documentComments_inputComment').value = ''; + this.getComments(); + }); + } catch (e) { + alert(e); } + } } diff --git a/src/Widgets/Extensions/DocumentValidation/DocumentValidationModule.js b/src/Widgets/Extensions/DocumentValidation/DocumentValidationModule.js index 613856240..c2b78f986 100644 --- a/src/Widgets/Extensions/DocumentValidation/DocumentValidationModule.js +++ b/src/Widgets/Extensions/DocumentValidation/DocumentValidationModule.js @@ -1,9 +1,11 @@ +/** @format */ + //Widgets -import { DocumentModule } from "../../Documents/DocumentModule"; +import { DocumentModule } from '../../Documents/DocumentModule'; -import { ValidationService } from "./Service/ValidationService"; -import { DocumentsInValidationDocumentSource } from "./Service/DocumentsInValidationSource"; -import { ValidationView } from "./View/ValidationView"; +import { ValidationService } from './Service/ValidationService'; +import { DocumentsInValidationDocumentSource } from './Service/DocumentsInValidationSource'; +import { ValidationView } from './View/ValidationView'; /** * The document extension to manage documents validation. It allows the user to @@ -16,15 +18,18 @@ export class DocumentValidationModule { * Creates the document validation module. Creates a validation service to * manage HTTP requests, a validation source to change the retrieving URL * and finally the view elements. - * - * @param {DocumentModule} documentModule The documents module. + * + * @param {DocumentModule} documentModule The documents module. */ constructor(documentModule, requestService, config) { this.validationService = new ValidationService(requestService, config); this.validationSource = new DocumentsInValidationDocumentSource(config); - new ValidationView(documentModule, this.validationService, - this.validationSource); + new ValidationView( + documentModule, + this.validationService, + this.validationSource + ); } -} \ No newline at end of file +} diff --git a/src/Widgets/Extensions/DocumentValidation/Service/DocumentsInValidationSource.js b/src/Widgets/Extensions/DocumentValidation/Service/DocumentsInValidationSource.js index 41331cd21..7f4469ec6 100644 --- a/src/Widgets/Extensions/DocumentValidation/Service/DocumentsInValidationSource.js +++ b/src/Widgets/Extensions/DocumentValidation/Service/DocumentsInValidationSource.js @@ -1,4 +1,6 @@ -import { DocumentSource } from "../../../Documents/Model/DocumentService"; +/** @format */ + +import { DocumentSource } from '../../../Documents/Model/DocumentService'; /** * The document source for documents in validation. @@ -6,7 +8,7 @@ import { DocumentSource } from "../../../Documents/Model/DocumentService"; export class DocumentsInValidationDocumentSource extends DocumentSource { /** * Creates the document source. - * + * * @param {object} config The UD-Viz configuration. * @param {object} config.server The configuration for the server. * @param {string} config.server.url The base URL of the server. @@ -29,4 +31,4 @@ export class DocumentsInValidationDocumentSource extends DocumentSource { getImageUrl(doc) { return this.documentUrl + '/' + doc.id + '/' + this.fileRoute; } -} \ No newline at end of file +} diff --git a/src/Widgets/Extensions/DocumentValidation/Service/ValidationService.js b/src/Widgets/Extensions/DocumentValidation/Service/ValidationService.js index 056388c79..173f352fe 100644 --- a/src/Widgets/Extensions/DocumentValidation/Service/ValidationService.js +++ b/src/Widgets/Extensions/DocumentValidation/Service/ValidationService.js @@ -1,7 +1,9 @@ +/** @format */ + //Components -import { RequestService } from "../../../../Components/Request/RequestService"; +import { RequestService } from '../../../../Components/Request/RequestService'; -import { Document } from "../../../Documents/Model/Document"; +import { Document } from '../../../Documents/Model/Document'; /** * This class is responsible for the validation requests. @@ -9,7 +11,7 @@ import { Document } from "../../../Documents/Model/Document"; export class ValidationService { /** * Constructs a validation service. - * + * * @param {RequestService} requestService The request service. * @param {object} config The UD-Viz configuration. * @param {object} config.server The configuration for the server. @@ -23,14 +25,14 @@ export class ValidationService { /** * Sends the request to validate the document. - * + * * @param {Document} doc The document to validate. */ async validate(doc) { let formData = new FormData(); formData.append('id', doc.id); let response = await this.requestService.request('POST', this.validateUrl, { - body: formData + body: formData, }); - }; -} \ No newline at end of file + } +} diff --git a/src/Widgets/Extensions/DocumentValidation/View/ValidationView.js b/src/Widgets/Extensions/DocumentValidation/View/ValidationView.js index e919a8efd..542e89866 100644 --- a/src/Widgets/Extensions/DocumentValidation/View/ValidationView.js +++ b/src/Widgets/Extensions/DocumentValidation/View/ValidationView.js @@ -1,17 +1,19 @@ -import { DocumentModule } from "../../../Documents/DocumentModule"; -import { DocumentSource } from "../../../Documents/Model/DocumentService"; -import { Document } from "../../../Documents/Model/Document"; +/** @format */ + +import { DocumentModule } from '../../../Documents/DocumentModule'; +import { DocumentSource } from '../../../Documents/Model/DocumentService'; +import { Document } from '../../../Documents/Model/Document'; //Components -import { Window } from "../../../../Components/GUI/js/Window"; +import { Window } from '../../../../Components/GUI/js/Window'; -import { ValidationService } from "../Service/ValidationService"; -import { DocumentsInValidationDocumentSource } from "../Service/DocumentsInValidationSource"; +import { ValidationService } from '../Service/ValidationService'; +import { DocumentsInValidationDocumentSource } from '../Service/DocumentsInValidationSource'; /** * This class represents the visual elements and their logic for the * validation module : - * + * * - Button "See documents in validation" to change the document source * - Panel "Currently seing ..." to inform the user that he/she is consulting * documents in validation or validated documents @@ -20,7 +22,7 @@ import { DocumentsInValidationDocumentSource } from "../Service/DocumentsInValid export class ValidationView { /** * Creates the view. - * + * * @param {DocumentModule} documentModule The document module. * @param {ValidationService} validationService The validation service. * @param {DocumentsInValidationDocumentSource} validationSource The source @@ -33,7 +35,7 @@ export class ValidationView { /** * Defines wether the interface displays documents to validate (`true`) or * validated documents (`false`). - * + * * @type {boolean} */ this.displayingDocumentsToValidate = false; @@ -41,14 +43,14 @@ export class ValidationView { /** * Stores the previous document source to restore it (the source for * validated documents). - * + * * @type {DocumentSource} */ this.previousDocumentSource = undefined; /** * The validation source. - * + * * @type {DocumentsInValidationDocumentSource} */ this.validationSource = validationSource; @@ -58,17 +60,19 @@ export class ValidationView { documentModule.addNavigatorExtension('Validation Filter', { type: 'div', container: 'filter', - html: /*html*/` + html: /*html*/ ` - ` + `, }); - documentModule.view.navigatorWindow.addEventListener(Window.EVENT_CREATED, - () => this._initView()); + documentModule.view.navigatorWindow.addEventListener( + Window.EVENT_CREATED, + () => this._initView() + ); } _initView() { @@ -76,7 +80,7 @@ export class ValidationView { this._toggleValidation(); this.switchElement.onchange = () => { this._toggleValidation(); - } + }; } /////////////////////////////////////// @@ -86,7 +90,7 @@ export class ValidationView { * Toggles the visualization of documents in validation, then refreshes the * document list with the new source. If the refresh fails (probably because * the user isn't logged in), reverts back to displaying validated documents. - * + * * @private */ _toggleValidation() { @@ -95,42 +99,46 @@ export class ValidationView { if (this.displayingDocumentsToValidate) { this._showDocumentsInValidation(); } else { - this._showValidatedDocuments() + this._showValidatedDocuments(); } - this.documentModule.refreshDocumentList().then(() => { - }, (reason) => { - this._showValidatedDocuments(); - this.displayingDocumentsToValidate = false; - this.switchElement.value = "validated"; - alert(reason); - }); + this.documentModule.refreshDocumentList().then( + () => {}, + (reason) => { + this._showValidatedDocuments(); + this.displayingDocumentsToValidate = false; + this.switchElement.value = 'validated'; + alert(reason); + } + ); } /** * Sets the document source to be documents in validation, and adds a * 'Validate' button in the browser. - * + * * @private */ _showDocumentsInValidation() { // Change the document source - this.previousDocumentSource = this.documentModule - .changeDocumentSource(this.validationSource, true); - + this.previousDocumentSource = this.documentModule.changeDocumentSource( + this.validationSource, + true + ); + // Adds the validate button this.documentModule.addInspectorExtension('Validate', { type: 'button', container: 'right', html: 'Validate', - callback: (doc) => this._validateDocument(doc) + callback: (doc) => this._validateDocument(doc), }); } /** * Sets to document source to validated documents, and removes the 'Validate' * button in the browser. - * + * * @private */ _showValidatedDocuments() { @@ -138,8 +146,10 @@ export class ValidationView { return; } - this.documentModule.changeDocumentSource(this.previousDocumentSource, - false); + this.documentModule.changeDocumentSource( + this.previousDocumentSource, + false + ); try { this.documentModule.removeBrowserExtension('Validate'); @@ -150,21 +160,28 @@ export class ValidationView { /** * Validates the document. - * + * * @private - * + * * @param {Document} doc The document to validate. */ _validateDocument(doc) { - if (!confirm('Are you sure do validate this document ? ' + - 'This operation is irreversible.')) { + if ( + !confirm( + 'Are you sure do validate this document ? ' + + 'This operation is irreversible.' + ) + ) { return; } - this.validationService.validate(this.documentModule.provider.getDisplayedDocument()).catch((reason) => { - alert(reason.statusText); - }).then(() => { - this.documentModule.refreshDocumentList(); - }); + this.validationService + .validate(this.documentModule.provider.getDisplayedDocument()) + .catch((reason) => { + alert(reason.statusText); + }) + .then(() => { + this.documentModule.refreshDocumentList(); + }); } ///////////// @@ -173,8 +190,8 @@ export class ValidationView { get switchId() { return 'document-validation-view-switch'; } - + get switchElement() { return document.getElementById(this.switchId); } -} \ No newline at end of file +} diff --git a/src/Widgets/Extensions/Extensions.js b/src/Widgets/Extensions/Extensions.js index d3f3f2a77..eca6b8968 100644 --- a/src/Widgets/Extensions/Extensions.js +++ b/src/Widgets/Extensions/Extensions.js @@ -15,5 +15,3 @@ export { Debug3DTilesWindow } from './3DTilesDebug/views/3DTilesDebugWindow'; export { ContributeModule } from './Contribute/ContributeModule'; export { DocumentValidationModule } from './DocumentValidation/DocumentValidationModule'; - - diff --git a/src/Widgets/Extensions/Geocoding/services/GeocodingService.js b/src/Widgets/Extensions/Geocoding/services/GeocodingService.js index 567047265..1e25f87d4 100644 --- a/src/Widgets/Extensions/Geocoding/services/GeocodingService.js +++ b/src/Widgets/Extensions/Geocoding/services/GeocodingService.js @@ -1,6 +1,8 @@ +/** @format */ + //Components -import { RequestService } from "../../../../Components/Request/RequestService"; -import { getAttributeByPath } from "../../../../Components/DataProcessing/DataProcessing"; +import { RequestService } from '../../../../Components/Request/RequestService'; +import { getAttributeByPath } from '../../../../Components/DataProcessing/DataProcessing'; export class GeocodingService { /** @@ -29,7 +31,7 @@ export class GeocodingService { * @param {String} searchString Either an address or the name of a place. */ async getCoordinates(searchString) { - if ((!!this.requestTimeIntervalMs) && !this.canDoRequest) { + if (!!this.requestTimeIntervalMs && !this.canDoRequest) { throw 'Cannot perform a request for now.'; } @@ -39,32 +41,36 @@ export class GeocodingService { //build the URL according to parameter description (in config file) let url = this.geocodingUrl + '?'; for (let [paramName, param] of Object.entries(this.parameters)) { - if (param.fill === "value") { + if (param.fill === 'value') { url += `${paramName}=${param.value}`; - } else if (param.fill === "query") { + } else if (param.fill === 'query') { url += `${paramName}=${queryString}`; - } else if (param.fill === "extent") { - url += paramName + '=' + param.format - .replace('SOUTH', this.extent.south) - .replace('WEST', this.extent.west) - .replace('NORTH', this.extent.north) - .replace('EAST', this.extent.east); + } else if (param.fill === 'extent') { + url += + paramName + + '=' + + param.format + .replace('SOUTH', this.extent.south) + .replace('WEST', this.extent.west) + .replace('NORTH', this.extent.north) + .replace('EAST', this.extent.east); } - url += "&"; + url += '&'; } //make the request const req = await this.requestService.request('GET', url, { - authenticate: false + authenticate: false, }); const response = JSON.parse(req.response); - const results = ((!!this.basePath) ? response[this.basePath] : response) - .map(res => { + const results = (!!this.basePath ? response[this.basePath] : response).map( + (res) => { return { lat: Number(getAttributeByPath(res, this.latPath)), - lng: Number(getAttributeByPath(res, this.lngPath)) + lng: Number(getAttributeByPath(res, this.lngPath)), }; - }); + } + ); if (!!this.requestTimeIntervalMs) { this.canDoRequest = false; diff --git a/src/Widgets/Extensions/Geocoding/views/GeocodingStyle.css b/src/Widgets/Extensions/Geocoding/views/GeocodingStyle.css index 32b53ef05..b627d18dc 100644 --- a/src/Widgets/Extensions/Geocoding/views/GeocodingStyle.css +++ b/src/Widgets/Extensions/Geocoding/views/GeocodingStyle.css @@ -1,3 +1,5 @@ +/** @format */ + #_geocoding_view { position: absolute; z-index: 200; @@ -32,9 +34,17 @@ } @keyframes open { - 0% { width: 0; opacity: 0; } - 20% { width: 0; opacity: 1; } - 100% { width: 300px; } + 0% { + width: 0; + opacity: 0; + } + 20% { + width: 0; + opacity: 1; + } + 100% { + width: 300px; + } } #_geocoding_view_centered { @@ -54,4 +64,4 @@ background-color: rgba(255, 255, 255, 0.5); padding: 5px 10px 5px 10px; border-radius: 10px; -} \ No newline at end of file +} diff --git a/src/Widgets/Extensions/Geocoding/views/GeocodingView.js b/src/Widgets/Extensions/Geocoding/views/GeocodingView.js index e51f5635d..dec63944f 100644 --- a/src/Widgets/Extensions/Geocoding/views/GeocodingView.js +++ b/src/Widgets/Extensions/Geocoding/views/GeocodingView.js @@ -1,13 +1,15 @@ +/** @format */ + import * as THREE from 'three'; import * as itowns from 'itowns'; -import Coordinates from "itowns/lib/Core/Geographic/Coordinates"; +import Coordinates from 'itowns/lib/Core/Geographic/Coordinates'; import proj4 from 'proj4'; //Components -import { ModuleView } from "../../../../Components/ModuleView/ModuleView"; -import { focusCameraOn } from "../../../../Components/Camera/CameraUtils"; +import { ModuleView } from '../../../../Components/ModuleView/ModuleView'; +import { focusCameraOn } from '../../../../Components/Camera/CameraUtils'; -import { GeocodingService } from "../services/GeocodingService"; +import { GeocodingService } from '../services/GeocodingService'; import './GeocodingStyle.css'; export class GeocodingView extends ModuleView { @@ -28,12 +30,15 @@ export class GeocodingView extends ModuleView { // (planarView of iTowns). It is indeed needed in getWorldCoordinates() // to convert the coordinates received from the geocoding service (WGS84) // to this coordinate system. - proj4.defs('EPSG:3946', '+proj=lcc +lat_1=45.25 +lat_2=46.75' + - ' +lat_0=46 +lon_0=3 +x_0=1700000 +y_0=5200000 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs'); + proj4.defs( + 'EPSG:3946', + '+proj=lcc +lat_1=45.25 +lat_2=46.75' + + ' +lat_0=46 +lon_0=3 +x_0=1700000 +y_0=5200000 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs' + ); } get html() { - return /*html*/` + return /*html*/ `
          { this.doGeocoding(); return false; - } + }; } } @@ -73,16 +78,16 @@ export class GeocodingView extends ModuleView { if (this.isCreated) { let div = this.viewElement; let input = this.searchInputElement; - input.style.transition = 'width 0.3s ease-out, opacity 0.4s ease-out' + input.style.transition = 'width 0.3s ease-out, opacity 0.4s ease-out'; input.style.width = '0'; input.style.opacity = '0'; input.ontransitionend = (event) => { - if (event.propertyName === "opacity") { + if (event.propertyName === 'opacity') { div.parentElement.removeChild(div); this.removePins(); resolve(); } - } + }; } else { resolve(); } @@ -100,8 +105,8 @@ export class GeocodingView extends ModuleView { try { let coords = await this.geocodingService.getCoordinates(searchString); - coords.forEach(c => { - let {lat, lng} = c; + coords.forEach((c) => { + let { lat, lng } = c; let i = 0; //step 1 : convert the lat/lng to coordinates used by itowns let targetPos = this.getWorldCoordinates(lat, lng); @@ -132,8 +137,11 @@ export class GeocodingView extends ModuleView { getWorldCoordinates(lat, lng) { const [targetX, targetY] = proj4('EPSG:3946').forward([lng, lat]); const coords = new Coordinates('EPSG:3946', targetX, targetY, 0); - const elevation = itowns.DEMUtils.getElevationValueAt(this.planarView.tileLayer, coords); - const targetZ = (!!elevation) ? elevation : undefined; + const elevation = itowns.DEMUtils.getElevationValueAt( + this.planarView.tileLayer, + coords + ); + const targetZ = !!elevation ? elevation : undefined; return new THREE.Vector3(targetX, targetY, targetZ); } @@ -146,12 +154,12 @@ export class GeocodingView extends ModuleView { async addPin(position) { const pinHeight = 50; const cylGeom = new THREE.CylinderGeometry(1, 8, pinHeight, 8); - const cylMat = new THREE.MeshToonMaterial({color: 0xff0000}); + const cylMat = new THREE.MeshToonMaterial({ color: 0xff0000 }); const cylMesh = new THREE.Mesh(cylGeom, cylMat); position.z += pinHeight / 2; this.addMeshToScene(cylMesh, position); const sphereGeom = new THREE.SphereGeometry(10, 16, 16); - const sphereMat = new THREE.MeshToonMaterial({color: 0xff00000}); + const sphereMat = new THREE.MeshToonMaterial({ color: 0xff00000 }); const sphereMesh = new THREE.Mesh(sphereGeom, sphereMat); position.z += pinHeight / 2; this.addMeshToScene(sphereMesh, position); @@ -277,7 +285,6 @@ export class GeocodingView extends ModuleView { * @override */ async disableView() { - await this.dispose(); } } diff --git a/src/Widgets/GuidedTour/GuidedTour.css b/src/Widgets/GuidedTour/GuidedTour.css index 8e0c4ca70..7939dd539 100644 --- a/src/Widgets/GuidedTour/GuidedTour.css +++ b/src/Widgets/GuidedTour/GuidedTour.css @@ -1,187 +1,187 @@ -#guidedTourTab{ - position: absolute; - margin : 3px; - border: 1px solid black; - background-color: white; - color: black; - height: 30px; - top: 0; - left: 5%; - pointer-events: auto; -} - -#guidedTourWindow{ - position: relative; - text-align: center; - color : black; - height: 100%; - font-size: 14; - pointer-events: none; -} - -#guidedTourTitle{ - display:inline-block; - margin-top: 10px; - color: black; - background-color: ivory; - text-align: center; - font-size: 16px; - font-weight: bold; - overflow: hidden; -} - -#guidedTourStepTitle{ - display:inline-block; - margin-top: 10px; - color: white; - text-align: center; - font-weight: bold; - overflow: hidden; -} - -#guidedTourText1{ - display:inline-block; - margin: 10px; - padding: 5px; - padding-left: 10px; - padding-right: 10px; - line-height: 130%; - /* height adjusted in GuidedTour.js, 45% or 60% */ - height: 45%; - color : black; - background-color: ivory ; - border : 1px solid rgb(90,90,90); - text-align: justify; - overflow: scroll; - pointer-events: auto; -} - -#guidedTourText2{ - display: none; - margin-top: 20px; - margin: 10px; - padding: 5px; - padding-left: 10px; - padding-right: 10px; - line-height: 130%; - height: 20%; - color : black; - background-color: ivory ; - border : 1px solid rgb(90,90,90); - text-align: justify; - overflow: scroll; - pointer-events: auto; -} - -#guidedTourDocTitle{ - display:inline-block; - margin-top: 10px; - color: white; - text-align: center; - font-weight: bold; - overflow: hidden; -} - -#guidedTourDocPreview{ - height: 25%; - display:inline-block; - margin: 5% ; -} - -#guidedTourDocPreviewImg{ - width: 100%; /* or any custom size */ - height: 100%; - object-fit: contain; -} - -#guidedTourStartButton{ - position: absolute; - bottom : 5px; - left: 0; - right: 0; - margin: auto; - border: 1px solid black; - background-color: white; - color: black; - height: 30px; - pointer-events: auto; -} - - -#guidedTourNextTourButton{ - position: absolute; - bottom : 5px; - right: 5px; - margin: auto; - font-size: 30px; - border: 1px solid black; - background-color: white; - color: black; - height: 40px; - pointer-events: auto; -} - -#guidedTourPreviousTourButton{ - position: absolute; - bottom : 5px; - left : 5px; - margin : auto; - font-size: 30px; - border: 1px solid black; - background-color: white; - color: black; - height: 40px; - pointer-events: auto; -} - -#guidedTourNextStepButton{ - position: absolute; - bottom : 5px; - right: 5px; - margin: auto; - font-size: 30px; - border: 1px solid black; - background-color: white; - color: black; - height: 40px; - pointer-events: auto; -} - -#guidedTourPreviousStepButton{ - position: absolute; - bottom : 5px; - left : 5px; - margin : auto; - font-size: 30px; - border: 1px solid black; - background-color: white; - color: black; - height: 40px; - pointer-events: auto; -} - -#guidedTourExitButton{ - position: absolute; - display:none; - bottom : 5px; - left: 0; - right: 0; - margin: auto; - border: 1px solid black; - background-color: white; - color: black; - height: 30px; - pointer-events: auto; -} - -#tourCpt{ - position: absolute; - margin-top: 10px; - color: white; - left : 15px; - bottom : 100px; - font-size: 14px; - font-weight: bold; - overflow: hidden; +/** @format */ +#guidedTourTab { + position: absolute; + margin: 3px; + border: 1px solid black; + background-color: white; + color: black; + height: 30px; + top: 0; + left: 5%; + pointer-events: auto; +} + +#guidedTourWindow { + position: relative; + text-align: center; + color: black; + height: 100%; + font-size: 14; + pointer-events: none; +} + +#guidedTourTitle { + display: inline-block; + margin-top: 10px; + color: black; + background-color: ivory; + text-align: center; + font-size: 16px; + font-weight: bold; + overflow: hidden; +} + +#guidedTourStepTitle { + display: inline-block; + margin-top: 10px; + color: white; + text-align: center; + font-weight: bold; + overflow: hidden; +} + +#guidedTourText1 { + display: inline-block; + margin: 10px; + padding: 5px; + padding-left: 10px; + padding-right: 10px; + line-height: 130%; + /* height adjusted in GuidedTour.js, 45% or 60% */ + height: 45%; + color: black; + background-color: ivory; + border: 1px solid rgb(90, 90, 90); + text-align: justify; + overflow: scroll; + pointer-events: auto; +} + +#guidedTourText2 { + display: none; + margin-top: 20px; + margin: 10px; + padding: 5px; + padding-left: 10px; + padding-right: 10px; + line-height: 130%; + height: 20%; + color: black; + background-color: ivory; + border: 1px solid rgb(90, 90, 90); + text-align: justify; + overflow: scroll; + pointer-events: auto; +} + +#guidedTourDocTitle { + display: inline-block; + margin-top: 10px; + color: white; + text-align: center; + font-weight: bold; + overflow: hidden; +} + +#guidedTourDocPreview { + height: 25%; + display: inline-block; + margin: 5%; +} + +#guidedTourDocPreviewImg { + width: 100%; /* or any custom size */ + height: 100%; + object-fit: contain; +} + +#guidedTourStartButton { + position: absolute; + bottom: 5px; + left: 0; + right: 0; + margin: auto; + border: 1px solid black; + background-color: white; + color: black; + height: 30px; + pointer-events: auto; +} + +#guidedTourNextTourButton { + position: absolute; + bottom: 5px; + right: 5px; + margin: auto; + font-size: 30px; + border: 1px solid black; + background-color: white; + color: black; + height: 40px; + pointer-events: auto; +} + +#guidedTourPreviousTourButton { + position: absolute; + bottom: 5px; + left: 5px; + margin: auto; + font-size: 30px; + border: 1px solid black; + background-color: white; + color: black; + height: 40px; + pointer-events: auto; +} + +#guidedTourNextStepButton { + position: absolute; + bottom: 5px; + right: 5px; + margin: auto; + font-size: 30px; + border: 1px solid black; + background-color: white; + color: black; + height: 40px; + pointer-events: auto; +} + +#guidedTourPreviousStepButton { + position: absolute; + bottom: 5px; + left: 5px; + margin: auto; + font-size: 30px; + border: 1px solid black; + background-color: white; + color: black; + height: 40px; + pointer-events: auto; +} + +#guidedTourExitButton { + position: absolute; + display: none; + bottom: 5px; + left: 0; + right: 0; + margin: auto; + border: 1px solid black; + background-color: white; + color: black; + height: 30px; + pointer-events: auto; +} + +#tourCpt { + position: absolute; + margin-top: 10px; + color: white; + left: 15px; + bottom: 100px; + font-size: 14px; + font-weight: bold; + overflow: hidden; } diff --git a/src/Widgets/GuidedTour/GuidedTour.js b/src/Widgets/GuidedTour/GuidedTour.js index 4698a9f09..de7c14d8b 100644 --- a/src/Widgets/GuidedTour/GuidedTour.js +++ b/src/Widgets/GuidedTour/GuidedTour.js @@ -1,8 +1,10 @@ +/** @format */ + //Components import { Window } from '../../Components/GUI/js/Window'; import '../../Components/GUI/css/window.css'; -import './GuidedTour.css' +import './GuidedTour.css'; /** * Class: GuidedTour @@ -15,9 +17,8 @@ import './GuidedTour.css' * //=============================================================================*/ export class GuidedTour extends Window { - constructor(guidedTourController) { - super('guidedTour', 'Guided Tour', false) + super('guidedTour', 'Guided Tour', false); this.guidedTourController = guidedTourController; this.tourIndex = 1; //current guided tour. Default is 1 (start) @@ -71,13 +72,16 @@ export class GuidedTour extends Window { // hide or show the guided tour window //============================================================================= - toggleGuidedTourWindow(){ - - document.getElementById('guidedTourWindow').style.display = - this.guidedTourWindowIsActive ? "block" : "none"; - this.guidedTourWindowIsActive = this.guidedTourWindowIsActive ? false : true; - - if(this.isStart){ + toggleGuidedTourWindow() { + document.getElementById('guidedTourWindow').style.display = this + .guidedTourWindowIsActive + ? 'block' + : 'none'; + this.guidedTourWindowIsActive = this.guidedTourWindowIsActive + ? false + : true; + + if (this.isStart) { this.startGuidedTourMode(); this.isStart = false; this.guidedTourController.toggleGuidedTourButtons(true); @@ -85,7 +89,7 @@ export class GuidedTour extends Window { } //get all available guided tour from the database - startGuidedTourMode(){ + startGuidedTourMode() { this.guidedTourController.getGuidedTours().then(() => { this.previewTour(); }); @@ -95,85 +99,90 @@ export class GuidedTour extends Window { * Initialize the preview of the guided tour */ //============================================================================= - previewTour(){ - document.getElementById('tourCpt').innerHTML = "Tour: " - + this.tourIndex + " out of " + this.guidedTourController.guidedTours.length; - document.getElementById("guidedTourPreviousTourButton").style.display = "block"; - document.getElementById("guidedTourNextTourButton").style.display = "block"; + previewTour() { + document.getElementById('tourCpt').innerHTML = + 'Tour: ' + + this.tourIndex + + ' out of ' + + this.guidedTourController.guidedTours.length; + document.getElementById('guidedTourPreviousTourButton').style.display = + 'block'; + document.getElementById('guidedTourNextTourButton').style.display = 'block'; // for the demo, until we have more than one finished guided tour // we can prevent user from changing tour by hiding the buttons - if(this.guidedTourController.preventUserFromChangingTour){ - document.getElementById("guidedTourPreviousTourButton").style.display = "none"; - document.getElementById("guidedTourNextTourButton").style.display = "none"; + if (this.guidedTourController.preventUserFromChangingTour) { + document.getElementById('guidedTourPreviousTourButton').style.display = + 'none'; + document.getElementById('guidedTourNextTourButton').style.display = + 'none'; } - document.getElementById("guidedTourPreviousStepButton").style.display = "none"; - document.getElementById("guidedTourNextStepButton").style.display = "none"; - document.getElementById("guidedTourExitButton").style.display = "none"; + document.getElementById('guidedTourPreviousStepButton').style.display = + 'none'; + document.getElementById('guidedTourNextStepButton').style.display = 'none'; + document.getElementById('guidedTourExitButton').style.display = 'none'; //document.getElementById("guidedTourText2").style.display = "none"; - document.getElementById("guidedTourStartButton").style.display = "block"; + document.getElementById('guidedTourStartButton').style.display = 'block'; let currentTour = this.guidedTourController.getCurrentTour(); - document.getElementById('guidedTourTitle').innerHTML = - currentTour ? currentTour.name - : 'No guided tour'; - document.getElementById('guidedTourText1').innerHTML = - currentTour ? currentTour.description - : 'Please add guided tours'; - document.getElementById("guidedTourText1").style.height = "45%"; - document.getElementById("guidedTourStepTitle").innerHTML = null; - + document.getElementById('guidedTourTitle').innerHTML = currentTour + ? currentTour.name + : 'No guided tour'; + document.getElementById('guidedTourText1').innerHTML = currentTour + ? currentTour.description + : 'Please add guided tours'; + document.getElementById('guidedTourText1').style.height = '45%'; + document.getElementById('guidedTourStepTitle').innerHTML = null; } - // update step with current step data //============================================================================= - updateStep(){ - + updateStep() { this.currentStep = this.guidedTourController.getCurrentStep(); this.documentBrowser.currentMetadata = - this.guidedTourController.getCurrentStep().document; - this.documentBrowser.currentDoc = this.guidedTourController.getCurrentStep().document; + this.guidedTourController.getCurrentStep().document; + this.documentBrowser.currentDoc = + this.guidedTourController.getCurrentStep().document; this.documentBrowser.updateBrowser(); - document.getElementById("guidedTourText1").innerHTML = this.currentStep.text1; - document.getElementById('guidedTourStepTitle').innerHTML = this.currentStep.title; + document.getElementById('guidedTourText1').innerHTML = + this.currentStep.text1; + document.getElementById('guidedTourStepTitle').innerHTML = + this.currentStep.title; this.documentBrowser.focusOnDoc(); } //start guided tour //============================================================================= - startGuidedTour(){ - - if(this.guidedTourController.getCurrentTour().extendedDocs.length > 0){ + startGuidedTour() { + if (this.guidedTourController.getCurrentTour().extendedDocs.length > 0) { this.tourIndex = 1; this.stepIndex = 1; this.updateStep(); // setup the display (hide & show elements) this.guidedTourController.toggleGuidedTourButtons(false); - document.getElementById("guidedTourDocPreviewImg").style.display = "none"; - document.getElementById("guidedTourText1").style.height = "60%"; - document.getElementById('tourCpt').style.display = "none"; - } - else { + document.getElementById('guidedTourDocPreviewImg').style.display = 'none'; + document.getElementById('guidedTourText1').style.height = '60%'; + document.getElementById('tourCpt').style.display = 'none'; + } else { alert('This guided tour is empty'); //should never happen. If a guided tour - //doesn't have steps, then it is not a guided tour + //doesn't have steps, then it is not a guided tour } - }; + } // Quit current guided tour //============================================================================= - exitGuidedTour(){ - this.guidedTourController.reset(); - }; + exitGuidedTour() { + this.guidedTourController.reset(); + } /** * Update guided tour preview by clicking on "guidedTourNextTourButton" button */ //============================================================================= - nextTour(){ - if(this.tourIndex < this.guidedTourController.guidedTours.length){ + nextTour() { + if (this.tourIndex < this.guidedTourController.guidedTours.length) { this.guidedTourController.getNextTour(); - this.tourIndex ++; + this.tourIndex++; this.previewTour(); } } @@ -182,10 +191,10 @@ export class GuidedTour extends Window { * Update guided tour preview by clicking on "guidedTourPreviousTourButton" button */ //============================================================================= - previousTour(){ + previousTour() { this.guidedTourController.getPreviousTour(); - if(this.tourIndex > 1 ){ - this.tourIndex --; + if (this.tourIndex > 1) { + this.tourIndex--; } this.previewTour(); } @@ -194,43 +203,48 @@ export class GuidedTour extends Window { * Update step by clicking on "guidedTourNextStepButton" button */ //============================================================================= - nextStep(){ - - if(this.stepIndex < this.guidedTourController.getCurrentTour().extendedDocs.length ){ - this.stepIndex ++; + nextStep() { + if ( + this.stepIndex < + this.guidedTourController.getCurrentTour().extendedDocs.length + ) { + this.stepIndex++; this.guidedTourController.getNextStep(); - this.updateStep(); + this.updateStep(); } - } /** * Update step by clicking on "guidedTourPreviousStepButton" button */ //============================================================================= - previousStep(){ - - if( this.stepIndex > 1 ){ + previousStep() { + if (this.stepIndex > 1) { this.guidedTourController.getPreviousStep(); - this.stepIndex --; + this.stepIndex--; this.updateStep(); } } // event listeners (buttons) initializeButtons() { - document.getElementById("guidedTourNextTourButton").addEventListener('mousedown', - this.nextTour.bind(this),false); - document.getElementById("guidedTourPreviousTourButton").addEventListener('mousedown', - this.previousTour.bind(this),false); - document.getElementById("guidedTourStartButton").addEventListener('mousedown', - this.startGuidedTour.bind(this),false); - document.getElementById("guidedTourNextStepButton").addEventListener('mousedown', - this.nextStep.bind(this),false); - document.getElementById("guidedTourPreviousStepButton").addEventListener('mousedown', - this.previousStep.bind(this),false); - document.getElementById("guidedTourExitButton").addEventListener('mousedown', - this.exitGuidedTour.bind(this),false); + document + .getElementById('guidedTourNextTourButton') + .addEventListener('mousedown', this.nextTour.bind(this), false); + document + .getElementById('guidedTourPreviousTourButton') + .addEventListener('mousedown', this.previousTour.bind(this), false); + document + .getElementById('guidedTourStartButton') + .addEventListener('mousedown', this.startGuidedTour.bind(this), false); + document + .getElementById('guidedTourNextStepButton') + .addEventListener('mousedown', this.nextStep.bind(this), false); + document + .getElementById('guidedTourPreviousStepButton') + .addEventListener('mousedown', this.previousStep.bind(this), false); + document + .getElementById('guidedTourExitButton') + .addEventListener('mousedown', this.exitGuidedTour.bind(this), false); } - } diff --git a/src/Widgets/GuidedTour/GuidedTourController.js b/src/Widgets/GuidedTour/GuidedTourController.js index b0fed6c47..2f2be96d7 100644 --- a/src/Widgets/GuidedTour/GuidedTourController.js +++ b/src/Widgets/GuidedTour/GuidedTourController.js @@ -1,20 +1,22 @@ +/** @format */ + //Components import { ModuleView } from '../../Components/ModuleView/ModuleView'; -import { RequestService } from "../../Components/Request/RequestService"; +import { RequestService } from '../../Components/Request/RequestService'; import './GuidedTour.css'; import { GuidedTour } from './GuidedTour.js'; import { DocumentModule } from '../Documents/DocumentModule'; /** -* Class: GuidedTourController -* Description : -* The GuidedTourController is an object handling the view, interracting with the -* server to get information and data (guided tours) -* It handles the display of guided tours in the guided tour window, and all the -* functionalities related to the guided tour (start, exit, next, previous...) -* GuidedTours are made of steps with properties : index, document, text1 and text2. -*/ + * Class: GuidedTourController + * Description : + * The GuidedTourController is an object handling the view, interracting with the + * server to get information and data (guided tours) + * It handles the display of guided tours in the guided tour window, and all the + * functionalities related to the guided tour (start, exit, next, previous...) + * GuidedTours are made of steps with properties : index, document, text1 and text2. + */ export class GuidedTourController extends ModuleView { /** * Constructor for GuidedTourController @@ -37,7 +39,7 @@ export class GuidedTourController extends ModuleView { constructor(documentModule, requestService, config) { super(); - this.guidedTourContainerId = "guidedTourContainer"; + this.guidedTourContainerId = 'guidedTourContainer'; this.documentModule = documentModule; //instance of DocumentModule @@ -65,8 +67,8 @@ export class GuidedTourController extends ModuleView { } /** - * initialize the controller - */ + * initialize the controller + */ //============================================================================= initialize() { this.guidedTour = new GuidedTour(this); @@ -76,11 +78,11 @@ export class GuidedTourController extends ModuleView { } /** - * Get all guided tour from a database */ + * Get all guided tour from a database */ //============================================================================= async getGuidedTours() { let req = await this.requestService.request('GET', this.url, { - authenticate: false + authenticate: false, }); this.guidedTours = JSON.parse(req.responseText); } @@ -92,8 +94,7 @@ export class GuidedTourController extends ModuleView { getCurrentTour() { if (this.guidedTours.length != 0) { return this.guidedTours[this.currentTourIndex]; - } - else { + } else { return null; } } @@ -107,7 +108,7 @@ export class GuidedTourController extends ModuleView { this.currentTourIndex++; } return this.getCurrentTour(); - }; + } /** * Sets the current guided tour to the previous guided tour and returns it. @@ -118,25 +119,24 @@ export class GuidedTourController extends ModuleView { this.currentTourIndex--; } return this.getCurrentTour(); - }; + } /** - * Returns the current tour step - */ + * Returns the current tour step + */ //============================================================================= getCurrentStep() { if (this.getCurrentTour().length != 0) { var steps = this.getCurrentTour().extendedDocs; return steps[this.currentStepIndex]; - } - else { + } else { return null; } } /** - * Sets the current step to the previous step and returns it. - */ + * Sets the current step to the previous step and returns it. + */ //============================================================================= getPreviousStep() { if (this.currentStepIndex > 0) { @@ -146,8 +146,8 @@ export class GuidedTourController extends ModuleView { } /** - * Sets the current step to the next step and returns it. - */ + * Sets the current step to the next step and returns it. + */ //============================================================================= getNextStep() { if (this.currentStepIndex < this.getCurrentTour().extendedDocs.length) { @@ -156,10 +156,9 @@ export class GuidedTourController extends ModuleView { return this.getCurrentStep(); } - /** - * Reset browser at the begining of the guided tours - */ + * Reset browser at the begining of the guided tours + */ //============================================================================= reset() { this.currentStepIndex = 0; @@ -167,19 +166,27 @@ export class GuidedTourController extends ModuleView { this.currentGuidedTour = this.guidedTours[this.currentTourIndex]; this.guidedTour.currentStep = this.getCurrentStep(); this.guidedTour.previewTour(); - } //Hide or show previous / next buttons in browser window //============================================================================= toggleGuidedTourButtons(active) { - document.getElementById("guidedTourPreviousTourButton").style.display = active ? "block" : "none"; - document.getElementById("guidedTourNextTourButton").style.display = active ? "block" : "none"; - document.getElementById("guidedTourPreviousStepButton").style.display = active ? "none" : "block"; - document.getElementById("guidedTourNextStepButton").style.display = active ? "none" : "block"; - document.getElementById('guidedTourStartButton').style.display = active ? "block" : "none"; - document.getElementById("guidedTourExitButton").style.display = active ? "none" : "block"; - + document.getElementById('guidedTourPreviousTourButton').style.display = + active ? 'block' : 'none'; + document.getElementById('guidedTourNextTourButton').style.display = active + ? 'block' + : 'none'; + document.getElementById('guidedTourPreviousStepButton').style.display = + active ? 'none' : 'block'; + document.getElementById('guidedTourNextStepButton').style.display = active + ? 'none' + : 'block'; + document.getElementById('guidedTourStartButton').style.display = active + ? 'block' + : 'none'; + document.getElementById('guidedTourExitButton').style.display = active + ? 'none' + : 'block'; } /////// MODULE MANAGEMENT FOR BASE DEMO @@ -191,5 +198,4 @@ export class GuidedTourController extends ModuleView { disableView() { this.guidedTour.dispose(); } - } diff --git a/src/Widgets/LayerChoice/views/LayerChoice.js b/src/Widgets/LayerChoice/views/LayerChoice.js index ef77d48be..6467deeb0 100644 --- a/src/Widgets/LayerChoice/views/LayerChoice.js +++ b/src/Widgets/LayerChoice/views/LayerChoice.js @@ -1,24 +1,26 @@ +/** @format */ + //Components -import { Window } from "../../../Components/GUI/js/Window"; -import { LayerManager } from "../../../Components/LayerManager/LayerManager"; +import { Window } from '../../../Components/GUI/js/Window'; +import { LayerManager } from '../../../Components/LayerManager/LayerManager'; export class LayerChoice extends Window { /** - * Creates the layer choice windows - * - * @param {LayerManager} layerManager + * Creates the layer choice windows + * + * @param {LayerManager} layerManager */ constructor(layerManager) { super('layer_choice', 'Layer', false); - /** + /** * the layerManager */ this.layerManager = layerManager; } get innerContentHtml() { - return /*html*/` + return /*html*/ `
          @@ -61,20 +63,31 @@ export class LayerChoice extends Window { let layers = this.layerManager.getColorLayers(); for (let i = 0; i < layers.length; i++) { let item = document.createElement('div'); - item.innerHTML = ` - Visible
          + item.innerHTML = ` + Visible
          - Opacity : ${layers[i].opacity} + Opacity : ${ + layers[i].opacity + }
          `; item.oninput = (event) => { - if (event.srcElement.id === "checkbox_" + i) { + if (event.srcElement.id === 'checkbox_' + i) { layers[i].visible = event.srcElement.checked; } - if (event.srcElement.id === "range_" + i) { - this.layerManager.updateOpacity(layers[i], event.srcElement.valueAsNumber); + if (event.srcElement.id === 'range_' + i) { + this.layerManager.updateOpacity( + layers[i], + event.srcElement.valueAsNumber + ); } - let span_opacity = document.getElementById("color_value_opacity_" + i); + let span_opacity = document.getElementById('color_value_opacity_' + i); span_opacity.innerHTML = `${layers[i].opacity}`; this.layerManager.notifyChange(); }; @@ -93,9 +106,14 @@ export class LayerChoice extends Window { Scale : ${layers[i].scale} `; item.oninput = (event) => { - this.layerManager.updateScale(layers[i], event.srcElement.valueAsNumber); + this.layerManager.updateScale( + layers[i], + event.srcElement.valueAsNumber + ); this.layerManager.notifyChange(); - let span_elevation = document.getElementById("elevation_value_scale_" + i); + let span_elevation = document.getElementById( + 'elevation_value_scale_' + i + ); span_elevation.innerHTML = `${layers[i].scale}`; }; list.appendChild(item); @@ -110,7 +128,9 @@ export class LayerChoice extends Window { let div = document.createElement('div'); div.innerHTML = ` - All Visible
          + All Visible
          `; div.onchange = (event) => { this.layerManager.changeVisibility(event.srcElement.checked); @@ -119,27 +139,46 @@ export class LayerChoice extends Window { list.append(div); for (let i = 0; i < layers.length; i++) { let item = document.createElement('div'); - item.innerHTML = ` - + item.innerHTML = ` +
          - Visible
          + Visible
          - Opacity : ${layers[i].opacity} + Opacity : ${ + layers[i].opacity + }
          `; item.oninput = (event) => { - if (event.srcElement.id === "checkbox_" + i) { + if (event.srcElement.id === 'checkbox_' + i) { layers[i].visible = event.srcElement.checked; } - if (event.srcElement.id === "range_" + i) { - this.layerManager.updateOpacity(layers[i], event.srcElement.valueAsNumber); + if (event.srcElement.id === 'range_' + i) { + this.layerManager.updateOpacity( + layers[i], + event.srcElement.valueAsNumber + ); } - let div_visible = document.getElementById("visible_" + i); - div_visible.innerHTML = `Visible
          `; - let span_opacity = document.getElementById("geometry_value_opacity_" + i); + let div_visible = document.getElementById('visible_' + i); + div_visible.innerHTML = `Visible
          `; + let span_opacity = document.getElementById( + 'geometry_value_opacity_' + i + ); span_opacity.innerHTML = `${layers[i].opacity}`; this.layerManager.notifyChange(); }; @@ -179,4 +218,4 @@ export class LayerChoice extends Window { get geometryLayerListElement() { return document.getElementById(this.geometryLayersId); } -} \ No newline at end of file +} diff --git a/src/Widgets/Links/LinkModule.js b/src/Widgets/Links/LinkModule.js index 001d55426..7950cecfb 100644 --- a/src/Widgets/Links/LinkModule.js +++ b/src/Widgets/Links/LinkModule.js @@ -1,12 +1,14 @@ +/** @format */ + //Components -import { RequestService } from "../../Components/Request/RequestService"; -import { Window } from "../../Components/GUI/js/Window"; +import { RequestService } from '../../Components/Request/RequestService'; +import { Window } from '../../Components/GUI/js/Window'; -import { LinkService } from "./Model/LinkService"; -import { DocumentModule } from "../Documents/DocumentModule"; -import { CityObjectModule } from "../CityObjects/CityObjectModule"; -import { LinkView } from "./View/LinkView"; -import { LinkProvider } from "./ViewModel/LinkProvider"; +import { LinkService } from './Model/LinkService'; +import { DocumentModule } from '../Documents/DocumentModule'; +import { CityObjectModule } from '../CityObjects/CityObjectModule'; +import { LinkView } from './View/LinkView'; +import { LinkProvider } from './ViewModel/LinkProvider'; /** * Manages the links between the city objects and the documents. This modules @@ -16,7 +18,7 @@ import { LinkProvider } from "./ViewModel/LinkProvider"; export class LinkModule { /** * Creates the link module. - * + * * @param {DocumentModule} documentModule The document module. * @param {CityObjectModule} cityObjectModule The city objects module. * @param {RequestService} requestService The request service. @@ -27,33 +29,51 @@ export class LinkModule { * @param {string} config.server.url The server URL. * @param {string} config.server.link The link route. */ - constructor(documentModule, cityObjectModule, requestService, itownsView, - cameraControls, config) { + constructor( + documentModule, + cityObjectModule, + requestService, + itownsView, + cameraControls, + config + ) { /** * The link service. - * + * * @type {LinkService} */ this.service = new LinkService(requestService, config); /** * The link provider. - * + * * @type {LinkProvider} */ - this.provider = new LinkProvider(documentModule.provider, cityObjectModule.provider, this.service, config); + this.provider = new LinkProvider( + documentModule.provider, + cityObjectModule.provider, + this.service, + config + ); this.provider.fetchLinks().then(() => { - this.view = new LinkView(documentModule, cityObjectModule, this.provider, - itownsView, cameraControls); + this.view = new LinkView( + documentModule, + cityObjectModule, + this.provider, + itownsView, + cameraControls + ); }); documentModule.view.addEventListener(Window.EVENT_DISABLED, () => { if (!cityObjectModule.provider.getLayer()) { return; } - if (cityObjectModule.provider.getLayer().filter.label === 'linkDisplayedDoc') { + if ( + cityObjectModule.provider.getLayer().filter.label === 'linkDisplayedDoc' + ) { cityObjectModule.provider.removeLayer(); } }); } -} \ No newline at end of file +} diff --git a/src/Widgets/Links/Model/Link.js b/src/Widgets/Links/Model/Link.js index 853d22c7f..59fea25b4 100644 --- a/src/Widgets/Links/Model/Link.js +++ b/src/Widgets/Links/Model/Link.js @@ -1,7 +1,10 @@ /** * Represents a link between a document and a target (in this example, the * only valid target types are city objects). + * + * @format */ + export class Link { /** * Constructs an empty link. @@ -9,21 +12,21 @@ export class Link { constructor() { /** * The ID of the link. - * + * * @type {number} */ this.id; /** * The source (document) ID. - * + * * @type {number} */ this.source_id; /** * The target ID. For the moment, the only targets are city objects. - * + * * @type {number} */ this.target_id; @@ -31,7 +34,7 @@ export class Link { /** * The X coordinate of the centroid. The centroid must be stored in the * in order to travel to the city object. - * + * * @type {number} */ this.centroid_x; @@ -39,7 +42,7 @@ export class Link { /** * The Y coordinate of the centroid. The centroid must be stored in the * in order to travel to the city object. - * + * * @type {number} */ this.centroid_y; @@ -47,9 +50,9 @@ export class Link { /** * The Z coordinate of the centroid. The centroid must be stored in the * in order to travel to the city object. - * + * * @type {number} */ this.centroid_z; } -} \ No newline at end of file +} diff --git a/src/Widgets/Links/Model/LinkService.js b/src/Widgets/Links/Model/LinkService.js index 8d188002b..b5bf88025 100644 --- a/src/Widgets/Links/Model/LinkService.js +++ b/src/Widgets/Links/Model/LinkService.js @@ -1,7 +1,9 @@ +/** @format */ + //Components -import { RequestService } from "../../../Components/Request/RequestService"; +import { RequestService } from '../../../Components/Request/RequestService'; -import { Link } from "./Link"; +import { Link } from './Link'; /** * This class is used to perform requests concerning links. @@ -9,7 +11,7 @@ import { Link } from "./Link"; export class LinkService { /** * Creates a link service Service. - * + * * @param {RequestService} requestService The request service. * @param {object} config The UD-Viz config. * @param {object} config.server The server configuration. @@ -23,22 +25,22 @@ export class LinkService { this.requestService = requestService; /** - * GET url to retrieve supported link types. - * GET url/ to retrieve links of this type. - * POST url/ to create a link of this type. + * GET url to retrieve supported link types. + * GET url/ to retrieve links of this type. + * POST url/ to create a link of this type. */ this.linkURL = `${config.server.url}${config.server.link}`; } /** * Return supported link types. - * + * * @returns {Promise>} An array containing the supported link * types. */ async getSupportedLinkTypes() { let req = await this.requestService.request('GET', this.linkURL, { - authenticate: false + authenticate: false, }); let types = JSON.parse(req.response); return types; @@ -46,19 +48,19 @@ export class LinkService { /** * Retrieves all links matching the given link type and filters. - * + * * @param {string} linkType A supported link type. * @param {FormData} [filters] Filtering criteria for the link. Possible filters * are `source_id` (which must be a document id) and `target_id` (an ID of * type `linkType`). - * + * * @returns {Promise>} An array of links. */ async getLinks(linkType, filters = null) { const url = `${this.linkURL}/${linkType}`; let req = await this.requestService.request('GET', url, { authenticate: false, - urlParameters: filters + urlParameters: filters, }); let links = JSON.parse(req.response); return links; @@ -66,7 +68,7 @@ export class LinkService { /** * Creates a new link with the given type. - * + * * @param {string} linkType A supported link type. * @param {FormData} formData Properties of the created link. It must include * `source_id` (the document id) and `target_id` (ID of the target of type @@ -76,7 +78,7 @@ export class LinkService { const url = `${this.linkURL}/${linkType}`; let req = await this.requestService.request('POST', url, { authenticate: false, - body: formData + body: formData, }); let created = JSON.parse(req.response); return created; @@ -84,14 +86,14 @@ export class LinkService { /** * Deletes a link of the given type with the given ID. - * + * * @param {string} linkType A supported link type. * @param {number} linkId ID of the link to delete. */ async deleteLink(linkType, linkId) { const url = `${this.linkURL}/${linkType}/${linkId}`; let req = await this.requestService.request('DELETE', url, { - authenticate: false + authenticate: false, }); let deleted = JSON.parse(req.response); return deleted; diff --git a/src/Widgets/Links/View/CityObjectLinkInterface.js b/src/Widgets/Links/View/CityObjectLinkInterface.js index b7542b7af..12d9ca96a 100644 --- a/src/Widgets/Links/View/CityObjectLinkInterface.js +++ b/src/Widgets/Links/View/CityObjectLinkInterface.js @@ -1,9 +1,11 @@ -import { LinkService } from "../Model/LinkService"; -import { CityObjectModule } from "../../CityObjects/CityObjectModule"; -import { CityObjectFilterSelector } from "../../CityObjects/View/CityObjectFilterSelector"; -import { LinkProvider } from "../ViewModel/LinkProvider"; -import { CityObjectProvider } from "../../CityObjects/ViewModel/CityObjectProvider"; -import { LinkView } from "./LinkView"; +/** @format */ + +import { LinkService } from '../Model/LinkService'; +import { CityObjectModule } from '../../CityObjects/CityObjectModule'; +import { CityObjectFilterSelector } from '../../CityObjects/View/CityObjectFilterSelector'; +import { LinkProvider } from '../ViewModel/LinkProvider'; +import { CityObjectProvider } from '../../CityObjects/ViewModel/CityObjectProvider'; +import { LinkView } from './LinkView'; /** * The interface extensions for the city object window. @@ -11,7 +13,7 @@ import { LinkView } from "./LinkView"; export class CityObjectLinkInterface { /** * Constructs the city object link interface. - * + * * @param {LinkView} linkView The link view. * @param {CityObjectModule} cityObjectModule The city object module. * @param {LinkProvider} linkProvider The link service. @@ -28,7 +30,7 @@ export class CityObjectLinkInterface { // to show them in the document navigator. cityObjectModule.addExtension('links', { type: 'div', - html: /*html*/` + html: /*html*/ `
          @@ -39,18 +41,20 @@ export class CityObjectLinkInterface { linkView.requestDisplayDocuments(); linkProvider.toggleLinkedDocumentsFilter(true); }; - } + }, }); /** * The link provider. - * + * * @type {LinkProvider} */ this.linkProvider = linkProvider; - this.linkProvider.addEventListener(CityObjectProvider.EVENT_CITY_OBJECT_SELECTED, - () => this._updateLinkList()); + this.linkProvider.addEventListener( + CityObjectProvider.EVENT_CITY_OBJECT_SELECTED, + () => this._updateLinkList() + ); } /** @@ -61,7 +65,7 @@ export class CityObjectLinkInterface { return; } let docs = this.linkProvider.getSelectedCityObjectLinkedDocuments(); - let listHtml = `

          ${docs.length} linked document(s)

          ` + let listHtml = `

          ${docs.length} linked document(s)

          `; if (docs.length > 0) { listHtml += `

            `; for (let doc of docs) { @@ -99,7 +103,7 @@ export class CityObjectLinkInterface { export class LinkCountFilterSelector extends CityObjectFilterSelector { /** * Creates the filter selector. - * + * * @param {LinkProvider} linkProvider The link provider. */ constructor(linkProvider) { @@ -112,7 +116,7 @@ export class LinkCountFilterSelector extends CityObjectFilterSelector { } get html() { - return /*html*/` + return /*html*/ ` `; @@ -121,4 +125,4 @@ export class LinkCountFilterSelector extends CityObjectFilterSelector { onSubmit(formData) { this.filter.requiredCount = Number(formData.get('requiredCount')) || 1; } -} \ No newline at end of file +} diff --git a/src/Widgets/Links/View/DocumentLinkInterface.js b/src/Widgets/Links/View/DocumentLinkInterface.js index 5a699d2f2..d3baac9ad 100644 --- a/src/Widgets/Links/View/DocumentLinkInterface.js +++ b/src/Widgets/Links/View/DocumentLinkInterface.js @@ -1,11 +1,13 @@ +/** @format */ + //Components -import { focusCameraOn } from "../../../Components/Camera/CameraUtils"; +import { focusCameraOn } from '../../../Components/Camera/CameraUtils'; -import { DocumentModule } from "../../Documents/DocumentModule"; +import { DocumentModule } from '../../Documents/DocumentModule'; import * as THREE from 'three'; -import { DocumentProvider } from "../../Documents/ViewModel/DocumentProvider"; -import { Link } from "../Model/Link"; -import { LinkProvider } from "../ViewModel/LinkProvider"; +import { DocumentProvider } from '../../Documents/ViewModel/DocumentProvider'; +import { Link } from '../Model/Link'; +import { LinkProvider } from '../ViewModel/LinkProvider'; /** * The interface extensions for the document windows. @@ -13,7 +15,7 @@ import { LinkProvider } from "../ViewModel/LinkProvider"; export class DocumentLinkInterface { /** * Constructs the document link interface. - * + * * @param {DocumentModule} documentModule The document module. * @param {LinkProvider} linkProvider The link provider. * @param {*} itownsView The iTowns view. @@ -22,14 +24,14 @@ export class DocumentLinkInterface { constructor(documentModule, linkProvider, itownsView, cameraControls) { /** * The link provider. - * + * * @type {LinkProvider} */ this.provider = linkProvider; /** * The list of links for the currently displayed document. - * + * * @type {Array} */ this.documentLinks = []; @@ -38,18 +40,18 @@ export class DocumentLinkInterface { * The itowns view. */ this.itownsView = itownsView; - + /** * The planar camera controls. */ this.cameraControls = cameraControls; // Adds the extension for the displayed documents. This extension shows the - // links and adds two buttons to highlight the linked city objects, and + // links and adds two buttons to highlight the linked city objects, and // create a new link. documentModule.addInspectorExtension('links', { type: 'div', - html: /*html*/` + html: /*html*/ `
            @@ -59,7 +61,7 @@ export class DocumentLinkInterface {
            `, - oncreated: () => this._init() + oncreated: () => this._init(), }); // Adds an extension in the navigator window to show the status of the @@ -68,18 +70,23 @@ export class DocumentLinkInterface { documentModule.addNavigatorExtension('linkFilter', { type: 'div', container: 'filter', - html: /*html*/` + html: /*html*/ ` `, oncreated: () => { - this.linkFilterElement.onchange = () => this.provider.toggleLinkedDocumentsFilter(); - } + this.linkFilterElement.onchange = () => + this.provider.toggleLinkedDocumentsFilter(); + }, }); - linkProvider.addEventListener(DocumentProvider.EVENT_FILTERED_DOCS_UPDATED, - () => this._updateLinkFilter()); + linkProvider.addEventListener( + DocumentProvider.EVENT_FILTERED_DOCS_UPDATED, + () => this._updateLinkFilter() + ); - linkProvider.addEventListener(DocumentProvider.EVENT_DISPLAYED_DOC_CHANGED, - () => this._updateLinkList()); + linkProvider.addEventListener( + DocumentProvider.EVENT_DISPLAYED_DOC_CHANGED, + () => this._updateLinkList() + ); } /** @@ -95,11 +102,16 @@ export class DocumentLinkInterface { if (!!this.provider.selectedCityObject) { let newLink = new Link(); newLink.source_id = this.provider.displayedDocument.id; - newLink.target_id = this.provider.selectedCityObject.props['cityobject.database_id']; + newLink.target_id = + this.provider.selectedCityObject.props['cityobject.database_id']; newLink.centroid_x = this.provider.selectedCityObject.centroid.x; newLink.centroid_y = this.provider.selectedCityObject.centroid.y; newLink.centroid_z = this.provider.selectedCityObject.centroid.z; - if (confirm('Are you sure you want to associate the document with this city object ?')) { + if ( + confirm( + 'Are you sure you want to associate the document with this city object ?' + ) + ) { try { await this.provider.createLink(newLink); } catch (e) { @@ -145,10 +157,14 @@ export class DocumentLinkInterface { for (let link of links) { newDivHtml += `
          • ID : ${link.target_id} - + travel - + delete
          • `; @@ -167,25 +183,28 @@ export class DocumentLinkInterface { } } - //////////////////// ///// LINK OPERATION /** * If the target is a city object, moves the camera to focus on its centroid. - * + * * @param {Link} link The link to travel to. */ async _travelToLink(link) { - let centroid = new THREE.Vector3(link.centroid_x, link.centroid_y, - link.centroid_z); - await focusCameraOn(this.itownsView, this.cameraControls, centroid, - {duration: 1}); + let centroid = new THREE.Vector3( + link.centroid_x, + link.centroid_y, + link.centroid_z + ); + await focusCameraOn(this.itownsView, this.cameraControls, centroid, { + duration: 1, + }); } /** * Deletes the link. - * + * * @param {Link} link The link to delete. */ async _deleteLink(link) { diff --git a/src/Widgets/Links/View/LinkView.js b/src/Widgets/Links/View/LinkView.js index 803be9b8b..57b9aaa17 100644 --- a/src/Widgets/Links/View/LinkView.js +++ b/src/Widgets/Links/View/LinkView.js @@ -1,12 +1,14 @@ -import { DocumentModule } from "../../Documents/DocumentModule"; -import { CityObjectModule } from "../../CityObjects/CityObjectModule"; -import { LinkService } from "../Model/LinkService"; -import { DocumentLinkInterface } from "./DocumentLinkInterface"; -import { CityObjectLinkInterface } from "./CityObjectLinkInterface"; -import { DocumentInspectorWindow } from "../../Documents/View/DocumentInspectorWindow"; -import { LinkProvider } from "../ViewModel/LinkProvider"; -import { DocumentView } from "../../Documents/View/DocumentView"; -import { CityObjectWindow } from "../../CityObjects/View/CityObjectWindow"; +/** @format */ + +import { DocumentModule } from '../../Documents/DocumentModule'; +import { CityObjectModule } from '../../CityObjects/CityObjectModule'; +import { LinkService } from '../Model/LinkService'; +import { DocumentLinkInterface } from './DocumentLinkInterface'; +import { CityObjectLinkInterface } from './CityObjectLinkInterface'; +import { DocumentInspectorWindow } from '../../Documents/View/DocumentInspectorWindow'; +import { LinkProvider } from '../ViewModel/LinkProvider'; +import { DocumentView } from '../../Documents/View/DocumentView'; +import { CityObjectWindow } from '../../CityObjects/View/CityObjectWindow'; /** * Represents the visual interface of the link module. This class contains @@ -16,45 +18,56 @@ import { CityObjectWindow } from "../../CityObjects/View/CityObjectWindow"; export class LinkView { /** * Constructs the link view. - * + * * @param {DocumentModule} documentModule The document module. * @param {CityObjectModule} cityObjectModule The city object module. * @param {LinkProvider} linkProvider The link service. * @param {*} itownsView The iTowns view. - * @param {*} cameraControls The planar camera controls + * @param {*} cameraControls The planar camera controls */ - constructor(documentModule, cityObjectModule, linkProvider, itownsView, - cameraControls) { - + constructor( + documentModule, + cityObjectModule, + linkProvider, + itownsView, + cameraControls + ) { /** * A reference to the document view. - * + * * @type {DocumentView} */ this.documentView = documentModule.view; /** * A reference to the city object window. - * + * * @type {CityObjectWindow} */ this.cityObjectView = cityObjectModule.view; /** * The interface extensions for the document module. - * + * * @type {DocumentLinkInterface} */ - this.documentInterface = new DocumentLinkInterface(documentModule, - linkProvider, itownsView, cameraControls); + this.documentInterface = new DocumentLinkInterface( + documentModule, + linkProvider, + itownsView, + cameraControls + ); /** * The interface extensions for the city object module. - * + * * @type {CityObjectLinkInterface} */ - this.cityObjectInterface = new CityObjectLinkInterface(this, - cityObjectModule, linkProvider); + this.cityObjectInterface = new CityObjectLinkInterface( + this, + cityObjectModule, + linkProvider + ); } /** @@ -70,4 +83,4 @@ export class LinkView { requestDisplayCityObjects() { this.cityObjectView.enable(); } -} \ No newline at end of file +} diff --git a/src/Widgets/Links/ViewModel/CityObjectLinkFilters.js b/src/Widgets/Links/ViewModel/CityObjectLinkFilters.js index 0aa4a7ac3..37aaf115d 100644 --- a/src/Widgets/Links/ViewModel/CityObjectLinkFilters.js +++ b/src/Widgets/Links/ViewModel/CityObjectLinkFilters.js @@ -1,8 +1,10 @@ +/** @format */ + //Components -import { CityObject } from "../../../Components/3DTiles/Model/CityObject"; +import { CityObject } from '../../../Components/3DTiles/Model/CityObject'; -import { CityObjectFilter } from "../../CityObjects/ViewModel/CityObjectFilter"; -import { LinkProvider } from "./LinkProvider"; +import { CityObjectFilter } from '../../CityObjects/ViewModel/CityObjectFilter'; +import { LinkProvider } from './LinkProvider'; /** * A filter for city objects based how many documents are linked to them. @@ -10,7 +12,7 @@ import { LinkProvider } from "./LinkProvider"; export class LinkCountFilter extends CityObjectFilter { /** * Instantiates the filter. - * + * * @param {LinkProvider} linkProvider The link provider. */ constructor(linkProvider) { @@ -23,7 +25,7 @@ export class LinkCountFilter extends CityObjectFilter { /** * The link provider - * + * * @type {LinkProvider} */ this.provider = linkProvider; @@ -32,8 +34,8 @@ export class LinkCountFilter extends CityObjectFilter { /** * Accepts city objects that have at least `this.requiredCount` linked * documents. - * - * @param {CityObject} cityObject + * + * @param {CityObject} cityObject */ accepts(cityObject) { let linkCount = this.provider.getLinksFromCityObject(cityObject).length; @@ -56,7 +58,7 @@ export class LinkCountFilter extends CityObjectFilter { export class LinkedWithDisplayedDocumentFilter extends CityObjectFilter { /** * Instantiates the filter. - * + * * @param {LinkProvider} linkProvider The link provider. */ constructor(linkProvider) { @@ -64,7 +66,7 @@ export class LinkedWithDisplayedDocumentFilter extends CityObjectFilter { /** * The link provider. - * + * * @type {LinkProvider} */ this.provider = linkProvider; @@ -72,12 +74,15 @@ export class LinkedWithDisplayedDocumentFilter extends CityObjectFilter { /** * Accepts city objects that are linked with the currently displayed document. - * - * @param {CityObject} cityObject + * + * @param {CityObject} cityObject */ accepts(cityObject) { - let found = this.provider.getDisplayedDocumentLinks().find((link) => - link.target_id == cityObject.props['cityobject.database_id']); + let found = this.provider + .getDisplayedDocumentLinks() + .find( + (link) => link.target_id == cityObject.props['cityobject.database_id'] + ); return !!found; } @@ -93,7 +98,7 @@ export class LinkedWithDisplayedDocumentFilter extends CityObjectFilter { export class LinkedWithFilteredDocumentsFilter extends CityObjectFilter { /** * Instantiates the filter. - * + * * @param {LinkProvider} linkProvider The link provider. */ constructor(linkProvider) { @@ -101,7 +106,7 @@ export class LinkedWithFilteredDocumentsFilter extends CityObjectFilter { /** * The link provider. - * + * * @type {LinkProvider} */ this.provider = linkProvider; @@ -109,16 +114,19 @@ export class LinkedWithFilteredDocumentsFilter extends CityObjectFilter { /** * Accepts city objects that are linked with the currently filtered documents. - * - * @param {CityObject} cityObject + * + * @param {CityObject} cityObject */ accepts(cityObject) { - let found = this.provider.getFilteredDocumentsLinks().find((link) => - link.target_id == cityObject.props['cityobject.database_id']); + let found = this.provider + .getFilteredDocumentsLinks() + .find( + (link) => link.target_id == cityObject.props['cityobject.database_id'] + ); return !!found; } toString() { return 'Linked to the filtered documents'; } -} \ No newline at end of file +} diff --git a/src/Widgets/Links/ViewModel/LinkProvider.js b/src/Widgets/Links/ViewModel/LinkProvider.js index 1a0d86a05..2e684b2c2 100644 --- a/src/Widgets/Links/ViewModel/LinkProvider.js +++ b/src/Widgets/Links/ViewModel/LinkProvider.js @@ -1,16 +1,21 @@ -//Components -import { CityObject } from "../../../Components/3DTiles/Model/CityObject"; -import { EventSender } from "../../../Components/Events/EventSender"; -import { CityObjectStyle } from "../../../Components/3DTiles/Model/CityObjectStyle"; - -import { LinkService } from "../Model/LinkService"; -import { DocumentProvider } from "../../Documents/ViewModel/DocumentProvider"; -import { CityObjectProvider } from "../../CityObjects/ViewModel/CityObjectProvider"; -import { Link } from "../Model/Link"; -import { Document } from "../../Documents/Model/Document"; -import { LinkCountFilter, LinkedWithDisplayedDocumentFilter, LinkedWithFilteredDocumentsFilter } from "./CityObjectLinkFilters"; -import { DocumentFilter } from "../../Documents/ViewModel/DocumentFilter"; +/** @format */ +//Components +import { CityObject } from '../../../Components/3DTiles/Model/CityObject'; +import { EventSender } from '../../../Components/Events/EventSender'; +import { CityObjectStyle } from '../../../Components/3DTiles/Model/CityObjectStyle'; + +import { LinkService } from '../Model/LinkService'; +import { DocumentProvider } from '../../Documents/ViewModel/DocumentProvider'; +import { CityObjectProvider } from '../../CityObjects/ViewModel/CityObjectProvider'; +import { Link } from '../Model/Link'; +import { Document } from '../../Documents/Model/Document'; +import { + LinkCountFilter, + LinkedWithDisplayedDocumentFilter, + LinkedWithFilteredDocumentsFilter, +} from './CityObjectLinkFilters'; +import { DocumentFilter } from '../../Documents/ViewModel/DocumentFilter'; /** * The link provider is responsible to manage links fetched from the server, @@ -21,7 +26,7 @@ import { DocumentFilter } from "../../Documents/ViewModel/DocumentFilter"; export class LinkProvider extends EventSender { /** * Constructs the link provider. - * + * * @param {DocumentProvider} documentProvider The document provider. * @param {CityObjectProvider} cityObjectProvider The city object provider. * @param {LinkService} linkService The link service. @@ -38,28 +43,28 @@ export class LinkProvider extends EventSender { /** * The link service. - * + * * @type {LinkService} */ this.linkService = linkService; /** * The document provider. - * + * * @type {DocumentProvider} */ this.documentProvider = documentProvider; /** * The city object provider. - * + * * @type {CityObjectProvider} */ this.cityObjectProvider = cityObjectProvider; /** * A filter for city objects based on their count of linked documents. - * + * * @type {LinkCountFilter} */ this.linkCountFilter = new LinkCountFilter(this); @@ -68,27 +73,32 @@ export class LinkProvider extends EventSender { /** * A filter for city objects based on wether they are linked with the * currently displayed document. - * + * * @type {LinkedWithDisplayedDocumentFilter} */ - this.linkedWithDisplayedDocFilter = new LinkedWithDisplayedDocumentFilter(this); + this.linkedWithDisplayedDocFilter = new LinkedWithDisplayedDocumentFilter( + this + ); this.cityObjectProvider.addFilter(this.linkedWithDisplayedDocFilter); /** * The style for city objects linked with the displayed document. - * + * * @type {CityObjectStyle} */ - this.linkDisplayedDocumentStyle = config.cityObjects.styles.linkedWithDisplayedDocument; + this.linkDisplayedDocumentStyle = + config.cityObjects.styles.linkedWithDisplayedDocument; /** * A filter for city objects based on wether they are linked with any of the * currently filtered documents (ie. the list of documents that appear in * the navigator). - * + * * @type {LinkedWithFilteredDocumentsFilter} */ - this.linkedWithFilteredDocsFilter = new LinkedWithFilteredDocumentsFilter(this); + this.linkedWithFilteredDocsFilter = new LinkedWithFilteredDocumentsFilter( + this + ); this.cityObjectProvider.addFilter(this.linkedWithFilteredDocsFilter); // The following adds a filter for documents, based on wether they are @@ -98,58 +108,62 @@ export class LinkProvider extends EventSender { * This value determines wether the filter is active. */ this.shouldFilterLinkedDocuments = false; - this.documentProvider.addFilter(new DocumentFilter((doc) => { - return !this.shouldFilterLinkedDocuments || - this.selectedCityObjectLinks.find(link => link.source_id === doc.id); - })); + this.documentProvider.addFilter( + new DocumentFilter((doc) => { + return ( + !this.shouldFilterLinkedDocuments || + this.selectedCityObjectLinks.find((link) => link.source_id === doc.id) + ); + }) + ); this.documentProvider.refreshDocumentList(); /** * The cached list of links. - * + * * @type {Array} */ this.links = []; /** * The currently displayed document. - * + * * @type {Document} */ this.displayedDocument = undefined; /** * The links of the currently displayed document. - * + * * @type {Array} */ this.displayedDocumentLinks = []; /** * The list of filtered documents. - * + * * @type {Array} */ this.filteredDocuments = []; /** * The links of the filtered documents. - * + * * @type {Array} */ this.filteredDocumentsLinks = []; /** * The currently selected city object. - * + * * @type {CityObject} */ this.selectedCityObject = undefined; /** * The links of the currently selected city object. - * + * * @type {Array} */ this.selectedCityObjectLinks = []; @@ -160,21 +174,27 @@ export class LinkProvider extends EventSender { this.registerEvent(DocumentProvider.EVENT_FILTERED_DOCS_UPDATED); this.registerEvent(CityObjectProvider.EVENT_CITY_OBJECT_SELECTED); - this.documentProvider.addEventListener(DocumentProvider.EVENT_DISPLAYED_DOC_CHANGED, - (doc) => this._onDisplayedDocumentChange(doc)); + this.documentProvider.addEventListener( + DocumentProvider.EVENT_DISPLAYED_DOC_CHANGED, + (doc) => this._onDisplayedDocumentChange(doc) + ); - this.documentProvider.addEventListener(DocumentProvider.EVENT_FILTERED_DOCS_UPDATED, - (docs) => this._onFilteredDocumentsUpdate(docs)); + this.documentProvider.addEventListener( + DocumentProvider.EVENT_FILTERED_DOCS_UPDATED, + (docs) => this._onFilteredDocumentsUpdate(docs) + ); - this.cityObjectProvider.addEventListener(CityObjectProvider.EVENT_CITY_OBJECT_SELECTED, - (co) => this._onCityObjectSelection(co)); + this.cityObjectProvider.addEventListener( + CityObjectProvider.EVENT_CITY_OBJECT_SELECTED, + (co) => this._onCityObjectSelection(co) + ); } /** * Triggers when the displayed document changed. Updates the displayed * document reference in the link provider and re-applies the styles for the * city objects. The event is propagated. - * + * * @param {Document} doc The newly displayed document. */ _onDisplayedDocumentChange(doc) { @@ -188,7 +208,7 @@ export class LinkProvider extends EventSender { * Triggers when the filtered documents change. Updates the filtered document * and their links in the provider, and re-applies the styles for the city * objects. The event is propagated. - * + * * @param {Array} docs The newly filtered documents. */ _onFilteredDocumentsUpdate(docs) { @@ -202,7 +222,7 @@ export class LinkProvider extends EventSender { * Triggers when a city object is selected. Updates the city object and its * links in the provider, and refreshes the list of documents. The event is * propagated. - * + * * @param {CityObject} co The newly selected city object. */ _onCityObjectSelection(co) { @@ -216,7 +236,7 @@ export class LinkProvider extends EventSender { /** * Fetches the links from the server. - * + * * @async */ async fetchLinks() { @@ -228,7 +248,7 @@ export class LinkProvider extends EventSender { /** * Deletes the link. - * + * * @async * @param {Link} link The link to delete. */ @@ -239,7 +259,7 @@ export class LinkProvider extends EventSender { /** * Creates a new link. - * + * * @param {Link} link The link to create. */ async createLink(link) { @@ -255,7 +275,7 @@ export class LinkProvider extends EventSender { /** * Returns the cached list of links. - * + * * @returns {Array} The cached list of links. */ getLinks() { @@ -264,27 +284,29 @@ export class LinkProvider extends EventSender { /** * Returns the links from a list of documents. - * + * * @param {Array} docs A list of documents. */ getLinksFromDocuments(docs) { - return this.links.filter((link) => - docs.find((doc) => doc.id == link.source_id) !== undefined); + return this.links.filter( + (link) => docs.find((doc) => doc.id == link.source_id) !== undefined + ); } /** * Returns the links from a city object. - * + * * @param {CityObject} cityObject The city object. */ getLinksFromCityObject(cityObject) { - return this.links.filter((link) => - link.target_id == cityObject.props['cityobject.database_id']); + return this.links.filter( + (link) => link.target_id == cityObject.props['cityobject.database_id'] + ); } /** * Returns the links from the displayed document. - * + * * @returns {Array} The list of links. */ getDisplayedDocumentLinks() { @@ -293,7 +315,7 @@ export class LinkProvider extends EventSender { /** * Returns the links from the filtered documents. - * + * * @returns {Array} The list of links. */ getFilteredDocumentsLinks() { @@ -302,7 +324,7 @@ export class LinkProvider extends EventSender { /** * Returns the links from the selected city object. - * + * * @returns {Array} The list of links. */ getSelectedCityObjectLinks() { @@ -311,19 +333,21 @@ export class LinkProvider extends EventSender { /** * Returns the list of documents linked to the selected city object. - * + * * @returns {Array} The list of linked documents. */ getSelectedCityObjectLinkedDocuments() { let allDocuments = this.documentProvider.getAllDocuments().slice(); - let docIdsToFind = this.selectedCityObjectLinks.map(link => link.source_id); - return allDocuments.filter(doc => docIdsToFind.includes(doc.id)); + let docIdsToFind = this.selectedCityObjectLinks.map( + (link) => link.source_id + ); + return allDocuments.filter((doc) => docIdsToFind.includes(doc.id)); } /** * Toggles the filter for the documents, based on wether they are linked with * the selected city object. - * + * * @param {Boolean} [toggle] The desired value (`true` activates the filter). * If not specified, the activation state of the filter is simply negated (ie. * if the filter was active, it is now inactive and vice-versa) @@ -340,13 +364,18 @@ export class LinkProvider extends EventSender { * Filters the city objects that are linked with the displayed document. */ highlightDisplayedDocumentLinks() { - this.cityObjectProvider.setLayer('linkDisplayedDoc', this.linkDisplayedDocumentStyle); + this.cityObjectProvider.setLayer( + 'linkDisplayedDoc', + this.linkDisplayedDocumentStyle + ); } /** * Filters the city objects that are linked with the filtered document. */ highlightFilteredDocumentsLinks() { - this.cityObjectProvider.setLayer('linkFilteredDocs', {materialProps: {color: 'blue'}}); + this.cityObjectProvider.setLayer('linkFilteredDocs', { + materialProps: { color: 'blue' }, + }); } -} \ No newline at end of file +} diff --git a/src/Widgets/Others/About.css b/src/Widgets/Others/About.css index f145d65e8..c9d65097b 100644 --- a/src/Widgets/Others/About.css +++ b/src/Widgets/Others/About.css @@ -1,30 +1,31 @@ +/** @format */ #aboutWindow { - position: absolute; - z-index: 11; - top: 10px; - width: 15%; - right : 22.5%; - color: white; - font-size: 75%; - padding: 0 1rem; - background-color: rgba(30,30,30,0.6); - border : 1px solid rgb(90,90,90); - pointer-events: auto; + position: absolute; + z-index: 11; + top: 10px; + width: 15%; + right: 22.5%; + color: white; + font-size: 75%; + padding: 0 1rem; + background-color: rgba(30, 30, 30, 0.6); + border: 1px solid rgb(90, 90, 90); + pointer-events: auto; } #aboutWindow > div > ul { - padding-left: 5px; + padding-left: 5px; } -#aboutCloseButton{ - position: absolute; - z-index: 40; - top: 0; - right: 3px; - margin : 3px; - border: 1px solid black; - background-color: white; - color: black; - pointer-events: auto; +#aboutCloseButton { + position: absolute; + z-index: 40; + top: 0; + right: 3px; + margin: 3px; + border: 1px solid black; + background-color: white; + color: black; + pointer-events: auto; } diff --git a/src/Widgets/Others/About.js b/src/Widgets/Others/About.js index fbb0be41b..265323ec4 100644 --- a/src/Widgets/Others/About.js +++ b/src/Widgets/Others/About.js @@ -1,3 +1,5 @@ +/** @format */ + //Components import { ModuleView } from '../../Components/ModuleView/ModuleView'; @@ -8,17 +10,16 @@ import './About.css'; * simply include this file in the html, no need to instanciate anything in main.js */ export class AboutWindow extends ModuleView { + constructor() { + super(); + // Create DOM element + let aboutDiv = document.createElement('div'); + aboutDiv.id = 'aboutWindow'; + document.getElementById('contentSection').append(aboutDiv); - constructor(options = {}) { - super(); - // Create DOM element - let aboutDiv = document.createElement("div"); - aboutDiv.id = 'aboutWindow'; - document.getElementById('contentSection').append(aboutDiv); - - // Create HMTL - document.getElementById("aboutWindow").innerHTML = - '
            \ + // Create HMTL + document.getElementById('aboutWindow').innerHTML = + '
            \
            \

            This UD-Viz-Core demo is part of the \ \

          • iTowns
          • \
          • Lyon Métropole Open\ Data
          • \ + href="https://data.grandlyon.com">Lyon Métropole Open Data\
          \

          \

          Legal and operational disclaimer: This demonstration\ @@ -75,19 +76,24 @@ export class AboutWindow extends ModuleView { \ '; - // Close the window...when close button is hit - document.getElementById("aboutCloseButton").addEventListener( - 'mousedown', () => { - this.disable(); - }, false); - } + // Close the window...when close button is hit + document.getElementById('aboutCloseButton').addEventListener( + 'mousedown', + () => { + this.disable(); + }, + false + ); + } - /////// MODULE VIEW MANAGEMENT - enableView() { - document.getElementById('aboutWindow').style.setProperty('display', 'block'); - } + /////// MODULE VIEW MANAGEMENT + enableView() { + document + .getElementById('aboutWindow') + .style.setProperty('display', 'block'); + } - disableView() { - document.getElementById('aboutWindow').style.setProperty('display', 'none'); - } + disableView() { + document.getElementById('aboutWindow').style.setProperty('display', 'none'); + } } diff --git a/src/Widgets/Others/Help.css b/src/Widgets/Others/Help.css index 0c84fa91a..01d0f5fa7 100644 --- a/src/Widgets/Others/Help.css +++ b/src/Widgets/Others/Help.css @@ -1,39 +1,41 @@ +/** @format */ + #helpWindow { - position: absolute; - z-index: 10; - width: 15%; - top: 10px; - left : 22.5%; - color: white; - font-size: 75%; - padding: 0 1rem; - background-color: rgba(30,30,30,0.6); - border : 1px solid rgb(90,90,90); - pointer-events: auto; + position: absolute; + z-index: 10; + width: 15%; + top: 10px; + left: 22.5%; + color: white; + font-size: 75%; + padding: 0 1rem; + background-color: rgba(30, 30, 30, 0.6); + border: 1px solid rgb(90, 90, 90); + pointer-events: auto; } #helpWindow > div > ul { - padding-left: 5px; + padding-left: 5px; } -#helpCloseButton{ - position: absolute; - z-index: 40; - top: 0; - right: 3px; - margin : 3px; - border: 1px solid black; - background-color: white; - color: black; - pointer-events: auto; +#helpCloseButton { + position: absolute; + z-index: 40; + top: 0; + right: 3px; + margin: 3px; + border: 1px solid black; + background-color: white; + color: black; + pointer-events: auto; } @media (max-width: 600px) { - #helpWindow { - display: none; - } + #helpWindow { + display: none; + } } hr { - color: white; + color: white; } diff --git a/src/Widgets/Others/Help.js b/src/Widgets/Others/Help.js index 729416bfa..3abf14592 100644 --- a/src/Widgets/Others/Help.js +++ b/src/Widgets/Others/Help.js @@ -1,24 +1,25 @@ +/** @format */ + //Components import { ModuleView } from '../../Components/ModuleView/ModuleView'; import './Help.css'; /** -* adds a "Help" window that can be open/closed with a button -* simply include this file in the html, no need to instanciate anything in main.js -*/ + * adds a "Help" window that can be open/closed with a button + * simply include this file in the html, no need to instanciate anything in main.js + */ export class HelpWindow extends ModuleView { - - constructor(options = {}) { + constructor() { super(); ///////////// Html elements - var helpDiv = document.createElement("div"); + var helpDiv = document.createElement('div'); helpDiv.id = 'helpWindow'; document.getElementById('contentSection').append(helpDiv); - document.getElementById("helpWindow").innerHTML = + document.getElementById('helpWindow').innerHTML = '

          \
          \

          { + document.getElementById('helpCloseButton').addEventListener( + 'mousedown', + () => { this.disable(); - }, false); + }, + false + ); } - /////// MODULE VIEW METHODS enableView() { diff --git a/src/Widgets/Temporal/Model/3DTemporalBatchTable.js b/src/Widgets/Temporal/Model/3DTemporalBatchTable.js index 57aa025ae..f965e8024 100644 --- a/src/Widgets/Temporal/Model/3DTemporalBatchTable.js +++ b/src/Widgets/Temporal/Model/3DTemporalBatchTable.js @@ -1,70 +1,90 @@ /** * Implements the batch table of the 3DTILES_temporal - * extension. See the spec in + * extension. See the spec in * ./jsonSchemas/3DTILES_temporal.batchTable.schema.json + * + * @format */ + export class $3DTemporalBatchTable { - /** - * Verifies the integrity and stores the data corresponding to the - * batch table part of the 3DTiles_temporal extension. - * @param {Object} json The json containing the 3DTiles_temporal - * extension batch table part for a given tile. - */ - constructor(json) { - // Poor verification that the handled json corresponds to the temporal - // extension spec. Should be done by comparing it with the JSON schema. - if (!json.startDates || !Array.isArray(json.startDates)) { - console.error("3D Tiles batch table temporal extension requires " + - "a startDates array. Refer to the spec."); - } - if (!json.endDates || !Array.isArray(json.endDates)) { - console.error("3D Tiles batch table temporal extension requires " + - "an endDates array. Refer to the spec."); - } - if (!json.featureIds || !Array.isArray(json.featureIds)) { - console.error("3D Tiles batch table temporal extension requires " + - "a featureIds array. Refer to the spec."); - } - if (json.startDates.length !== json.endDates.length || - json.startDates.length !== json.featureIds.length) { - console.error("3D Tiles temporal extensions arrays startDates " + - "(length: " + json.startDates.length + "), endDates (length: " + - json.endDates.length + ") and json.featureIds (length: " + - json.featureIds.length + ") must be the same length."); - } - - this.startDates = json.startDates; - this.endDates = json.endDates; - this.featureIds = json.featureIds; + /** + * Verifies the integrity and stores the data corresponding to the + * batch table part of the 3DTiles_temporal extension. + * @param {Object} json The json containing the 3DTiles_temporal + * extension batch table part for a given tile. + */ + constructor(json) { + // Poor verification that the handled json corresponds to the temporal + // extension spec. Should be done by comparing it with the JSON schema. + if (!json.startDates || !Array.isArray(json.startDates)) { + console.error( + '3D Tiles batch table temporal extension requires ' + + 'a startDates array. Refer to the spec.' + ); } - - /** - * Checks that the batch table temporal extension has values for a given - * identifier. - * @param {Number} batchId The identifier to check (identifier in the batch, - * i.e. position in the arrays). - */ - hasInfoForId(batchId) { - // The constructor ensures that the three arrays have the same size. - return !!this.startDates[batchId]; + if (!json.endDates || !Array.isArray(json.endDates)) { + console.error( + '3D Tiles batch table temporal extension requires ' + + 'an endDates array. Refer to the spec.' + ); + } + if (!json.featureIds || !Array.isArray(json.featureIds)) { + console.error( + '3D Tiles batch table temporal extension requires ' + + 'a featureIds array. Refer to the spec.' + ); } + if ( + json.startDates.length !== json.endDates.length || + json.startDates.length !== json.featureIds.length + ) { + console.error( + '3D Tiles temporal extensions arrays startDates ' + + '(length: ' + + json.startDates.length + + '), endDates (length: ' + + json.endDates.length + + ') and json.featureIds (length: ' + + json.featureIds.length + + ') must be the same length.' + ); + } + + this.startDates = json.startDates; + this.endDates = json.endDates; + this.featureIds = json.featureIds; + } + + /** + * Checks that the batch table temporal extension has values for a given + * identifier. + * @param {Number} batchId The identifier to check (identifier in the batch, + * i.e. position in the arrays). + */ + hasInfoForId(batchId) { + // The constructor ensures that the three arrays have the same size. + return !!this.startDates[batchId]; + } - /** - * Returns information for the given batchId. - * Can be used to display information associated with an object - * picked with the mouse for instance. - * @param {*} batchId The given identifier (identifier in the batch, - * i.e. position in the arrays). - */ - getInfoById(batchId) { - if (!this.hasInfoForId(batchId)) { - console.error("3D Tiles batch table temporal extension does not " + - "have information for batch ID " + batchId); - } - return { - 'featureId': this.featureIds[batchId], - 'startDate': this.startDates[batchId], - 'endDate': this.endDates[batchId] - }; + /** + * Returns information for the given batchId. + * Can be used to display information associated with an object + * picked with the mouse for instance. + * @param {*} batchId The given identifier (identifier in the batch, + * i.e. position in the arrays). + */ + getInfoById(batchId) { + if (!this.hasInfoForId(batchId)) { + console.error( + '3D Tiles batch table temporal extension does not ' + + 'have information for batch ID ' + + batchId + ); } -} \ No newline at end of file + return { + featureId: this.featureIds[batchId], + startDate: this.startDates[batchId], + endDate: this.endDates[batchId], + }; + } +} diff --git a/src/Widgets/Temporal/Model/3DTemporalBoundingVolume.js b/src/Widgets/Temporal/Model/3DTemporalBoundingVolume.js index a5d518c95..8b3c770a4 100644 --- a/src/Widgets/Temporal/Model/3DTemporalBoundingVolume.js +++ b/src/Widgets/Temporal/Model/3DTemporalBoundingVolume.js @@ -1,25 +1,32 @@ /** * Implements the bounding volume part of the 3DTILES_temporal - * extension. See the spec in + * extension. See the spec in * ./jsonSchemas/3DTILES_temporal.boundingVolume.schema.json + * + * @format */ + export class $3DTemporalBoundingVolume { - /** - * Verifies the integrity and stores the data corresponding to the - * bounding volume part of the 3DTiles_temporal extension. - * @param {Object} json The json containing the 3DTiles_temporal - * extension bounding volume part for a given tile. - */ - constructor(json) { - if (!json.startDate) { - console.error("3D Tiles bounding volume temporal extension " + - "requires a startDate. Refer to the spec."); - } - if (!json.endDate) { - console.error("3D Tiles bounding volume temporal extension " + - "requires an endDate. Refer to the spec."); - } - this.startDate = json.startDate; - this.endDate = json.endDate; + /** + * Verifies the integrity and stores the data corresponding to the + * bounding volume part of the 3DTiles_temporal extension. + * @param {Object} json The json containing the 3DTiles_temporal + * extension bounding volume part for a given tile. + */ + constructor(json) { + if (!json.startDate) { + console.error( + '3D Tiles bounding volume temporal extension ' + + 'requires a startDate. Refer to the spec.' + ); } + if (!json.endDate) { + console.error( + '3D Tiles bounding volume temporal extension ' + + 'requires an endDate. Refer to the spec.' + ); + } + this.startDate = json.startDate; + this.endDate = json.endDate; + } } diff --git a/src/Widgets/Temporal/Model/3DTemporalExtension.js b/src/Widgets/Temporal/Model/3DTemporalExtension.js index 5f22b94f6..f73fb46a5 100644 --- a/src/Widgets/Temporal/Model/3DTemporalExtension.js +++ b/src/Widgets/Temporal/Model/3DTemporalExtension.js @@ -1,135 +1,149 @@ +/** @format */ + import { $3DTemporalTileset } from './3DTemporalTileset.js'; /** - * Entrypoint of the temporal module model. + * Entrypoint of the temporal module model. * Stores all parts of the 3D Tiles temporal extension model */ export class $3DTemporalExtension { - constructor() { - this.extensionName = "3DTILES_temporal"; + constructor() { + this.extensionName = '3DTILES_temporal'; - /** - * A map with feature IDs as keys and transactions of these features - * as value. - */ - this.transactionsPerFeature = new Map(); + /** + * A map with feature IDs as keys and transactions of these features + * as value. + */ + this.transactionsPerFeature = new Map(); - /** - * A map of map with transactions as values and organized - * per tiles and per features. This structure is used for - * optimizing the temporal culling (to decide which features - * should be displayed and with which style depending on the time, - * see TemporalProvider.js for more information). It is structured - * as follows: - * { tileId : featureID : { - * asSource: transaction; - * asDestination: transaction; - * } - * } - * Note that currently only the first transaction where the feature - * is a source or where the feature is a destination is kept. - * NORMALLY a feature shouldn't be the source (reps. the - * destination) of multiple transaction, since in this case one - * should create aggregates. Otherwise it might represent - * concurrent evolutions which are not managed in this - * implementation. However, in practical terms there is cases where - * a feature is the source (resp. destination) of multiple - * transactions. These cases might need to be investigated in more - * depth.... - * @type {Map} - */ - this.transactionsPerTile = new Map(); + /** + * A map of map with transactions as values and organized + * per tiles and per features. This structure is used for + * optimizing the temporal culling (to decide which features + * should be displayed and with which style depending on the time, + * see TemporalProvider.js for more information). It is structured + * as follows: + * { tileId : featureID : { + * asSource: transaction; + * asDestination: transaction; + * } + * } + * Note that currently only the first transaction where the feature + * is a source or where the feature is a destination is kept. + * NORMALLY a feature shouldn't be the source (reps. the + * destination) of multiple transaction, since in this case one + * should create aggregates. Otherwise it might represent + * concurrent evolutions which are not managed in this + * implementation. However, in practical terms there is cases where + * a feature is the source (resp. destination) of multiple + * transactions. These cases might need to be investigated in more + * depth.... + * @type {Map} + */ + this.transactionsPerTile = new Map(); - /** - * The temporal extension part of the batch tables mapped to the tile - * IDs (keys of the map). - */ - this.temporalBatchTables = new Map(); + /** + * The temporal extension part of the batch tables mapped to the tile + * IDs (keys of the map). + */ + this.temporalBatchTables = new Map(); - /** - * The temporal extension part of the bounding volumes part mapped to - * the tile IDs (keys of the map). - */ - this.temporalBoundingVolumes = new Map(); + /** + * The temporal extension part of the bounding volumes part mapped to + * the tile IDs (keys of the map). + */ + this.temporalBoundingVolumes = new Map(); - // Events - // $3DTemporalTileset triggers an event when it is loaded - window.addEventListener( - $3DTemporalTileset.TEMPORAL_TILESET_LOADED, - this.temporalTilesetLoaded.bind(this)); + // Events + // $3DTemporalTileset triggers an event when it is loaded + window.addEventListener( + $3DTemporalTileset.TEMPORAL_TILESET_LOADED, + this.temporalTilesetLoaded.bind(this) + ); - // Another strategy is used for the batch table part and - // for the bounding volume part of the temporal extension - // since we need to know to which tile this batch table - // extension belongs to (that is not stored in the batch - // table extension part). Therefore, we use the - // TilesManager.EVENT_TILE_LOADED instead which is fired - // by the 3D Tiles itowns layer when a tile has been - // loaded. To avoid creating a dependency between this class - // and the tilesManager, we add this event listener in the - // TemporalCntroler which knows both this model and the tilesManager. - // This is not ideal but improving this would asks for more - // modifications in itowns, which is currently not possible. - } + // Another strategy is used for the batch table part and + // for the bounding volume part of the temporal extension + // since we need to know to which tile this batch table + // extension belongs to (that is not stored in the batch + // table extension part). Therefore, we use the + // TilesManager.EVENT_TILE_LOADED instead which is fired + // by the 3D Tiles itowns layer when a tile has been + // loaded. To avoid creating a dependency between this class + // and the tilesManager, we add this event listener in the + // TemporalCntroler which knows both this model and the tilesManager. + // This is not ideal but improving this would asks for more + // modifications in itowns, which is currently not possible. + } - /** - * Fills this.transactionsPerFeature map when the tileset has been loaded - * (all transactions are stored in the temporal extension part of the - * tileset). - * @param {*} event The evet triggered; holds the temporal part of the - * extension in event.detail - */ - temporalTilesetLoaded(event) { - const allTransactions = event.detail.temporalTileset.transactions; + /** + * Fills this.transactionsPerFeature map when the tileset has been loaded + * (all transactions are stored in the temporal extension part of the + * tileset). + * @param {*} event The evet triggered; holds the temporal part of the + * extension in event.detail + */ + temporalTilesetLoaded(event) { + const allTransactions = event.detail.temporalTileset.transactions; - for (let i = 0; i < allTransactions.length; i++) { - const transaction = allTransactions[i]; - for (let j = 0; j < transaction.source.length; j++) { - const source = transaction.source[j]; - if (this.transactionsPerFeature.get(source) === undefined) { - this.transactionsPerFeature.set(source, {}); - } - if (this.transactionsPerFeature.get(source).asSource === - undefined) { - this.transactionsPerFeature.get(source).asSource = - transaction; - } - } - for (let j = 0; j < transaction.destination.length; j++) { - const destination = transaction.destination[j]; - if (this.transactionsPerFeature.get(destination) === undefined) { - this.transactionsPerFeature.set(destination, {}); - } - if (this.transactionsPerFeature.get(destination).asDestination === - undefined) { - this.transactionsPerFeature.get(destination).asDestination = - transaction; - } - } + for (let i = 0; i < allTransactions.length; i++) { + const transaction = allTransactions[i]; + for (let j = 0; j < transaction.source.length; j++) { + const source = transaction.source[j]; + if (this.transactionsPerFeature.get(source) === undefined) { + this.transactionsPerFeature.set(source, {}); + } + if (this.transactionsPerFeature.get(source).asSource === undefined) { + this.transactionsPerFeature.get(source).asSource = transaction; + } + } + for (let j = 0; j < transaction.destination.length; j++) { + const destination = transaction.destination[j]; + if (this.transactionsPerFeature.get(destination) === undefined) { + this.transactionsPerFeature.set(destination, {}); } + if ( + this.transactionsPerFeature.get(destination).asDestination === + undefined + ) { + this.transactionsPerFeature.get(destination).asDestination = + transaction; + } + } } + } - /** - * Triggered when the content of a tile has been loaded. Fills - * this.transactionsPerTile list with the transaction of this tile. - * @param {*} tileContent - */ - updateTileExtensionModel(tileContent) { - this.temporalBoundingVolumes.set(tileContent.tileId, - tileContent.boundingVolume.extensions[this.extensionName]); + /** + * Triggered when the content of a tile has been loaded. Fills + * this.transactionsPerTile list with the transaction of this tile. + * @param {*} tileContent + */ + updateTileExtensionModel(tileContent) { + this.temporalBoundingVolumes.set( + tileContent.tileId, + tileContent.boundingVolume.extensions[this.extensionName] + ); - // The batch table is not mandatory (e.g. the root tile - // has no batch table) - if (tileContent.batchTable) { - this.temporalBatchTables.set(tileContent.tileId, - tileContent.batchTable.extensions[this.extensionName]); - if (! this.transactionsPerTile.has(tileContent.tileId)) { - this.transactionsPerTile.set(tileContent.tileId, new Map()); - } - for (let i = 0; i < this.temporalBatchTables.get(tileContent.tileId).featureIds.length; i++) { - const featureId = this.temporalBatchTables.get(tileContent.tileId).featureIds[i]; - this.transactionsPerTile.get(tileContent.tileId).set(featureId, this.transactionsPerFeature.get(featureId)); - } - } + // The batch table is not mandatory (e.g. the root tile + // has no batch table) + if (tileContent.batchTable) { + this.temporalBatchTables.set( + tileContent.tileId, + tileContent.batchTable.extensions[this.extensionName] + ); + if (!this.transactionsPerTile.has(tileContent.tileId)) { + this.transactionsPerTile.set(tileContent.tileId, new Map()); + } + for ( + let i = 0; + i < this.temporalBatchTables.get(tileContent.tileId).featureIds.length; + i++ + ) { + const featureId = this.temporalBatchTables.get(tileContent.tileId) + .featureIds[i]; + this.transactionsPerTile + .get(tileContent.tileId) + .set(featureId, this.transactionsPerFeature.get(featureId)); + } } + } } diff --git a/src/Widgets/Temporal/Model/3DTemporalPrimaryTransaction.js b/src/Widgets/Temporal/Model/3DTemporalPrimaryTransaction.js index 031ae35e2..2ff3a2d84 100644 --- a/src/Widgets/Temporal/Model/3DTemporalPrimaryTransaction.js +++ b/src/Widgets/Temporal/Model/3DTemporalPrimaryTransaction.js @@ -1,17 +1,19 @@ +/** @format */ + import { $3DTemporalTransaction } from './3DTemporalTransaction.js'; /** * Implements the primary transaction of the 3DTILES_temporal - * extension. See the spec in + * extension. See the spec in * ./jsonSchemas/3DTILES_temporal.primaryTransaction.schema.json */ export class $3DTemporalPrimaryTransaction extends $3DTemporalTransaction { - constructor(json) { - super(json); + constructor(json) { + super(json); - this.type = json.type; - // type testing is not reliable in javascript therefore we have to use - // booleans to do so... - this.isPrimary = true; - } + this.type = json.type; + // type testing is not reliable in javascript therefore we have to use + // booleans to do so... + this.isPrimary = true; + } } diff --git a/src/Widgets/Temporal/Model/3DTemporalTileset.js b/src/Widgets/Temporal/Model/3DTemporalTileset.js index 9dc6a31be..1f56a395b 100644 --- a/src/Widgets/Temporal/Model/3DTemporalTileset.js +++ b/src/Widgets/Temporal/Model/3DTemporalTileset.js @@ -1,53 +1,59 @@ +/** @format */ + import { $3DTemporalPrimaryTransaction } from '../Model/3DTemporalPrimaryTransaction.js'; import { $3DTemporalTransactionAggregate } from '../Model/3DTemporalTransactionAggregate.js'; import { $3DTemporalVersion } from './3DTemporalVersion.js'; /** * Implements the tileset part of the 3DTILES_temporal - * extension. See the spec in + * extension. See the spec in * ./jsonSchemas/3DTILES_temporal.tileset.schema.json */ export class $3DTemporalTileset { - constructor(json) { - this.startDate = json.startDate; - this.endDate = json.endDate; + constructor(json) { + this.startDate = json.startDate; + this.endDate = json.endDate; - this.transactions = []; - // Fill this.transactions - this.parseTransactions(json.transactions); + this.transactions = []; + // Fill this.transactions + this.parseTransactions(json.transactions); - this.temporalVersions = new $3DTemporalVersion(json.versions); - this.versionTransitions = json.versionTransitions; - - // Trapped by 3DTemporalExtension.js that stores this instance of - // $3DTemporalTileset - window.dispatchEvent(new CustomEvent( - $3DTemporalTileset.TEMPORAL_TILESET_LOADED, - {detail: { temporalTileset: this}})); - } + this.temporalVersions = new $3DTemporalVersion(json.versions); + this.versionTransitions = json.versionTransitions; - /** - * Parses transactions from a json file and creates primary and aggregated - * transactions. - * @param {Object} transactions The json holding the transactions. - */ - parseTransactions(transactions) { - for (let i = 0; i < transactions.length; i++) { - let parsedTransac; - if (transactions[i].type) { - // Transactions aggregates don't have a type attribute - parsedTransac = new $3DTemporalPrimaryTransaction(transactions[i]); - } else if (transactions[i].transactions) { - // Primary transactions don't have a transactions attribute - parsedTransac = new $3DTemporalTransactionAggregate(transactions[i]); - // Recursively parse the aggregated transactions. - parsedTransac.transactions = this.parseTransactions(transactions[i].transactions); - } - this.transactions.push(parsedTransac); - } - } + // Trapped by 3DTemporalExtension.js that stores this instance of + // $3DTemporalTileset + window.dispatchEvent( + new CustomEvent($3DTemporalTileset.TEMPORAL_TILESET_LOADED, { + detail: { temporalTileset: this }, + }) + ); + } - static get TEMPORAL_TILESET_LOADED() { - return 'TEMPORAL_TILESET_LOADED'; + /** + * Parses transactions from a json file and creates primary and aggregated + * transactions. + * @param {Object} transactions The json holding the transactions. + */ + parseTransactions(transactions) { + for (let i = 0; i < transactions.length; i++) { + let parsedTransac; + if (transactions[i].type) { + // Transactions aggregates don't have a type attribute + parsedTransac = new $3DTemporalPrimaryTransaction(transactions[i]); + } else if (transactions[i].transactions) { + // Primary transactions don't have a transactions attribute + parsedTransac = new $3DTemporalTransactionAggregate(transactions[i]); + // Recursively parse the aggregated transactions. + parsedTransac.transactions = this.parseTransactions( + transactions[i].transactions + ); } + this.transactions.push(parsedTransac); + } + } + + static get TEMPORAL_TILESET_LOADED() { + return 'TEMPORAL_TILESET_LOADED'; + } } diff --git a/src/Widgets/Temporal/Model/3DTemporalTransaction.js b/src/Widgets/Temporal/Model/3DTemporalTransaction.js index 406a42dec..8f092e0c4 100644 --- a/src/Widgets/Temporal/Model/3DTemporalTransaction.js +++ b/src/Widgets/Temporal/Model/3DTemporalTransaction.js @@ -1,15 +1,18 @@ /** * Implements the transaction concept of the 3DTILES_temporal - * extension. See the spec in + * extension. See the spec in * ./jsonSchemas/3DTILES_temporal.transaction.schema.json + * + * @format */ + export class $3DTemporalTransaction { - constructor(json) { - this.id = json.id; - this.startDate = json.startDate; - this.endDate = json.endDate; - this.source = json.source; - this.destination = json.destination; - this.tags = json.tags; - } + constructor(json) { + this.id = json.id; + this.startDate = json.startDate; + this.endDate = json.endDate; + this.source = json.source; + this.destination = json.destination; + this.tags = json.tags; + } } diff --git a/src/Widgets/Temporal/Model/3DTemporalTransactionAggregate.js b/src/Widgets/Temporal/Model/3DTemporalTransactionAggregate.js index eabcafd93..15af7d1c0 100644 --- a/src/Widgets/Temporal/Model/3DTemporalTransactionAggregate.js +++ b/src/Widgets/Temporal/Model/3DTemporalTransactionAggregate.js @@ -1,17 +1,19 @@ +/** @format */ + import { $3DTemporalTransaction } from './3DTemporalTransaction.js'; /** * Implements the aggregated transaction of the 3DTILES_temporal - * extension. See the spec in + * extension. See the spec in * ./jsonSchemas/3DTILES_temporal.transactionAggregate.schema.json */ export class $3DTemporalTransactionAggregate extends $3DTemporalTransaction { - constructor(json) { - super(json); + constructor(json) { + super(json); - this.transactions = {}; - // type testing is not reliable in javascript therefore we have to use - // booleans to do so... - this.isAggregate = true; - } + this.transactions = {}; + // type testing is not reliable in javascript therefore we have to use + // booleans to do so... + this.isAggregate = true; + } } diff --git a/src/Widgets/Temporal/Model/3DTemporalVersion.js b/src/Widgets/Temporal/Model/3DTemporalVersion.js index 814f1bf58..ead41e705 100644 --- a/src/Widgets/Temporal/Model/3DTemporalVersion.js +++ b/src/Widgets/Temporal/Model/3DTemporalVersion.js @@ -1,17 +1,20 @@ /** * Implements the version concept of the 3DTILES_temporal - * extension. See the spec in + * extension. See the spec in * ./jsonSchemas/3DTILES_temporal.version.schema.json + * + * @format */ + export class $3DTemporalVersion { - constructor(json) { - this.versions = json; - for (let i = 0; i < json.length; i++) { - // Add the fields missing for the graph window - this.versions[i].label = json[i].name; - this.versions[i].level = i; - this.versions[i].group = "consensusScenario"; // Needs to be changed if one wants multiple scenario - this.versions[i].title = json[i].description; - } - } -} \ No newline at end of file + constructor(json) { + this.versions = json; + for (let i = 0; i < json.length; i++) { + // Add the fields missing for the graph window + this.versions[i].label = json[i].name; + this.versions[i].level = i; + this.versions[i].group = 'consensusScenario'; // Needs to be changed if one wants multiple scenario + this.versions[i].title = json[i].description; + } + } +} diff --git a/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.batchTable.schema.json b/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.batchTable.schema.json index 307593267..8fa357703 100644 --- a/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.batchTable.schema.json +++ b/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.batchTable.schema.json @@ -24,7 +24,7 @@ "featuresIds": { "description": "Array of ids of the features. Used in versions and transactions to identify the features.", "type": "array", - "items": {"type": "string"} + "items": { "type": "string" } } } } diff --git a/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.primaryTransaction.json b/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.primaryTransaction.json index 7a1864eef..eac1b5377 100644 --- a/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.primaryTransaction.json +++ b/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.primaryTransaction.json @@ -3,15 +3,24 @@ "id": "3DTILES_temporal.primaryTransaction.schema.json", "title": "3DTILES_temporal_primaryTransaction extension", "type": "object", - "allOf" : [{ - "$ref" : "3DTILES_temporal.transaction.schema.json" - }, { - "properties" : { + "allOf": [ + { + "$ref": "3DTILES_temporal.transaction.schema.json" + }, + { + "properties": { "type": { "description": "Type of transaction", "type": "string", - "enum": ["creation", "demolition", "modification", "union", "division"] + "enum": [ + "creation", + "demolition", + "modification", + "union", + "division" + ] } } - }] + } + ] } diff --git a/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.tileset.schema.json b/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.tileset.schema.json index 2fb94c330..7b56a644c 100644 --- a/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.tileset.schema.json +++ b/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.tileset.schema.json @@ -18,20 +18,22 @@ "versions": { "description": "Versions of the city", "type": "array", - "items": {"$ref": "3DTILES_temporal.version.schema.json"} + "items": { "$ref": "3DTILES_temporal.version.schema.json" } }, "versionTransitions": { "description": "Transitions between versions of the city", "type": "array", - "items": {"$ref": "3DTILES_temporal.versionTransition.schema.json"} + "items": { "$ref": "3DTILES_temporal.versionTransition.schema.json" } }, "transactions": { "description": "Transactions between features", "type": "array", - "items": { "anyOf": [ - {"$ref": "3DTILES_temporal.primaryTransaction.schema.json"}, - {"$ref": "3DTILES_temporal.transactionAggregate.schema.json"} - ]} + "items": { + "anyOf": [ + { "$ref": "3DTILES_temporal.primaryTransaction.schema.json" }, + { "$ref": "3DTILES_temporal.transactionAggregate.schema.json" } + ] + } } } } diff --git a/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.transaction.schema.json b/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.transaction.schema.json index 7b603d6cf..d89ec67f4 100644 --- a/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.transaction.schema.json +++ b/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.transaction.schema.json @@ -21,17 +21,17 @@ "source": { "description": "Array of Features Ids (stored in the 3DTILES_temporal extension of the batch table) representing a state before the transaction", "type": "array", - "items": {"type": "string"} + "items": { "type": "string" } }, "destination": { "description": "Array of Features Ids (stored in the 3DTILES_temporal extension of the batch table) representing a state after the transaction", "type": "array", - "items": {"type": "string"} + "items": { "type": "string" } }, "tags": { "description": "tags of the transaction", "type": "array", - "items": {"type": "string"} + "items": { "type": "string" } } } } diff --git a/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.transactionAggregate.schema.json b/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.transactionAggregate.schema.json index 77c280382..332dc5fe5 100644 --- a/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.transactionAggregate.schema.json +++ b/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.transactionAggregate.schema.json @@ -3,18 +3,23 @@ "id": "3DTILES_temporal.transactionAggregate.schema.json", "title": "3DTILES_temporal_transactionAggregate extension", "type": "object", - "allOf" : [{ - "$ref" : "3DTILES_temporal.transaction.schema.json" - }, { - "properties" : { + "allOf": [ + { + "$ref": "3DTILES_temporal.transaction.schema.json" + }, + { + "properties": { "primaryTransactions": { "description": "Array of transactionAggregate or of primaryTransactions", "type": "array", - "items": { "anyOf": [ - {"$ref": "3DTILES_temporal.primaryTransaction.schema.json"}, - {"$ref": "3DTILES_temporal.transactionAggregate.schema.json"} - ]} + "items": { + "anyOf": [ + { "$ref": "3DTILES_temporal.primaryTransaction.schema.json" }, + { "$ref": "3DTILES_temporal.transactionAggregate.schema.json" } + ] + } } } - }] + } + ] } diff --git a/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.version.schema.schema.json b/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.version.schema.schema.json index de599adae..d04258e3b 100644 --- a/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.version.schema.schema.json +++ b/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.version.schema.schema.json @@ -28,12 +28,12 @@ }, "tags": { "type": "array", - "items": {"type": "string"} + "items": { "type": "string" } }, "featuresIds": { "description": "Array of Features Ids composing the version (stored in the 3DTILES_temporal extension of the batch table)", "type": "array", - "items": {"type": "string"} + "items": { "type": "string" } } } } diff --git a/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.versionTransition.schema.json b/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.versionTransition.schema.json index 7da39fee7..6dc924425 100644 --- a/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.versionTransition.schema.json +++ b/src/Widgets/Temporal/Model/jsonSchemas/3DTILES_temporal.versionTransition.schema.json @@ -42,7 +42,7 @@ "transactionsIds": { "type": "array", "description": "ids of the transactions composing this VersionTransition", - "items": {"type": "string"} + "items": { "type": "string" } } } } diff --git a/src/Widgets/Temporal/TemporalModule.js b/src/Widgets/Temporal/TemporalModule.js index c00da400b..0b62d2f75 100644 --- a/src/Widgets/Temporal/TemporalModule.js +++ b/src/Widgets/Temporal/TemporalModule.js @@ -1,12 +1,14 @@ +/** @format */ + import { $3DTemporalExtension } from './Model/3DTemporalExtension.js'; import { TemporalProvider } from './ViewModel/TemporalProvider.js'; -import { TemporalView } from './View/TemporalView.js' +import { TemporalView } from './View/TemporalView.js'; /** * Entrypoint of the temporal module (that can be instanciated in the demos) */ export class TemporalModule { - /** + /** * Constructs a new temporal module. * * @param {TilesManager} tilesManager - The tiles manager associated with @@ -15,13 +17,15 @@ export class TemporalModule { * module. }; */ - constructor(tilesManager, temporalOptions) { - - this.model = new $3DTemporalExtension(); + constructor(tilesManager, temporalOptions) { + this.model = new $3DTemporalExtension(); - this.provider = new TemporalProvider(this.model, tilesManager, - temporalOptions.currentTime); + this.provider = new TemporalProvider( + this.model, + tilesManager, + temporalOptions.currentTime + ); - this.view = new TemporalView(this.provider, temporalOptions); - } -} \ No newline at end of file + this.view = new TemporalView(this.provider, temporalOptions); + } +} diff --git a/src/Widgets/Temporal/View/EnumWindows.js b/src/Widgets/Temporal/View/EnumWindows.js index e7a4538ec..374f8c093 100644 --- a/src/Widgets/Temporal/View/EnumWindows.js +++ b/src/Widgets/Temporal/View/EnumWindows.js @@ -1,8 +1,10 @@ +/** @format */ + export class EnumTemporalWindow { - static get SLIDERWINDOW(){ - return "SLIDERWINDOW"; - } - static get GRAPHWINDOW(){ - return "GRAPHWINDOW"; - } -} \ No newline at end of file + static get SLIDERWINDOW() { + return 'SLIDERWINDOW'; + } + static get GRAPHWINDOW() { + return 'GRAPHWINDOW'; + } +} diff --git a/src/Widgets/Temporal/View/NetworkManager.js b/src/Widgets/Temporal/View/NetworkManager.js index 96f0d6931..0b2e84fb3 100644 --- a/src/Widgets/Temporal/View/NetworkManager.js +++ b/src/Widgets/Temporal/View/NetworkManager.js @@ -1,11 +1,13 @@ -const Network = require('vis-network').Network +/** @format */ + +const Network = require('vis-network').Network; /** -* Manager for the graph -* It take care of all data needed by vis.js -*/ + * Manager for the graph + * It take care of all data needed by vis.js + */ export class NetworkManager { - /** + /** * Constructs a NetworkManager. * * @param {String} id_network - HTML id which will be the container of the graph @@ -30,69 +32,72 @@ export class NetworkManager { * * network {Vis.Network Object} - hold the network/graph instance created by viz.js */ - constructor(id_network="mynetwork", - data={"nodes": null, - "edges": null, - "groups": { - "id":0, - "label":"consensusScenario"} - }, - option=null){ - this.network = null; - this.data = data; - this.option = option; - this.id_network = id_network; - this.getAsynchronousData = null; - - } + constructor( + id_network = 'mynetwork', + data = { + nodes: null, + edges: null, + groups: { + id: 0, + label: 'consensusScenario', + }, + }, + option = null + ) { + this.network = null; + this.data = data; + this.option = option; + this.id_network = id_network; + this.getAsynchronousData = null; + } - /** - * Kill the simulation network - * When the graph is shown, a simulation is running. It allows dynamics interactions - * When killed, the graph disappear. - */ - destroy() { - if (this.network !== null) { - this.network.destroy(); - this.network = null; - } + /** + * Kill the simulation network + * When the graph is shown, a simulation is running. It allows dynamics interactions + * When killed, the graph disappear. + */ + destroy() { + if (this.network !== null) { + this.network.destroy(); + this.network = null; } + } - /** - * Initiate the vis.Network with the container (html), data (nodes & edges) and options (graphics) - * The data is got asynchronously. It's coming from tileset.json so we need to wait for it. - */ - init(){ - this.destroy(); + /** + * Initiate the vis.Network with the container (html), data (nodes & edges) and options (graphics) + * The data is got asynchronously. It's coming from tileset.json so we need to wait for it. + */ + init() { + this.destroy(); - this.data.nodes = this.getAsynchronousData()[0]; - this.data.edges = this.getAsynchronousData()[1]; - const container = document.getElementById(this.id_network); - this.network = new Network(container, this.data, this.option); - } + this.data.nodes = this.getAsynchronousData()[0]; + this.data.edges = this.getAsynchronousData()[1]; + const container = document.getElementById(this.id_network); + this.network = new Network(container, this.data, this.option); + } - /** - * Add callback to the graph - * Click on node = event - * Click on edge = event - * In both case, a date is passed - * @param : callback (function) ( the function to be call when the event is done) - */ - add_event(callback){ - this.network.on("selectNode", function (params) { - let nodeId = this.getNodeAt(params.pointer.DOM); - let node = this.body.nodes[nodeId]; - let time = node.options.name; - callback(time); - }); + /** + * Add callback to the graph + * Click on node = event + * Click on edge = event + * In both case, a date is passed + * @param : callback (function) ( the function to be call when the event is done) + */ + add_event(callback) { + this.network.on('selectNode', function (params) { + let nodeId = this.getNodeAt(params.pointer.DOM); + let node = this.body.nodes[nodeId]; + let time = node.options.name; + callback(time); + }); - this.network.on("selectEdge", function (params) { - let edgeId = this.getEdgeAt(params.pointer.DOM); - let connectedNodesId = this.getConnectedNodes(edgeId); - let from_time = this.body.nodes[connectedNodesId[0]].options.name; - let to_time = this.body.nodes[connectedNodesId[1]].options.name; - let time = (from_time/1 + to_time/1) / 2 ; - callback(time); - }); - } + this.network.on('selectEdge', function (params) { + let edgeId = this.getEdgeAt(params.pointer.DOM); + let connectedNodesId = this.getConnectedNodes(edgeId); + let from_time = this.body.nodes[connectedNodesId[0]].options.name; + let to_time = this.body.nodes[connectedNodesId[1]].options.name; + let time = (from_time / 1 + to_time / 1) / 2; + callback(time); + }); + } } diff --git a/src/Widgets/Temporal/View/TemporalGraphWindow.js b/src/Widgets/Temporal/View/TemporalGraphWindow.js index 0c1d5ab99..4fd949bb6 100644 --- a/src/Widgets/Temporal/View/TemporalGraphWindow.js +++ b/src/Widgets/Temporal/View/TemporalGraphWindow.js @@ -1,7 +1,9 @@ +/** @format */ + //Components -import { Window } from "../../../Components/GUI/js/Window"; +import { Window } from '../../../Components/GUI/js/Window'; -import { NetworkManager } from "./NetworkManager"; +import { NetworkManager } from './NetworkManager'; import './TemporalWindow.css'; /** @@ -16,55 +18,56 @@ import './TemporalWindow.css'; * @param options : optional parameters (min time, max time and current time) */ export class TemporalGraphWindow extends Window { - constructor(refreshCallback, options = {}) { + constructor(refreshCallback, options = {}) { // option : getAsynchronousData - super('temporal', 'Temporal Graph Navigation', false); + super('temporal', 'Temporal Graph Navigation', false); - this.refreshCallback = refreshCallback; + this.refreshCallback = refreshCallback; - // graph - this.networkManager = new NetworkManager(); - this.networkManager.option=options.viewOptions; - this.networkManager.getAsynchronousData = options.temporalWindow.getAsynchronousData; - } + // graph + this.networkManager = new NetworkManager(); + this.networkManager.option = options.viewOptions; + this.networkManager.getAsynchronousData = + options.temporalWindow.getAsynchronousData; + } - get innerContentHtml() { - return /*html*/` + get innerContentHtml() { + return /*html*/ `
          `; - } - - windowCreated() { - // Magical code to center an absolute positionned window - this.window.style.setProperty('left', '0'); - this.window.style.setProperty('right', '0'); - this.window.style.setProperty('margin-left', 'auto'); - this.window.style.setProperty('margin-right', 'auto'); - // Put it at the bottom of the page - this.window.style.setProperty('top', 'unset'); - this.window.style.setProperty('bottom', '0'); - this.window.style.setProperty('margin-bottom', 'auto'); - // Window size and center text - this.window.style.setProperty('width', '700px'); - this.window.style.setProperty('height', '215px'); -// this.window.style.setProperty('height', '115px'); - this.window.style.setProperty('text-align', 'center'); - - // Add graph - this.networkManager.init(); - this.networkManager.add_event((param)=>{this.changeTime(param)}); - } + } + windowCreated() { + // Magical code to center an absolute positionned window + this.window.style.setProperty('left', '0'); + this.window.style.setProperty('right', '0'); + this.window.style.setProperty('margin-left', 'auto'); + this.window.style.setProperty('margin-right', 'auto'); + // Put it at the bottom of the page + this.window.style.setProperty('top', 'unset'); + this.window.style.setProperty('bottom', '0'); + this.window.style.setProperty('margin-bottom', 'auto'); + // Window size and center text + this.window.style.setProperty('width', '700px'); + this.window.style.setProperty('height', '215px'); + // this.window.style.setProperty('height', '115px'); + this.window.style.setProperty('text-align', 'center'); - // change the current date and sync the temporal version to this new date - changeTime(time) { - this.currentTime = time; + // Add graph + this.networkManager.init(); + this.networkManager.add_event((param) => { + this.changeTime(param); + }); + } - // Eventually inform who it may concern (e.g. an associated iTowns layer) - // that the currentTime has changed: - this.refreshCallback(this.currentTime); - } + // change the current date and sync the temporal version to this new date + changeTime(time) { + this.currentTime = time; + // Eventually inform who it may concern (e.g. an associated iTowns layer) + // that the currentTime has changed: + this.refreshCallback(this.currentTime); + } } diff --git a/src/Widgets/Temporal/View/TemporalSliderWindow.js b/src/Widgets/Temporal/View/TemporalSliderWindow.js index 47b0da04b..27bd71894 100644 --- a/src/Widgets/Temporal/View/TemporalSliderWindow.js +++ b/src/Widgets/Temporal/View/TemporalSliderWindow.js @@ -1,10 +1,12 @@ +/** @format */ + //Components -import { Window } from "../../../Components/GUI/js/Window"; +import { Window } from '../../../Components/GUI/js/Window'; import './TemporalWindow.css'; /** - * Handles the GUI part enabling the user to specify the chosen "time" (year) + * Handles the GUI part enabling the user to specify the chosen "time" (year) * of observation for displayal of the (3D) scene. * Note that it is not the Temporal View's responsability to * alter/modify/update the scene according to the user specified moment (but @@ -13,25 +15,25 @@ import './TemporalWindow.css'; * @param options : optional parameters (min time, max time and current time) */ export class TemporalSliderWindow extends Window { - constructor(refreshCallback, options = {}) { - super('temporal', 'Temporal Navigation', false); + constructor(refreshCallback, options = {}) { + super('temporal', 'Temporal Navigation', false); - // Minimum and maximum times that can be displayed by this occurence - this.minTime = options.minTime || 2009; - this.maxTime = options.maxTime || 2015; + // Minimum and maximum times that can be displayed by this occurence + this.minTime = options.minTime || 2009; + this.maxTime = options.maxTime || 2015; - // The currently selected timestamp - this.currentTime = options.currentTime || 2009; + // The currently selected timestamp + this.currentTime = options.currentTime || 2009; - // The timestep used to increment or decrement time with the slide buttons. - // Note that timeStep is a "duration" as opposed to a timestamp. - this.timeStep = options.timeStep || 1; + // The timestep used to increment or decrement time with the slide buttons. + // Note that timeStep is a "duration" as opposed to a timestamp. + this.timeStep = options.timeStep || 1; - this.refreshCallback = refreshCallback; - } + this.refreshCallback = refreshCallback; + } - get innerContentHtml() { - return /*html*/` + get innerContentHtml() { + return /*html*/ `
          ${this.minTime}
          ${this.maxTime}
          @@ -40,45 +42,49 @@ export class TemporalSliderWindow extends Window { value=${this.currentTime} step=${this.timeStep}>
          `; - } + } - windowCreated() { - // Magical code to center an absolute positionned window - this.window.style.setProperty('left', '0'); - this.window.style.setProperty('right', '0'); - this.window.style.setProperty('margin-left', 'auto'); - this.window.style.setProperty('margin-right', 'auto'); - // Put it at the bottom of the page - this.window.style.setProperty('top', 'unset'); - this.window.style.setProperty('bottom', '10px'); - this.window.style.setProperty('margin-bottom', 'auto'); - // Window size and center text - this.window.style.setProperty('width', '700px'); - this.window.style.setProperty('height', '115px'); - this.window.style.setProperty('text-align', 'center'); + windowCreated() { + // Magical code to center an absolute positionned window + this.window.style.setProperty('left', '0'); + this.window.style.setProperty('right', '0'); + this.window.style.setProperty('margin-left', 'auto'); + this.window.style.setProperty('margin-right', 'auto'); + // Put it at the bottom of the page + this.window.style.setProperty('top', 'unset'); + this.window.style.setProperty('bottom', '10px'); + this.window.style.setProperty('margin-bottom', 'auto'); + // Window size and center text + this.window.style.setProperty('width', '700px'); + this.window.style.setProperty('height', '115px'); + this.window.style.setProperty('text-align', 'center'); - // Hook up the callbacks - document.getElementById('timeSliderValue').addEventListener( - 'input', this.timeSelection.bind(this), false); - document.getElementById('timeSlider').addEventListener( - 'input', this.timeSelectionSlider.bind(this), false); - } + // Hook up the callbacks + document + .getElementById('timeSliderValue') + .addEventListener('input', this.timeSelection.bind(this), false); + document + .getElementById('timeSlider') + .addEventListener('input', this.timeSelectionSlider.bind(this), false); + } - // Call back on new user input with the date selector - timeSelection() { - this.currentTime = document.getElementById('timeSliderValue').value.toString(); - document.getElementById('timeSlider').value = this.currentTime; - // Eventually inform who it may concern (e.g. an associated iTowns layer) - // that the currentTime has changed: - this.refreshCallback(this.currentTime); - } + // Call back on new user input with the date selector + timeSelection() { + this.currentTime = document + .getElementById('timeSliderValue') + .value.toString(); + document.getElementById('timeSlider').value = this.currentTime; + // Eventually inform who it may concern (e.g. an associated iTowns layer) + // that the currentTime has changed: + this.refreshCallback(this.currentTime); + } - // Call back on new user input with the time slider - timeSelectionSlider() { - this.currentTime = document.getElementById('timeSlider').value.toString(); - document.getElementById('timeSliderValue').value = this.currentTime; - // Eventually inform who it may concern (e.g. an associated iTowns layer) - // that the currentTime has changed: - this.refreshCallback(this.currentTime); - } + // Call back on new user input with the time slider + timeSelectionSlider() { + this.currentTime = document.getElementById('timeSlider').value.toString(); + document.getElementById('timeSliderValue').value = this.currentTime; + // Eventually inform who it may concern (e.g. an associated iTowns layer) + // that the currentTime has changed: + this.refreshCallback(this.currentTime); + } } diff --git a/src/Widgets/Temporal/View/TemporalView.js b/src/Widgets/Temporal/View/TemporalView.js index 794467aa4..532f70f03 100644 --- a/src/Widgets/Temporal/View/TemporalView.js +++ b/src/Widgets/Temporal/View/TemporalView.js @@ -1,3 +1,5 @@ +/** @format */ + //Components import { ModuleView } from '../../../Components/ModuleView/ModuleView.js'; @@ -21,30 +23,38 @@ export class TemporalView extends ModuleView { this.currentTime = temporalOptions.currentTime; function currentTimeUpdated(newDate) { - this.currentTime = Number(newDate); - this.provider.currentTime = this.currentTime; // TODO: verify that the - // flow is good with MVVM - this.provider.changeVisibleTilesStates(); + this.currentTime = Number(newDate); + this.provider.currentTime = this.currentTime; // TODO: verify that the + // flow is good with MVVM + this.provider.changeVisibleTilesStates(); } const refreshCallback = currentTimeUpdated.bind(this); // Callback to get data asynchronously from the tileset.json - function getAsynchronousData(){ - let versions = this.temporalExtension.temporal_tileset.temporalVersions.versions; - let versionTransitions = this.temporalExtension.temporal_tileset.versionTransitions; - return [versions, versionTransitions] - } + function getAsynchronousData() { + let versions = + this.temporalExtension.temporal_tileset.temporalVersions.versions; + let versionTransitions = + this.temporalExtension.temporal_tileset.versionTransitions; + return [versions, versionTransitions]; + } // Select the window type: switch (temporalOptions.view) { - case EnumTemporalWindow.SLIDERWINDOW : - this.temporalWindow = new TemporalSliderWindow(refreshCallback, temporalOptions); - break; - case EnumTemporalWindow.GRAPHWINDOW : - temporalOptions.getAsynchronousData = getAsynchronousData.bind(this); - this.temporalWindow = new TemporalGraphWindow(refreshCallback, temporalOptions); - break; - } + case EnumTemporalWindow.SLIDERWINDOW: + this.temporalWindow = new TemporalSliderWindow( + refreshCallback, + temporalOptions + ); + break; + case EnumTemporalWindow.GRAPHWINDOW: + temporalOptions.getAsynchronousData = getAsynchronousData.bind(this); + this.temporalWindow = new TemporalGraphWindow( + refreshCallback, + temporalOptions + ); + break; + } } ///////////////// @@ -56,4 +66,4 @@ export class TemporalView extends ModuleView { disableView() { this.temporalWindow.dispose(); } -} \ No newline at end of file +} diff --git a/src/Widgets/Temporal/View/TemporalWindow.css b/src/Widgets/Temporal/View/TemporalWindow.css index 8983a912f..e1c9c57c0 100644 --- a/src/Widgets/Temporal/View/TemporalWindow.css +++ b/src/Widgets/Temporal/View/TemporalWindow.css @@ -1,43 +1,45 @@ +/** @format */ + #temporalWindow { - position: absolute; - width: 100%; + position: absolute; + width: 100%; } #timeSliderMinDate { - position: absolute; - left : 10px; - top : 5px; - font: 28px 'Lucida Grande',sans-serif; - font-weight: bold; + position: absolute; + left: 10px; + top: 5px; + font: 28px 'Lucida Grande', sans-serif; + font-weight: bold; } #timeSliderMaxDate { - position: absolute; - right : 10px; - top : 5px; - font: 28px 'Lucida Grande',sans-serif; - font-weight: bold; + position: absolute; + right: 10px; + top: 5px; + font: 28px 'Lucida Grande', sans-serif; + font-weight: bold; } -#timeSliderValue{ - position: absolute; - text-align: center; - margin : auto; - color : black; - font: 28px 'Lucida Grande',sans-serif; - font-weight: bold; - top: 30px; - right : 0; - left : 0; - border: 1px solid black; - background-color: whitesmoke; - height: 40px; - width : 90px; +#timeSliderValue { + position: absolute; + text-align: center; + margin: auto; + color: black; + font: 28px 'Lucida Grande', sans-serif; + font-weight: bold; + top: 30px; + right: 0; + left: 0; + border: 1px solid black; + background-color: whitesmoke; + height: 40px; + width: 90px; } #timeSlider { - width: 65%; - position: absolute; - text-align: center; - margin : auto; - top: 10px; - left: 0; - right : 0; + width: 65%; + position: absolute; + text-align: center; + margin: auto; + top: 10px; + left: 0; + right: 0; } diff --git a/src/Widgets/Temporal/ViewModel/TemporalProvider.js b/src/Widgets/Temporal/ViewModel/TemporalProvider.js index 16f6494e9..622eed27c 100644 --- a/src/Widgets/Temporal/ViewModel/TemporalProvider.js +++ b/src/Widgets/Temporal/ViewModel/TemporalProvider.js @@ -1,224 +1,276 @@ +/** @format */ + //Components -import { TilesManager } from '../../../Components/3DTiles/TilesManager.js' +import { TilesManager } from '../../../Components/3DTiles/TilesManager.js'; import { getVisibleTiles } from '../../../Components/3DTiles/3DTilesUtils.js'; import { CityObjectStyle } from '../../../Components/3DTiles/Model/CityObjectStyle.js'; import { CityObjectID } from '../../../Components/3DTiles/Model/CityObject.js'; /** * The ViewModel of the temporal module. Contains intermediate data structures - * between the model and the view as well as the logic for city objects and + * between the model and the view as well as the logic for city objects and * transactions display. */ export class TemporalProvider { - /** - * Constructs a new temporal provider: initialize data structures - * used for the view (this.COStyles), initialize the possible - * city objects styles that displays transactions and set events. - * @param {$3DTemporalExtension} tempExtModel The model of the temporal - * module (i.e. holding data from the 3D Tiles temporal extension). - * @param {TilesManager} tilesManager The tiles manager associated - * with the itowns 3D Tiles layer holding the temporal extension. - * @param {Number} currentTime The current display time, updated by the - * TemporalView. - */ + /** + * Constructs a new temporal provider: initialize data structures + * used for the view (this.COStyles), initialize the possible + * city objects styles that displays transactions and set events. + * @param {$3DTemporalExtension} tempExtModel The model of the temporal + * module (i.e. holding data from the 3D Tiles temporal extension). + * @param {TilesManager} tilesManager The tiles manager associated + * with the itowns 3D Tiles layer holding the temporal extension. + * @param {Number} currentTime The current display time, updated by the + * TemporalView. + */ constructor(tempExtModel, tilesManager, currentTime) { - this.tempExtModel = tempExtModel; this.tilesManager = tilesManager; this.currentTime = currentTime; - /** Stores city objects (CO) styles per tile and per date - * to avoid computing it multiple times. It's actually a map + /** Stores city objects (CO) styles per tile and per date + * to avoid computing it multiple times. It's actually a map * of a map and its structure is: - * { date: tile : styles[] } } where the position in the styles + * { date: tile : styles[] } } where the position in the styles * array is the id of the city object - * */ + * */ this.COStyles = new Map(); this.initCOStyles(); // Initializes the model. One part of this model is filled when the - // temporal extension is loaded by iTowns; an other part is filled + // temporal extension is loaded by iTowns; an other part is filled // with the event declared below (when a tile is loaded). // See the comment at the end of the $3DTemporalExtension constructor // for more details. this.tilesManager.addEventListener( TilesManager.EVENT_TILE_LOADED, - this.tempExtModel.updateTileExtensionModel.bind( - this.tempExtModel)); + this.tempExtModel.updateTileExtensionModel.bind(this.tempExtModel) + ); // When a tile is loaded, we compute the state of its city objects (e.g. // should they be displayed or not and in which color, etc.) this.tilesManager.addEventListener( - TilesManager.EVENT_TILE_LOADED, - this.changeTileState.bind(this)); + TilesManager.EVENT_TILE_LOADED, + this.changeTileState.bind(this) + ); } /** - * Initializes the styles affected to city objects to represent + * Initializes the styles affected to city objects to represent * transactions (see 3DTiles_temporal extension for more information * on transactions). The names of the styles match transaction names, * except for 'noTransaction' dans 'hide'. */ initCOStyles() { - this.tilesManager.registerStyle('noTransaction', new CityObjectStyle({ - materialProps: { opacity: 1.0, color: 0xffffff } })); // white + this.tilesManager.registerStyle( + 'noTransaction', + new CityObjectStyle({ + materialProps: { opacity: 1.0, color: 0xffffff }, + }) + ); // white - this.tilesManager.registerStyle('creation', new CityObjectStyle({ - materialProps: { opacity: 0.6, color: 0x009900 } })); // green + this.tilesManager.registerStyle( + 'creation', + new CityObjectStyle({ + materialProps: { opacity: 0.6, color: 0x009900 }, + }) + ); // green - this.tilesManager.registerStyle('demolition', new CityObjectStyle({ - materialProps: { opacity: 0.6, color: 0xff0000 } })); // red + this.tilesManager.registerStyle( + 'demolition', + new CityObjectStyle({ + materialProps: { opacity: 0.6, color: 0xff0000 }, + }) + ); // red - this.tilesManager.registerStyle('modification', new CityObjectStyle({ - materialProps: { opacity: 0.6, color: 0xFFD700 } })); // yellow + this.tilesManager.registerStyle( + 'modification', + new CityObjectStyle({ + materialProps: { opacity: 0.6, color: 0xffd700 }, + }) + ); // yellow - this.tilesManager.registerStyle('hide', new CityObjectStyle({ - materialProps: { opacity: 0, color: 0xffffff, alphaTest: 0.3 } })); // hidden + this.tilesManager.registerStyle( + 'hide', + new CityObjectStyle({ + materialProps: { opacity: 0, color: 0xffffff, alphaTest: 0.3 }, + }) + ); // hidden } /** * Sets the style of a given city object in the tiles manager if this - * style has been registered in the tiles manager (e.g. in - * this.initCOStyles()). + * style has been registered in the tiles manager (e.g. in + * this.initCOStyles()). * @param {Number} tileId Id of the tile of the city object. * @param {Number} cityObjectId Id of the city object. * @param {String} styleName Name of the style to apply. */ setCityObjectStyle(tileId, cityObjectId, styleName) { - if(this.tilesManager.isStyleRegistered(styleName)) { - this.tilesManager.setStyle(new CityObjectID(tileId, cityObjectId), - styleName); + if (this.tilesManager.isStyleRegistered(styleName)) { + this.tilesManager.setStyle( + new CityObjectID(tileId, cityObjectId), + styleName + ); } else { - console.warn("Style " + styleName + " is not " + - "registered. Defaulting to style noTransaction.") - this.tilesManager.setStyle(new CityObjectID(tileId, cityObjectId), - 'noTransaction'); + console.warn( + 'Style ' + + styleName + + ' is not ' + + 'registered. Defaulting to style noTransaction.' + ); + this.tilesManager.setStyle( + new CityObjectID(tileId, cityObjectId), + 'noTransaction' + ); } } - /** - * Generates the style name of a transaction. This method is recursive - * for aggregated transactions that may have multiple nested transactions. - * The style name correspond to the one created in the - * initCOStyles method). - * - * @param {$3DTemporalTransaction} transaction The transaction - * to generate the style name from. - * - * @returns {string} If the transaction is a primary transaction, - * returns its type. If it is an aggregated transaction, it returns a - * concatenation of the primary transactions types aggregated in - * transaction, prefixed by 'aggregate'. Currently, no style are - * declared for transactions aggregates for a simpler visual - * rendering. We could also generate styles with random colors - * and add them to a legend and provide a user the possibility to - * update these colors and / or to disable them from the GUI. - */ - getTransactionStyleName(transaction, styleName) { - if (transaction.isPrimary) return transaction.type; - else if (transaction.isAggregate) { - if (styleName === '') styleName = 'aggregate'; // prefix - for (let i = 0 ; i < transaction.transactions.length ; i++) { - styleName = styleName + '-' + this.getTransactionStyleName( - transaction.transactions[i], styleName); - } - return styleName - } else { - console.warn('Transaction which is not a primary nor an aggregate.') - } + /** + * Generates the style name of a transaction. This method is recursive + * for aggregated transactions that may have multiple nested transactions. + * The style name correspond to the one created in the + * initCOStyles method). + * + * @param {$3DTemporalTransaction} transaction The transaction + * to generate the style name from. + * + * @returns {string} If the transaction is a primary transaction, + * returns its type. If it is an aggregated transaction, it returns a + * concatenation of the primary transactions types aggregated in + * transaction, prefixed by 'aggregate'. Currently, no style are + * declared for transactions aggregates for a simpler visual + * rendering. We could also generate styles with random colors + * and add them to a legend and provide a user the possibility to + * update these colors and / or to disable them from the GUI. + */ + getTransactionStyleName(transaction, styleName) { + if (transaction.isPrimary) return transaction.type; + else if (transaction.isAggregate) { + if (styleName === '') styleName = 'aggregate'; // prefix + for (let i = 0; i < transaction.transactions.length; i++) { + styleName = + styleName + + '-' + + this.getTransactionStyleName(transaction.transactions[i], styleName); + } + return styleName; + } else { + console.warn('Transaction which is not a primary nor an aggregate.'); } + } - /* *** Culling with transactions and colors management */ - // Rules for culling: - // * If the feature exists at the currentTime we display it in gray - // * If there is a transaction between the feature and another - // feature at the currentTime: - // * the displayed geometry is the one of the old feature for the - // first half duration of the transaction - // * the displayed geometry is the one of the new feature for the - // second half of the duration - // * the opacity is set to 0.6 - // * the color is set depending on the transaction type - // * else we hide the feature. - culling(BT, tileId, tileTransactions) { - const featuresDisplayStates = []; - for (let i = 0; i < BT.featureIds.length; i++) { - const featureId = BT.featureIds[i]; - if (this.currentTime >= BT.startDates[i] && this.currentTime <= - BT.endDates[i]) { - // ** FEATURE EXISTS - featuresDisplayStates.push('noTransaction'); - this.setCityObjectStyle(tileId, i, 'noTransaction'); - } else if (tileTransactions.has(featureId) && tileTransactions.get(featureId)) { - // ** TRANSACTION CASE - const featureTransactions = tileTransactions.get(featureId); - let hasTransac = false; - if (featureTransactions.asSource) { - const transacAsSource = featureTransactions.asSource - const transacAsSourceHalfDuration = (transacAsSource.endDate - - transacAsSource.startDate) / 2; - if (this.currentTime > transacAsSource.startDate && this.currentTime <= - transacAsSource.startDate + transacAsSourceHalfDuration) { - hasTransac = true; - const transactionStyleName = this.getTransactionStyleName(transacAsSource, ''); - featuresDisplayStates.push(transactionStyleName); - this.setCityObjectStyle(tileId, i, transactionStyleName); - } - } - if (featureTransactions.asDestination) { - const transacAsDest = featureTransactions.asDestination; - const transacAsDestHalfDuration = (transacAsDest.endDate - - transacAsDest.startDate) / 2; - if (this.currentTime > transacAsDest.startDate + - transacAsDestHalfDuration && this.currentTime <= - transacAsDest.endDate) { - hasTransac = true; - const transactionStyleName = this.getTransactionStyleName(transacAsDest, ''); - featuresDisplayStates.push(transactionStyleName); - this.setCityObjectStyle(tileId, i, transactionStyleName); - } - } + /* *** Culling with transactions and colors management */ + // Rules for culling: + // * If the feature exists at the currentTime we display it in gray + // * If there is a transaction between the feature and another + // feature at the currentTime: + // * the displayed geometry is the one of the old feature for the + // first half duration of the transaction + // * the displayed geometry is the one of the new feature for the + // second half of the duration + // * the opacity is set to 0.6 + // * the color is set depending on the transaction type + // * else we hide the feature. + culling(BT, tileId, tileTransactions) { + const featuresDisplayStates = []; + for (let i = 0; i < BT.featureIds.length; i++) { + const featureId = BT.featureIds[i]; + if ( + this.currentTime >= BT.startDates[i] && + this.currentTime <= BT.endDates[i] + ) { + // ** FEATURE EXISTS + featuresDisplayStates.push('noTransaction'); + this.setCityObjectStyle(tileId, i, 'noTransaction'); + } else if ( + tileTransactions.has(featureId) && + tileTransactions.get(featureId) + ) { + // ** TRANSACTION CASE + const featureTransactions = tileTransactions.get(featureId); + let hasTransac = false; + if (featureTransactions.asSource) { + const transacAsSource = featureTransactions.asSource; + const transacAsSourceHalfDuration = + (transacAsSource.endDate - transacAsSource.startDate) / 2; + if ( + this.currentTime > transacAsSource.startDate && + this.currentTime <= + transacAsSource.startDate + transacAsSourceHalfDuration + ) { + hasTransac = true; + const transactionStyleName = this.getTransactionStyleName( + transacAsSource, + '' + ); + featuresDisplayStates.push(transactionStyleName); + this.setCityObjectStyle(tileId, i, transactionStyleName); + } + } + if (featureTransactions.asDestination) { + const transacAsDest = featureTransactions.asDestination; + const transacAsDestHalfDuration = + (transacAsDest.endDate - transacAsDest.startDate) / 2; + if ( + this.currentTime > + transacAsDest.startDate + transacAsDestHalfDuration && + this.currentTime <= transacAsDest.endDate + ) { + hasTransac = true; + const transactionStyleName = this.getTransactionStyleName( + transacAsDest, + '' + ); + featuresDisplayStates.push(transactionStyleName); + this.setCityObjectStyle(tileId, i, transactionStyleName); + } + } - if (!hasTransac) { - // ** TRANSACTION NOT AT THE RIGHT DATE - featuresDisplayStates.push('hide'); - this.setCityObjectStyle(tileId, i, 'hide'); - } - } else { - // ** FEATURE DOES NOT EXIST AND THERE IS NO TRANSACTION + if (!hasTransac) { + // ** TRANSACTION NOT AT THE RIGHT DATE + featuresDisplayStates.push('hide'); + this.setCityObjectStyle(tileId, i, 'hide'); + } + } else { + // ** FEATURE DOES NOT EXIST AND THERE IS NO TRANSACTION - // ** MANAGE CREATIONS AND DEMOLITIONS (this step must be - // done because the creation and demolitions transactions - // are currently not in the tileset. However, the tileset - // should have them later on). - const halfVintage = 1.5; + // ** MANAGE CREATIONS AND DEMOLITIONS (this step must be + // done because the creation and demolitions transactions + // are currently not in the tileset. However, the tileset + // should have them later on). + const halfVintage = 1.5; - if (this.currentTime + halfVintage >= BT.startDates[i] && - this.currentTime < BT.startDates[i]) { - // ** CREATION - featuresDisplayStates.push('creation'); - this.setCityObjectStyle(tileId, i, 'creation'); - } else if (this.currentTime - halfVintage < BT.endDates[i] && - this.currentTime > BT.endDates[i]) { - // ** DEMOLITION - featuresDisplayStates.push('demolition'); - this.setCityObjectStyle(tileId, i, 'demolition'); - } else { - // ** FEATURE DOES NOT EXIST - featuresDisplayStates.push('hide'); - this.setCityObjectStyle(tileId, i, 'hide'); - } - } + if ( + this.currentTime + halfVintage >= BT.startDates[i] && + this.currentTime < BT.startDates[i] + ) { + // ** CREATION + featuresDisplayStates.push('creation'); + this.setCityObjectStyle(tileId, i, 'creation'); + } else if ( + this.currentTime - halfVintage < BT.endDates[i] && + this.currentTime > BT.endDates[i] + ) { + // ** DEMOLITION + featuresDisplayStates.push('demolition'); + this.setCityObjectStyle(tileId, i, 'demolition'); + } else { + // ** FEATURE DOES NOT EXIST + featuresDisplayStates.push('hide'); + this.setCityObjectStyle(tileId, i, 'hide'); + } } + } - return featuresDisplayStates; + return featuresDisplayStates; } /** - * Computes and sets the style of the features of a given tile. + * Computes and sets the style of the features of a given tile. * @param {Number} tileId The id of the given tile. */ computeTileState(tileId) { @@ -226,53 +278,63 @@ export class TemporalProvider { if (tileId === 0) return; // Skip the root tile which has no geometry // If it has already been computed, don't do it again - if (this.COStyles.has(this.currentTime) && - this.COStyles.get(this.currentTime).has(tileId)) { - const tileDisplayStates = this.COStyles.get(this.currentTime).get(tileId); - for (let i = 0 ; i < tileDisplayStates.length ; i++) { - this.setCityObjectStyle(tileId, i, tileDisplayStates[i]); - } + if ( + this.COStyles.has(this.currentTime) && + this.COStyles.get(this.currentTime).has(tileId) + ) { + const tileDisplayStates = this.COStyles.get(this.currentTime).get(tileId); + for (let i = 0; i < tileDisplayStates.length; i++) { + this.setCityObjectStyle(tileId, i, tileDisplayStates[i]); + } } else { - if (this.tempExtModel.temporalBatchTables.has(tileId)) { - const tileTemporalBT = this.tempExtModel.temporalBatchTables.get(tileId); - if (! this.COStyles.has(this.currentTime)) { - this.COStyles.set(this.currentTime, new Map()); - } - this.COStyles.get(this.currentTime).set(tileId, this.culling(tileTemporalBT, tileId, this.tempExtModel.transactionsPerTile.get(tileId))); - } else { + if (this.tempExtModel.temporalBatchTables.has(tileId)) { + const tileTemporalBT = + this.tempExtModel.temporalBatchTables.get(tileId); + if (!this.COStyles.has(this.currentTime)) { + this.COStyles.set(this.currentTime, new Map()); + } + this.COStyles.get(this.currentTime).set( + tileId, + this.culling( + tileTemporalBT, + tileId, + this.tempExtModel.transactionsPerTile.get(tileId) + ) + ); + } else { console.warn(`Cannot compute features states for tile ${tileId} since the temporal extension of the batch table has not yet been loaded for this tile`); return; - } + } } } /** * Computes and applies the display state of a tile. This method - * is triggered by an event (TilesManager.EVENT_TILE_LOADED) - * indicating that a new tile content has been loaded (e.g. because it + * is triggered by an event (TilesManager.EVENT_TILE_LOADED) + * indicating that a new tile content has been loaded (e.g. because it * becomes visible by the camera) * @param {Object} tileContent The tile content loaded. */ changeTileState(tileContent) { - this.computeTileState(tileContent.tileId); - this.tilesManager.applyStyleToTile(tileContent.tileId, - { updateView: false }); - } + this.computeTileState(tileContent.tileId); + this.tilesManager.applyStyleToTile(tileContent.tileId, { + updateView: false, + }); + } /** - * Computes and applies the display state of currently visible tiles - * (i.e. those in the camera field of view and having features - * at the current display time). This method is triggered by the + * Computes and applies the display state of currently visible tiles + * (i.e. those in the camera field of view and having features + * at the current display time). This method is triggered by the * TemporalView when the time of the view is updated. */ changeVisibleTilesStates() { - const tiles = getVisibleTiles(this.tilesManager.layer); - for (let i = 0; i < tiles.length; i++) { - this.computeTileState(tiles[i].tileId); - } - this.tilesManager.applyStyles(); + const tiles = getVisibleTiles(this.tilesManager.layer); + for (let i = 0; i < tiles.length; i++) { + this.computeTileState(tiles[i].tileId); + } + this.tilesManager.applyStyles(); } - -} \ No newline at end of file +} From 92ac4747c3fe95ba781fa7b6b62712b1df150e1b Mon Sep 17 00:00:00 2001 From: valentinMachado Date: Tue, 8 Jun 2021 11:10:10 +0200 Subject: [PATCH 59/68] eslint return no error --- .eslintrc.js | 1 + .travis.yml | 11 +- package.json | 3 +- src/Components/3DTiles/3DTilesUtils.js | 20 +- src/Components/3DTiles/Model/CityObject.js | 2 +- .../3DTiles/Model/CityObjectStyle.js | 4 +- src/Components/3DTiles/StyleManager.js | 14 +- src/Components/3DTiles/TilesManager.js | 60 +-- src/Components/Camera/CameraUtils.js | 17 +- src/Components/Camera/PositionerWindow.js | 4 +- .../DataProcessing/DataProcessing.js | 36 +- src/Components/Events/EventSender.js | 96 ++--- src/Components/GUI/js/Draggable.js | 70 ++-- src/Components/GUI/js/Window.js | 396 +++++++++--------- src/Components/GUI/js/WindowExtension.js | 8 +- src/Components/GUI/js/WindowManager.js | 2 +- src/Components/LayerManager/LayerManager.js | 254 +++++------ src/Components/ModuleView/ModuleView.js | 84 ++-- src/Components/Request/RequestService.js | 132 +++--- src/Game/Components/AssetsManager.js | 22 +- .../Shared/GameObject/Components/Collider.js | 50 ++- src/Game/Shared/GameObject/GameObject.js | 9 - src/Game/Shared/WorldState.js | 2 +- src/Game/UDVDebugger/UDVDebugger.js | 18 - .../View/CityObjectFilterWindow.js | 4 +- .../CityObjects/View/CityObjectWindow.js | 6 +- .../CityObjects/ViewModel/AttributeFilter.js | 6 +- .../ViewModel/CityObjectProvider.js | 6 +- .../Documents/View/DocumentNavigatorWindow.js | 16 +- .../3DTilesDebug/views/3DTilesDebugWindow.js | 4 +- .../Contribute/View/DocumentCreationWindow.js | 2 +- .../views/DocumentCommentsWindow.js | 8 +- .../Geocoding/services/GeocodingService.js | 4 +- .../Geocoding/views/GeocodingView.js | 4 +- .../GuidedTour/GuidedTourController.js | 4 +- src/Widgets/LayerChoice/views/LayerChoice.js | 36 +- .../Links/View/CityObjectLinkInterface.js | 7 +- .../Links/View/DocumentLinkInterface.js | 12 +- 38 files changed, 715 insertions(+), 719 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 00b804fc4..6b41370fc 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -19,5 +19,6 @@ module.exports = { 'linebreak-style': ['error', 'unix'], quotes: ['error', 'single'], semi: ['error', 'always'], + 'no-unused-vars': 'off', }, }; diff --git a/.travis.yml b/.travis.yml index fcaa6727f..3683952db 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,10 +18,9 @@ install: jobs: include: - - stage: test + - stage: build script: - - npm run test - # - stage: lint - # script: - # - ./node_modules/eslint/bin/eslint.js --version - # - npm run lint + - npm run build + - stage: eslint + script: + - npm run eslint diff --git a/package.json b/package.json index 28ac51c2e..f9a72ec1b 100644 --- a/package.json +++ b/package.json @@ -4,8 +4,7 @@ "description": "A collection of itowns plugins", "main": "src", "scripts": { - "eslint": "./node_modules/.bin/eslint ./src", - "test": "npm run build", + "eslint": "./node_modules/.bin/eslint ./src --fix", "build": "cross-env NODE_ENV=production webpack", "build-debug": "cross-env NODE_ENV=development webpack", "debug": "nodemon --verbose --watch src --delay 2500ms ./bin/debug.js -e js,css,html" diff --git a/src/Components/3DTiles/3DTilesUtils.js b/src/Components/3DTiles/3DTilesUtils.js index 97f192b35..4d49d5235 100644 --- a/src/Components/3DTiles/3DTilesUtils.js +++ b/src/Components/3DTiles/3DTilesUtils.js @@ -9,9 +9,9 @@ import { objectEquals } from '../DataProcessing/DataProcessing.js'; * @param {*} tile A 3DTiles tile object from THREE.js. */ export function getBatchTableFromTile(tile) { - if (!!tile.batchTable) { + if (tile.batchTable) { return tile.batchTable; - } else if (!!tile.parent) { + } else if (tile.parent) { return getBatchTableFromTile(tile.parent); } return undefined; @@ -66,11 +66,11 @@ export function getVisibleTiles(layer) { let rootTile = layer.object3d.children[0]; let tiles = []; let exploreTree = (node) => { - if (!!node) { - if (!!node.batchTable) { + if (node) { + if (node.batchTable) { // It's an actual tile tiles.push(node); - }; + } for (let childIndex = 0; childIndex < node.children.length; childIndex++) { let child = node.children[childIndex]; if (child.type === 'Object3D') { @@ -157,8 +157,8 @@ export function setTileVerticesColor(tile, newColor, indexArray = null) { if (!!indexArray && (lowerBound > i || upperBound < i)) { //If i is not one of the selected indexes, we keep the previous color let previousColor = (tile.geometry.attributes.color) ? - tile.geometry.attributes.color.array.slice(i * 3, i * 3 + 3) : - tile.material.color.toArray(); + tile.geometry.attributes.color.array.slice(i * 3, i * 3 + 3) : + tile.material.color.toArray(); vertexColor = previousColor; } @@ -215,8 +215,8 @@ export function createTileGroups(tile, materialsProps, ranges) { let mesh = getMeshFromTile(tile); let defaultMaterial = Array.isArray(mesh.material) ? - mesh.material[0] : - mesh.material; + mesh.material[0] : + mesh.material; // Reset the materials mesh.material = [ defaultMaterial ]; @@ -335,7 +335,7 @@ export function createTileGroupsFromBatchIDs(tile, groups) { if (materialIndex < 0) { // If the material is new, push it materialIndex = materials.length; - materials.push(group.material) + materials.push(group.material); } // Push the batch IDs and remember their material diff --git a/src/Components/3DTiles/Model/CityObject.js b/src/Components/3DTiles/Model/CityObject.js index 2cf7a218e..b50305560 100644 --- a/src/Components/3DTiles/Model/CityObject.js +++ b/src/Components/3DTiles/Model/CityObject.js @@ -1,4 +1,4 @@ -import { Tile } from "./Tile.js"; +import { Tile } from './Tile.js'; import * as THREE from 'three'; /** diff --git a/src/Components/3DTiles/Model/CityObjectStyle.js b/src/Components/3DTiles/Model/CityObjectStyle.js index 0ee07dff1..7c3c4c509 100644 --- a/src/Components/3DTiles/Model/CityObjectStyle.js +++ b/src/Components/3DTiles/Model/CityObjectStyle.js @@ -1,4 +1,4 @@ -import * as THREE from "three"; +import * as THREE from 'three'; /** * Represents the style of a tile part. Accepted parameters are : @@ -14,7 +14,7 @@ export class CityObjectStyle { */ this.materialProps = null; - if (typeof(params) !== "object") { + if (typeof(params) !== 'object') { throw 'TilePartStyle require parameters in its constructor'; } diff --git a/src/Components/3DTiles/StyleManager.js b/src/Components/3DTiles/StyleManager.js index c72c513eb..5f668076e 100644 --- a/src/Components/3DTiles/StyleManager.js +++ b/src/Components/3DTiles/StyleManager.js @@ -1,7 +1,7 @@ -import { CityObjectStyle } from "./Model/CityObjectStyle.js"; -import { CityObjectID } from "./Model/CityObject.js"; -import { createTileGroups } from "./3DTilesUtils.js"; -import { Tile } from "./Model/Tile.js"; +import { CityObjectStyle } from './Model/CityObjectStyle.js'; +import { CityObjectID } from './Model/CityObject.js'; +import { createTileGroups } from './3DTilesUtils.js'; +import { Tile } from './Model/Tile.js'; /** * Class used to manage the styles of city objects. @@ -115,9 +115,9 @@ export class StyleManager { * @returns {CityObjectStyle} */ getStyle(identifier) { - if (typeof(identifier) === "string") { + if (typeof(identifier) === 'string') { return this.registeredStyles[identifier]; - } else if (typeof(identifier) === "number") { + } else if (typeof(identifier) === 'number') { return this.anonymousStyles[identifier]; } throw 'Style identifier must be a string or a number'; @@ -197,7 +197,7 @@ export class StyleManager { this._registerUsage(styleIdentifier, cityObjectId); } else if (Array.isArray(cityObjectId)) { cityObjectId.sort((idA, idB) => { - return idA.tileId - idB.tileId + return idA.tileId - idB.tileId; }); for (let id of cityObjectId) { if (this.styleTable[id.tileId] === undefined) { diff --git a/src/Components/3DTiles/TilesManager.js b/src/Components/3DTiles/TilesManager.js index 792e03d0c..12b645fa5 100644 --- a/src/Components/3DTiles/TilesManager.js +++ b/src/Components/3DTiles/TilesManager.js @@ -1,9 +1,9 @@ -import { Tile } from "./Model/Tile.js"; -import { getVisibleTiles, updateITownsView } from "./3DTilesUtils.js"; -import { CityObjectID, CityObject, createCityObjectID } from "./Model/CityObject.js"; -import { CityObjectStyle } from "./Model/CityObjectStyle.js"; -import { StyleManager } from "./StyleManager.js"; -import { EventSender } from "../Events/EventSender.js"; +import { Tile } from './Model/Tile.js'; +import { getVisibleTiles, updateITownsView } from './3DTilesUtils.js'; +import { CityObjectID, CityObject, createCityObjectID } from './Model/CityObject.js'; +import { CityObjectStyle } from './Model/CityObjectStyle.js'; +import { StyleManager } from './StyleManager.js'; +import { EventSender } from '../Events/EventSender.js'; /** * Manages the tiles and the style for city objects. @@ -54,15 +54,15 @@ export class TilesManager extends EventSender { this.tiles = []; if (this.totalTileCount !== 0) { - // Load existing tiles - const tiles = getVisibleTiles(this.layer); - for (let tile of tiles) { - if (this.tiles[tile.tileId] === undefined) { - this.tiles[tile.tileId] = new Tile(this.layer, tile.tileId); - this.tiles[tile.tileId].loadCityObjects(); - this.loadedTileCount += 1; - } + // Load existing tiles + const tiles = getVisibleTiles(this.layer); + for (let tile of tiles) { + if (this.tiles[tile.tileId] === undefined) { + this.tiles[tile.tileId] = new Tile(this.layer, tile.tileId); + this.tiles[tile.tileId].loadCityObjects(); + this.loadedTileCount += 1; } + } } ///// EVENTS @@ -93,22 +93,22 @@ export class TilesManager extends EventSender { } loadTile(tile) { - // Update the totalTileCount. - // TODO: this should be managed with an event: when the tileset is - // loaded (i.e. tileIndex filled), then totalTileCount should be set. - this.totalTileCount = this.layer.tileset.tiles.length; - // Verifies that the tile has not been already added (might be removed - // when tile unloading will be managed) - if (this.tiles[tile.tileId] === undefined) { - this.tiles[tile.tileId] = new Tile(this.layer, tile.tileId); - this.tiles[tile.tileId].loadCityObjects(); - this.loadedTileCount += 1; - } - // Callback when a tile is loaded. - // TODO: Les tuiles d'iTowns devraient etre rendues invisibles plutot - // que d'etre déchargées et rechargées. A ce moment là, ce callback - // pourra etre dans le if ci dessus - this.sendEvent(TilesManager.EVENT_TILE_LOADED, tile); + // Update the totalTileCount. + // TODO: this should be managed with an event: when the tileset is + // loaded (i.e. tileIndex filled), then totalTileCount should be set. + this.totalTileCount = this.layer.tileset.tiles.length; + // Verifies that the tile has not been already added (might be removed + // when tile unloading will be managed) + if (this.tiles[tile.tileId] === undefined) { + this.tiles[tile.tileId] = new Tile(this.layer, tile.tileId); + this.tiles[tile.tileId].loadCityObjects(); + this.loadedTileCount += 1; + } + // Callback when a tile is loaded. + // TODO: Les tuiles d'iTowns devraient etre rendues invisibles plutot + // que d'etre déchargées et rechargées. A ce moment là, ce callback + // pourra etre dans le if ci dessus + this.sendEvent(TilesManager.EVENT_TILE_LOADED, tile); } /** diff --git a/src/Components/Camera/CameraUtils.js b/src/Components/Camera/CameraUtils.js index 74d5815b5..f5cb1794e 100644 --- a/src/Components/Camera/CameraUtils.js +++ b/src/Components/Camera/CameraUtils.js @@ -1,6 +1,10 @@ +/** @format */ + +const THREE = require('three'); + /** * Makes the camera move to focus on the target position. - * + * * @param {itowns.View} view The iTowns view. * @param {itowns.PlanarControls} controls The camera controls. * @param {THREE.Vector3} targetPos The target position. @@ -23,10 +27,11 @@ export function focusCameraOn(view, controls, targetPos, options = {}) { const horizontalDist = options.horizontalDistance || 1000; let cameraPos = view.camera.camera3D.position.clone(); - const direction = (new THREE.Vector3()).subVectors(targetPos, cameraPos); - const currentDist = Math.sqrt(direction.x * direction.x + - direction.y * direction.y); - cameraPos.addScaledVector(direction, (1 - horizontalDist / currentDist)); + const direction = new THREE.Vector3().subVectors(targetPos, cameraPos); + const currentDist = Math.sqrt( + direction.x * direction.x + direction.y * direction.y + ); + cameraPos.addScaledVector(direction, 1 - horizontalDist / currentDist); cameraPos.z = targetPos.z + verticalDist; const travelDuration = duration ? duration : 'auto'; const timeoutDuration = duration ? duration * 1000 : 0; @@ -36,4 +41,4 @@ export function focusCameraOn(view, controls, targetPos, options = {}) { reject(e); } }); -} \ No newline at end of file +} diff --git a/src/Components/Camera/PositionerWindow.js b/src/Components/Camera/PositionerWindow.js index 81ad9ecef..fc2c3eed3 100644 --- a/src/Components/Camera/PositionerWindow.js +++ b/src/Components/Camera/PositionerWindow.js @@ -1,4 +1,4 @@ -import { Window } from "../GUI/js/Window"; +import { Window } from '../GUI/js/Window'; import { MAIN_LOOP_EVENTS } from 'itowns'; import * as THREE from 'three'; @@ -60,7 +60,7 @@ export class PositionerWindow extends Window { this.buttonValidateElement.onclick = () => { this._validate(); - } + }; } ///////////////////////// diff --git a/src/Components/DataProcessing/DataProcessing.js b/src/Components/DataProcessing/DataProcessing.js index c0c6f0baa..4da11ed30 100644 --- a/src/Components/DataProcessing/DataProcessing.js +++ b/src/Components/DataProcessing/DataProcessing.js @@ -3,14 +3,17 @@ * would update those fields to an empty string if they were sent in the * body. To check if a value is empty, this function just convert it into * a boolean. + * + * @format * @param {FormData} formData The form data. * @returns The same data, without the fields containing an empty value. */ + export function removeEmptyValues(formData) { let emptyKeys = []; formData.forEach((value, key) => { if (!value) { - emptyKeys.push(key) + emptyKeys.push(key); } }); emptyKeys.forEach((key) => { @@ -24,7 +27,7 @@ export function removeEmptyValues(formData) { * on a file) to a data URI. This is required, for example, to display images * fetched from the server. As we need authentication headers to retrieve some * protected files, we get the raw data dynamically and need to convert it to - * a data URI do display it. + * a data URI do display it. * The basic scheme of the URI is defined in the * [RFC 2397](https://tools.ietf.org/html/rfc2397), with the mediaType set to * `mimeType` and the raw data converted to base64. @@ -45,12 +48,13 @@ export function imageToDataURI(arrayBuffer, mimeType, chunkSize = 8 * 1024) { // String.fromCharCode), we need to split it into chunks let responseAsString = ''; for (let i = 0; i < responseArray.length / chunkSize; i++) { - responseAsString += String.fromCharCode.apply(null, - responseArray.slice(i * chunkSize, (i + 1) * chunkSize)); + responseAsString += String.fromCharCode.apply( + null, + responseArray.slice(i * chunkSize, (i + 1) * chunkSize) + ); } - let b64data = 'data:' + mimeType - + ';base64,' + btoa(responseAsString); + let b64data = 'data:' + mimeType + ';base64,' + btoa(responseAsString); return b64data; } @@ -58,11 +62,11 @@ export function imageToDataURI(arrayBuffer, mimeType, chunkSize = 8 * 1024) { * Gets an attribute of an object from the given path. To get nested attributes, * the path qualifiers must be separated by dots ('.'). If the path is not * nested (does not contain any dot), the function is equivalent to `obj[path]`. - * - * - * @param {object} obj - * @param {string} path - * + * + * + * @param {object} obj + * @param {string} path + * * @example * const obj = {test: {msg: "Hello world !"}}; * console.log(getAttributeByPath(obj, "test.msg")); // prints "Hello world !"; @@ -83,7 +87,7 @@ export function getAttributeByPath(obj, path) { /** * Checks the equality of two objects by their properties. For two objects to * be equal, they must have the same keys and the same values. - * + * * @param {any} a An object. * @param {any} b An object. */ @@ -91,16 +95,16 @@ export function objectEquals(a, b) { // Set of a's keys let keys = new Set(Object.keys(a)); for (let key of Object.keys(b)) { - if (!keys.has(key)) { + if (!keys.has(key)) { // If b has a key unknown to a, they aren't equal - return false; + return false; } } for (let key of keys) { // For each key of a, b must also have the key and the values must be equal if (b[key] === undefined || a[key] !== b[key]) { - return false; + return false; } } return true; -}; \ No newline at end of file +} diff --git a/src/Components/Events/EventSender.js b/src/Components/Events/EventSender.js index 212c1a9e5..78fe89c43 100644 --- a/src/Components/Events/EventSender.js +++ b/src/Components/Events/EventSender.js @@ -4,98 +4,98 @@ * specific events, or to all events. */ export class EventSender { - constructor() { - /** + constructor() { + /** * The listeners attached to a specific event. * * @type {Object. any>>} */ - this.eventListeners = {}; - /** + this.eventListeners = {}; + /** * The listeners attached to no particular event. They will receive * all notifications. * * @type {Array<(data: any) => any>} */ - this.allEventsListeners = []; - } + this.allEventsListeners = []; + } - /** + /** * Registers an event. Should be called by the implementing class to * specify its own events. * @param event The event to register. Can be of any type. The class will be * able to send only the events that it has registered. */ - registerEvent(event) { - this.eventListeners[event] = []; - } + registerEvent(event) { + this.eventListeners[event] = []; + } - /** + /** * Registers an event listener attached to a specific event. The `action` * function will be called only when `event` is fired. * * @param event The event to listen to. * @param {(data: any)} action The function to call. */ - addEventListener(event, action) { - if (this.eventListeners[event]) { - this.eventListeners[event].push(action); - } else { - throw `This event is not defined by this listener : ${event}`; - } + addEventListener(event, action) { + if (this.eventListeners[event]) { + this.eventListeners[event].push(action); + } else { + throw `This event is not defined by this listener : ${event}`; } + } - /** + /** * Registers an event listener attached to no specific event. The `action` * function will be called when any event is fired. * * @param {(event: any, data: any)} action The function to call. */ - addListener(action) { - if (typeof(action) !== 'function') { - throw 'A listener must be a function'; - } - this.allEventsListeners.push(action); + addListener(action) { + if (typeof(action) !== 'function') { + throw 'A listener must be a function'; } + this.allEventsListeners.push(action); + } - /** + /** * Sends an event to the listeners. `event` must be first registers through the `registerEvent` * method. An argument can be passed but is optional. * * @param event The event to fire. Must be first registered. * @param data The optional data to pass as parameter. */ - async sendEvent(event, data = null) { - let listeners = this.eventListeners[event]; - if (!!listeners) { - for (let action of listeners) { - action(data); - } - for (let action of this.allEventsListeners) { - action(event, data); - } - } else { - throw `This event must be registered before being sent : ${event}`; - } + async sendEvent(event, data = null) { + let listeners = this.eventListeners[event]; + if (listeners) { + for (let action of listeners) { + action(data); + } + for (let action of this.allEventsListeners) { + action(event, data); + } + } else { + throw `This event must be registered before being sent : ${event}`; } + } - /** + /** * Removes a specific event listener. * * @param {(data: any) => any} action The event listener to remove. This * should be the same reference that was used to register it. */ - removeEventListener(action) { - for (let eventListeners of Object.values(this.eventListeners)) { - let index = eventListeners.findIndex((list) => action === list); - if (index >= 0) { - eventListeners.splice(index, 1); - } - } + removeEventListener(action) { + for (let eventListeners of Object.values(this.eventListeners)) { + let index = eventListeners.findIndex((list) => action === list); + if (index >= 0) { + eventListeners.splice(index, 1); + } + } - let index = this.allEventsListeners.findIndex((list) => action === list); - if (index >= 0) { - this.allEventsListeners.splice(index, 1); - } + let index = this.allEventsListeners.findIndex((list) => action === list); + if (index >= 0) { + this.allEventsListeners.splice(index, 1); } + } } \ No newline at end of file diff --git a/src/Components/GUI/js/Draggable.js b/src/Components/GUI/js/Draggable.js index fe4149478..7ae2bef9e 100644 --- a/src/Components/GUI/js/Draggable.js +++ b/src/Components/GUI/js/Draggable.js @@ -1,44 +1,44 @@ // Code from https://www.w3schools.com/howto/howto_js_draggable.asp // Make the DIV element draggable: export function dragElement(elmnt, dragelmnt) { - var pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0; + var pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0; - dragelmnt.onmousedown = dragMouseDown; + dragelmnt.onmousedown = dragMouseDown; - function dragMouseDown(e) { - e = e || window.event; - // get the mouse cursor position at startup: - pos3 = e.clientX; - pos4 = e.clientY; - document.onmouseup = closeDragElement; - // call a function whenever the cursor moves: - document.onmousemove = elementDrag; - } + function dragMouseDown(e) { + e = e || window.event; + // get the mouse cursor position at startup: + pos3 = e.clientX; + pos4 = e.clientY; + document.onmouseup = closeDragElement; + // call a function whenever the cursor moves: + document.onmousemove = elementDrag; + } - function elementDrag(e) { - e = e || window.event; - e.preventDefault(); - // calculate the new cursor position: - pos1 = pos3 - e.clientX; - pos2 = pos4 - e.clientY; - pos3 = e.clientX; - pos4 = e.clientY; - // set the element's new position: - let newTop = (elmnt.offsetTop - pos2); - if (newTop < 0) { - newTop = 0; - } - let newLeft = (elmnt.offsetLeft - pos1); - if (newLeft < 0) { - newLeft = 0; - } - elmnt.style.top = newTop + "px"; - elmnt.style.left = newLeft + "px"; + function elementDrag(e) { + e = e || window.event; + e.preventDefault(); + // calculate the new cursor position: + pos1 = pos3 - e.clientX; + pos2 = pos4 - e.clientY; + pos3 = e.clientX; + pos4 = e.clientY; + // set the element's new position: + let newTop = (elmnt.offsetTop - pos2); + if (newTop < 0) { + newTop = 0; } - - function closeDragElement() { - // stop moving when mouse button is released: - document.onmouseup = null; - document.onmousemove = null; + let newLeft = (elmnt.offsetLeft - pos1); + if (newLeft < 0) { + newLeft = 0; } + elmnt.style.top = newTop + 'px'; + elmnt.style.left = newLeft + 'px'; + } + + function closeDragElement() { + // stop moving when mouse button is released: + document.onmouseup = null; + document.onmousemove = null; + } } \ No newline at end of file diff --git a/src/Components/GUI/js/Window.js b/src/Components/GUI/js/Window.js index 229bccd08..47d92c3b7 100644 --- a/src/Components/GUI/js/Window.js +++ b/src/Components/GUI/js/Window.js @@ -1,6 +1,6 @@ import { dragElement } from './Draggable.js'; import { ModuleView } from '../../ModuleView/ModuleView.js'; -import { windowManager } from "./WindowManager.js"; +import { windowManager } from './WindowManager.js'; import { WindowExtension } from './WindowExtension.js'; // Documentation is on the Wiki @@ -12,7 +12,7 @@ import { WindowExtension } from './WindowExtension.js'; * @extends ModuleView */ export class Window extends ModuleView { - /** + /** * Creates a window. * * @param {string} uniqueName The name used to generate HTML ids. @@ -21,160 +21,160 @@ export class Window extends ModuleView { * the 'close' button is hit. If set to true, the window will `hide`. If set * to false, the window will `dispose`. */ - constructor(uniqueName, title, hideOnClose = true) { - super(); + constructor(uniqueName, title, hideOnClose = true) { + super(); - /** + /** * Name of the window. Used to generate unique ids. * * @member {string} */ - this.name = uniqueName; - /** + this.name = uniqueName; + /** * Title displayed on the window. * * @member {string} */ - this.title = title; - /** + this.title = title; + /** * Behaviour of the window when the 'close' button is hit. If set to * true, the window will `hide`. If set to false, the window will * `dispose`. * * @member {boolean} */ - this.hideOnClose = hideOnClose; + this.hideOnClose = hideOnClose; - /** + /** * Defines if the window has its default style. If set to false, you * should override the `html` getter and set the `windowDisplayWhenVisible` * property. * * @type {true} */ - this.defaultStyle = true; + this.defaultStyle = true; - /** + /** * Define the css `display` property when the window is visible. * * @type {string} */ - this.windowDisplayWhenVisible = 'grid'; + this.windowDisplayWhenVisible = 'grid'; - /** + /** * The list of extensions for this window. * * @type {Array} */ - this.windowExtensions = []; + this.windowExtensions = []; - this.registerEvent(Window.EVENT_CREATED); - this.registerEvent(Window.EVENT_DESTROYED); - this.registerEvent(Window.EVENT_SHOWN); - this.registerEvent(Window.EVENT_HIDDEN); + this.registerEvent(Window.EVENT_CREATED); + this.registerEvent(Window.EVENT_DESTROYED); + this.registerEvent(Window.EVENT_SHOWN); + this.registerEvent(Window.EVENT_HIDDEN); - windowManager.registerWindow(this); - } + windowManager.registerWindow(this); + } - //////////// Methods to override - //////////////////////////////// + //////////// Methods to override + //////////////////////////////// - /** + /** * HTML string representing the inner content of the window. * * @abstract */ - get innerContentHtml() { - return null; - }; + get innerContentHtml() { + return null; + } - /** + /** * Method called when the window is created. During and after the call, * all HTML properties are not null. * * @abstract */ - windowCreated() { + windowCreated() { - }; + } - /** + /** * Method called when the window is destroyed. * * @abstract */ - windowDestroyed() { + windowDestroyed() { - }; + } - //////////// Do NOT override these methods - ////////////////////////////////////////// + //////////// Do NOT override these methods + ////////////////////////////////////////// - /** + /** * Creates the HTML elements of the window and add them to the given parent * node. Calls the `windowCreated` hook method and sends two events, * `EVENT_CREATED` and `EVENT_SHOWN`. * * @param {HTMLElement} htmlElement */ - appendTo(htmlElement) { - if (!this.isCreated) { - this.parentElement = htmlElement; - let windowDiv = document.createElement('div'); - windowDiv.innerHTML = this.html; - windowDiv.id = this.windowId; - htmlElement.appendChild(windowDiv); - if (this.defaultStyle) { - windowDiv.className = "window"; - dragElement(windowDiv, this.header); - this.headerCloseButton.onclick = this.disable.bind(this); - } - - for (let extension of this.windowExtensions) { - extension.appendTo(this.window); - } - - this.windowCreated(); - this.sendEvent(Window.EVENT_CREATED); - this.sendEvent(Window.EVENT_SHOWN); - } + appendTo(htmlElement) { + if (!this.isCreated) { + this.parentElement = htmlElement; + let windowDiv = document.createElement('div'); + windowDiv.innerHTML = this.html; + windowDiv.id = this.windowId; + htmlElement.appendChild(windowDiv); + if (this.defaultStyle) { + windowDiv.className = 'window'; + dragElement(windowDiv, this.header); + this.headerCloseButton.onclick = this.disable.bind(this); + } + + for (let extension of this.windowExtensions) { + extension.appendTo(this.window); + } + + this.windowCreated(); + this.sendEvent(Window.EVENT_CREATED); + this.sendEvent(Window.EVENT_SHOWN); } + } - /** + /** * Destroys the window. Calls the `windowDestroyed` hook method and sends an * `EVENT_DESTROYED` event. */ - dispose() { - if (this.isCreated) { - this.parentElement.removeChild(this.window); + dispose() { + if (this.isCreated) { + this.parentElement.removeChild(this.window); - this.windowDestroyed(); - this.sendEvent(Window.EVENT_DESTROYED); - } + this.windowDestroyed(); + this.sendEvent(Window.EVENT_DESTROYED); } + } - /** + /** * Shows the window. Sends an `EVENT_SHOWN` event. */ - show() { - if (this.isCreated && !this.isVisible) { - this.window.style.setProperty('display', this.windowDisplayWhenVisible); - this.sendEvent(Window.EVENT_SHOWN); - } + show() { + if (this.isCreated && !this.isVisible) { + this.window.style.setProperty('display', this.windowDisplayWhenVisible); + this.sendEvent(Window.EVENT_SHOWN); } + } - /** + /** * Hides the window. Sends an `EVENT_DESTROYED` event. */ - hide() { - if (this.isVisible) { - this.window.style.setProperty('display', 'none'); - this.sendEvent(Window.EVENT_HIDDEN); - } + hide() { + if (this.isVisible) { + this.window.style.setProperty('display', 'none'); + this.sendEvent(Window.EVENT_HIDDEN); } + } - get html() { - return ` + get html() { + return `

          ${this.title}

          @@ -185,12 +185,12 @@ export class Window extends ModuleView {

          `; - } + } - //////////// Extensions management - ////////////////////////////////// + //////////// Extensions management + ////////////////////////////////// - /** + /** * Adds a new extension in the window. * * @param {string} label The unique label for the extension. @@ -206,138 +206,138 @@ export class Window extends ModuleView { * @param {function} [options.callback] The callback to call when the user * clicks on a `button` extension. This has no effects on `div` extensions. */ - addExtension(label, options) { - options.id = `${this.windowId}__extensions_${label.toLowerCase().replace(/ +/, '_')}`; - let extension = new WindowExtension(label, options); - if (!!this.windowExtensions.find(ext => ext.label === label)) { - throw 'Extension already exist : ' + label; - } - this.windowExtensions.push(extension); - - if (this.isCreated) { - extension.appendTo(this.window); - } + addExtension(label, options) { + options.id = `${this.windowId}__extensions_${label.toLowerCase().replace(/ +/, '_')}`; + let extension = new WindowExtension(label, options); + if (this.windowExtensions.find(ext => ext.label === label)) { + throw 'Extension already exist : ' + label; } + this.windowExtensions.push(extension); - /** + if (this.isCreated) { + extension.appendTo(this.window); + } + } + + /** * Removes an existing extension from the window. * * @param {string} label The label identifying the extension to remove. */ - removeExtension(label) { - let index = this.windowExtensions.findIndex(ext => ext.label === label); - if (index < 0) { - throw 'Extension does not exist : ' + label; - } - - let extension = this.windowExtensions[index]; - if (this.isCreated) { - let extensionElement = document.getElementById(extension.id); - extensionElement.parentElement.removeChild(extensionElement); - } - - this.windowExtensions.splice(index, 1); + removeExtension(label) { + let index = this.windowExtensions.findIndex(ext => ext.label === label); + if (index < 0) { + throw 'Extension does not exist : ' + label; } - //////////// Module view overrides - ////////////////////////////////// + let extension = this.windowExtensions[index]; + if (this.isCreated) { + let extensionElement = document.getElementById(extension.id); + extensionElement.parentElement.removeChild(extensionElement); + } - /** + this.windowExtensions.splice(index, 1); + } + + //////////// Module view overrides + ////////////////////////////////// + + /** * Creates and show the window. * * @override */ - async enableView() { - this.appendTo(this.parentElement); - this.show(); - } + async enableView() { + this.appendTo(this.parentElement); + this.show(); + } - /** + /** * If `hideOnClose` is `true`, hides the window. Else, destroys it. * * @override */ - async disableView() { - if (this.hideOnClose) { - this.hide(); - } else { - this.dispose(); - } - } - - //////////// IDs, HTML and other getters - //////////////////////////////////////// - - get isCreated() { - let windowDiv = this.window; - return windowDiv !== null && windowDiv !== undefined; - } - - get isVisible() { - return this.isCreated && window.getComputedStyle(this.window).getPropertyValue('display') === this.windowDisplayWhenVisible; - } - - get windowId() { - return `_window_${this.name}`; - } - - get window() { - return document.getElementById(this.windowId); - } - - get headerId() { - return `_window_header_${this.name}`; - } - - get header() { - return document.getElementById(this.headerId); - } - - get headerTitleId() { - return `_window_header_title_${this.name}`; - } - - get headerTitle() { - return document.getElementById(this.headerTitleId); - } - - get headerCloseButtonId() { - return `_window_header_close_button_${this.name}`; - } - - get headerCloseButton() { - return document.getElementById(this.headerCloseButtonId); - } - - get contentId() { - return `_window_content_${this.name}`; - } - - get content() { - return document.getElementById(this.contentId); - } - - get innerContentId() { - return `_window_inner_content_${this.name}`; - } - - get innerContent() { - return document.getElementById(this.innerContentId); - } - - //////////// Events - /////////////////// - - static get EVENT_CREATED() { - return 'WINDOW_CREATED'; - } - static get EVENT_DESTROYED() { - return 'WINDOW_DESTROYED'; - } - static get EVENT_HIDDEN() { - return 'WINDOW_HIDDEN'; - } - static get EVENT_SHOWN() { - return 'WINDOW_SHOWN'; + async disableView() { + if (this.hideOnClose) { + this.hide(); + } else { + this.dispose(); } + } + + //////////// IDs, HTML and other getters + //////////////////////////////////////// + + get isCreated() { + let windowDiv = this.window; + return windowDiv !== null && windowDiv !== undefined; + } + + get isVisible() { + return this.isCreated && window.getComputedStyle(this.window).getPropertyValue('display') === this.windowDisplayWhenVisible; + } + + get windowId() { + return `_window_${this.name}`; + } + + get window() { + return document.getElementById(this.windowId); + } + + get headerId() { + return `_window_header_${this.name}`; + } + + get header() { + return document.getElementById(this.headerId); + } + + get headerTitleId() { + return `_window_header_title_${this.name}`; + } + + get headerTitle() { + return document.getElementById(this.headerTitleId); + } + + get headerCloseButtonId() { + return `_window_header_close_button_${this.name}`; + } + + get headerCloseButton() { + return document.getElementById(this.headerCloseButtonId); + } + + get contentId() { + return `_window_content_${this.name}`; + } + + get content() { + return document.getElementById(this.contentId); + } + + get innerContentId() { + return `_window_inner_content_${this.name}`; + } + + get innerContent() { + return document.getElementById(this.innerContentId); + } + + //////////// Events + /////////////////// + + static get EVENT_CREATED() { + return 'WINDOW_CREATED'; + } + static get EVENT_DESTROYED() { + return 'WINDOW_DESTROYED'; + } + static get EVENT_HIDDEN() { + return 'WINDOW_HIDDEN'; + } + static get EVENT_SHOWN() { + return 'WINDOW_SHOWN'; + } } \ No newline at end of file diff --git a/src/Components/GUI/js/WindowExtension.js b/src/Components/GUI/js/WindowExtension.js index 8a95604ef..71b9e9201 100644 --- a/src/Components/GUI/js/WindowExtension.js +++ b/src/Components/GUI/js/WindowExtension.js @@ -105,17 +105,17 @@ export class WindowExtension { */ findContainer(htmlRoot) { let queries = []; - if (!!this.container) { + if (this.container) { queries.push(`[data-ext-container="${this.type}-${this.container}"]`); queries.push(`[data-ext-container="${this.container}"]`); } - queries.push(`[data-ext-container="${this.type}"]`) - queries.push(`[data-ext-container-default="${this.type}"]`) + queries.push(`[data-ext-container="${this.type}"]`); + queries.push(`[data-ext-container-default="${this.type}"]`); let container; for (let query of queries) { container = htmlRoot.querySelector(query); - if (!!container) { + if (container) { break; } } diff --git a/src/Components/GUI/js/WindowManager.js b/src/Components/GUI/js/WindowManager.js index 5456ce52e..b57112f77 100644 --- a/src/Components/GUI/js/WindowManager.js +++ b/src/Components/GUI/js/WindowManager.js @@ -1,4 +1,4 @@ -import { Window } from "./Window.js"; +import { Window } from './Window.js'; const BASE_Z_INDEX = 100; diff --git a/src/Components/LayerManager/LayerManager.js b/src/Components/LayerManager/LayerManager.js index 3b15de9d0..d1435421c 100644 --- a/src/Components/LayerManager/LayerManager.js +++ b/src/Components/LayerManager/LayerManager.js @@ -1,247 +1,247 @@ -import { getFirstTileIntersection, getBatchIdFromIntersection, getObject3DFromTile, getVisibleTileCount } from "../3DTiles/3DTilesUtils.js"; +import { getFirstTileIntersection, getBatchIdFromIntersection, getObject3DFromTile, getVisibleTileCount } from '../3DTiles/3DTilesUtils.js'; export class LayerManager { - /** + /** * Creates a new TilesManager from an iTowns view and the 3DTiles layer. * * @param {*} view The iTowns view. */ - constructor(view) { - /** + constructor(view) { + /** * The iTowns view. */ - this.view = view; + this.view = view; - /** + /** * The set of tiles Manager that have been loaded. * @type {Array} */ - this.tilesManagers = []; - } + this.tilesManagers = []; + } - /** + /** * Register a new or modify an existing registered style for all tilesManager. * * @param {string} name A name to identify the style. * @param {CityObjectStyle} style The style to register. */ - registerStyle(name, style) { - this.tilesManagers.forEach(function(tilesManager){ - tilesManager.registerStyle(name, style); - }); - } + registerStyle(name, style) { + this.tilesManagers.forEach(function(tilesManager){ + tilesManager.registerStyle(name, style); + }); + } - /** + /** * Removes all styles currently registered. */ - removeAll3DTilesStyles() { - this.tilesManagers.forEach(function(tilesManager){ - tilesManager.removeAllStyles(); - }); - } + removeAll3DTilesStyles() { + this.tilesManagers.forEach(function(tilesManager){ + tilesManager.removeAllStyles(); + }); + } - /** + /** * Applies the current styles added with `setStyle` or `addStyle`. * * @param {object} options Options of the method. * @param {() => any} [options.updateFunction] The function used to update the * view. Default is `udpateITownsView(view, layer)`. */ - applyAll3DTilesStyles(options = {}) { - this.tilesManagers.forEach(function(tilesManager){ - tilesManager.applyStyles(options); - }); - } + applyAll3DTilesStyles(options = {}) { + this.tilesManagers.forEach(function(tilesManager){ + tilesManager.applyStyles(options); + }); + } - /** + /** * Check if at least one 3DTiles layer is visible * * @returns {boolean} */ - isOneLayerVisible() { - for (let i = 0; i < this.tilesManagers.length; i++) { - if (this.tilesManagers[i].layer.visible) { - return true; - } - } - return false; + isOneLayerVisible() { + for (let i = 0; i < this.tilesManagers.length; i++) { + if (this.tilesManagers[i].layer.visible) { + return true; + } } + return false; + } - /** + /** * Change the visibilty of all 3DTiles layers * */ - changeVisibility(bool) { - this.tilesManagers.forEach(function(tilesManager){ - tilesManager.layer.visible = bool ; - }); - } + changeVisibility(bool) { + this.tilesManagers.forEach(function(tilesManager){ + tilesManager.layer.visible = bool ; + }); + } - /** + /** * Update the scale of the given layer * @param {itowns.Layer} layer one layer loaded. * @param {float} scale Value of the new scale */ - updateScale(layer, scale) { - layer.scale = scale; - this.notifyChange(); - } + updateScale(layer, scale) { + layer.scale = scale; + this.notifyChange(); + } - /** + /** * Update the opacity of the given layer * @param {itowns.Layer} layer one layer loaded. * @param {float} opacity Value of the new scale */ - updateOpacity(layer, opacity) { - layer.opacity = opacity; - this.notifyChange(); - } - /** + updateOpacity(layer, opacity) { + layer.opacity = opacity; + this.notifyChange(); + } + /** * Update the view when called. Must be called when a change have been made * The view.camera.camera3D is passed to actualize all of the layer, but the * the documentation of notifyChange says taht it should not be needed */ - notifyChange() { - this.view.notifyChange(this.view.camera.camera3D); - } + notifyChange() { + this.view.notifyChange(this.view.camera.camera3D); + } - /** + /** * Returns the city object under the mouse cursor. * * @param {MouseEvent} event The mouse event. * * @returns {CityObject | undefined} */ - pickCityObject(event) { - /** + pickCityObject(event) { + /** * Make sure the event is captured by a click listener attached * to the div#viewerDiv, which contains the iTowns canvas. All click * listeners should be instantiated this way as of iTowns 2.24.0 */ - if (event.currentTarget.id.toUpperCase() === 'VIEWERDIV') { - // Get the intersecting objects where our mouse pointer is - let intersections = []; - //As the current pickObjectsAt on all layer is not working, we need - //to call pickObjectsAt() for each layer. - for (let i = 0; i < this.tilesManagers.length; i++) { - intersections = intersections.concat(this.view.pickObjectsAt( - event, - 5, - this.tilesManagers[i].layer - )); - } - let firstInter = getFirstTileIntersection(intersections); - if (!!firstInter) { - let tilesManager = this.getTilesManagerByLayerID(firstInter.layer.id); - let batchId = getBatchIdFromIntersection(firstInter); - let tileId = getObject3DFromTile(firstInter.object).tileId; - return tilesManager.tiles[tileId].cityObjects[batchId]; - } - } - return undefined; - } - - /** + if (event.currentTarget.id.toUpperCase() === 'VIEWERDIV') { + // Get the intersecting objects where our mouse pointer is + let intersections = []; + //As the current pickObjectsAt on all layer is not working, we need + //to call pickObjectsAt() for each layer. + for (let i = 0; i < this.tilesManagers.length; i++) { + intersections = intersections.concat(this.view.pickObjectsAt( + event, + 5, + this.tilesManagers[i].layer + )); + } + let firstInter = getFirstTileIntersection(intersections); + if (firstInter) { + let tilesManager = this.getTilesManagerByLayerID(firstInter.layer.id); + let batchId = getBatchIdFromIntersection(firstInter); + let tileId = getObject3DFromTile(firstInter.object).tileId; + return tilesManager.tiles[tileId].cityObjects[batchId]; + } + } + return undefined; + } + + /** * Returns a tilesManager given a layer ID. * * @param {string} id the layer ID. * * @returns {TilesManager} */ - getTilesManagerByLayerID(id) { - for (let i = 0; i < this.tilesManagers.length; i++) { - if (this.tilesManagers[i].layer.id === id) - return this.tilesManagers[i]; - } + getTilesManagerByLayerID(id) { + for (let i = 0; i < this.tilesManagers.length; i++) { + if (this.tilesManagers[i].layer.id === id) + return this.tilesManagers[i]; } + } - /** + /** * Get all Layers loaded in the view. */ - getLayers() { - return this.view.getLayers(); - } + getLayers() { + return this.view.getLayers(); + } - /** + /** * Get the number of tiles that have been loaded, across all the tileset that * have been loaded * * @returns {int} */ - getLoaded3DTilesTileCount() { - let loadedTileCount = 0; - for (let i = 0; i < this.tilesManagers.length; i++) { - loadedTileCount += this.tilesManagers[i].loadedTileCount; - } - return loadedTileCount; + getLoaded3DTilesTileCount() { + let loadedTileCount = 0; + for (let i = 0; i < this.tilesManagers.length; i++) { + loadedTileCount += this.tilesManagers[i].loadedTileCount; } + return loadedTileCount; + } - /** + /** * Get the number of tiles across all the tileset * * @returns {int} */ - getTotal3DTilesTileCount() { - let totalTileCount = 0; - for (let i = 0; i < this.tilesManagers.length; i++) { - totalTileCount += this.tilesManagers[i].totalTileCount; - } - return totalTileCount; + getTotal3DTilesTileCount() { + let totalTileCount = 0; + for (let i = 0; i < this.tilesManagers.length; i++) { + totalTileCount += this.tilesManagers[i].totalTileCount; } + return totalTileCount; + } - /** + /** * Get the number of tiles visible, across all the tileset that * have been loaded * * @returns {int} */ - getVisible3DTilesTileCountFromLayers() { - let visibleTileCount = 0; - for (let i = 0; i < this.tilesManagers.length; i++) { - visibleTileCount += getVisibleTileCount(this.tilesManagers[i].layer); - } - return visibleTileCount; + getVisible3DTilesTileCountFromLayers() { + let visibleTileCount = 0; + for (let i = 0; i < this.tilesManagers.length; i++) { + visibleTileCount += getVisibleTileCount(this.tilesManagers[i].layer); } + return visibleTileCount; + } - /** + /** * Get Color layers in the view * * @returns {Array} */ - getColorLayers() { - return this.view.getLayers(layer => layer.isColorLayer); - } + getColorLayers() { + return this.view.getLayers(layer => layer.isColorLayer); + } - /** + /** * Get Elevation layers in the view * * @returns {Array} */ - getElevationLayers() { - return this.view.getLayers(layer => layer.isElevationLayer); - } + getElevationLayers() { + return this.view.getLayers(layer => layer.isElevationLayer); + } - /** + /** * Get Geometry layers in the view * * @returns {Array} */ - getGeometryLayers() { - return this.view.getLayers(layer => layer.isGeometryLayer); - } + getGeometryLayers() { + return this.view.getLayers(layer => layer.isGeometryLayer); + } - /** + /** * Get Geometry layers in the view, without the planar one * * @returns {Array} */ - getGeometryLayersWithoutPlanar() { - return this.view.getLayers(layer => layer.id !== "planar" + getGeometryLayersWithoutPlanar() { + return this.view.getLayers(layer => layer.id !== 'planar' && layer.isGeometryLayer); - } + } } diff --git a/src/Components/ModuleView/ModuleView.js b/src/Components/ModuleView/ModuleView.js index de1e4847b..77e4f819c 100644 --- a/src/Components/ModuleView/ModuleView.js +++ b/src/Components/ModuleView/ModuleView.js @@ -5,82 +5,82 @@ import { EventSender } from '../Events/EventSender.js'; * a module, but is strongly advised as it simplifies the integration is demos. */ export class ModuleView extends EventSender { - /** + /** * Creates a new ModuleView. */ - constructor() { - super(); + constructor() { + super(); - /** + /** * Represents the parent HTML element of this view. Must be defined * by the user of the view * * @member {HTMLElement} */ - this.parentElement = null; + this.parentElement = null; - this.registerEvent(ModuleView.EVENT_ENABLED); - this.registerEvent(ModuleView.EVENT_DISABLED); - } + this.registerEvent(ModuleView.EVENT_ENABLED); + this.registerEvent(ModuleView.EVENT_DISABLED); + } - ///////// Overideable methods - // These methods should be overriden by the implementing class - // By default, they do nothing. They are supposed to enable - // or disable the view. (Can be done by destroying / creating, or - // by hiding, showing). - // These methods should never be called manually as they do not - // send appropriate events. - /** + ///////// Overideable methods + // These methods should be overriden by the implementing class + // By default, they do nothing. They are supposed to enable + // or disable the view. (Can be done by destroying / creating, or + // by hiding, showing). + // These methods should never be called manually as they do not + // send appropriate events. + /** * Must be overriden by the implementing class. Supposedly enables the view. * @abstract */ - async enableView() { } - /** + async enableView() { } + /** * Must be overriden by the implementing class. Supposedly disables the view. * @abstract */ - async disableView() { } + async disableView() { } - ///////// Do not override - // These methods are the public methods called to destroy or - // create the view. - /** + ///////// Do not override + // These methods are the public methods called to destroy or + // create the view. + /** * Enables the view (depends on the implementation). * * Sends a EVENT_ENABLED event once the view is enabled. * * @async */ - async enable() { - await this.enableView(); - this.sendEvent(ModuleView.EVENT_ENABLED); - } + async enable() { + await this.enableView(); + this.sendEvent(ModuleView.EVENT_ENABLED); + } - /** + /** * Disables the view (depends on the implementation). * * Sends a EVENT_DISABLED event once the view is disabled. * * @async */ - async disable() { - await this.disableView(); - this.sendEvent(ModuleView.EVENT_DISABLED); - } + async disable() { + await this.disableView(); + this.sendEvent(ModuleView.EVENT_DISABLED); + } - ///////// Events - // Events called when enabling / disabling the view - /** + ///////// Events + // Events called when enabling / disabling the view + /** * Event sent when the view is enabled */ - static get EVENT_ENABLED() { - return 'MODULE_VIEW_ENABLED'; - } + static get EVENT_ENABLED() { + return 'MODULE_VIEW_ENABLED'; + } - /** + /** * Event sent when the view is disabled */ - static get EVENT_DISABLED() { - return 'MODULE_VIEW_DISABLED'; - } + static get EVENT_DISABLED() { + return 'MODULE_VIEW_DISABLED'; + } } \ No newline at end of file diff --git a/src/Components/Request/RequestService.js b/src/Components/Request/RequestService.js index c11472fa6..6b39fe2cb 100644 --- a/src/Components/Request/RequestService.js +++ b/src/Components/Request/RequestService.js @@ -1,30 +1,30 @@ // Service used to make HTTP requests and manage authentication // Wiki : https://github.com/MEPP-team/UD-Viz/wiki/Request-Service#request-service export function RequestService() { - // eslint-disable-next-line no-unused-expressions - this.authenticationService; - this.useAuthentication = false; + // eslint-disable-next-line no-unused-expressions + this.authenticationService; + this.useAuthentication = false; - // eslint-disable-next-line func-names - this.initialize = function () { + // eslint-disable-next-line func-names + this.initialize = function () { - }; + }; - /** + /** * @deprecated Prefer using `RequestService.request` instead. * // eslint-disable-next-line valid-jsdoc */ - // eslint-disable-next-line func-names - this.send = function (method, url, body = '', authenticate = true) { - return this.request(method, url, { - // eslint-disable-next-line object-shorthand - body: body, - // eslint-disable-next-line object-shorthand - authenticate: authenticate, - }); - }; + // eslint-disable-next-line func-names + this.send = function (method, url, body = '', authenticate = true) { + return this.request(method, url, { + // eslint-disable-next-line object-shorthand + body: body, + // eslint-disable-next-line object-shorthand + authenticate: authenticate, + }); + }; - /** + /** * Performs an HTTP request. * * @async @@ -43,64 +43,64 @@ export function RequestService() { * * @returns {Promise} */ - this.request = (method, url, options = {}) => { - const args = options || {}; - const body = args.body || ''; - let authenticate = (args.authenticate !== null + this.request = (method, url, options = {}) => { + const args = options || {}; + const body = args.body || ''; + let authenticate = (args.authenticate !== null && args.authenticate !== undefined) ? - args.authenticate : true; - if (authenticate === 'auto') { - authenticate = !!window.sessionStorage.getItem('user.token'); + args.authenticate : true; + if (authenticate === 'auto') { + authenticate = !!window.sessionStorage.getItem('user.token'); + } + const responseType = args.responseType || null; + const urlParameters = args.urlParameters || null; + return new Promise((resolve, reject) => { + const req = new XMLHttpRequest(); + if (!!urlParameters) { // eslint-disable-line no-extra-boolean-cast + url += '?'; + for (const [paramKey, paramValue] of Object.entries(urlParameters)) { + url += `${encodeURIComponent(paramKey)}=${encodeURIComponent(paramValue)}&`; } - const responseType = args.responseType || null; - const urlParameters = args.urlParameters || null; - return new Promise((resolve, reject) => { - const req = new XMLHttpRequest(); - if (!!urlParameters) { // eslint-disable-line no-extra-boolean-cast - url += '?'; - for (const [paramKey, paramValue] of Object.entries(urlParameters)) { - url += `${encodeURIComponent(paramKey)}=${encodeURIComponent(paramValue)}&`; - } - } - req.open(method, url, true); + } + req.open(method, url, true); - if (this.useAuthentication && authenticate) { - const token = window.sessionStorage.getItem('user.token'); - if (token === null) { - reject(new AuthNeededError()); - return; - } - req.setRequestHeader('Authorization', `Bearer ${token}`); - } + if (this.useAuthentication && authenticate) { + const token = window.sessionStorage.getItem('user.token'); + if (token === null) { + reject(new AuthNeededError()); + return; + } + req.setRequestHeader('Authorization', `Bearer ${token}`); + } - if (!!responseType) { // eslint-disable-line no-extra-boolean-cast - req.responseType = responseType; - } + if (!!responseType) { // eslint-disable-line no-extra-boolean-cast + req.responseType = responseType; + } - req.send(body); + req.send(body); - req.onload = () => { - if (req.status >= 200 && req.status < 300) { - resolve(req); - } else { - reject(req.responseText); - } - }; - }); - }; + req.onload = () => { + if (req.status >= 200 && req.status < 300) { + resolve(req); + } else { + reject(req.responseText); + } + }; + }); + }; - // eslint-disable-next-line func-names - this.setAuthenticationService = function (authenticationService) { - this.authenticationService = authenticationService; - this.useAuthentication = true; - }; + // eslint-disable-next-line func-names + this.setAuthenticationService = function (authenticationService) { + this.authenticationService = authenticationService; + this.useAuthentication = true; + }; - this.initialize(); + this.initialize(); } export class AuthNeededError extends Error { - constructor() { - super('Login needed for this request'); - this.name = 'AuthNeededError'; - } + constructor() { + super('Login needed for this request'); + this.name = 'AuthNeededError'; + } } diff --git a/src/Game/Components/AssetsManager.js b/src/Game/Components/AssetsManager.js index 73901e897..5df2acd3a 100644 --- a/src/Game/Components/AssetsManager.js +++ b/src/Game/Components/AssetsManager.js @@ -277,19 +277,27 @@ export class AssetsManager { const parent = new THREE.Object3D(); switch (anchor) { case 'center': - let center = bbox.min.lerp(bbox.max, 0.5); - obj.position.sub(center); + { + let center = bbox.min.lerp(bbox.max, 0.5); + obj.position.sub(center); + } break; case 'max': - obj.position.sub(bbox.max); + { + obj.position.sub(bbox.max); + } break; case 'min': - obj.position.sub(bbox.min); + { + obj.position.sub(bbox.min); + } break; case 'center_min': - let centerMin = bbox.min.clone().lerp(bbox.max, 0.5); - centerMin.z = bbox.min.z; - obj.position.sub(centerMin); + { + let centerMin = bbox.min.clone().lerp(bbox.max, 0.5); + centerMin.z = bbox.min.z; + obj.position.sub(centerMin); + } break; default: } diff --git a/src/Game/Shared/GameObject/Components/Collider.js b/src/Game/Shared/GameObject/Components/Collider.js index 2f15cda5b..f1f0661e3 100644 --- a/src/Game/Shared/GameObject/Components/Collider.js +++ b/src/Game/Shared/GameObject/Components/Collider.js @@ -93,37 +93,41 @@ class ShapeWrapper { initFromJSON(json) { switch (json.type) { case 'Circle': - const circle = new Circle(json.center.x, json.center.y, json.radius); + { + const circle = new Circle(json.center.x, json.center.y, json.radius); - this.update = function (worldtransform) { - const wp = worldtransform.getPosition(); - circle.x = json.center.x + wp.x; - circle.y = json.center.y + wp.y; - }; + this.update = function (worldtransform) { + const wp = worldtransform.getPosition(); + circle.x = json.center.x + wp.x; + circle.y = json.center.y + wp.y; + }; - this.shape = circle; + this.shape = circle; + } break; case 'Polygon': - const points = []; - json.points.forEach(function (p) { - points.push([p.x, p.y]); - }); - - const polygon = new Polygon(0, 0, points); - - //attach userData to perform update - this.update = function (worldtransform) { + { const points = []; json.points.forEach(function (p) { - const wp = worldtransform.getPosition(); - const point = [p.x + wp.x, p.y + wp.y]; - points.push(point); - //TODO handle rotation + points.push([p.x, p.y]); }); - polygon.setPoints(points); - }; - this.shape = polygon; + const polygon = new Polygon(0, 0, points); + + //attach userData to perform update + this.update = function (worldtransform) { + const points = []; + json.points.forEach(function (p) { + const wp = worldtransform.getPosition(); + const point = [p.x + wp.x, p.y + wp.y]; + points.push(point); + //TODO handle rotation + }); + polygon.setPoints(points); + }; + + this.shape = polygon; + } break; default: } diff --git a/src/Game/Shared/GameObject/GameObject.js b/src/Game/Shared/GameObject/GameObject.js index 0285a6e2c..aaa84509d 100644 --- a/src/Game/Shared/GameObject/GameObject.js +++ b/src/Game/Shared/GameObject/GameObject.js @@ -10,7 +10,6 @@ const THREE = require('three'); const RenderComponent = require('./Components/Render'); const ColliderComponent = require('./Components/Collider'); const WorldScriptComponent = require('./Components/WorldScript'); -const JSONUtils = require('../../../Components/SystemUtils/JSONUtils'); const LocalScriptModule = require('./Components/LocalScript'); const THREEUtils = require('../Components/THREEUtils'); @@ -290,14 +289,6 @@ const GameObjectModule = class GameObject { return obj; } - getTransform() { - return this.transform; - } - - setTransform(transform) { - this.transform = transform; - } - clone() { return new GameObject(this.toJSON(true)); } diff --git a/src/Game/Shared/WorldState.js b/src/Game/Shared/WorldState.js index 5acc1a471..879011021 100644 --- a/src/Game/Shared/WorldState.js +++ b/src/Game/Shared/WorldState.js @@ -63,7 +63,7 @@ const WorldStateModule = class WorldState { if (uuidGO.includes(uuid)) count++; }); if (uuidGO.length != count) { - debugger; + throw new Error('count of go error'); } const result = new WorldState({ diff --git a/src/Game/UDVDebugger/UDVDebugger.js b/src/Game/UDVDebugger/UDVDebugger.js index f3a731399..04c68bc7d 100644 --- a/src/Game/UDVDebugger/UDVDebugger.js +++ b/src/Game/UDVDebugger/UDVDebugger.js @@ -125,22 +125,4 @@ export class UDVDebugger { this.root.style.width = w + 'px'; this.root.style.height = h + 'px'; } - - //TODO used twice put it in a UTILS - async loadConfigFile(filePath, cb) { - return new Promise((resolve, reject) => { - $.ajax({ - type: 'GET', - url: filePath, - datatype: 'json', - success: (data) => { - resolve(data); - }, - error: (e) => { - console.error(e); - reject(); - }, - }); - }); - } } diff --git a/src/Widgets/CityObjects/View/CityObjectFilterWindow.js b/src/Widgets/CityObjects/View/CityObjectFilterWindow.js index e9b018a86..180524de2 100644 --- a/src/Widgets/CityObjects/View/CityObjectFilterWindow.js +++ b/src/Widgets/CityObjects/View/CityObjectFilterWindow.js @@ -67,7 +67,7 @@ export class CityObjectFilterWindow extends Window { * add. */ addFilterSelector(filterSelector) { - if (!!this.getFilterSelector(filterSelector.filterLabel)) { + if (this.getFilterSelector(filterSelector.filterLabel)) { throw ( 'A filter selector with the same filter label already exist: ' + filterSelector.filterLabel @@ -119,7 +119,7 @@ export class CityObjectFilterWindow extends Window { _onFilterSelection() { this.filterSectionElement.innerHTML = ''; let selector = this._getCurrentSelector(); - if (!!selector) { + if (selector) { selector.appendFormFieldsTo(this.filterSectionElement); } } diff --git a/src/Widgets/CityObjects/View/CityObjectWindow.js b/src/Widgets/CityObjects/View/CityObjectWindow.js index 5359230a6..fdbf9c113 100644 --- a/src/Widgets/CityObjects/View/CityObjectWindow.js +++ b/src/Widgets/CityObjects/View/CityObjectWindow.js @@ -1,5 +1,7 @@ /** @format */ +const THREE = require('three'); + //Components import { Window } from '../../../Components/GUI/js/Window'; import { CityObjectStyle } from '../../../Components/3DTiles/Model/CityObjectStyle'; @@ -168,7 +170,7 @@ export class CityObjectWindow extends Window { _updateLayerDescription() { if (this.isCreated) { let layer = this.provider.getLayer(); - if (!!layer) { + if (layer) { this.selectedFilterElement.innerText = layer.filter.toString(); this.layerColorIndicatorElement.style.display = ''; this.layerColorIndicatorElement.style.background = @@ -200,7 +202,7 @@ export class CityObjectWindow extends Window { * @param {string} filterLabel The selected filter label. */ _onFilterSelected(filterLabel) { - if (!!filterLabel) { + if (filterLabel) { this.provider.setLayer(filterLabel, this.defaultLayerStyle); } else { this.provider.removeLayer(); diff --git a/src/Widgets/CityObjects/ViewModel/AttributeFilter.js b/src/Widgets/CityObjects/ViewModel/AttributeFilter.js index 3b8a3c056..8ba36058f 100644 --- a/src/Widgets/CityObjects/ViewModel/AttributeFilter.js +++ b/src/Widgets/CityObjects/ViewModel/AttributeFilter.js @@ -73,16 +73,16 @@ export class AttributeFilter extends CityObjectFilter { let result = ''; let attributes = []; - if (!!this.tileId) { + if (this.tileId) { attributes.push(['tileId', this.tileId]); } - if (!!this.batchId) { + if (this.batchId) { attributes.push(['batchId', this.batchId]); } for (let entry of Object.entries(this.props)) { - if (!!entry[1]) { + if (entry[1]) { attributes.push([entry[0], entry[1]]); } } diff --git a/src/Widgets/CityObjects/ViewModel/CityObjectProvider.js b/src/Widgets/CityObjects/ViewModel/CityObjectProvider.js index 99b40e6a5..ee839dfc4 100644 --- a/src/Widgets/CityObjects/ViewModel/CityObjectProvider.js +++ b/src/Widgets/CityObjects/ViewModel/CityObjectProvider.js @@ -85,7 +85,7 @@ export class CityObjectProvider extends EventSender { */ selectCityObject(mouseEvent) { let cityObject = this.layerManager.pickCityObject(mouseEvent); - if (!!cityObject) { + if (cityObject) { this.selectedCityObject = cityObject; this.removeLayer(); this.sendEvent(CityObjectProvider.EVENT_CITY_OBJECT_SELECTED, cityObject); @@ -160,7 +160,7 @@ export class CityObjectProvider extends EventSender { let filter = this.filters[filterLabel]; if (filter === undefined) { - throw 'No filter found with the label : ' + label; + throw 'No filter found with the label : ' + filterLabel; } this.cityOjectLayer = new CityObjectLayer(filter, style); @@ -198,7 +198,7 @@ export class CityObjectProvider extends EventSender { */ _updateTilesManager() { this.layerManager.removeAll3DTilesStyles(); - if (!!this.selectedCityObject) { + if (this.selectedCityObject) { let tileManager = this.layerManager.getTilesManagerByLayerID( this.selectedCityObject.tile.layer.id ); diff --git a/src/Widgets/Documents/View/DocumentNavigatorWindow.js b/src/Widgets/Documents/View/DocumentNavigatorWindow.js index 12897b158..a2becb139 100644 --- a/src/Widgets/Documents/View/DocumentNavigatorWindow.js +++ b/src/Widgets/Documents/View/DocumentNavigatorWindow.js @@ -145,8 +145,8 @@ export class DocumentNavigatorWindow extends AbstractDocumentWindow { item.innerHTML = /*html*/ `
          ${doc.title}
          Refering ${new Date( - doc.refDate - ).toLocaleDateString()}
          + doc.refDate + ).toLocaleDateString()}
          `; item.classList.add('navigator-result-doc'); item.onclick = () => { @@ -170,10 +170,10 @@ export class DocumentNavigatorWindow extends AbstractDocumentWindow { } let previouslySelected = this.documentListElement.querySelector('.document-selected'); - if (!!previouslySelected) { + if (previouslySelected) { previouslySelected.classList.remove('document-selected'); } - if (!!document) { + if (document) { let newIndex = this.provider.getDisplayedDocumentIndex(); let newSelected = this.documentListElement.querySelector( `li:nth-child(${newIndex + 1})` @@ -203,22 +203,22 @@ export class DocumentNavigatorWindow extends AbstractDocumentWindow { rightsHolder !== '' ? rightsHolder : undefined; let pubStartDate = this.inputPubDateStartElement.value; - this.searchFilter.pubStartDate = !!pubStartDate + this.searchFilter.pubStartDate = pubStartDate ? new Date(pubStartDate) : undefined; let pubEndDate = this.inputPubDateEndElement.value; - this.searchFilter.pubEndDate = !!pubEndDate + this.searchFilter.pubEndDate = pubEndDate ? new Date(pubEndDate) : undefined; let refStartDate = this.inputRefDateStartElement.value; - this.searchFilter.refStartDate = !!refStartDate + this.searchFilter.refStartDate = refStartDate ? new Date(refStartDate) : undefined; let refEndDate = this.inputRefDateEndElement.value; - this.searchFilter.refEndDate = !!refEndDate + this.searchFilter.refEndDate = refEndDate ? new Date(refEndDate) : undefined; diff --git a/src/Widgets/Extensions/3DTilesDebug/views/3DTilesDebugWindow.js b/src/Widgets/Extensions/3DTilesDebug/views/3DTilesDebugWindow.js index 0fac2b999..d618741c1 100644 --- a/src/Widgets/Extensions/3DTilesDebug/views/3DTilesDebugWindow.js +++ b/src/Widgets/Extensions/3DTilesDebug/views/3DTilesDebugWindow.js @@ -1,5 +1,7 @@ /** @format */ +const THREE = require('three'); + //Components import { Window } from '../../../../Components/GUI/js/Window'; import { CityObjectStyle } from '../../../../Components/3DTiles/Model/CityObjectStyle'; @@ -154,7 +156,7 @@ export class Debug3DTilesWindow extends Window { this.clickDivElement.innerHTML += `
          ${key} : ${value}`; } - if (!!this.selectedCityObject) { + if (this.selectedCityObject) { this.selectedTilesManager.removeStyle( this.selectedCityObject.cityObjectId ); diff --git a/src/Widgets/Extensions/Contribute/View/DocumentCreationWindow.js b/src/Widgets/Extensions/Contribute/View/DocumentCreationWindow.js index 4b06675d8..f8c7d77a2 100644 --- a/src/Widgets/Extensions/Contribute/View/DocumentCreationWindow.js +++ b/src/Widgets/Extensions/Contribute/View/DocumentCreationWindow.js @@ -266,7 +266,7 @@ export class DocumentCreationWindow extends AbstractDocumentWindow { * @private */ _updateFormButtons() { - if (!!this.docImageElement.value) { + if (this.docImageElement.value) { this.buttonPositionElement.disabled = false; } else { this.buttonPositionElement.disabled = true; diff --git a/src/Widgets/Extensions/DocumentComments/views/DocumentCommentsWindow.js b/src/Widgets/Extensions/DocumentComments/views/DocumentCommentsWindow.js index 8b4f957a3..b295541d9 100644 --- a/src/Widgets/Extensions/DocumentComments/views/DocumentCommentsWindow.js +++ b/src/Widgets/Extensions/DocumentComments/views/DocumentCommentsWindow.js @@ -80,12 +80,12 @@ export class DocumentCommentsWindow extends AbstractDocumentWindow { div.innerHTML = `

          ${comment.author.firstName} ${ - comment.author.lastName - }

          + comment.author.lastName +}

          ${text}

          ${new Date( - comment.date - ).toLocaleString()}

          + comment.date + ).toLocaleString()}

          `; document.getElementById('documentComments_left').appendChild(div); diff --git a/src/Widgets/Extensions/Geocoding/services/GeocodingService.js b/src/Widgets/Extensions/Geocoding/services/GeocodingService.js index 1e25f87d4..29b50f89d 100644 --- a/src/Widgets/Extensions/Geocoding/services/GeocodingService.js +++ b/src/Widgets/Extensions/Geocoding/services/GeocodingService.js @@ -63,7 +63,7 @@ export class GeocodingService { authenticate: false, }); const response = JSON.parse(req.response); - const results = (!!this.basePath ? response[this.basePath] : response).map( + const results = (this.basePath ? response[this.basePath] : response).map( (res) => { return { lat: Number(getAttributeByPath(res, this.latPath)), @@ -72,7 +72,7 @@ export class GeocodingService { } ); - if (!!this.requestTimeIntervalMs) { + if (this.requestTimeIntervalMs) { this.canDoRequest = false; setTimeout(() => { this.canDoRequest = true; diff --git a/src/Widgets/Extensions/Geocoding/views/GeocodingView.js b/src/Widgets/Extensions/Geocoding/views/GeocodingView.js index dec63944f..d57b9dff0 100644 --- a/src/Widgets/Extensions/Geocoding/views/GeocodingView.js +++ b/src/Widgets/Extensions/Geocoding/views/GeocodingView.js @@ -110,7 +110,7 @@ export class GeocodingView extends ModuleView { let i = 0; //step 1 : convert the lat/lng to coordinates used by itowns let targetPos = this.getWorldCoordinates(lat, lng); - if (!!targetPos.z) { + if (targetPos.z) { //if we could convert the coords (ie. they are on the map) //step 2 : add a mesh representing a pin this.addPin(targetPos); @@ -141,7 +141,7 @@ export class GeocodingView extends ModuleView { this.planarView.tileLayer, coords ); - const targetZ = !!elevation ? elevation : undefined; + const targetZ = elevation ? elevation : undefined; return new THREE.Vector3(targetX, targetY, targetZ); } diff --git a/src/Widgets/GuidedTour/GuidedTourController.js b/src/Widgets/GuidedTour/GuidedTourController.js index 2f2be96d7..fc464dc80 100644 --- a/src/Widgets/GuidedTour/GuidedTourController.js +++ b/src/Widgets/GuidedTour/GuidedTourController.js @@ -21,9 +21,9 @@ export class GuidedTourController extends ModuleView { /** * Constructor for GuidedTourController * The controller reads data from a database to build one or more guided tours - * Each guided tour is a succession of "steps" + * Each guided tour is a succession of "steps" * Each step has a document + tour text + doc text (steps are instances of - * the TourStep class) + * the TourStep class) * Multiple guided tours are supported (only one tour is finished for the demo) * For the demo : options.preventUserFromChangingTour allows to hide the buttons for changing tour * diff --git a/src/Widgets/LayerChoice/views/LayerChoice.js b/src/Widgets/LayerChoice/views/LayerChoice.js index 6467deeb0..aaa68e565 100644 --- a/src/Widgets/LayerChoice/views/LayerChoice.js +++ b/src/Widgets/LayerChoice/views/LayerChoice.js @@ -67,14 +67,14 @@ export class LayerChoice extends Window { layers[i].id }-spoiler" class="section-title">${layers[i].id} Visible
          + layers[i].visible ? 'checked' : '' +}>
          Opacity : ${ - layers[i].opacity - } + layers[i].opacity +}
          `; item.oninput = (event) => { @@ -129,8 +129,8 @@ export class LayerChoice extends Window { let div = document.createElement('div'); div.innerHTML = ` All Visible
          + this.layerManager.isOneLayerVisible() ? 'checked' : '' +}>
          `; div.onchange = (event) => { this.layerManager.changeVisibility(event.srcElement.checked); @@ -143,22 +143,22 @@ export class LayerChoice extends Window { layers[i].id }-spoiler"> + layers[i].id +}-spoiler" class="subsection-title">${ + layers[i].id +}
          Visible
          + layers[i].visible ? 'checked' : '' +}>
          Opacity : ${ - layers[i].opacity - } + layers[i].opacity +}
          `; diff --git a/src/Widgets/Links/View/CityObjectLinkInterface.js b/src/Widgets/Links/View/CityObjectLinkInterface.js index 12d9ca96a..70a61f20f 100644 --- a/src/Widgets/Links/View/CityObjectLinkInterface.js +++ b/src/Widgets/Links/View/CityObjectLinkInterface.js @@ -1,6 +1,5 @@ /** @format */ -import { LinkService } from '../Model/LinkService'; import { CityObjectModule } from '../../CityObjects/CityObjectModule'; import { CityObjectFilterSelector } from '../../CityObjects/View/CityObjectFilterSelector'; import { LinkProvider } from '../ViewModel/LinkProvider'; @@ -67,7 +66,7 @@ export class CityObjectLinkInterface { let docs = this.linkProvider.getSelectedCityObjectLinkedDocuments(); let listHtml = `

          ${docs.length} linked document(s)

          `; if (docs.length > 0) { - listHtml += `

            `; + listHtml += '

              '; for (let doc of docs) { listHtml += `
            • ${doc.title}
            • `; } @@ -80,7 +79,7 @@ export class CityObjectLinkInterface { ////// GETTERS get linkListId() { - return `city_objects_link_list`; + return 'city_objects_link_list'; } get linkListElement() { @@ -88,7 +87,7 @@ export class CityObjectLinkInterface { } get showDocsButtonId() { - return `city_objects_link_show_doc`; + return 'city_objects_link_show_doc'; } get showDocsButtonElement() { diff --git a/src/Widgets/Links/View/DocumentLinkInterface.js b/src/Widgets/Links/View/DocumentLinkInterface.js index d3baac9ad..4822c1831 100644 --- a/src/Widgets/Links/View/DocumentLinkInterface.js +++ b/src/Widgets/Links/View/DocumentLinkInterface.js @@ -99,7 +99,7 @@ export class DocumentLinkInterface { }; this.createLinkButtonElement.onclick = async () => { - if (!!this.provider.selectedCityObject) { + if (this.provider.selectedCityObject) { let newLink = new Link(); newLink.source_id = this.provider.displayedDocument.id; newLink.target_id = @@ -158,13 +158,13 @@ export class DocumentLinkInterface { newDivHtml += `
            • ID : ${link.target_id} + link + )}" class="clickable-text"> travel + link + )}" class="clickable-text"> delete
            • `; @@ -229,7 +229,7 @@ export class DocumentLinkInterface { } get linkFilterId() { - return `city_object_link_filter`; + return 'city_object_link_filter'; } get linkFilterElement() { From e3e4ac664f927245c0906decebaffda07f5dcac5 Mon Sep 17 00:00:00 2001 From: valentinMachado Date: Fri, 4 Jun 2021 12:25:19 +0200 Subject: [PATCH 60/68] refacto --- src/Game/Shared/Components/THREEUtils.js | 78 ++---------------------- 1 file changed, 6 insertions(+), 72 deletions(-) diff --git a/src/Game/Shared/Components/THREEUtils.js b/src/Game/Shared/Components/THREEUtils.js index 520ec4d96..8ed2f06b0 100644 --- a/src/Game/Shared/Components/THREEUtils.js +++ b/src/Game/Shared/Components/THREEUtils.js @@ -1,8 +1,10 @@ /** @format */ -const THREE = require('three'); +import * as THREE from 'three'; -module.exports = { +//TODO create an object Transform with a clone method + +const THREEUtils = { textureEncoding: THREE.RGBDEncoding, addLights(scene) { @@ -35,74 +37,6 @@ module.exports = { // renderer.toneMapping = THREE.ReinhardToneMapping; // renderer.toneMappingExposure = 1; }, - - Transform: class Transform { - constructor(position, rotation, scale) { - this.position = position || new THREE.Vector3(); - this.rotation = rotation || new THREE.Vector3(); - this.scale = scale || new THREE.Vector3(1, 1, 1); - } - - getPosition() { - return this.position; - } - - setPosition(position) { - this.position = position; - } - - getRotation() { - return this.rotation; - } - - setRotation(rotation) { - this.rotation = rotation; - } - - getScale() { - return this.scale; - } - - setScale(scale) { - this.scale = scale; - } - - clone() { - return new Transform( - this.position.clone(), - this.rotation.clone(), - this.scale.clone() - ); - } - - lerp(transform, ratio) { - this.position.lerp(transform.getPosition(), ratio); - this.rotation.lerp(transform.getRotation(), ratio); - this.scale.lerp(transform.getScale(), ratio); - } - - toJSON() { - return { - position: this.position.toArray(), - rotation: this.rotation.toArray(), - scale: this.scale.toArray(), - }; - } - - setFromJSON(json) { - if (json) { - if (json.position) { - this.position.fromArray(json.position); - } - - if (json.rotation) { - this.rotation.fromArray(json.rotation); - } - - if (json.scale) { - this.scale.fromArray(json.scale); - } - } - } - }, }; + +export { THREEUtils }; From 2affc5d67f5094f8fd55d5d562621f65672a24d7 Mon Sep 17 00:00:00 2001 From: valentinMachado Date: Fri, 4 Jun 2021 12:25:29 +0200 Subject: [PATCH 61/68] refacto bis --- src/Game/Shared/Components/THREEUtils.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/Game/Shared/Components/THREEUtils.js b/src/Game/Shared/Components/THREEUtils.js index 8ed2f06b0..759049a1c 100644 --- a/src/Game/Shared/Components/THREEUtils.js +++ b/src/Game/Shared/Components/THREEUtils.js @@ -1,10 +1,10 @@ /** @format */ -import * as THREE from 'three'; +const THREE = require('three'); //TODO create an object Transform with a clone method -const THREEUtils = { +module.exports = { textureEncoding: THREE.RGBDEncoding, addLights(scene) { @@ -37,6 +37,10 @@ const THREEUtils = { // renderer.toneMapping = THREE.ReinhardToneMapping; // renderer.toneMappingExposure = 1; }, -}; -export { THREEUtils }; + Transform: class { + constructor() { + console.log('new transform'); + } + }, +}; From 23496faab7fb1dd8a06ae553696aff276a88b2a0 Mon Sep 17 00:00:00 2001 From: valentinMachado Date: Fri, 4 Jun 2021 14:19:05 +0200 Subject: [PATCH 62/68] transform class --- src/Game/Shared/Components/THREEUtils.js | 62 ++++++++++++++++++++++-- 1 file changed, 59 insertions(+), 3 deletions(-) diff --git a/src/Game/Shared/Components/THREEUtils.js b/src/Game/Shared/Components/THREEUtils.js index 759049a1c..992b9ac27 100644 --- a/src/Game/Shared/Components/THREEUtils.js +++ b/src/Game/Shared/Components/THREEUtils.js @@ -38,9 +38,65 @@ module.exports = { // renderer.toneMappingExposure = 1; }, - Transform: class { - constructor() { - console.log('new transform'); + Transform: class Transform { + constructor(position, rotation, scale) { + this.position = position || new THREE.Vector3(); + this.rotation = rotation || new THREE.Vector3(); + this.scale = scale || new THREE.Vector3(1, 1, 1); + } + + getPosition() { + return this.position; + } + + setPosition(position) { + this.position = position; + } + + getRotation() { + return this.rotation; + } + + setRotation(rotation) { + this.rotation = rotation; + } + + getScale() { + return this.scale; + } + + setScale(scale) { + this.scale = scale; + } + + clone() { + return new Transform( + this.position.clone(), + this.rotation.clone(), + this.scale.clone() + ); + } + + setFromJSON(json) { + if (json) { + if (json.position) { + this.position.x = json.position.x; + this.position.y = json.position.y; + this.position.z = json.position.z; + } + + if (json.rotation) { + this.rotation.x = json.rotation.x; + this.rotation.y = json.rotation.y; + this.rotation.z = json.rotation.z; + } + + if (json.scale) { + this.scale.x = json.scale.x; + this.scale.y = json.scale.y; + this.scale.z = json.scale.z; + } + } } }, }; From 96e73b7d9ca067ed8a890718f774cb73e51edb2b Mon Sep 17 00:00:00 2001 From: valentinMachado Date: Fri, 4 Jun 2021 15:27:06 +0200 Subject: [PATCH 63/68] transform refacto --- src/Game/Shared/Components/THREEUtils.js | 28 ++++++++++++++---------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/src/Game/Shared/Components/THREEUtils.js b/src/Game/Shared/Components/THREEUtils.js index 992b9ac27..520ec4d96 100644 --- a/src/Game/Shared/Components/THREEUtils.js +++ b/src/Game/Shared/Components/THREEUtils.js @@ -2,8 +2,6 @@ const THREE = require('three'); -//TODO create an object Transform with a clone method - module.exports = { textureEncoding: THREE.RGBDEncoding, @@ -77,24 +75,32 @@ module.exports = { ); } + lerp(transform, ratio) { + this.position.lerp(transform.getPosition(), ratio); + this.rotation.lerp(transform.getRotation(), ratio); + this.scale.lerp(transform.getScale(), ratio); + } + + toJSON() { + return { + position: this.position.toArray(), + rotation: this.rotation.toArray(), + scale: this.scale.toArray(), + }; + } + setFromJSON(json) { if (json) { if (json.position) { - this.position.x = json.position.x; - this.position.y = json.position.y; - this.position.z = json.position.z; + this.position.fromArray(json.position); } if (json.rotation) { - this.rotation.x = json.rotation.x; - this.rotation.y = json.rotation.y; - this.rotation.z = json.rotation.z; + this.rotation.fromArray(json.rotation); } if (json.scale) { - this.scale.x = json.scale.x; - this.scale.y = json.scale.y; - this.scale.z = json.scale.z; + this.scale.fromArray(json.scale); } } } From c79517a4816551474afe86f1c9e088b6a3cbb972 Mon Sep 17 00:00:00 2001 From: valentinMachado Date: Tue, 8 Jun 2021 10:35:59 +0200 Subject: [PATCH 64/68] format with prettier widgets sources --- .../Documents/View/DocumentNavigatorWindow.js | 4 +-- .../views/DocumentCommentsWindow.js | 8 ++--- .../Geocoding/services/GeocodingService.js | 2 +- .../Geocoding/views/GeocodingView.js | 2 +- src/Widgets/LayerChoice/views/LayerChoice.js | 36 +++++++++---------- .../Links/View/DocumentLinkInterface.js | 8 ++--- 6 files changed, 30 insertions(+), 30 deletions(-) diff --git a/src/Widgets/Documents/View/DocumentNavigatorWindow.js b/src/Widgets/Documents/View/DocumentNavigatorWindow.js index a2becb139..acfdc23eb 100644 --- a/src/Widgets/Documents/View/DocumentNavigatorWindow.js +++ b/src/Widgets/Documents/View/DocumentNavigatorWindow.js @@ -145,8 +145,8 @@ export class DocumentNavigatorWindow extends AbstractDocumentWindow { item.innerHTML = /*html*/ `
              ${doc.title}
              Refering ${new Date( - doc.refDate - ).toLocaleDateString()}
              + doc.refDate + ).toLocaleDateString()}
          `; item.classList.add('navigator-result-doc'); item.onclick = () => { diff --git a/src/Widgets/Extensions/DocumentComments/views/DocumentCommentsWindow.js b/src/Widgets/Extensions/DocumentComments/views/DocumentCommentsWindow.js index b295541d9..8b4f957a3 100644 --- a/src/Widgets/Extensions/DocumentComments/views/DocumentCommentsWindow.js +++ b/src/Widgets/Extensions/DocumentComments/views/DocumentCommentsWindow.js @@ -80,12 +80,12 @@ export class DocumentCommentsWindow extends AbstractDocumentWindow { div.innerHTML = `

          ${comment.author.firstName} ${ - comment.author.lastName -}

          + comment.author.lastName + }

          ${text}

          ${new Date( - comment.date - ).toLocaleString()}

          + comment.date + ).toLocaleString()}

          `; document.getElementById('documentComments_left').appendChild(div); diff --git a/src/Widgets/Extensions/Geocoding/services/GeocodingService.js b/src/Widgets/Extensions/Geocoding/services/GeocodingService.js index 29b50f89d..b461383e9 100644 --- a/src/Widgets/Extensions/Geocoding/services/GeocodingService.js +++ b/src/Widgets/Extensions/Geocoding/services/GeocodingService.js @@ -63,7 +63,7 @@ export class GeocodingService { authenticate: false, }); const response = JSON.parse(req.response); - const results = (this.basePath ? response[this.basePath] : response).map( + const results = (!!this.basePath ? response[this.basePath] : response).map( (res) => { return { lat: Number(getAttributeByPath(res, this.latPath)), diff --git a/src/Widgets/Extensions/Geocoding/views/GeocodingView.js b/src/Widgets/Extensions/Geocoding/views/GeocodingView.js index d57b9dff0..304bc4f14 100644 --- a/src/Widgets/Extensions/Geocoding/views/GeocodingView.js +++ b/src/Widgets/Extensions/Geocoding/views/GeocodingView.js @@ -141,7 +141,7 @@ export class GeocodingView extends ModuleView { this.planarView.tileLayer, coords ); - const targetZ = elevation ? elevation : undefined; + const targetZ = !!elevation ? elevation : undefined; return new THREE.Vector3(targetX, targetY, targetZ); } diff --git a/src/Widgets/LayerChoice/views/LayerChoice.js b/src/Widgets/LayerChoice/views/LayerChoice.js index aaa68e565..6467deeb0 100644 --- a/src/Widgets/LayerChoice/views/LayerChoice.js +++ b/src/Widgets/LayerChoice/views/LayerChoice.js @@ -67,14 +67,14 @@ export class LayerChoice extends Window { layers[i].id }-spoiler" class="section-title">${layers[i].id} Visible
          + layers[i].visible ? 'checked' : '' + }>
          Opacity : ${ - layers[i].opacity -} + layers[i].opacity + }
          `; item.oninput = (event) => { @@ -129,8 +129,8 @@ export class LayerChoice extends Window { let div = document.createElement('div'); div.innerHTML = ` All Visible
          + this.layerManager.isOneLayerVisible() ? 'checked' : '' + }>
          `; div.onchange = (event) => { this.layerManager.changeVisibility(event.srcElement.checked); @@ -143,22 +143,22 @@ export class LayerChoice extends Window { layers[i].id }-spoiler"> + layers[i].id + }-spoiler" class="subsection-title">${ + layers[i].id + }
          Visible
          + layers[i].visible ? 'checked' : '' + }>
          Opacity : ${ - layers[i].opacity -} + layers[i].opacity + }
          `; diff --git a/src/Widgets/Links/View/DocumentLinkInterface.js b/src/Widgets/Links/View/DocumentLinkInterface.js index 4822c1831..aff876248 100644 --- a/src/Widgets/Links/View/DocumentLinkInterface.js +++ b/src/Widgets/Links/View/DocumentLinkInterface.js @@ -158,13 +158,13 @@ export class DocumentLinkInterface { newDivHtml += `
        • ID : ${link.target_id} + link + )}" class="clickable-text"> travel + link + )}" class="clickable-text"> delete
        • `; From 64f7b4d24d56dbc843fe60e0334447ce5cb393bc Mon Sep 17 00:00:00 2001 From: valentinMachado Date: Tue, 8 Jun 2021 11:10:10 +0200 Subject: [PATCH 65/68] eslint return no error --- .../Documents/View/DocumentNavigatorWindow.js | 4 +-- .../views/DocumentCommentsWindow.js | 8 ++--- .../Geocoding/services/GeocodingService.js | 2 +- .../Geocoding/views/GeocodingView.js | 2 +- src/Widgets/LayerChoice/views/LayerChoice.js | 36 +++++++++---------- .../Links/View/DocumentLinkInterface.js | 8 ++--- 6 files changed, 30 insertions(+), 30 deletions(-) diff --git a/src/Widgets/Documents/View/DocumentNavigatorWindow.js b/src/Widgets/Documents/View/DocumentNavigatorWindow.js index acfdc23eb..a2becb139 100644 --- a/src/Widgets/Documents/View/DocumentNavigatorWindow.js +++ b/src/Widgets/Documents/View/DocumentNavigatorWindow.js @@ -145,8 +145,8 @@ export class DocumentNavigatorWindow extends AbstractDocumentWindow { item.innerHTML = /*html*/ `
          ${doc.title}
          Refering ${new Date( - doc.refDate - ).toLocaleDateString()}
          + doc.refDate + ).toLocaleDateString()}
          `; item.classList.add('navigator-result-doc'); item.onclick = () => { diff --git a/src/Widgets/Extensions/DocumentComments/views/DocumentCommentsWindow.js b/src/Widgets/Extensions/DocumentComments/views/DocumentCommentsWindow.js index 8b4f957a3..b295541d9 100644 --- a/src/Widgets/Extensions/DocumentComments/views/DocumentCommentsWindow.js +++ b/src/Widgets/Extensions/DocumentComments/views/DocumentCommentsWindow.js @@ -80,12 +80,12 @@ export class DocumentCommentsWindow extends AbstractDocumentWindow { div.innerHTML = `

          ${comment.author.firstName} ${ - comment.author.lastName - }

          + comment.author.lastName +}

          ${text}

          ${new Date( - comment.date - ).toLocaleString()}

          + comment.date + ).toLocaleString()}

          `; document.getElementById('documentComments_left').appendChild(div); diff --git a/src/Widgets/Extensions/Geocoding/services/GeocodingService.js b/src/Widgets/Extensions/Geocoding/services/GeocodingService.js index b461383e9..29b50f89d 100644 --- a/src/Widgets/Extensions/Geocoding/services/GeocodingService.js +++ b/src/Widgets/Extensions/Geocoding/services/GeocodingService.js @@ -63,7 +63,7 @@ export class GeocodingService { authenticate: false, }); const response = JSON.parse(req.response); - const results = (!!this.basePath ? response[this.basePath] : response).map( + const results = (this.basePath ? response[this.basePath] : response).map( (res) => { return { lat: Number(getAttributeByPath(res, this.latPath)), diff --git a/src/Widgets/Extensions/Geocoding/views/GeocodingView.js b/src/Widgets/Extensions/Geocoding/views/GeocodingView.js index 304bc4f14..d57b9dff0 100644 --- a/src/Widgets/Extensions/Geocoding/views/GeocodingView.js +++ b/src/Widgets/Extensions/Geocoding/views/GeocodingView.js @@ -141,7 +141,7 @@ export class GeocodingView extends ModuleView { this.planarView.tileLayer, coords ); - const targetZ = !!elevation ? elevation : undefined; + const targetZ = elevation ? elevation : undefined; return new THREE.Vector3(targetX, targetY, targetZ); } diff --git a/src/Widgets/LayerChoice/views/LayerChoice.js b/src/Widgets/LayerChoice/views/LayerChoice.js index 6467deeb0..aaa68e565 100644 --- a/src/Widgets/LayerChoice/views/LayerChoice.js +++ b/src/Widgets/LayerChoice/views/LayerChoice.js @@ -67,14 +67,14 @@ export class LayerChoice extends Window { layers[i].id }-spoiler" class="section-title">${layers[i].id} Visible
          + layers[i].visible ? 'checked' : '' +}>
          Opacity : ${ - layers[i].opacity - } + layers[i].opacity +}
          `; item.oninput = (event) => { @@ -129,8 +129,8 @@ export class LayerChoice extends Window { let div = document.createElement('div'); div.innerHTML = ` All Visible
          + this.layerManager.isOneLayerVisible() ? 'checked' : '' +}>
          `; div.onchange = (event) => { this.layerManager.changeVisibility(event.srcElement.checked); @@ -143,22 +143,22 @@ export class LayerChoice extends Window { layers[i].id }-spoiler"> + layers[i].id +}-spoiler" class="subsection-title">${ + layers[i].id +}
          Visible
          + layers[i].visible ? 'checked' : '' +}>
          Opacity : ${ - layers[i].opacity - } + layers[i].opacity +}
          `; diff --git a/src/Widgets/Links/View/DocumentLinkInterface.js b/src/Widgets/Links/View/DocumentLinkInterface.js index aff876248..4822c1831 100644 --- a/src/Widgets/Links/View/DocumentLinkInterface.js +++ b/src/Widgets/Links/View/DocumentLinkInterface.js @@ -158,13 +158,13 @@ export class DocumentLinkInterface { newDivHtml += `
        • ID : ${link.target_id} + link + )}" class="clickable-text"> travel + link + )}" class="clickable-text"> delete
        • `; From 0bb43893980068154eb756ef53e003b051b7c18a Mon Sep 17 00:00:00 2001 From: valentinMachado Date: Tue, 8 Jun 2021 11:14:37 +0200 Subject: [PATCH 66/68] modify travis test (without --fix) --- .travis.yml | 7 ++----- package.json | 1 + 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 3683952db..e0d536338 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,9 +18,6 @@ install: jobs: include: - - stage: build + - stage: travis script: - - npm run build - - stage: eslint - script: - - npm run eslint + - npm run travis diff --git a/package.json b/package.json index f9a72ec1b..13b159cda 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,7 @@ "description": "A collection of itowns plugins", "main": "src", "scripts": { + "travis": "./node_modules/.bin/eslint ./src && npm run build", "eslint": "./node_modules/.bin/eslint ./src --fix", "build": "cross-env NODE_ENV=production webpack", "build-debug": "cross-env NODE_ENV=development webpack", From 83182d01e03e8836776c9400dc02922892b3dbba Mon Sep 17 00:00:00 2001 From: valentinMachado Date: Tue, 8 Jun 2021 11:56:04 +0200 Subject: [PATCH 67/68] remove --fix from script npm --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 13b159cda..c9c75c6e6 100644 --- a/package.json +++ b/package.json @@ -4,8 +4,8 @@ "description": "A collection of itowns plugins", "main": "src", "scripts": { - "travis": "./node_modules/.bin/eslint ./src && npm run build", - "eslint": "./node_modules/.bin/eslint ./src --fix", + "travis": "npm run eslint && npm run build", + "eslint": "./node_modules/.bin/eslint ./src", "build": "cross-env NODE_ENV=production webpack", "build-debug": "cross-env NODE_ENV=development webpack", "debug": "nodemon --verbose --watch src --delay 2500ms ./bin/debug.js -e js,css,html" From 09db777b0aa08585c11ee0ca4391d5e050bd5c22 Mon Sep 17 00:00:00 2001 From: valentinMachado Date: Tue, 8 Jun 2021 14:03:03 +0200 Subject: [PATCH 68/68] 2.32.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c9c75c6e6..c7723866d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ud-viz", - "version": "2.31.9", + "version": "2.32.0", "description": "A collection of itowns plugins", "main": "src", "scripts": {