Coverage for gws-app/gws/base/search/action.py: 0%
68 statements
« prev ^ index » next coverage.py v7.8.0, created at 2025-04-17 01:37 +0200
« prev ^ index » next coverage.py v7.8.0, created at 2025-04-17 01:37 +0200
1"""Search API."""
3from typing import Optional
5import gws
6import gws.base.model
7import gws.base.action
8import gws.base.template
9import gws.base.feature
10import gws.base.shape
11import gws.lib.uom
13gws.ext.new.action('search')
15_DEFAULT_VIEWS = ['title', 'teaser', 'description']
16_DEFAULT_TOLERANCE = 50, gws.Uom.px
19class Config(gws.base.action.Config):
20 """Search action"""
22 limit: int = 1000
23 """search results limit"""
24 tolerance: Optional[gws.UomValueStr]
25 """default tolerance"""
28class Props(gws.base.action.Props):
29 pass
32class Request(gws.Request):
33 crs: Optional[gws.CrsName]
34 extent: Optional[gws.Extent]
35 keyword: str = ''
36 layerUids: list[str]
37 limit: Optional[int]
38 resolution: float
39 shapes: Optional[list[gws.base.shape.Props]]
40 tolerance: Optional[str]
41 views: Optional[list[str]]
44class Response(gws.Response):
45 features: list[gws.FeatureProps]
48class Object(gws.base.action.Object):
49 limit = 0
50 tolerance: gws.UomValue
52 def configure(self):
53 self.limit = self.cfg('limit')
54 self.tolerance = self.cfg('tolerance') or _DEFAULT_TOLERANCE
56 @gws.ext.command.api('searchFind')
57 def find(self, req: gws.WebRequester, p: Request) -> Response:
58 """Perform a search"""
60 return Response(features=self._get_features(req, p))
62 def _get_features(self, req: gws.WebRequester, p: Request) -> list[gws.FeatureProps]:
64 project = req.user.require_project(p.projectUid)
65 search = gws.SearchQuery(project=project)
67 if p.layerUids:
68 search.layers = gws.u.compact(req.user.acquire(uid, gws.ext.object.layer) for uid in p.layerUids)
70 search.bounds = project.map.bounds
71 if p.extent:
72 search.bounds = gws.Bounds(crs=p.crs or project.map.bounds.crs, extent=p.extent)
74 search.limit = self.limit
75 if p.limit:
76 search.limit = min(int(p.limit), self.limit)
78 if p.shapes:
79 shapes = [gws.base.shape.from_props(s) for s in p.shapes]
80 search.shape = shapes[0] if len(shapes) == 1 else shapes[0].union(shapes[1:])
82 search.tolerance = self.tolerance
83 if p.tolerance:
84 search.tolerance = gws.lib.uom.parse(p.tolerance, gws.Uom.px)
86 if p.resolution:
87 search.resolution = p.resolution
89 if p.keyword.strip():
90 search.keyword = p.keyword.strip()
92 results = self.root.app.searchMgr.run_search(search, req.user)
93 if not results:
94 return []
96 mc = gws.ModelContext(
97 op=gws.ModelOperation.read,
98 target=gws.ModelReadTarget.searchResults,
99 project=project,
100 user=req.user
101 )
103 for res in results:
104 templates = gws.u.compact(
105 self.root.app.templateMgr.find_template(f'feature.{v}', where=[res.finder, res.layer, project], user=req.user)
106 for v in p.views or _DEFAULT_VIEWS
107 )
108 res.feature.render_views(templates, user=req.user, project=project, layer=res.layer)
110 return [res.feature.model.feature_to_view_props(res.feature, mc) for res in results]