Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1#!/usr/bin/env python 

2# encoding: utf-8 

3""" 

4*A sortable, customisable HTML table* 

5 

6:Author: 

7 David Young 

8""" 

9from __future__ import division 

10from builtins import str 

11from builtins import object 

12from past.utils import old_div 

13from . import * 

14import sys 

15import os 

16import datetime 

17import math 

18import re 

19# from ..__init__ import * 

20from khufu.typography import * 

21from khufu.addons import * 

22from khufu.tables import * 

23from khufu.helpers import * 

24from fundamentals import times 

25 

26class sortable_table(object): 

27 """ 

28 *The worker class for the sortable_table module* 

29 

30 **Key Arguments** 

31 

32 - ``dbConn`` -- mysql database connection 

33 - ``log`` -- logger 

34 - ``currentPageUrl`` -- the baseurl for the webpage 

35 - ``columnsToDisplay`` -- a list of column objects for the table 

36 - ``defaultSort`` -- the column to sort on by default 

37 - ``tableRowsDictionary`` -- dictionary of column names and values (e.g. a mysql query result) 

38  

39 """ 

40 

41 def __init__( 

42 self, 

43 log, 

44 dbConn=False, 

45 currentPageUrl="", 

46 columnsToDisplay=[], 

47 defaultSort=False, 

48 tableRowsDictionary={} 

49 ): 

50 self.log = log 

51 self.dbConn = dbConn 

52 self.currentPageUrl = currentPageUrl 

53 self.columnsToDisplay = columnsToDisplay 

54 self.defaultSort = defaultSort 

55 self.tableRowsDictionary = tableRowsDictionary 

56 # xt-self-arg-tmpx 

57 

58 # VARIABLE DATA ATRRIBUTES 

59 self.colors = ["green", "blue", "red", "yellow", 

60 "orange", "violet", "magenta", "cyan", ] 

61 self.modifyDisplayNameDict = {} 

62 self.modifySortByDict = {} 

63 self.modifyColumnWidths = [] 

64 self.headerPopoverText = "click to sort" 

65 self.searchKeyAndColumn = False 

66 self.columnsToHide = [] 

67 self.columnWidth = int(math.floor(old_div(100, len(self.columnsToDisplay)))) 

68 self.extraColumnWidth = 100 - \ 

69 self.columnWidth * len(self.columnsToDisplay) 

70 

71 # DETERMINE HOW TABLE IS TO BE SORTED FROM URL 

72 thisSort = re.search( 

73 r'sortBy=(\w+)&', 

74 self.currentPageUrl, 

75 flags=0 # re.S 

76 ) 

77 if thisSort: 

78 thisSort = thisSort.group(1) 

79 elif self.defaultSort: 

80 thisSort = self.defaultSort 

81 else: 

82 thisSort = False 

83 

84 thisSortDesc = re.search( 

85 r'sortDesc=(\w+)&?', 

86 self.currentPageUrl, 

87 flags=0 # re.S 

88 ) 

89 if thisSortDesc: 

90 thisSortDesc = thisSortDesc.group(1) 

91 else: 

92 thisSortDesc = "False" 

93 

94 arrow = "" 

95 if "true" in thisSortDesc.lower(): 

96 arrow = coloredText( 

97 text="""&nbsp&nbsp<i class="icon-arrow-up4"></i>""" % locals(), 

98 color="red", 

99 ) 

100 else: 

101 arrow = coloredText( 

102 text="""&nbsp&nbsp<i class="icon-arrow-down4"></i>""", 

103 color="red", 

104 ) 

105 self.thisSort = thisSort 

106 self.thisSortDesc = thisSortDesc 

107 self.arrow = arrow 

108 

109 # REMOVE SORT AND SORTDESC FROM URL TO GENERAL A BASEURL FOR HEADER 

110 # SORTING 

111 reSort = re.compile(r'sortBy=\w+&?') 

112 reDesc = re.compile(r'sortDesc=\w+&?') 

113 self.baseUrl = reSort.sub("", self.currentPageUrl) 

114 self.baseUrl = reDesc.sub("", self.baseUrl) 

115 thisUrl = self.baseUrl 

116 if thisUrl[-3:] == ".py": 

117 thisUrl = "%(thisUrl)s?" % locals() 

118 elif "?" not in thisUrl: 

119 thisUrl = "%(thisUrl)s?" % locals() 

120 elif thisUrl[-1:] not in ["?", "&"]: 

121 thisUrl = "%(thisUrl)s&" % locals() 

122 self.baseUrl = thisUrl 

123 

124 return None 

125 

126 def close(self): 

127 del self 

128 return None 

129 

130 def get(self): 

131 """ 

132 *get the sortable_table object* 

133 

134 **Return** 

135 

136 - ``sortable_table`` 

137  

138 """ 

139 

140 tableHead = self.get_table_head() 

141 tbody = self.get_table_body() 

142 

143 sortable_table = table( 

144 caption='', 

145 thead=tableHead, 

146 tbody=tbody, 

147 striped=True, 

148 bordered=False, 

149 hover=True, 

150 condensed=True, 

151 ) 

152 

153 return sortable_table 

154 

155 def get_table_head( 

156 self): 

157 """ 

158 *get table head* 

159 

160 **Return** 

161 

162 - ``tableHead`` -- the table head 

163  

164 """ 

165 tableHead = "" 

166 

167 # BUILD THE TABLE HEADER 

168 _popover = popover( 

169 tooltip=True, 

170 placement="bottom", # [ top | bottom | left | right ] 

171 trigger="hover", # [ False | click | hover | focus | manual ] 

172 title=self.headerPopoverText, 

173 content=False, 

174 delay=600 

175 ) 

176 

177 colorIndex = 0 

