Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
M
Mapserver REST API
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Redmine
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Deploy
Releases
Package registry
Container registry
Model registry
Operate
Terraform modules
Analyze
Contributor analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Miscellaneous
Mapserver REST API
Compare revisions
a7e05ca5743fb76dc4af059b960e46a1c7b137d9 to f67e79373ed554f5493572c972027e0c0b76604b
Compare revisions
Changes are shown as if the
source
revision was being merged into the
target
revision.
Learn more about comparing revisions.
Source
misc/mra
Select target project
No results found
f67e79373ed554f5493572c972027e0c0b76604b
Select Git revision
Branches
branch-debug
develop
master
Tags
1.0.0
1.0.1
1.0.2
1.1.0
1.1.2
1.1.3
1.1.4
1.1.5
1.1.6
1.1.7
1.1.8
1.1.9
15 results
Swap
Target
misc/mra
Select target project
misc/mra
1 result
a7e05ca5743fb76dc4af059b960e46a1c7b137d9
Select Git revision
Branches
branch-debug
develop
master
Tags
1.0.0
1.0.1
1.0.2
1.1.0
1.1.2
1.1.3
1.1.4
1.1.5
1.1.6
1.1.7
1.1.8
1.1.9
15 results
Show changes
Only incoming changes from source
Include changes to target since source was created
Compare
Commits on Source (2)
REDMINE_ISSUE-14221
API Endpoint with MRA/Mapserver/GDAL version
· 1f4777f9
Sébastien DA ROCHA
authored
2 years ago
and
m431m
committed
2 years ago
1f4777f9
Merge branch 'redmine-issues/14221' into 'develop'
· f67e7937
m431m
authored
2 years ago
Resolve
REDMINE_ISSUE-14221
See merge request
!5
f67e7937
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
requirements.txt
+1
-1
1 addition, 1 deletion
requirements.txt
setup.py
+2
-4
2 additions, 4 deletions
setup.py
src/__init__.py
+3
-0
3 additions, 0 deletions
src/__init__.py
src/mra.py
+67
-41
67 additions, 41 deletions
src/mra.py
src/server.py
+13
-0
13 additions, 0 deletions
src/server.py
with
86 additions
and
46 deletions
requirements.txt
View file @
f67e7937
web.py
>=0.
5
0,<0.
6
0
web.py
>=0.
6
0,<0.
7
0
gdal
<2.5.0
pyyaml
<5.4
This diff is collapsed.
Click to expand it.
setup.py
View file @
f67e7937
...
...
@@ -24,9 +24,7 @@
import
os.path
from
setuptools
import
setup
version
=
'
1.1.8
'
from
src
import
__version__
def
parse_requirements
(
filename
):
...
...
@@ -42,7 +40,7 @@ reqs = [str(req) for req in parse_requirements(reqs_filename)]
setup
(
name
=
"
MapServer Rest API
"
,
version
=
version
,
version
=
__
version
__
,
description
=
"
A RESTFul interface for MapServer
"
,
author
=
"
Neogeo Technologies
"
,
author_email
=
"
contact@neogeo.fr
"
,
...
...
This diff is collapsed.
Click to expand it.
src/__init__.py
View file @
f67e7937
...
...
@@ -20,3 +20,6 @@
# GNU General Public License for more details. #
# #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
__version__
=
'
1.1.9
'
This diff is collapsed.
Click to expand it.
src/mra.py
View file @
f67e7937
...
...
@@ -96,7 +96,7 @@ OUTPUTFORMAT = {
imagemode
=
mapscript
.
MS_IMAGEMODE_FEATURE
,
transparent
=
mapscript
.
MS_OFF
,
options
=
{
"
FORM
"
:
"
SIMPLE
"
,
"
STORAGE
"
:
"
stream
"
})
},
},
'
WMS
'
:
{
'
PNG8
'
:
outputformat
(
"
AGG/PNG8
"
,
"
png8
"
,
mimetype
=
"
image/png; mode=8bit
"
,
...
...
@@ -109,8 +109,8 @@ OUTPUTFORMAT = {
"
AGG/JPEG
"
,
"
jpeg
"
,
mimetype
=
"
image/jpeg
"
,
imagemode
=
mapscript
.
MS_IMAGEMODE_RGB
,
extension
=
"
jpg
"
,
options
=
{
"
GAMMA
"
:
"
0.75
"
})
}
}
}
class
MetadataMixin
(
object
):
...
...
@@ -134,7 +134,8 @@ class Layer(MetadataMixin):
self
.
ms
=
backend
def
enable
(
self
,
enabled
=
True
):
wms
=
(
"
GetCapabilities
"
,
"
GetMap
"
,
"
GetFeatureInfo
"
,
"
GetLegendGraphic
"
,
"
DescribeLayer
"
,
"
GetStyles
"
)
wms
=
(
"
GetCapabilities
"
,
"
GetMap
"
,
"
GetFeatureInfo
"
,
"
GetLegendGraphic
"
,
"
DescribeLayer
"
,
"
GetStyles
"
)
wcs
=
(
"
GetCapabilities
"
,
"
GetCoverage
"
,
"
DescribeCoverage
"
)
wfs
=
(
"
GetCapabilities
"
,
"
GetFeature
"
,
"
DescribeFeatureType
"
)
...
...
@@ -147,11 +148,14 @@ class Layer(MetadataMixin):
self
.
set_metadata
(
"
wfs_enable_request
"
,
"
"
.
join
(
wfs
))
else
:
self
.
ms
.
status
=
mapscript
.
MS_OFF
self
.
set_metadata
(
"
wms_enable_request
"
,
"
"
.
join
([
"
!%s
"
%
m
for
m
in
wms
]))
self
.
set_metadata
(
"
wms_enable_request
"
,
"
"
.
join
([
"
!%s
"
%
m
for
m
in
wms
]))
if
self
.
ms
.
type
==
3
:
self
.
set_metadata
(
"
wcs_enable_request
"
,
"
"
.
join
([
"
!%s
"
%
m
for
m
in
wcs
]))
self
.
set_metadata
(
"
wcs_enable_request
"
,
"
"
.
join
([
"
!%s
"
%
m
for
m
in
wcs
]))
else
:
self
.
set_metadata
(
"
wfs_enable_request
"
,
"
"
.
join
([
"
!%s
"
%
m
for
m
in
wfs
]))
self
.
set_metadata
(
"
wfs_enable_request
"
,
"
"
.
join
([
"
!%s
"
%
m
for
m
in
wfs
]))
def
get_type_name
(
self
):
return
{
...
...
@@ -160,7 +164,7 @@ class Layer(MetadataMixin):
2
:
"
POLYGON
"
,
3
:
"
RASTER
"
,
4
:
"
ANNOTATION
"
,
}[
self
.
ms
.
type
]
}[
self
.
ms
.
type
]
def
get_proj4
(
self
):
return
self
.
ms
.
getProjection
()
...
...
@@ -232,7 +236,8 @@ class Layer(MetadataMixin):
xmlsld
.
firstChild
.
getElementsByTagNameNS
(
"
*
"
,
"
NamedLayer
"
)[
0
]
\
.
getElementsByTagNameNS
(
"
*
"
,
"
Name
"
)[
0
].
firstChild
.
data
=
sld_layer_name
except
Exception
as
e
:
logging
.
error
(
"
mra.py::Layer::add_style_sld: Bad sld (No NamedLayer/Name): %s
"
,
e
)
logging
.
error
(
"
mra.py::Layer::add_style_sld: Bad sld (No NamedLayer/Name): %s
"
,
e
)
raise
ValueError
(
"
Bad sld (No NamedLayer/Name)
"
)
new_sld
=
xmlsld
.
toxml
()
...
...
@@ -245,7 +250,8 @@ class Layer(MetadataMixin):
try
:
ms_template_layer
.
applySLD
(
new_sld
,
sld_layer_name
)
except
Exception
as
e
:
logging
.
error
(
"
mra.py::Layer::add_style_sld: Unable to access storage : %s
"
,
e
)
logging
.
error
(
"
mra.py::Layer::add_style_sld: Unable to access storage : %s
"
,
e
)
raise
ValueError
(
"
Unable to access storage.
"
)
for
i
in
range
(
ms_template_layer
.
numclasses
):
...
...
@@ -270,9 +276,11 @@ class Layer(MetadataMixin):
return
None
try
:
style
=
open
(
os
.
path
.
join
(
os
.
path
.
dirname
(
__file__
),
"
%s.sld
"
%
s_name
),
encoding
=
"
utf-8
"
).
read
()
style
=
open
(
os
.
path
.
join
(
os
.
path
.
dirname
(
__file__
),
"
%s.sld
"
%
s_name
),
encoding
=
"
utf-8
"
).
read
()
except
IOError
as
OSError
:
logging
.
warning
(
"
mra.py::Layer::set_default_style IOError %s
"
,
OSError
)
logging
.
warning
(
"
mra.py::Layer::set_default_style IOError %s
"
,
OSError
)
return
self
.
add_style_sld
(
mf
,
s_name
,
style
)
...
...
@@ -379,7 +387,8 @@ class Mapfile(MetadataMixin):
self
.
set_metadata
(
"
%s_enable_request
"
%
ows
,
"
*
"
)
if
'
onlineresource
'
in
config
:
onlineresource
=
urljoin
(
config
.
get
(
'
onlineresource
'
),
self
.
ms
.
name
)
onlineresource
=
urljoin
(
config
.
get
(
'
onlineresource
'
),
self
.
ms
.
name
)
self
.
set_metadata
(
'
ows_onlineresource
'
,
onlineresource
)
fontset
and
self
.
ms
.
setFontSet
(
fontset
)
...
...
@@ -443,7 +452,7 @@ class Mapfile(MetadataMixin):
# Add metadata.
metadata
=
{
"
wms_srs
"
:
self
.
get_metadata
(
"
ows_srs
"
),
}
}
metadata
.
update
(
l_metadata
)
layer
.
update_metadatas
(
metadata
)
...
...
@@ -534,8 +543,10 @@ class FeatureTypeModel(LayerModel):
cparam
=
info
[
"
connectionParameters
"
]
if
cparam
.
get
(
"
dbtype
"
,
None
)
in
[
"
postgis
"
,
"
postgres
"
,
"
postgresql
"
]:
self
.
ms
.
connectiontype
=
mapscript
.
MS_POSTGIS
connection
=
"
dbname=%s port=%s host=%s
"
%
(
cparam
.
get
(
"
database
"
,
"
postgres
"
),
cparam
.
get
(
"
port
"
,
"
5432
"
),
cparam
.
get
(
"
host
"
,
"
localhost
"
))
connection
+=
"
"
.
join
(
"
%s=%s
"
%
(
p
,
cparam
[
p
])
for
p
in
[
"
user
"
,
"
password
"
]
if
p
in
cparam
)
connection
=
"
dbname=%s port=%s host=%s
"
%
(
cparam
.
get
(
"
database
"
,
"
postgres
"
),
cparam
.
get
(
"
port
"
,
"
5432
"
),
cparam
.
get
(
"
host
"
,
"
localhost
"
))
connection
+=
"
"
.
join
(
"
%s=%s
"
%
(
p
,
cparam
[
p
])
for
p
in
[
"
user
"
,
"
password
"
]
if
p
in
cparam
)
self
.
ms
.
connection
=
connection
self
.
ms
.
data
=
'
%s FROM %s.%s
'
%
(
ds
[
ft_name
].
get_geometry_column
(),
...
...
@@ -554,7 +565,8 @@ class FeatureTypeModel(LayerModel):
# Update mra metadata, and make sure the mandatory ones are left untouched.
self
.
update_mra_metadatas
(
metadata
)
self
.
update_mra_metadatas
({
"
name
"
:
ft_name
,
"
type
"
:
"
featuretype
"
,
"
storage
"
:
ds_name
})
self
.
update_mra_metadatas
(
{
"
name
"
:
ft_name
,
"
type
"
:
"
featuretype
"
,
"
storage
"
:
ds_name
})
def
configure_layer
(
self
,
layer
,
enabled
=
True
):
ws
=
self
.
ws
...
...
@@ -578,7 +590,7 @@ class FeatureTypeModel(LayerModel):
"
type
"
:
self
.
get_mra_metadata
(
"
type
"
),
"
storage
"
:
self
.
get_mra_metadata
(
"
storage
"
),
"
workspace
"
:
ws
.
name
,
})
})
layer
.
enable
(
enabled
)
...
...
@@ -596,7 +608,7 @@ class FeatureTypeModel(LayerModel):
"
gml_%s_type
"
%
field_name
:
field
.
get_type_gml
(),
# "gml_%s_precision" % field_name
# "gml_%s_width" % field_name
})
})
geometry_column
=
ft
.
get_geometry_column
()
if
geometry_column
is
None
:
...
...
@@ -611,7 +623,7 @@ class FeatureTypeModel(LayerModel):
self
.
ms
.
extent
.
miny
,
self
.
ms
.
extent
.
maxx
,
self
.
ms
.
extent
.
maxy
,
),
),
"
ows_include_items
"
:
"
,
"
.
join
(
field_names
),
"
gml_include_items
"
:
"
,
"
.
join
(
field_names
),
"
gml_geometries
"
:
geometry_column
,
...
...
@@ -619,13 +631,13 @@ class FeatureTypeModel(LayerModel):
# TODO: Add gml_<geometry name>_occurances,
"
wfs_srs
"
:
ws
.
get_metadata
(
"
ows_srs
"
),
"
wfs_getfeature_formatlist
"
:
"
,
"
.
join
(
list
(
OUTPUTFORMAT
[
"
WFS
"
].
keys
()))
})
})
if
ft
.
get_fid_column
()
is
not
None
:
layer
.
set_metadatas
({
"
wfs_featureid
"
:
ft
.
get_fid_column
(),
"
gml_featureid
"
:
ft
.
get_fid_column
(),
})
})
plugins
.
extend
(
"
post_configure_vector_layer
"
,
self
,
ws
,
ds
,
ft
,
layer
)
...
...
@@ -645,7 +657,8 @@ class CoverageModel(LayerModel):
try
:
crs
=
metadata
.
pop
(
"
crs
"
)
proj4
=
"
+init=%s:%s
"
%
(
crs
[
"
authority_name
"
],
crs
[
"
authority_code
"
])
proj4
=
"
+init=%s:%s
"
%
(
crs
[
"
authority_name
"
],
crs
[
"
authority_code
"
])
except
Exception
as
e
:
logging
.
warn
(
'
mra.py::MRA::CoverageModel.update error %s
'
,
e
)
proj4
=
cs
.
get_proj4
()
...
...
@@ -672,12 +685,12 @@ class CoverageModel(LayerModel):
url
=
urlparse
(
cparam
[
"
url
"
])
filename
=
self
.
ws
.
mra
.
get_file_path
(
url
.
path
)
if
cs
.
tindex
is
None
:
#if cparam["dbtype"] in ["tif", "tiff"]:
#
if cparam["dbtype"] in ["tif", "tiff"]:
self
.
ms
.
data
=
filename
self
.
ms
.
tileindex
=
None
self
.
ms
.
tileitem
=
None
# TODO: strip extention.
#else:
#
else:
# raise ValueError("Unhandled type \"%s\"." % cparam["dbtype"])
else
:
self
.
ms
.
data
=
None
...
...
@@ -719,7 +732,7 @@ class CoverageModel(LayerModel):
"
type
"
:
self
.
get_mra_metadata
(
"
type
"
),
"
storage
"
:
self
.
get_mra_metadata
(
"
storage
"
),
"
workspace
"
:
ws
.
name
,
})
})
layer
.
set_metadatas
({
"
ows_name
"
:
layer_name
,
...
...
@@ -730,11 +743,11 @@ class CoverageModel(LayerModel):
self
.
ms
.
extent
.
miny
,
self
.
ms
.
extent
.
maxx
,
self
.
ms
.
extent
.
maxy
,
),
),
"
wcs_name
"
:
layer
.
get_metadata
(
"
wcs_name
"
,
None
)
or
layer_name
,
"
wcs_label
"
:
layer
.
get_metadata
(
"
wcs_label
"
,
None
)
or
layer_name
,
"
wcs_description
"
:
layer
.
get_metadata
(
"
wcs_description
"
,
None
)
or
layer_name
})
})
layer
.
enable
(
enabled
)
...
...
@@ -843,7 +856,8 @@ class Workspace(Mapfile):
except
(
StopIteration
,
SystemError
):
pass
# No layers use our store, all OK.
else
:
raise
ValueError
(
"
The datastore
\"
%s
\"
can
'
t be delete because it is used.
"
%
name
)
raise
ValueError
(
"
The datastore
\"
%s
\"
can
'
t be delete because it is used.
"
%
name
)
return
self
.
delete_store
(
"
datastore
"
,
name
)
# Coveragestores (this is c/p from datastores):
...
...
@@ -886,7 +900,8 @@ class Workspace(Mapfile):
except
(
StopIteration
,
SystemError
):
pass
# No layers use our store, all OK.
else
:
raise
ValueError
(
"
The coveragestore
\"
%s
\"
can
'
t be delete because it is used.
"
%
name
)
raise
ValueError
(
"
The coveragestore
\"
%s
\"
can
'
t be delete because it is used.
"
%
name
)
return
self
.
delete_store
(
"
coveragestore
"
,
name
)
# LayerModels:
...
...
@@ -945,7 +960,8 @@ class Workspace(Mapfile):
def
delete_layermodel
(
self
,
st_type
,
ds_name
,
ft_name
):
lm
=
self
.
get_layermodel
(
st_type
,
ds_name
,
ft_name
)
if
lm
.
get_mra_metadata
(
"
layers
"
,
[]):
raise
ValueError
(
"
The %s
\"
%s
\"
can
'
t be delete because it is used.
"
%
(
st_type
,
ft_name
))
raise
ValueError
(
"
The %s
\"
%s
\"
can
'
t be delete because it is used.
"
%
(
st_type
,
ft_name
))
self
.
ms
.
removeLayer
(
lm
.
ms
.
index
)
# Featuretypes
...
...
@@ -998,7 +1014,7 @@ class MRA(object):
self
.
config
=
yaml
.
load
(
open
(
config_path
,
"
r
"
),
# Loader=yaml.FullLoader
)
)
except
yaml
.
YAMLError
as
e
:
exit
(
"
Error in configuration file: %s
"
%
e
)
...
...
@@ -1025,7 +1041,8 @@ class MRA(object):
return
os
.
path
.
relpath
(
path
,
self
.
get_path
())
def
get_resource_path
(
self
,
*
args
):
root
=
self
.
config
[
"
storage
"
].
get
(
"
resources
"
,
self
.
get_path
(
"
resources
"
))
root
=
self
.
config
[
"
storage
"
].
get
(
"
resources
"
,
self
.
get_path
(
"
resources
"
))
return
self
.
get_path
(
root
,
*
args
)
def
pub_resource_path
(
self
,
path
):
...
...
@@ -1052,7 +1069,8 @@ class MRA(object):
fontset
.
close
def
get_font_path
(
self
,
*
args
):
root
=
self
.
config
[
"
storage
"
].
get
(
"
fonts
"
,
self
.
get_resource_path
(
"
fonts
"
))
root
=
self
.
config
[
"
storage
"
].
get
(
"
fonts
"
,
self
.
get_resource_path
(
"
fonts
"
))
return
self
.
get_resource_path
(
root
,
*
args
)
def
create_font
(
self
,
name
,
data
=
None
):
...
...
@@ -1074,7 +1092,8 @@ class MRA(object):
# Styles:
def
get_style_path
(
self
,
*
args
):
root
=
self
.
config
[
"
storage
"
].
get
(
"
styles
"
,
self
.
get_resource_path
(
"
styles
"
))
root
=
self
.
config
[
"
storage
"
].
get
(
"
styles
"
,
self
.
get_resource_path
(
"
styles
"
))
return
self
.
get_resource_path
(
root
,
*
args
)
def
pub_style_path
(
self
,
path
):
...
...
@@ -1118,7 +1137,8 @@ class MRA(object):
# Files:
def
get_file_path
(
self
,
*
args
):
root
=
self
.
config
[
"
storage
"
].
get
(
"
data
"
,
self
.
get_resource_path
(
"
data
"
))
root
=
self
.
config
[
"
storage
"
].
get
(
"
data
"
,
self
.
get_resource_path
(
"
data
"
))
return
self
.
get_resource_path
(
root
,
*
args
)
def
pub_file_path
(
self
,
path
):
...
...
@@ -1134,7 +1154,8 @@ class MRA(object):
# Available (get):
def
get_available_path
(
self
,
*
args
):
root
=
self
.
config
[
"
storage
"
].
get
(
"
available
"
,
self
.
get_path
(
"
available
"
))
root
=
self
.
config
[
"
storage
"
].
get
(
"
available
"
,
self
.
get_path
(
"
available
"
))
return
self
.
get_path
(
root
,
*
args
)
def
pub_available_path
(
self
,
path
):
...
...
@@ -1169,12 +1190,14 @@ class MRA(object):
def
delete_workspace
(
self
,
name
):
# path = self.get_available_path("%s.ws.map" % name)
raise
NotImplementedError
(
"
Method
'
delete_workspace
'
is not yet available. (TODO)
"
)
raise
NotImplementedError
(
"
Method
'
delete_workspace
'
is not yet available. (TODO)
"
)
# Services:
def
get_service_path
(
self
,
*
args
):
root
=
self
.
config
[
"
storage
"
].
get
(
"
services
"
,
self
.
get_path
(
"
services
"
))
root
=
self
.
config
[
"
storage
"
].
get
(
"
services
"
,
self
.
get_path
(
"
services
"
))
return
self
.
get_path
(
root
,
*
args
)
def
pub_service_path
(
self
,
path
):
...
...
@@ -1210,9 +1233,11 @@ class MRA(object):
cparam
=
info
[
"
connectionParameters
"
]
if
cparam
.
get
(
"
dbtype
"
,
""
)
==
"
postgis
"
:
# First mandatory
url
=
"
PG:dbname=%s port=%s host=%s
"
%
(
cparam
[
"
database
"
],
cparam
[
"
port
"
],
cparam
[
"
host
"
])
url
=
"
PG:dbname=%s port=%s host=%s
"
%
(
cparam
[
"
database
"
],
cparam
[
"
port
"
],
cparam
[
"
host
"
])
# Then optionals:
url
+=
"
"
.
join
(
"
%s=%s
"
%
(
p
,
cparam
[
p
])
for
p
in
[
"
user
"
,
"
password
"
]
if
p
in
cparam
)
url
+=
"
"
.
join
(
"
%s=%s
"
%
(
p
,
cparam
[
p
])
for
p
in
[
"
user
"
,
"
password
"
]
if
p
in
cparam
)
return
url
elif
"
url
"
in
cparam
:
url
=
urlparse
(
cparam
[
"
url
"
])
...
...
@@ -1220,4 +1245,5 @@ class MRA(object):
raise
ValueError
(
"
Only local files are suported.
"
)
return
self
.
get_file_path
(
url
.
path
)
else
:
raise
ValueError
(
"
Unhandled type
\"
%s
\"
.
"
%
cparam
.
get
(
"
dbtype
"
,
"
<unknown>
"
))
raise
ValueError
(
"
Unhandled type
\"
%s
\"
.
"
%
cparam
.
get
(
"
dbtype
"
,
"
<unknown>
"
))
This diff is collapsed.
Click to expand it.
src/server.py
View file @
f67e7937
...
...
@@ -44,6 +44,7 @@ import webapp
from
webapp
import
get_data
from
webapp
import
HTTPCompatible
from
webapp
import
urlmap
from
src
import
__version__
# Some helper functions first.
...
...
@@ -64,6 +65,7 @@ class index(object):
@HTTPCompatible
(
authorized
=
[
"
html
"
])
def
GET
(
self
,
format
):
return
{
"
version
"
:
href
(
"
version
"
),
"
about/version
"
:
href
(
"
about/version
"
),
"
workspaces
"
:
href
(
"
workspaces
"
),
"
styles
"
:
href
(
"
styles
"
),
...
...
@@ -76,6 +78,15 @@ class index(object):
}
class
app_version
(
object
):
"""
To know about application version
"""
@HTTPCompatible
()
def
GET
(
self
,
format
):
return
{
"
mra
"
:
__version__
}
class
version
(
object
):
"""
To know about used versions...
...
...
@@ -1661,6 +1672,8 @@ class OWSWorkspaceSettings(object):
# Index:
urlmap
(
index
,
""
)
# App Version:
urlmap
(
app_version
,
"
version
"
)
# About version:
urlmap
(
version
,
"
about
"
,
"
version
"
)
# Workspaces:
...
...
This diff is collapsed.
Click to expand it.