@@ -4,6 +4,36 @@ import { mapToDbColumn } from './util.js'
44const zoneDbMap = { id : 'nt_zone_id' , gid : 'nt_group_id' }
55const boolFields = [ 'deleted' ]
66
7+ function applyZoneFilters ( query , params , filters = { } ) {
8+ let nextQuery = query
9+ const nextParams = [ ...params ]
10+
11+ const append = ( sql ) => {
12+ nextQuery += `${ / \b W H E R E \b / . test ( nextQuery ) ? ' AND' : ' WHERE' } ${ sql } `
13+ }
14+
15+ const search = typeof filters . search === 'string' ? filters . search . trim ( ) : ''
16+ if ( search ) {
17+ append ( '(zone LIKE ? OR description LIKE ?)' )
18+ const wildcard = `%${ search } %`
19+ nextParams . push ( wildcard , wildcard )
20+ }
21+
22+ const zoneLike = typeof filters . zone_like === 'string' ? filters . zone_like . trim ( ) : ''
23+ if ( zoneLike ) {
24+ append ( 'zone LIKE ?' )
25+ nextParams . push ( `%${ zoneLike } %` )
26+ }
27+
28+ const descriptionLike = typeof filters . description_like === 'string' ? filters . description_like . trim ( ) : ''
29+ if ( descriptionLike ) {
30+ append ( 'description LIKE ?' )
31+ nextParams . push ( `%${ descriptionLike } %` )
32+ }
33+
34+ return [ nextQuery , nextParams ]
35+ }
36+
737class Zone {
838 constructor ( ) {
939 this . mysql = Mysql
@@ -20,12 +50,34 @@ class Zone {
2050
2151 async get ( args ) {
2252 args = JSON . parse ( JSON . stringify ( args ) )
23- if ( args . deleted === undefined ) args . deleted = false
53+ args . deleted = args . deleted ?? false
54+
55+ const filters = {
56+ search : args . search ,
57+ zone_like : args . zone_like ,
58+ description_like : args . description_like ,
59+ }
60+ delete args . search
61+ delete args . zone_like
62+ delete args . description_like
63+
64+ const sortByMap = {
65+ id : 'nt_zone_id' ,
66+ zone : 'zone' ,
67+ description : 'description' ,
68+ last_modified : 'last_modified' ,
69+ }
70+ const sortBy = sortByMap [ args . sort_by ] ?? 'zone'
71+ const sortDir = args . sort_dir === 'desc' ? 'DESC' : 'ASC'
72+ delete args . sort_by
73+ delete args . sort_dir
2474
2575 const limit = Number . isInteger ( args . limit ) ? args . limit : undefined
2676 delete args . limit
77+ const offset = Number . isInteger ( args . offset ) ? Math . max ( 0 , args . offset ) : 0
78+ delete args . offset
2779
28- const sqlLimit = limit === undefined ? '' : ` LIMIT ${ Math . max ( 1 , limit ) } `
80+ const sqlLimit = limit === undefined ? '' : ` LIMIT ${ Math . max ( 1 , limit ) } OFFSET ${ offset } `
2981
3082 const [ query , params ] = Mysql . select (
3183 `SELECT nt_zone_id AS id
@@ -46,7 +98,10 @@ class Zone {
4698 mapToDbColumn ( args , zoneDbMap ) ,
4799 )
48100
49- const rows = await Mysql . execute ( `${ query } ${ sqlLimit } ` , params )
101+ let [ finalQuery , finalParams ] = applyZoneFilters ( query , params , filters )
102+ finalQuery += ` ORDER BY ${ sortBy } ${ sortDir } `
103+
104+ const rows = await Mysql . execute ( `${ finalQuery } ${ sqlLimit } ` , finalParams )
50105 for ( const row of rows ) {
51106 for ( const b of boolFields ) {
52107 row [ b ] = row [ b ] === 1
@@ -77,6 +132,30 @@ class Zone {
77132 return rows
78133 }
79134
135+ async count ( args = { } ) {
136+ args = JSON . parse ( JSON . stringify ( args ) )
137+ args . deleted = args . deleted ?? false
138+
139+ const filters = {
140+ search : args . search ,
141+ zone_like : args . zone_like ,
142+ description_like : args . description_like ,
143+ }
144+ delete args . search
145+ delete args . zone_like
146+ delete args . description_like
147+
148+ const [ query , params ] = Mysql . select (
149+ `SELECT COUNT(*) AS total
150+ FROM nt_zone` ,
151+ mapToDbColumn ( args , zoneDbMap ) ,
152+ )
153+
154+ const [ finalQuery , finalParams ] = applyZoneFilters ( query , params , filters )
155+ const rows = await Mysql . execute ( finalQuery , finalParams )
156+ return rows ?. [ 0 ] ?. total ?? 0
157+ }
158+
80159 async put ( args ) {
81160 if ( ! args . id ) return false
82161 const id = args . id
0 commit comments