Skip to content

Commit

Permalink
Merge pull request #57 from 3dcitydb/url-controller
Browse files Browse the repository at this point in the history
Compact URL parameters, KML proxy, ion and Bing access token
  • Loading branch information
Son-HNguyen authored Aug 7, 2020
2 parents a064d63 + 9aa6146 commit 89fdb6f
Show file tree
Hide file tree
Showing 16 changed files with 1,491 additions and 548 deletions.
18 changes: 10 additions & 8 deletions 3dwebclient/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@
<script src="utils/mashup-data-source-service/application/KMLDataSource.js"></script>
<script src="utils/mashup-data-source-service/core/MashupDataSource.js"></script>
<script src="utils/mashup-data-source-service/application/DataSourceController.js"></script>
<!-- URL controller -->
<script src="utils/UrlController.js"></script>

<style>
@import url(../ThirdParty/Cesium/Widgets/widgets.css);
Expand Down Expand Up @@ -484,7 +486,7 @@
<div class="citydb_overSelect"></div>
</div>
<div class="citydb_short_container">
<button type="button" style="width: 100%;" class="cesium-button" onclick="removeSplashWindow()">Remove Splash Window</button>
<button type="button" style="width: 100%;" class="cesium-button" onclick="splashController.removeSplashWindow(jQuery)">Remove Splash Window</button>
</div>
<div id="citydb_addsplashwindow" class="citydb_dynamic_box">
<table class="citydb_inputtable">
Expand All @@ -504,7 +506,7 @@
</tbody>
</table>
<div class="citydb_long_container">
<button style="width: 100%;" type="button" class="cesium-button" onclick="addSplashWindow()">Add Splash Window</button>
<button style="width: 100%;" type="button" class="cesium-button" onclick="splashController.addSplashWindow(jQuery)">Add Splash Window</button>
</div>
</div>
</div>
Expand Down Expand Up @@ -569,8 +571,8 @@

<!-- Splash window -->
<div class="splashscreen-buttons">
<input id="not_show_again_button" type="button" value="Ignore" onclick="ignoreSplashWindow()">
<input id="close_button" type="button" value="Close" onclick="closeSplashWindow()">
<input id="not_show_again_button" type="button" value="Ignore" onclick="splashController.ignoreSplashWindow(jQuery)">
<input id="close_button" type="button" value="Close" onclick="splashController.closeSplashWindow(jQuery)">
</div>
<div id="splashwindow_iframe" class="splash-wrapper">
<div class="splash-iframe-container">
Expand Down Expand Up @@ -628,15 +630,15 @@
}
}

