Fossil SCM
Change the user list to a sortable table.
Commit
72de3100c29070aaf2c237a0d1ddaf2f7e6f7543
Parent
d3fbf717386970e…
1 file changed
+40
-65
+40
-65
| --- src/setup.c | ||
| +++ src/setup.c | ||
| @@ -145,118 +145,93 @@ | ||
| 145 | 145 | ** screen for that user. Requires Admin privileges. |
| 146 | 146 | */ |
| 147 | 147 | void setup_ulist(void){ |
| 148 | 148 | Stmt s; |
| 149 | 149 | int prevLevel = 0; |
| 150 | - int nRow = 0; | |
| 151 | - int iSort; | |
| 152 | - static const char *azSortOptions[] = { | |
| 153 | - "0", "Name", | |
| 154 | - "1", "Uid", | |
| 155 | - "2", "Capabilities", | |
| 156 | - "3", "Last Change", | |
| 157 | - "4", "Expiration" | |
| 158 | - }; | |
| 159 | - const char *zOrderBy[] = { | |
| 160 | - "login COLLATE nocase", | |
| 161 | - "uid", | |
| 162 | - "cap, login COLLATE nocase", | |
| 163 | - "mtime DESC", | |
| 164 | - "exp DESC, login COLLATE nocase" | |
| 165 | - }; | |
| 166 | 150 | |
| 167 | 151 | login_check_credentials(); |
| 168 | 152 | if( !g.perm.Admin ){ |
| 169 | 153 | login_needed(0); |
| 170 | 154 | return; |
| 171 | 155 | } |
| 172 | - iSort = atoi(PD("sx", "0")); | |
| 173 | - if( iSort<0 || iSort>ArraySize(zOrderBy) ) iSort = 0; | |
| 174 | - | |
| 175 | 156 | |
| 176 | 157 | style_submenu_element("Add", "Add User", "setup_uedit"); |
| 177 | 158 | style_submenu_element("Help", "Help", "setup_ulist_notes"); |
| 178 | - style_submenu_multichoice("sx", ArraySize(azSortOptions)/2, azSortOptions, 0); | |
| 179 | 159 | style_header("User List"); |
| 180 | - @ <table border=0 cellpadding=0 cellspacing=0> | |
| 160 | + @ <table border=1 cellpadding=2 cellspacing=0 class='userTable'> | |
| 161 | + @ <thead><tr><th>UID <th>Category <th>Capabilities <th>Info <th>Last Change</tr></thead> | |
| 162 | + @ <tbody> | |
| 181 | 163 | db_prepare(&s, |
| 182 | - "SELECT uid, login, cap, info, datetime(mtime,'unixepoch'), NULL AS exp " | |
| 164 | + "SELECT uid, login, cap, date(mtime,'unixepoch')" | |
| 183 | 165 | " FROM user" |
| 184 | 166 | " WHERE login IN ('anonymous','nobody','developer','reader')" |
| 185 | - " ORDER BY %s", | |
| 186 | - zOrderBy[iSort]/*safe-for-%s*/ | |
| 167 | + " ORDER BY login" | |
| 187 | 168 | ); |
| 188 | 169 | while( db_step(&s)==SQLITE_ROW ){ |
| 189 | 170 | int uid = db_column_int(&s, 0); |
| 190 | 171 | const char *zLogin = db_column_text(&s, 1); |
| 191 | 172 | const char *zCap = db_column_text(&s, 2); |
| 192 | 173 | const char *zDate = db_column_text(&s, 4); |
| 193 | - if( nRow++ ){ | |
| 194 | - @ <tr><td colspan=3><hr></td></tr> | |
| 195 | - } | |
| 196 | - @ <tr><td valign='top'>Category:</td> | |
| 197 | - @ <td> </td> | |
| 174 | + @ <tr> | |
| 175 | + @ <td><a href='setup_uedit?id=%d(uid)'>%d(uid)</a> | |
| 198 | 176 | @ <td><a href='setup_uedit?id=%d(uid)'>%h(zLogin)</a> |
| 177 | + @ <td>%h(zCap) | |
| 178 | + | |
| 199 | 179 | if( fossil_strcmp(zLogin,"anonymous")==0 ){ |
| 200 | - @ (All logged-in users) | |
| 180 | + @ <td>All logged-in users | |
| 201 | 181 | }else if( fossil_strcmp(zLogin,"developer")==0 ){ |
| 202 | - @ (Users with '<b>v</b>' capability) | |
| 182 | + @ <td>Users with '<b>v</b>' capability | |
| 203 | 183 | }else if( fossil_strcmp(zLogin,"nobody")==0 ){ |
| 204 | - @ (All users without login) | |
| 184 | + @ <td>All users without login | |
| 205 | 185 | }else if( fossil_strcmp(zLogin,"reader")==0 ){ |
| 206 | - @ (Users with '<b>u</b>' capability) | |
| 186 | + @ <td>Users with '<b>u</b>' capability | |
| 187 | + }else{ | |
| 188 | + @ <td> | |
| 207 | 189 | } |
| 208 | - @ </td></tr> | |
| 209 | - @ <tr><td valign='top'>Capabilities:</td><td></td> | |
| 210 | - @ <td>%h(zCap)</a></td></tr> | |
| 211 | 190 | if( zDate && zDate[0] ){ |
| 212 | - @ <tr><td valign='top'>Last change:</td><td></td> | |
| 213 | - @ <td>%h(zDate)</a></td></tr> | |
| 191 | + @ <td>%h(zDate) | |
| 192 | + }else{ | |
| 193 | + @ <td> | |
| 214 | 194 | } |
| 195 | + @ </tr> | |
| 215 | 196 | } |
| 216 | 197 | db_finalize(&s); |
| 217 | - | |
| 218 | - nRow = 0; | |
| 198 | + @ </tbody></table> | |
| 199 | + @ <div class='section'>Users</div> | |
| 200 | + @ <table border=1 cellpadding=2 cellspacing=0 class='userTable' id='userlist'> | |
| 201 | + @ <thead><tr> | |
| 202 | + @ <th>ID<th>Login<th>Caps<th>Info<th>Chng<th>Expire</tr></thead> | |
| 203 | + @ <tbody> | |
| 219 | 204 | db_prepare(&s, |
| 220 | - "SELECT uid, login, cap, info, datetime(mtime,'unixepoch'), " | |
| 205 | + "SELECT uid, login, cap, info, date(mtime,'unixepoch'), lower(login) AS sortkey, " | |
| 221 | 206 | " CASE WHEN info LIKE '%%expires 20%%'" |
| 222 | 207 | " THEN substr(info,instr(lower(info),'expires')+8,10)" |
| 223 | 208 | " END AS exp" |
| 224 | 209 | " FROM user" |
| 225 | 210 | " WHERE login NOT IN ('anonymous','nobody','developer','reader')" |
| 226 | - " ORDER BY %s", | |
| 227 | - zOrderBy[iSort]/*safe-for-%s*/ | |
| 211 | + " ORDER BY sortkey" | |
| 228 | 212 | ); |
| 229 | 213 | while( db_step(&s)==SQLITE_ROW ){ |
| 230 | 214 | int uid = db_column_int(&s, 0); |
| 231 | 215 | const char *zLogin = db_column_text(&s, 1); |
| 232 | 216 | const char *zCap = db_column_text(&s, 2); |
| 233 | 217 | const char *zInfo = db_column_text(&s, 3); |
| 234 | 218 | const char *zDate = db_column_text(&s, 4); |
| 235 | - const char *zExp = db_column_text(&s,5); | |
| 236 | - if( (nRow++)==0 ){ | |
| 237 | - @ <tr><td colspan=3><div class='section'>Users</div></tr> | |
| 238 | - }else{ | |
| 239 | - @ <tr><td colspan=3><hr></td></tr> | |
| 240 | - } | |
| 241 | - @ <tr><td valign='top'>Username:</td><td></td> | |
| 242 | - @ <td><a href='setup_uedit?id=%d(uid)'>%h(zLogin) (uid: %d(uid))</a></td><tr> | |
| 243 | - @ <tr><td valign='top'>Capabilities:</td><td></td> | |
| 244 | - @ <td>%h(zCap)</a></td></tr> | |
| 245 | - if( zExp && zExp[0] ){ | |
| 246 | - @ <tr><td valign='top'>Login expires:</td><td></td> | |
| 247 | - @ <td>%h(zExp)</a></td></tr> | |
| 248 | - } | |
| 249 | - @ <tr><td valign='top'>Notes:</td><td></td> | |
| 250 | - @ <td>%h(zInfo)</a></td></tr> | |
| 251 | - if( zDate && zDate[0] ){ | |
| 252 | - @ <tr><td valign='top'>Last change:</td><td></td> | |
| 253 | - @ <td>%h(zDate)</a></td></tr> | |
| 254 | - } | |
| 255 | - } | |
| 256 | - @ </table> | |
| 219 | + const char *zSortKey = db_column_text(&s,5); | |
| 220 | + const char *zExp = db_column_text(&s,6); | |
| 221 | + @ <tr> | |
| 222 | + @ <td><a href='setup_uedit?id=%d(uid)'>%d(uid)</a> | |
| 223 | + @ <td data-sortkey='%h(zSortKey)'><a href='setup_uedit?id=%d(uid)'>%h(zLogin)</a> | |
| 224 | + @ <td>%h(zCap) | |
| 225 | + @ <td>%h(zInfo) | |
| 226 | + @ <td>%h(zDate?zDate:"") | |
| 227 | + @ <td>%h(zExp?zExp:"") | |
| 228 | + @ </tr> | |
| 229 | + } | |
| 230 | + @ </tbody></table> | |
| 257 | 231 | db_finalize(&s); |
| 232 | + output_table_sorting_javascript("userlist","nktxTT",2); | |
| 258 | 233 | style_footer(); |
| 259 | 234 | } |
| 260 | 235 | |
| 261 | 236 | /* |
| 262 | 237 | ** WEBPAGE: setup_ulist_notes |
| 263 | 238 |
| --- src/setup.c | |
| +++ src/setup.c | |
| @@ -145,118 +145,93 @@ | |
| 145 | ** screen for that user. Requires Admin privileges. |
| 146 | */ |
| 147 | void setup_ulist(void){ |
| 148 | Stmt s; |
| 149 | int prevLevel = 0; |
| 150 | int nRow = 0; |
| 151 | int iSort; |
| 152 | static const char *azSortOptions[] = { |
| 153 | "0", "Name", |
| 154 | "1", "Uid", |
| 155 | "2", "Capabilities", |
| 156 | "3", "Last Change", |
| 157 | "4", "Expiration" |
| 158 | }; |
| 159 | const char *zOrderBy[] = { |
| 160 | "login COLLATE nocase", |
| 161 | "uid", |
| 162 | "cap, login COLLATE nocase", |
| 163 | "mtime DESC", |
| 164 | "exp DESC, login COLLATE nocase" |
| 165 | }; |
| 166 | |
| 167 | login_check_credentials(); |
| 168 | if( !g.perm.Admin ){ |
| 169 | login_needed(0); |
| 170 | return; |
| 171 | } |
| 172 | iSort = atoi(PD("sx", "0")); |
| 173 | if( iSort<0 || iSort>ArraySize(zOrderBy) ) iSort = 0; |
| 174 | |
| 175 | |
| 176 | style_submenu_element("Add", "Add User", "setup_uedit"); |
| 177 | style_submenu_element("Help", "Help", "setup_ulist_notes"); |
| 178 | style_submenu_multichoice("sx", ArraySize(azSortOptions)/2, azSortOptions, 0); |
| 179 | style_header("User List"); |
| 180 | @ <table border=0 cellpadding=0 cellspacing=0> |
| 181 | db_prepare(&s, |
| 182 | "SELECT uid, login, cap, info, datetime(mtime,'unixepoch'), NULL AS exp " |
| 183 | " FROM user" |
| 184 | " WHERE login IN ('anonymous','nobody','developer','reader')" |
| 185 | " ORDER BY %s", |
| 186 | zOrderBy[iSort]/*safe-for-%s*/ |
| 187 | ); |
| 188 | while( db_step(&s)==SQLITE_ROW ){ |
| 189 | int uid = db_column_int(&s, 0); |
| 190 | const char *zLogin = db_column_text(&s, 1); |
| 191 | const char *zCap = db_column_text(&s, 2); |
| 192 | const char *zDate = db_column_text(&s, 4); |
| 193 | if( nRow++ ){ |
| 194 | @ <tr><td colspan=3><hr></td></tr> |
| 195 | } |
| 196 | @ <tr><td valign='top'>Category:</td> |
| 197 | @ <td> </td> |
| 198 | @ <td><a href='setup_uedit?id=%d(uid)'>%h(zLogin)</a> |
| 199 | if( fossil_strcmp(zLogin,"anonymous")==0 ){ |
| 200 | @ (All logged-in users) |
| 201 | }else if( fossil_strcmp(zLogin,"developer")==0 ){ |
| 202 | @ (Users with '<b>v</b>' capability) |
| 203 | }else if( fossil_strcmp(zLogin,"nobody")==0 ){ |
| 204 | @ (All users without login) |
| 205 | }else if( fossil_strcmp(zLogin,"reader")==0 ){ |
| 206 | @ (Users with '<b>u</b>' capability) |
| 207 | } |
| 208 | @ </td></tr> |
| 209 | @ <tr><td valign='top'>Capabilities:</td><td></td> |
| 210 | @ <td>%h(zCap)</a></td></tr> |
| 211 | if( zDate && zDate[0] ){ |
| 212 | @ <tr><td valign='top'>Last change:</td><td></td> |
| 213 | @ <td>%h(zDate)</a></td></tr> |
| 214 | } |
| 215 | } |
| 216 | db_finalize(&s); |
| 217 | |
| 218 | nRow = 0; |
| 219 | db_prepare(&s, |
| 220 | "SELECT uid, login, cap, info, datetime(mtime,'unixepoch'), " |
| 221 | " CASE WHEN info LIKE '%%expires 20%%'" |
| 222 | " THEN substr(info,instr(lower(info),'expires')+8,10)" |
| 223 | " END AS exp" |
| 224 | " FROM user" |
| 225 | " WHERE login NOT IN ('anonymous','nobody','developer','reader')" |
| 226 | " ORDER BY %s", |
| 227 | zOrderBy[iSort]/*safe-for-%s*/ |
| 228 | ); |
| 229 | while( db_step(&s)==SQLITE_ROW ){ |
| 230 | int uid = db_column_int(&s, 0); |
| 231 | const char *zLogin = db_column_text(&s, 1); |
| 232 | const char *zCap = db_column_text(&s, 2); |
| 233 | const char *zInfo = db_column_text(&s, 3); |
| 234 | const char *zDate = db_column_text(&s, 4); |
| 235 | const char *zExp = db_column_text(&s,5); |
| 236 | if( (nRow++)==0 ){ |
| 237 | @ <tr><td colspan=3><div class='section'>Users</div></tr> |
| 238 | }else{ |
| 239 | @ <tr><td colspan=3><hr></td></tr> |
| 240 | } |
| 241 | @ <tr><td valign='top'>Username:</td><td></td> |
| 242 | @ <td><a href='setup_uedit?id=%d(uid)'>%h(zLogin) (uid: %d(uid))</a></td><tr> |
| 243 | @ <tr><td valign='top'>Capabilities:</td><td></td> |
| 244 | @ <td>%h(zCap)</a></td></tr> |
| 245 | if( zExp && zExp[0] ){ |
| 246 | @ <tr><td valign='top'>Login expires:</td><td></td> |
| 247 | @ <td>%h(zExp)</a></td></tr> |
| 248 | } |
| 249 | @ <tr><td valign='top'>Notes:</td><td></td> |
| 250 | @ <td>%h(zInfo)</a></td></tr> |
| 251 | if( zDate && zDate[0] ){ |
| 252 | @ <tr><td valign='top'>Last change:</td><td></td> |
| 253 | @ <td>%h(zDate)</a></td></tr> |
| 254 | } |
| 255 | } |
| 256 | @ </table> |
| 257 | db_finalize(&s); |
| 258 | style_footer(); |
| 259 | } |
| 260 | |
| 261 | /* |
| 262 | ** WEBPAGE: setup_ulist_notes |
| 263 |
| --- src/setup.c | |
| +++ src/setup.c | |
| @@ -145,118 +145,93 @@ | |
| 145 | ** screen for that user. Requires Admin privileges. |
| 146 | */ |
| 147 | void setup_ulist(void){ |
| 148 | Stmt s; |
| 149 | int prevLevel = 0; |
| 150 | |
| 151 | login_check_credentials(); |
| 152 | if( !g.perm.Admin ){ |
| 153 | login_needed(0); |
| 154 | return; |
| 155 | } |
| 156 | |
| 157 | style_submenu_element("Add", "Add User", "setup_uedit"); |
| 158 | style_submenu_element("Help", "Help", "setup_ulist_notes"); |
| 159 | style_header("User List"); |
| 160 | @ <table border=1 cellpadding=2 cellspacing=0 class='userTable'> |
| 161 | @ <thead><tr><th>UID <th>Category <th>Capabilities <th>Info <th>Last Change</tr></thead> |
| 162 | @ <tbody> |
| 163 | db_prepare(&s, |
| 164 | "SELECT uid, login, cap, date(mtime,'unixepoch')" |
| 165 | " FROM user" |
| 166 | " WHERE login IN ('anonymous','nobody','developer','reader')" |
| 167 | " ORDER BY login" |
| 168 | ); |
| 169 | while( db_step(&s)==SQLITE_ROW ){ |
| 170 | int uid = db_column_int(&s, 0); |
| 171 | const char *zLogin = db_column_text(&s, 1); |
| 172 | const char *zCap = db_column_text(&s, 2); |
| 173 | const char *zDate = db_column_text(&s, 4); |
| 174 | @ <tr> |
| 175 | @ <td><a href='setup_uedit?id=%d(uid)'>%d(uid)</a> |
| 176 | @ <td><a href='setup_uedit?id=%d(uid)'>%h(zLogin)</a> |
| 177 | @ <td>%h(zCap) |
| 178 | |
| 179 | if( fossil_strcmp(zLogin,"anonymous")==0 ){ |
| 180 | @ <td>All logged-in users |
| 181 | }else if( fossil_strcmp(zLogin,"developer")==0 ){ |
| 182 | @ <td>Users with '<b>v</b>' capability |
| 183 | }else if( fossil_strcmp(zLogin,"nobody")==0 ){ |
| 184 | @ <td>All users without login |
| 185 | }else if( fossil_strcmp(zLogin,"reader")==0 ){ |
| 186 | @ <td>Users with '<b>u</b>' capability |
| 187 | }else{ |
| 188 | @ <td> |
| 189 | } |
| 190 | if( zDate && zDate[0] ){ |
| 191 | @ <td>%h(zDate) |
| 192 | }else{ |
| 193 | @ <td> |
| 194 | } |
| 195 | @ </tr> |
| 196 | } |
| 197 | db_finalize(&s); |
| 198 | @ </tbody></table> |
| 199 | @ <div class='section'>Users</div> |
| 200 | @ <table border=1 cellpadding=2 cellspacing=0 class='userTable' id='userlist'> |
| 201 | @ <thead><tr> |
| 202 | @ <th>ID<th>Login<th>Caps<th>Info<th>Chng<th>Expire</tr></thead> |
| 203 | @ <tbody> |
| 204 | db_prepare(&s, |
| 205 | "SELECT uid, login, cap, info, date(mtime,'unixepoch'), lower(login) AS sortkey, " |
| 206 | " CASE WHEN info LIKE '%%expires 20%%'" |
| 207 | " THEN substr(info,instr(lower(info),'expires')+8,10)" |
| 208 | " END AS exp" |
| 209 | " FROM user" |
| 210 | " WHERE login NOT IN ('anonymous','nobody','developer','reader')" |
| 211 | " ORDER BY sortkey" |
| 212 | ); |
| 213 | while( db_step(&s)==SQLITE_ROW ){ |
| 214 | int uid = db_column_int(&s, 0); |
| 215 | const char *zLogin = db_column_text(&s, 1); |
| 216 | const char *zCap = db_column_text(&s, 2); |
| 217 | const char *zInfo = db_column_text(&s, 3); |
| 218 | const char *zDate = db_column_text(&s, 4); |
| 219 | const char *zSortKey = db_column_text(&s,5); |
| 220 | const char *zExp = db_column_text(&s,6); |
| 221 | @ <tr> |
| 222 | @ <td><a href='setup_uedit?id=%d(uid)'>%d(uid)</a> |
| 223 | @ <td data-sortkey='%h(zSortKey)'><a href='setup_uedit?id=%d(uid)'>%h(zLogin)</a> |
| 224 | @ <td>%h(zCap) |
| 225 | @ <td>%h(zInfo) |
| 226 | @ <td>%h(zDate?zDate:"") |
| 227 | @ <td>%h(zExp?zExp:"") |
| 228 | @ </tr> |
| 229 | } |
| 230 | @ </tbody></table> |
| 231 | db_finalize(&s); |
| 232 | output_table_sorting_javascript("userlist","nktxTT",2); |
| 233 | style_footer(); |
| 234 | } |
| 235 | |
| 236 | /* |
| 237 | ** WEBPAGE: setup_ulist_notes |
| 238 |