Questions about Immerse
Hello. I got OmniSci Enterprise License and am using it.
I have 5 questions. 1. When uploading GeoData(Shape File) to PointMap, I want to use MAP THEME instead of minimalist, but is there any way? For example, Demo Site can use various THEMEs including Satellite. -> I will fix this by referrring to customization in the documentation, Is this correct???
-
All DemoSites except TweetMap have banners such as logo(omnisci), DASHBOARDS, DATA MANAGER, HELP in the upper left, Is it possible to customize to remove these parts? Administrators may need tabs including DASHBOARDS, but from a user point of view I don't think it's necessary.
-
The types of GeoData I currently have are Point, LineString, Multipolygon, etc. There is a Problem that MultiPolygon data is not uploaded to CHOROPLETH. How can I purify the data I have to use MultiPolygon data in Immerse?
The error I saw is this: Importing Error : detect_column_types error: Unknown OGR geom type:5 Importing Error : detect_column_types error: Unsupported geometry type: MULTILINESTRING
-
Is it possible to separately extract the created Dashboard as a file other than json or csv? (I wonder if extracting allows for instant filtering and interaction.)
-
Can I customize in Korean? I would like to show all English parts of the site in Korean.
Thank you, Have a nice day!
-
Hi @MyeoNoh,
Thanks for joining the community forum and your interest in Immerse and OmnisciDB.
1 - When you uploaded any kind of geometry, you can use any of the themes when you place a Map in a dashboard, which is the default behavior. You can change this using a custom JSON file for your maps as stated here
2 - Also, this is the standard behavior, and it can be changed, but AFAIK is not in the way you are asking, so I don't think that's possible to have one section displayed if I am a superuser and not if I'm a simple user. Anyway, with customization, you can hide some elements like Data Manager for everyone and UI Settings for non-superusers; Please refer to this section on the documentation
3 - Actually, we don't support Multilinestrings or Collections, so that you can import just a single type for each defined column, and you cannot import a file containing mixed and/or unsupported data types. I will ask internally if there is a faster way, but in the meantime, I would use a tool like ogr2ogr to filter out the unsupported datatypes.
Haven'ìt tried the command but it would work
ogr2ogr -where "OGR_GEOMETRY='Multipolygon'" -f "ESRI Shapefile" your_shape_file.shp your_new_shapefile.shp
4 - You can duplicate a dashboard to use interactively, but you can export in JSON format only; I'm not sure if I correctly interpreted your question
5 - At the time of writing it's not possible to translate the UI into another language, but I can ask internally.
Bets regards, Candido
-
Hello. There are three more things I would like to ask you in continuation of the previous question.
Asking the second question in detail, is it possible for the administrator to change the order of menus, insert new menus, or delete existing menus such as DASHBOARDS, DATA MANAGER, HELP? Therefore, it is possible to show the user the screen we want.
What happened to the Korean customization you asked in question 5? In practice, it was impossible to save the table name or imported data in Korean. Previously, it was possible to call the attribute names in Korean from shapefile data. Can i express the menu or table names on the screen in Korean?
Third, what do you mean by enabling Jupyter feature in Immerse when customizing properties in servers.json? Is it simply running a query in conjunction with the DB? Or is it possible to code for customization?
Finally, I tried to change the OmniSci logo, but the file system path was not supported. Should I set it as a URL path unconditionally?
Thank you for your kind reply.
-
Hi, replying to your questions
[quote="MyeoNoh, post:3, topic:2760"] Asking the second question in detail, is it possible for the administrator to change the order of menus, insert new menus, or delete existing menus such as DASHBOARDS, DATA MANAGER, HELP? Therefore, it is possible to show the user the screen we want. [/quote]
At the time of writing, it's impossible to customize the menus in the Immerse Interface; the only thing you can hide is the SQL Editor on a user (or role) basis because it's a grant of the database. The default of that privilege is enabled, so you have to revoke this way.
`revoke view SQL editor on database omnisci from user1;
At first glance, you need something that makes the charts read-only for the users and with everything disabled, like the apps in a Kiosk, so with a minimal interface user. I will come back in this thread when I get feedback. Talking internally about this topic, we could have something valuable to your need in the 5.10 release that would come out in late December.
[quote="MyeoNoh, post:3, topic:2760"] What happened to the Korean customization you asked in question 5? In practice, it was impossible to save the table name or imported data in Korean. Previously, it was possible to call the attribute names in Korean from shapefile data. Can I express the menu or table names on the screen in Korean? [/quote]
Well, I thought you needed to translate the interface of Immerse in another language, and it is pretty tricky because everything is in the javascript bundle, so you can try to do everything with a tool like sed e.g.
cat ../bundle.2b6ff3f9981ac2109d28137503065d667facaa6e.js | sed "s/\"Dashboards\"/\"Cruscotti Analitici\"/g" | sed "s/\"Data Manager\"/\"Organizzatore dei Dati\"/g" | sed "s/\"SQL Editor\"/\"Editor SQL\"/g" | sed "s/\"HELP\"/\"Aiuto\"/g" >bundle.2b6ff3f9981ac2109d28137503065d667facaa6e.js
And this is going to translate the elements in the menu bar into Italian, but it's a pretty dangerous thing, and you need to change a lot more other things. Of course, it can break everything, and it's not supported at all.
for the records, this is the result
About table/columns names in Korean. Are you talking about Immerse, or you can't create the tables also using the database directly? What do you mean when you say " Previously, it was possible to call the attribute names in Korean from shapefile data" Do you mean that the previous release was possible, and now it has become impossible? Could you supply one of those shapefiles? Maybe I can find a workaround to load them.
[quote="MyeoNoh, post:3, topic:2760"] Third, what do you mean by enabling Jupyter feature in Immerse when customizing properties in servers.json? Is it simply running a query in conjunction with the DB? Or is it possible to code for customization? [/quote]
I guess you are talking about the
"enableJupyter": "<boolean>"
parameter. The parameter is set to show and enable a button to open a session for the user on a JupyterLab environment, used to run external code accessing the database, including IBIS.To get an idea about what IBIS is follow this link
I guess you can also create UDF with python, but I never tried, but I can find out some examples if needed.
[quote="MyeoNoh, post:3, topic:2760"] Finally, I tried to change the OmniSci logo, but the file system path was not supported. Should I set it as a URL path unconditionally? [/quote]
Yeah, you need to supply an URL that's accessible from the client's browser; Immerse it's a javascript application that's running locally so it's borrowing resources from a web server. If you haven't a local webserver in your network, you can add the picture needed into the /installation/frontend path, but you should remember to place the picture there each time you are going to upgrade the software.
Regards, Candido
-
HI,
you can setup immerse with automatic login using the servers-JSON parameter to set up an automatic login as we do for our demos into our website
as an example, these parameters would login the user myuser into database mydatabase automatically
"database": "mydatabase", "url": "localhost", "port": "6273", "username": "myuser", "password": "mypassword"
If needed you can setup two web servers; the first with automated login and the second one without, on different IP Addresses or on the same server using different ports.
Regards, Candido
-
First, let me explain our position and continue with the questions. The reason I keep asking is to build a system using the OmniSci solution. 1. Show a page including maps and charts to users through Immerse, or 2. In order to embed the map or chart provided by Immerse in the form of a component in the page we have individually built.
I would like to ask you three additional questions. 1. From our point of view, we need to provide users with a web page in Korean. Looking at the example translated into Italian above, you said that it is very dangerous, requires many changes, and is not supported at all, right? Because OmniSci is an expensive solution, it needs to be tested. I hope you find a way to ensure the stability of the product. We are considering adoption and i think OmniSci need to take responsibility.
-
Last time we had a web meeting with our company, we can see posted graphs and maps on our web page. (That page isn't Immerse, it's a page we created individually.) Can you give me the sample code that implements that webpage? And I want to know the address of that site. Ultimately, what we want is to use OmniSci as a BI tool. We want to give our users a single view by putting some of the dashboards provided by Immerse (any charts or maps) on our individually created pages.
-
We are currently testing with a Free License of CentOS/GPU. When other computer's user want to connect with a page that admin has built, does AWS(or AZURE) necessary? And I wonder if it inevitably costs money.
Let me ask you two more questions in detail.
-
Among the immersive interface demo sites with a menu at the top, why doesn't the tweetmap have a menu at the top? I want to customize it that way. No way at all?
-
Previously, to be able to call attribute names in Korean from shapefile data means that data stored in Korean could be called simply, and that the attribute names were not uploaded to Immerse's Data Manager in Korean. For example, Korean attributes such as 'name' and 'location' are replaced with c1 and c2. We want this to be resolved.
Thank you for your detailed reply.
-
-
Hi @MyeoNoh,
I think you are asking for a Kiosk mode, and as I said before, we have some customization that should be available in the 5.10 release and some API to embed charts and maps into a custom web page.
Right now, there isn't an easy way to embed a chart from Immerse into a web page; there are some APIs, that you can try to use, like the mapd-charting, but right now, I cannot recommend anything with an enterprise adoption in mid,
Anyway, the Twitter demo uses the mapd-charting API, so this is the reason it hasn't any interface element.
Replying to your points.
-
About the localization of Immerse, we haven't any near term plan to localize the tool in any language; I provided an example of how it can be done using UNIX commands, but it isn't supported as it could break the software because it is more a hack than a solution. When a proper localization solution is available, it will be fully supported, as our entire software stack is.
-
I guess you talked with @Brad_Shao? I haven't any idea about what they showed to you. I can ask what has been shown to you. I'm not sure if they used mapd-charting or vega to embed individual charts into a webpage.
-
You can deploy Omnisci where you prefer, on-premise or in the cloud, depending on your needs. Almost all the demos of our website, as an example, run on internal machines; you have to be sure that the server you are using to run the services is reachable from the Internet (or Intranet, if your users are located in the same network) You could also continue to use the server you are using for evaluation, just swapping the free license with an enterprise's one.
About your last questions; As I said before, the tweet map isn't built on Immerse, but the mapd-carting API, among others. You can find the code in GitHub at this link https://github.com/omnisci/omnisci-tweetmap-2
Yap, I tried with a Kanji file, and I faced the same problem; In which version was working? I tried with old versions like the 5.5 and the columns containing encoded text are renamed.
Regards, Candido
-
-
Hello. Thanks for your kind reply, we are testing it well.
I would like to know if it is possible to solve the 3 problems.
-
I have implemented POINTMAP as follows in Immerse. I used the OpenStreetMap API, and I want to know how to solve the problem that the map is in English. I wish it was displayed in Korean.
-
What is currently being tested is whether OmnSci's POINTMAP, LINEMAP, GEO HEATMAP, CHOROPLETH can be used on the intranet. I found that the map service required for openstreetmap cannot be used in an environment where there is no communication with the outside network. (As before, only the MAP THEME(Minimalist) can be used.) Is there any way to utilize the OpenStreetMap data remaining in the cache on the intranet?
3. We applied the Month option to the Y Axis in the HEATMAP. Is it possible to customize these parts in Korean?
thank you.
-
-
Hi @MyeoNoh,
I asked internally, and we don't currently support any localization, for it's a no for questions 1 and 3. I something changes, I will reach you here (I guess it's likely that this could change for 1)
About your second question, we have customers that can do that, but I don't know how exactly configure; I'm waiting for a detailed response, and I will come back to you when I have something solid. My best guess is that you can implement using a Mapbox Atlas server or something similar that can render the layers needed in your intranet and use it with custom mapbox styles.
-
Hi @MyeoNoh,
We made some progress on controlling which part of the immerse interface has to be shown or not. This can be useful when you have a group of users that would see a predefined dashboard without the need to navigate between multiple dashboards.
using the ui_off on the query string, you can turn off everything you want
http://xxxzxxx/dashboard/3?tab=-Mt8ZUu8Y5iZdXYEIv5r&ui_off=IMMERSE_UI_NAVBAR,IMMERSE_UI_TABS,IMMERSE_UI_ADD_CHART,immerse_ui_headerbar,immerse_ui_side_panels=
without any switch, the result would be like this
the ui_off parameter turns off the objects specified in a list of comma-separated values; on our example is used
IMMERSE_UI_NAVBAR IMMERSE_UI_TABS IMMERSE_UI_ADD_CHART immerse_ui_headerbar immerse_ui_side_panels
As you can see, the case isn't important.
I sent you a private message with more detailed instructions on how to use this
-
Hi @MyeoNoh,
There is a way to have the mapd in Korean (almost) and run on a local Intranet without the need of an Internet connection for the client.
You can use the OpenMapTiles server from klokantech, that's almost free and relatively easy to use.
Just run the command to start the server
mapd@zion-tr:~$ sudo docker run --rm -it -v $(pwd):/data -p 8080:80 klokantech/openmaptiles-server
If needed, it will start to download the docker images required; it takes a while because they are more or less 1.5 GB.
the out for the first time would be something like that
/usr/lib/python2.7/dist-packages/supervisor/options.py:298: UserWarning: Supervisord is running as root and it is searching for its configuration file in default locations (including its current working directory); you probably want to specify a "-c" argument specifying an absolute path to a configuration file for improved security. 'Supervisord is running as root and it is searching ' 2022-02-02 09:03:25,507 CRIT Supervisor running as root (no user in config file) 2022-02-02 09:03:25,507 INFO Included extra file "/etc/supervisor/conf.d/openmaptiles.conf" during parsing 2022-02-02 09:03:25,509 INFO Creating socket tcp://localhost:8081 2022-02-02 09:03:25,510 INFO Closing socket tcp://localhost:8081 2022-02-02 09:03:25,518 INFO RPC interface 'supervisor' initialized 2022-02-02 09:03:25,518 CRIT Server 'unix_http_server' running without any HTTP authentication checking 2022-02-02 09:03:25,519 INFO supervisord started with pid 1 2022-02-02 09:03:26,521 INFO spawned: 'wizard' with pid 9 2022-02-02 09:03:26,522 INFO spawned: 'xvfb' with pid 10 Starting OpenMapTiles Map Server (action: run) 2022-02-02 09:03:26,921 INFO success: wizard entered RUNNING state, process has stayed up for > than 0 seconds (startsecs) 2022-02-02 09:03:26,921 INFO success: xvfb entered RUNNING state, process has stayed up for > than 0 seconds (startsecs) Config file not found! Starting installation... Installation wizard started at http://:::80/ List of available downloads ready.
Then connect to the host where you installed the server with your favorite browser to run the wizard that will assist in configuring the server.
Start the wizard, then select the region you need for your maps; in this case, I chose South Korea only to minimize the download size.
Then I leave all the styles selected, choosing the Koran as the predefined language for the maps.
Select the services you will use with that server (in this case, every service is selected, but we will go to use just the raster)
Then before starting the download, we had to get a key that could be commercial or free. After that, you request clicking the link on the page.
Just select the license needed; in this case, I picked a personal key for evaluation only, getting an outdated map from 2017
Then come back, and insert the key to download the map's files.
and start the server
You can use the local viewer for each style to check if everything is ok.
You have to customize Immerse with the MapBoxCustomStyles section of the servers.json file to use those maps.
I added all four styles of the maps, so the user can choose which one fits more to his needs.
[ { "database": "omnisci", "url": "localhost", "port": "6273", "protocol": "http", "username": "admin", "password": "HyperInteractive", "feature_flags": { "ui/default_theme": "dark", "ui/enable_crosslink_panel" : true , "ui/enable_global_custom_sql" : true, "dev/SQLLogging" : false }, "mapboxCustomStyles": [ { "label": "local_positron", "value": { "version": 8, "sources": { "openstreetmap": { "type": "raster", "tiles": [ "http://localhost:8080/styles/positron/{z}/{x}/{y}.png" ], "tileSize": 256 } }, "layers": [{ "id": "openstreetmap", "type": "raster", "source": "openstreetmap", "minzoom": 0, "maxzoom": 22 }] } }, { "label": "local_dark-matter", "value": { "version": 8, "sources": { "openstreetmap": { "type": "raster", "tiles": [ "http://localhost:8080/styles/dark-matter/{z}/{x}/{y}.png" ], "tileSize": 256 } }, "layers": [{ "id": "openstreetmap", "type": "raster", "source": "openstreetmap", "minzoom": 0, "maxzoom": 22 }] } }, { "label": "local_klokantech-basic", "value": { "version": 8, "sources": { "openstreetmap": { "type": "raster", "tiles": [ "http://localhost:8080/styles/klokantech-basic/{z}/{x}/{y}.png" ], "tileSize": 256 } }, "layers": [{ "id": "openstreetmap", "type": "raster", "source": "openstreetmap", "minzoom": 0, "maxzoom": 22 }] } }, { "label": "local_osm-bright", "value": { "version": 8, "sources": { "openstreetmap": { "type": "raster", "tiles": [ "http://localhost:8080/styles/osm-bright/{z}/{x}/{y}.png" ], "tileSize": 256 } }, "layers": [{ "id": "openstreetmap", "type": "raster", "source": "openstreetmap", "minzoom": 0, "maxzoom": 22 }] } } ] } ]
and this is the final result on Immerse
You can further personalize the configuration by modifying the config.json file created into the directory you run the docker.
Hope it helps.
Regards, Candido
-
Hello. While customizing immerse using docker, there was a problem that could not connect to the DB server.
systemctl restart omnisci_server and
systemctl stop omnisci_server systemctl start omnisci_server
systemctl disable omnisci_server doesn't work at all. Any solution?
What was going on was as follows.
- yum -y update
- yum -y install docker docker-registry
- sudo docker run --rm -it -v $(pwd):/data -p 8080:80 klokantech/openmaptiles-server
POC is scheduled for this week, but I am on a very difficult situation due to DB server fail problem. I'm really sorry for urging you but can I get a reply as soon as possible?
omnisci.conf
res-gpu-mem = 700000000 render-mem-bytes=500000000 port = 6274 http-port = 6278 calcite-port = 6279 data = "/var/lib/omnisci/data" null-div-by-zero = true allowed-import-paths = ["/opt/omnisci/data/mapd_import"] renderer-use-vulkan-driver=false
[web] servers-json = "/var/lib/omnisci/servers.json" port = 6273 frontend = "/opt/omnisci/frontend"
servers.json
[ { "database": "omnisci", "url": "localhost", "port": "6273", "username": "admin", "password": "HyperInteractive", "feature_flags": { "ui/default_theme": "light" }, "customStyles": { "logoURL": "http://192.168.1.6:6273/omni_logo.png", "loginText": "Login to KEPCO Next Generation Power Information System", "title": "KEPCO Next Generation Power Information System", "buttonPrimaryColor": "#888888", "buttonSecondaryColor": "#444444", "buttonSecondaryHighlightColor": "#000000"
} } ]
-
Looks that after installing Vulkan the server is starting as expected when run from the command line (it's using OpenGL because of the config).
But still, fail to run from the systemctl (it looks multiple restarts happened), and that's unexpected, so we should look at the logs located in /var/lib/omnisci/data/mapd_log/ and check the file omnisci_server.INFO for errors.
In the meantime, I checked of in the 5.10 the Vulkan library is mandatory, but it looks like nothing changed, so I don't get what's happened to your installation.
Candido.
-
It was a version issue. I solved it as you said. thank you.
-
I think that the session problem that came up during iframe can be solved through enterprise license. Please let me know if there are any enterprise licenses available.
-
Also, if I want to show the desired data by hovering the mouse in the new combo chart, is it customizable? I am trying to work by modifying the current table.
-
How can I start omnisql? So far we have been working with SQL Editor, but in the future we want to export the table we worked on for backup. Thank you for your kind reply.
-
-
Hi,
I am pleased you solved the problem, and you can proceed with your demo.
The session limit problem is indirectly caused by the use of special instructions to hide the header bar of omnisci, hiding also the log-out button; the free edition has a maximum number of 3 sessions, so the error. The enterprise license hasn't any limit, but we should work to resolve this problem in the long run.
I got an Enterprise trial license for you, and I sent as a private message and email ;)
In the combo chart, you can customize the formats of the fields you used to build the charts; I don't think you can hide or add something in the legend.
I will ask about it the front-end team.
To start omnisql, you have to log on to the server and run /opt/omnisci/bin/omnisql [database name] I guess you want to run the dump/restore command.
https://docs-new.omnisci.com/sql/data-definition-ddl/tables#dump-table https://docs-new.omnisci.com/sql/data-definition-ddl/tables#restore-table
both those commands run from Immerse's SQL Editor, Omnisql, or any other tool, assuming you have white-listed the server paths you are going to write the backups (the files are saved into the local server, whatever the tool you are using, as for the copy command)
Regards, Candido.
-
thank you. I can't run omnisql, but I didn't know if I could dump it through SQL Editor. I'm working through the SQL Editor, how do I add a path to a whitelist?
The problem of 'Too much Sessions' was solved through the Enterprise license you gave me, but when I access it using an iFrame, a 'Session not valid' error still appears. I'm using the Chrome browser, but I can't connect even if I allow all cookies.
thank you for your kind reply:)
-
Hi,
for the omnisql, type the command omnisql with the options needed (you can specify the Database you want to connect on, the user and the password you wish to use, and so on) refer to the docs here
Whitelisting a path for writing is like what you did for reading, so add to the main section of omnisci.conf
allowed-export-paths = ["/the_dir_where_you_want_to_place_the_dumps"]
The path added, could be used for COPY, DUMP, and every command that needs to write something into the local filesystem.
The exact path should also be added to the allowed-import-paths to use the RESTORE command.
The "Session not valid" error you are getting is likely caused by a CORS error and can be corrected in two ways.
The first is to place the webserver and the database server into the same domain, so if you use for the iframe an address of http://192.168.1.6, the same would be used for the attribute of URL of the servers.json, and you should call http://192.168.1.6:6273/ from your browser.
In the case of IP Addresses, the CORS can be avoided only using the same IP for Immerse and the Database, so putting into the mix localhost or other addresses could lead to such errors.
The second that I haven't tried is to use both Immerse and the Database in HTTPS, adding
enable-cross-domain=true
to the parameters of the web section of the config file; Anyway, it should be better not to force this kind of thing, so if possible, configure everything with the IP or the name of your machine, and if you have more than one machine, place both into the same domain.Regards, Candido
-
Hello. Thank you for your active support. I have some questions during the POC.
-
I wonder if the map layer of our company's GIS server can be used as a background map in OmniSci. Our GIS server uses OpenLayers, GeoServer (WAS), and postgreGIS (DB). Can we add the map service of our GIS server to servers.json in URL format (http://localhost:8080/styles/positron/{z}/{x}/{y}.png)?
-
If No. 1 is possible and our company purchases OmniSci products, I wonder what kind of technical work your company can do for our company. For example, Is it possible that modifying OpenLayers using JAVASCRIPT? I'm also curious about how long it will take.
-
If No. 2 does not take a long time and is not complicated, we would like to try it within this POC period. Do you have any more URL addresses or documents for sites where I can get help?
-
While working with SQL, I wanted to do a CONCATENATE operation, but I couldn't find the function (CONCAT function or ||). I want to put the unit after the number. ex) 154 -> 154kV Since there are tens of thousands of data, DML is needed to combine two columns to put a unit after every number. Does OmniSQL support these grammars? Or is there a way to print the table, graph, or map with units attached even if the data is not modified?
-
-
Hi,
Thanks for your kind words. I am also enjoying our discussion.
- It's possible to call a WMS service using the Mapbox API, a service exposed by the Geoserver software you are using.
The configuration is similar to the OpenStreetMap configuration; you must use the getmap request.
{ "label": "global_wms", "value": { "version": 8, "sources": { "local_wms": { "type": "raster", "tiles": [ "https://www.gebco.net/data_and_products/gebco_web_services/web_map_service/mapserv?request=getmap&service=wms&BBOX={bbox-epsg-3857}&crs=EPSG:3857&format=image/jpeg&layers=gebco_latest&width=256&height=256&version=1.3.0" ], "tileSize": 256 } }, "layers": [{ "id": "local_wms", "type": "raster", "source": "local_wms", "minzoom": 0, "maxzoom": 22 }] } }
I used a relief WMS public service, but it's entirely usable with a GeoServer WMS service. Is it helpful for your POC? Let me know.
2 and 3. I don't get what it's asked here. Openlayers is an API to build map visualization on the Web; are you asking for deep integration of that API with Immerse? Anyway, to speed up this kind of question, which belongs more to the Enterprise support than Community, I suggest you contact (or if you prefer, be got reached) my colleagues in the Asia area. They can be faster because of the TZ (I'm located in Europe, so I'm halfway between the SF and Seoul, so it takes me more time to get info back to you). I have sent a PM about that.
- Inimmerse you can define a Custom Formatting for measures or dimensions.
As an example, in this Combo Chart, I want to specify that the result values are expressed in minutes, so I define on the fly a Custom formatting of {.2f} mins on Date and formatting tab
In the case of Multiple Measures, you can choose for each one of them
So adding fields or doing transformations isn't needed for such tasks; this saves memory at runtime and the time needed to do the transformations
I hope I replied completely to your questions.
Regards, Candido
Please sign in to leave a comment.
Comments
26 comments