var expanded4 = false;
var expanded5 = false;
function showAddSplashWindow() {
var citydb_addsplashwindow = document.getElementById("citydb_addsplashwindow");
if (!expanded4) {
if (!expanded5) {
citydb_addsplashwindow.style.display = "block";
expanded4 = true;
expanded5 = true;
} else {
citydb_addsplashwindow.style.display = "none";
expanded4 = false;
expanded5 = false;
}
}
</script>
Expand Down
434 changes: 139 additions & 295 deletions 3dwebclient/script.js

Large diffs are not rendered by default.

424 changes: 227 additions & 197 deletions 3dwebclient/utils/SplashController.js

Large diffs are not rendered by default.

294 changes: 294 additions & 0 deletions 3dwebclient/utils/UrlController.js

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,11 @@ var DataSourceController = /** @class */ (function () {
scope._dataSource = new KMLDataSource(signInController, scope._options);
}
}
DataSourceController.prototype.fetchData = function (id, callback, limit) {
DataSourceController.prototype.fetchData = function (id, callback, limit, clickedObject) {
var scope = this;
scope._dataSource.queryUsingId(id, function (result) {
callback(scope._dataSource.responseToKvp(result));
}, limit);
}, limit, clickedObject);
};
Object.defineProperty(DataSourceController.prototype, "dataSource", {
get: function () {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,10 +103,10 @@ var GoogleSheets = /** @class */ (function (_super) {
// TODO
return null;
};
GoogleSheets.prototype.queryUsingId = function (id, callback, limit) {
this.queryUsingSql("SELECT * WHERE A='" + id + "'", callback, !limit ? Number.MAX_VALUE : limit);
GoogleSheets.prototype.queryUsingId = function (id, callback, limit, clickedObject) {
this.queryUsingSql("SELECT * WHERE A='" + id + "'", callback, !limit ? Number.MAX_VALUE : limit, clickedObject);
};
GoogleSheets.prototype.queryUsingSql = function (sql, callback, limit) {
GoogleSheets.prototype.queryUsingSql = function (sql, callback, limit, clickedObject) {
// TODO handle limit
var baseUrl = "https://docs.google.com/spreadsheets/d/";
var xmlHttp = new XMLHttpRequest();
Expand All @@ -122,7 +122,9 @@ var GoogleSheets = /** @class */ (function (_super) {
}
};
xmlHttp.open("GET", baseUrl + this._spreadsheetId + "/gviz/tq?tq=" + encodeURI(sql), true); // true for asynchronous
xmlHttp.setRequestHeader('Authorization', 'Bearer ' + this._signInController.accessToken);
if (this._signInController != null) {
xmlHttp.setRequestHeader('Authorization', 'Bearer ' + this._signInController.accessToken);
}
xmlHttp.send(null);
};
// This function is implemented using gapi
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,14 @@ var __extends = (this && this.__extends) || (function () {
var KMLDataSource = /** @class */ (function (_super) {
__extends(KMLDataSource, _super);
function KMLDataSource(signInController, options) {
return _super.call(this, signInController, options) || this;
var _this = _super.call(this, signInController, options) || this;
_this._useOwnKmlParser = false;
return _this;
}
KMLDataSource.prototype.responseToKvp = function (response) {
if (this._useOwnKmlParser) {
return this.responseOwnToKvp(response);
}
if (this._thirdPartyHandler) {
switch (this._thirdPartyHandler.type) {
case ThirdPartyHandler.Cesium: {
Expand All @@ -33,7 +38,7 @@ var KMLDataSource = /** @class */ (function (_super) {
}
};
KMLDataSource.prototype.responseCesiumToKvp = function (response) {
// response is already in JSON
// response is a list of JSON elements
// only support Data https://cesium.com/docs/cesiumjs-ref-doc/KmlFeatureData.html
var result = new Map();
/* <Data name="">
Expand All @@ -53,8 +58,22 @@ var KMLDataSource = /** @class */ (function (_super) {
return result;
};
KMLDataSource.prototype.responseOwnToKvp = function (response) {
// TODO
return null;
// response is a list of XML DOM element
var result = new Map();
/* read extended data, only works for the following structure
<ExtendedData>
<SchemaData schemaUrl="#some_schema">
<SimpleData name="A">Text</SimpleData>
<SimpleData name="B">Text</SimpleData>
</SchemaData>
</ExtendedData>
TODO more general implementation?
*/
for (var i = 0; i < response.length; i++) {
var simpleData = response[i];
result[simpleData.getAttribute('name')] = simpleData.textContent;
}
return result;
};
KMLDataSource.prototype.countFromResult = function (res) {
return res.getSize();
Expand All @@ -79,7 +98,7 @@ var KMLDataSource = /** @class */ (function (_super) {
// TODO
return null;
};
KMLDataSource.prototype.queryUsingId = function (id, callback, limit) {
KMLDataSource.prototype.queryUsingId = function (id, callback, limit, clickedObject) {
if (this._thirdPartyHandler) {
// prioritize the implementation of the provided 3rd-party handler
switch (this._thirdPartyHandler.type) {
Expand All @@ -88,7 +107,15 @@ var KMLDataSource = /** @class */ (function (_super) {
var entities = this._thirdPartyHandler.handler.entities;
var entity = entities.getById(id);
// entity is Cesium.KMLFeatureData
callback(entity.kml.extendedData);
var extendedData = entity.kml.extendedData;
if (typeof extendedData === "undefined"
|| (Object.keys(extendedData).length === 0 && extendedData.constructor === Object)) {
// empty response -> use custom implementation
this.queryUsingIdCustom(id, callback, limit, clickedObject);
}
else {
callback(extendedData);
}
break;
}
default: {
Expand All @@ -100,10 +127,44 @@ var KMLDataSource = /** @class */ (function (_super) {
}
else {
// using own implementation
// TODO
this.queryUsingIdCustom(id, callback);
}
};
KMLDataSource.prototype.queryUsingSql = function (sql, callback, limit) {
KMLDataSource.prototype.queryUsingIdCustom = function (id, callback, limit, clickedObject) {
this._useOwnKmlParser = true;
// read KML file
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
var xmlParser = new DOMParser();
var xmlDoc = xmlParser.parseFromString(xhttp.responseText, "text/xml");
var placemark = xmlDoc.getElementById(id);
if (placemark == null) {
var placemarkNameSearch = clickedObject._name;
// the placemarks in the KML file probably do not have IDs
// search for its name values instead
var placemarks = xmlDoc.getElementsByTagName("Placemark");
for (var i = 0; i < placemarks.length; i++) {
var iPlacemark = placemarks[i];
var placemarkName = iPlacemark.getElementsByTagName("name")[0];
if (placemarkName != null && placemarkName.textContent === placemarkNameSearch) {
placemark = iPlacemark;
break;
}
}
}
var extendedData = placemark.getElementsByTagName('ExtendedData')[0];
var schemaData = extendedData.getElementsByTagName('SchemaData')[0];
var simpleDataList = schemaData.getElementsByTagName('SimpleData');
// return XML DOM element
callback(simpleDataList);
}
};
// TODO enable proxy for other Data Sources?
xhttp.open("GET", (this._uri.indexOf(this._proxyPrefix) >= 0 ? "" : this._proxyPrefix) + this._uri, true);
xhttp.send();
};
KMLDataSource.prototype.queryUsingSql = function (sql, callback, limit, clickedObject) {
// TODO
return;
};
Expand All @@ -123,5 +184,15 @@ var KMLDataSource = /** @class */ (function (_super) {
// TODO
return null;
};
Object.defineProperty(KMLDataSource.prototype, "useOwnKmlParser", {
get: function () {
return this._useOwnKmlParser;
},
set: function (value) {
this._useOwnKmlParser = value;
},
enumerable: true,
configurable: true
});
return KMLDataSource;
}(XMLDataSource));
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,11 @@ var PostgreSQL = /** @class */ (function (_super) {
// TODO
return null;
};
PostgreSQL.prototype.queryUsingId = function (id, callback, limit) {
PostgreSQL.prototype.queryUsingId = function (id, callback, limit, clickedObject) {
// TODO use column number instead of column name (such as gmlid here)
this.queryUsingSql("?" + this.idColName + "=eq." + id, callback, !limit ? Number.MAX_VALUE : limit);
this.queryUsingSql("?" + this.idColName + "=eq." + id, callback, !limit ? Number.MAX_VALUE : limit, clickedObject);
};
PostgreSQL.prototype.queryUsingSql = function (sql, callback, limit) {
PostgreSQL.prototype.queryUsingSql = function (sql, callback, limit, clickedObject) {
// TODO handle limit
var baseUrl = this._uri;
var xmlHttp = new XMLHttpRequest();
Expand Down
11 changes: 11 additions & 0 deletions 3dwebclient/utils/mashup-data-source-service/core/DataSource.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ var DataSource = /** @class */ (function () {
this._tableType = !options.tableType ? TableTypes.Horizontal : options.tableType;
this._thirdPartyHandler = !options.thirdPartyHandler ? undefined : options.thirdPartyHandler;
this._signInController = signInController;
this._proxyPrefix = !options.proxyPrefix ? "" : options.proxyPrefix;
}
Object.defineProperty(DataSource.prototype, "name", {
get: function () {
Expand Down Expand Up @@ -104,5 +105,15 @@ var DataSource = /** @class */ (function () {
enumerable: true,
configurable: true
});
Object.defineProperty(DataSource.prototype, "proxyPrefix", {
get: function () {
return this._proxyPrefix;
},
set: function (value) {
this._proxyPrefix = value;
},
enumerable: true,
configurable: true
});
return DataSource;
}());
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ var MashupDataSource = /** @class */ (function () {
// TODO
return null;
};
MashupDataSource.prototype.queryUsingId = function (id, callback, limit) {
MashupDataSource.prototype.queryUsingId = function (id, callback, limit, clickedObject) {
// TODO
};
MashupDataSource.prototype.queryUsingIds = function (ids) {
Expand All @@ -62,7 +62,7 @@ var MashupDataSource = /** @class */ (function () {
// TODO
return null;
};
MashupDataSource.prototype.queryUsingSql = function (sql, callback, limit) {
MashupDataSource.prototype.queryUsingSql = function (sql, callback, limit, clickedObject) {
// TODO
};
MashupDataSource.prototype.queryUsingTypes = function (types, limit) {
Expand Down
59 changes: 57 additions & 2 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,63 @@
# Change Log

### 1.8.4 - Active [[Demo Link]](https://www.3dcitydb.org/3dcitydb-web-map/1.8.4/3dwebclient/index.html)
### 1.9.0 - Released [[Demo Link]](https://www.3dcitydb.org/3dcitydb-web-map/1.9.0/3dwebclient/index.html)

##### NEW
* Added own parser for thematic `SchemaData`
(see [`1e78886`](https://github.com/3dcitydb/3dcitydb-web-map/commit/1e788861d760da0f428c0d3e3259aece31510655))
besides simple `Data` in KML covered in `v1.8.3`:
+ An example of a KML document with thematic `SchemaData`:
```xml
...
<Placemark>
...
<ExtendedData>
<SchemaData schemaUrl="#some_schema">
<SimpleData name="A">Text</SimpleData>
<SimpleData name="B">Text</SimpleData>
</SchemaData>
</ExtendedData>
</Placemark>
```
+ Note that the parser will not check the structural validity of the used `SchemaData`.
This should be ensured by the provider.

+ The thematic data are found using the IDs of the placemarks in the KML file.
If the placemarks do not have IDs, their `name` will be used for lookup instead,
see [`95b5086`](https://github.com/3dcitydb/3dcitydb-web-map/commit/95b508696689975ddaee72f433004314f38149ff).

* URLs in the thematic info table (when an object has been clicked)
are now clickable, see [`dab83ee`](https://github.com/3dcitydb/3dcitydb-web-map/commit/dab83ee7202da8fef6c97737034e8734e3aff491)
and [`3dc8d33`](https://github.com/3dcitydb/3dcitydb-web-map/commit/3dc8d33efb8b696c966cae7ea2179e7ac0e29458).

##### CHANGES
* The ``SplashController`` has been refactored to be a separate class for modular use (see [`e7a5a74`](https://github.com/3dcitydb/3dcitydb-web-map/commit/e7a5a7430dcbe333cca8d43daa65a2d6baf91314)).

* Added a URL controller to export and parse project URLs (see
[`ff07d0c`](https://github.com/3dcitydb/3dcitydb-web-map/commit/ff07d0ca5ea001758e48d14e6d31380b53450295) and
[`f076322`](https://github.com/3dcitydb/3dcitydb-web-map/commit/f076322cc37aad8d831fb8e4bfb96a57f8972446)):
+ The URL parameters and its values are now kept compact;
+ For the list of the abbreviations used for the URL parameters, please refer to [this list](3dwebclient/utils/UrlController.js):
+ Backwards compatibility is enabled to also parse URLs generated from older versions;
+ To convert older URLs to newer ones, simply open them using the newest version of the 3DCityDB Web Map Client and then export the scene link again.

##### FIXES
* Fixed handling of ion and Bing token (see [`52aa4f9`](https://github.com/3dcitydb/3dcitydb-web-map/commit/52aa4f9c8769a33f6153348b4c57eb6c41ba09ad)):
+ An ion access token is required for the Cesium World Terrain, please refer to Cesium to acquire this access token.
+ A Bing access token is required for all Bing Maps, please refer to Microsoft to acquire this access token.
+ Both the tokens can be inserted in the project URL using the following parameters
+ ``&ionToken=<your_token>`` (or short ``&it=<your_token>``) for the Cesium World Terrain
+ ``&bingToken=<your_token>`` (or short ``&bt=<your_token>``) for all Bing Maps
+ **NOTE:** Cesium ion uses Bing Imagery by default, which means you do not need to provide a Bing access token if an ion access token is already available.
On the other hand, a Bing access token alone does not suffice. It requires an ion access token additionally.

* Fixed loading data sources when table type (vertical/horizontal) has been changed,
see [`670c4c5`](https://github.com/3dcitydb/3dcitydb-web-map/commit/670c4c573db532f1c206ddd518485603a907d0f1).

* Fixed loading options of data sources,
see [`df2c1f2`](https://github.com/3dcitydb/3dcitydb-web-map/commit/df2c1f23d24e6cefb207d32157118316517fc548).

* Fix a bug that prevented loading of Cesium 3D Tiles,
* Fixed a bug that prevented loading of Cesium 3D Tiles,
see [`9966228`](https://github.com/3dcitydb/3dcitydb-web-map/commit/9966228394acc86c51578e40e322c9c699617e6a).

### 1.8.3 - Released [[Demo Link]](https://www.3dcitydb.org/3dcitydb-web-map/1.8.3/3dwebclient/index.html)
Expand Down Expand Up @@ -227,6 +280,8 @@ If no corresponding parameters exist or are found in the URL, the camera shall f
add your own token as a string paramter in the client's URL, such as
`&bingToken=<your_bing_token>` or `&ionToken=<your_ion_token`.
Note that the given token(s) must be valid.
While Cesium's ion features can be accessed using the parameter ``ionToken``,
Bing features require both the ``ionToken`` and ``bingToken``.
* If a valid ion token is available,
you can force the client to use the Cesium World Terrain on loading
using the string paramater `&cesiumWorldTerrain=<true|false>`
Expand Down
Loading

0 comments on commit 89fdb6f

Please sign in to comment.