178 columnIndex = 0 

179 

180 for i, c in enumerate(self.columnsToDisplay): 

181 # build sort url 

182 direction = "False" 

183 if c in list(self.modifySortByDict.keys()): 

184 columnSortByAlias = self.modifySortByDict[c] 

185 else: 

186 columnSortByAlias = c 

187 

188 if not columnSortByAlias: 

189 newSortUrl = False 

190 thisPopover = False 

191 thisArrow = "" 

192 else: 

193 thisPopover = _popover 

194 if self.thisSort == columnSortByAlias and self.thisSortDesc == "False": 

195 direction = "True" 

196 thisUrl = self.baseUrl 

197 newSortUrl = """%(thisUrl)ssortBy=%(columnSortByAlias)s&sortDesc=%(direction)s""" % locals( 

198 ) 

199 

200 thisArrow = "" 

201 if self.thisSort and (columnSortByAlias.lower() == self.thisSort.lower()): 

202 thisArrow = self.arrow 

203 

204 # add text color and change display names if necessary 

205 if c in list(self.modifyDisplayNameDict.keys()): 

206 thisText = self.modifyDisplayNameDict[c] 

207 else: 

208 thisText = c 

209 self.modifyDisplayNameDict[c] = coloredText( 

210 text=thisText + thisArrow, 

211 color=self.colors[colorIndex], 

212 size=False, # 1-10 

213 pull=False, # "left" | "right" 

214 ) 

215 if colorIndex < len(self.colors) - 1: 

216 colorIndex += 1 

217 else: 

218 colorIndex = 0 

219 

220 if c not in self.columnsToHide: 

221 if len(self.modifyColumnWidths) == len(self.columnsToDisplay) - len(self.columnsToHide): 

222 columnWidth = self.modifyColumnWidths[columnIndex] 

223 elif columnIndex < self.extraColumnWidth: 

224 columnWidth = self.columnWidth + 1 

225 else: 

226 columnWidth = self.columnWidth 

227 columnIndex += 1 

228 cell = th( 

229 content=self.modifyDisplayNameDict[c], 

230 color=False, 

231 href=newSortUrl, 

232 popover=thisPopover, 

233 columnWidth=columnWidth 

234 ) 

235 tableHead = "%(tableHead)s %(cell)s" % locals() 

236 

237 tableHead = tr( 

238 cellContent=tableHead, 

239 color=False, 

240 ) 

241 tableHead = thead( 

242 trContent=tableHead 

243 ) 

244 return tableHead 

245 

246 def get_table_body( 

247 self): 

248 """ 

249 *get table body* 

250 

251 **Return** 

252 

253 - ``tableBody`` 

254  

255 """ 

256 theseTickets = "" 

257 

258 # BUILD THE TABLE BODY 

259 for obj in self.tableRowsDictionary: 

260 

261 if self.searchKeyAndColumn: 

262 regex = re.compile(r'^(.*?)\?.*') 

263 href = regex.sub("\g<1>", self.baseUrl, count=1) 

264 href = href.replace("?", "") 

265 href = href + "\\" + \ 

266 self.searchKeyAndColumn[0] + "=" + \ 

267 obj[self.searchKeyAndColumn[1]] 

268 else: 

269 href = False 

270 

271 tableRow = "" 

272 colorIndex = 0 

273 

274 for i, c in enumerate(self.columnsToDisplay): 

275 

276 if (isinstance(obj[c], ("".__class__, u"".__class__)) or isinstance(obj[c], str)) and "." not in obj[c]: 

277 try: 

278 obj[c] = int(obj[c]) 

279 except: 

280 pass 

281 

282 if not isinstance(obj[c], int): 

283 try: 

284 obj[c] = float(obj[c]) 

285 except: 

286 pass 

287 

288 if c.lower() in ["radeg", "decdeg"]: 

289 obj[c] = "%6.3f" % obj[c] 

290 elif (isinstance(obj[c], float) or isinstance(obj[c], int)) and obj[c]: 

291 obj[c] = "%6.2f" % obj[c] 

292 elif obj[c] == 0: 

293 pass 

294 elif not obj[c] or ((isinstance(obj[c], ("".__class__, u"".__class__)) or isinstance(obj[c], str)) and ("unkn" in obj[c].lower())): 

295 obj[c] = "" 

296 elif isinstance(obj[c], datetime.datetime): 

297 # obj[c] = "boom" 

298 

299 relativeDate = times.datetime_relative_to_now(obj[c]) 

300 thisDate = str(obj[c])[:10] 

301 thisDate = coloredText( 

302 text="(%(thisDate)s)" % locals(), 

303 color="grey", 

304 size=2, 

305 ) 

306 thisDate = hide_from_device( 

307 content=thisDate, 

308 onPhone=False, 

309 onTablet=False, 

310 onDesktop=True 

311 ) 

312 obj[c] = "%(relativeDate)s %(thisDate)s" % locals() 

313 

314 obj[c] = coloredText( 

315 text=obj[c], 

316 color=self.colors[colorIndex], 

317 ) 

318 if colorIndex < len(self.colors) - 1: 

319 colorIndex += 1 

320 else: 

321 colorIndex = 0 

322 

323 if c not in self.columnsToHide: 

324 cell = td( 

325 content=obj[c], 

326 ) 

327 tableRow = "%(tableRow)s %(cell)s" % locals() 

328 

329 tableRow = tr( 

330 cellContent=tableRow, 

331 color=False, 

332 href=href, 

333 popover=False, 

334 ) 

335 theseTickets = "%(theseTickets)s%(tableRow)s" % locals() 

336 

337 tableBody = tbody( 

338 trContent=theseTickets 

339 ) 

340 return tableBody 

341 

342 # xt-class-method