Fossil SCM

Add some links to improve navigation between attachments and their target. Experimentally use a collapsed DETAILS element for attachment lists in forum post to save some UI clutter.

stephan 2026-06-04 16:50 UTC attach-v2
Commit 48445daff04eb47fc333149b20b6fe85de0c60ca1d0082b1dd053bf7508a75a5
+41 -8
--- src/attach.c
+++ src/attach.c
@@ -215,20 +215,21 @@
215215
** At most one of technote=, tkt=, forumpost=, or page= may be supplied.
216216
**
217217
** If none are given, all attachments are listed. If one is given, only
218218
** attachments for the designated technote, ticket or wiki page are shown.
219219
**
220
-** HASH may be just a prefix of the relevant technical note or ticket
221
-** artifact hash, in which case all attachments of all technical notes or
222
-** tickets with the prefix will be listed. Forum posts, on the other hand,
223
-** require a unique hash prefix.
220
+** HASH may be just a prefix of the relevant forum post, technical
221
+** note, or ticket artifact hash, in which case all attachments of all
222
+** technical notes or tickets with the prefix will be listed. Forum
223
+** posts, on the other hand, require a unique hash or hash prefix.
224224
*/
225225
void attachlist_page(void){
226226
const char *zPage = P("page");
227227
const char *zTkt = P("tkt");
228228
const char *zTechNote = P("technote");
229229
const char *zForumPost = P("forumpost");
230
+ char *zLink = 0;
230231
Blob sql;
231232
Stmt q;
232233
233234
if( zPage && zTkt ) zTkt = 0;
234235
login_check_credentials();
@@ -248,32 +249,47 @@
248249
if( fnid<=0 ){
249250
webpage_error("Invalid forum post ID: %h", zForumPost);
250251
}
251252
blob_append_sql(&sql, " WHERE target="
252253
"(SELECT uuid FROM blob WHERE rid=%d)", fnid);
254
+ zLink = mprintf("forum post <a href='%R/forumpost/%t'>%#h</a>",
255
+ zForumPost, hash_digits(0), zForumPost);
253256
}else if( zPage ){
254257
if( g.perm.RdWiki==0 ){ login_needed(g.anon.RdWiki); return; }
255258
style_header("Attachments To Wiki page %h", zPage);
256259
blob_append_sql(&sql, " WHERE target=%Q", zPage);
260
+ zLink = mprintf("wiki page <a href='%R/wiki?name=%t'>%h</a>",
261
+ zPage, zPage);
257262
}else if( zTkt ){
258263
if( g.perm.RdTkt==0 ){ login_needed(g.anon.RdTkt); return; }
259264
style_header("Attachments To Ticket %S", zTkt);
260265
blob_append_sql(&sql, " WHERE target GLOB '%q*'", zTkt);
266
+ zLink = mprintf("ticket <a href='%R/tktview?name=%t'>%#h</a>",
267
+ zTkt, hash_digits(0), zTkt);
261268
}else if( zTechNote ){
262269
if( g.perm.RdWiki==0 ){ login_needed(g.anon.RdWiki); return; }
263270
style_header("Attachments To Tech Note %S", zTechNote);
264271
blob_append_sql(&sql, " WHERE target GLOB '%q*'",
265272
zTechNote);
273
+ zLink = mprintf("tech-note <a href='%R/technote?name=%t'>%#h</a>",
274
+ zTechNote, hash_digits(0), zTechNote);
266275
}else{
267276
if( g.perm.RdTkt==0 && g.perm.RdWiki==0 ){
268277
login_needed(g.anon.RdTkt || g.anon.RdWiki);
269278
return;
270279
}
271280
style_header("All Attachments");
272281
}
273282
blob_append_sql(&sql, " ORDER BY mtime DESC");
274283
db_prepare(&q, "%s", blob_sql_text(&sql));
284
+
285
+ if( zLink ){
286
+ @ <h2>Attachments for %s(zLink)</h2>
287
+ fossil_free(zLink);
288
+ zLink = 0;
289
+ }
290
+
275291
@ <ol>
276292
while( db_step(&q)==SQLITE_ROW ){
277293
const char *zDate;
278294
const char *zSrc;
279295
const char *zTarget;
@@ -954,11 +970,11 @@
954970
zTarget = db_text(0, "SELECT substr(tagname,7) FROM tag"
955971
" WHERE tagname GLOB 'event-%q*'", zTarget);
956972
if( zTarget==0) fossil_redirect_home();
957973
}
958974
zTo = zFrom ? 0 : mprintf("%R/technote?name=%T", zTarget);
959
- zTargetType = mprintf("Tech Note <a href=\"%R/technote/%s\">%S</a>",
975
+ zTargetType = mprintf("Tech-note <a href=\"%R/technote/%s\">%S</a>",
960976
zTarget, zTarget);
961977
noJsArgs[1] = zTarget;
962978
break;
963979
}
964980
case CFTYPE_TICKET:{
@@ -984,11 +1000,11 @@
9841000
}
9851001
if( !db_exists("SELECT 1 FROM tag WHERE tagname='wiki-%q'", zTarget) ){
9861002
fossil_redirect_home();
9871003
}
9881004
zTo = zFrom ? 0 : mprintf("%R/wiki?name=%T", zTarget);
989
- zTargetType = mprintf("Wiki Page <a href=\"%R/wiki?name=%h\">%h</a>",
1005
+ zTargetType = mprintf("Wiki page <a href=\"%R/wiki?name=%h\">%h</a>",
9901006
zTarget, zTarget);
9911007
noJsArgs[3] = zTarget;
9921008
break;
9931009
}
9941010
}
@@ -1306,10 +1322,12 @@
13061322
*/
13071323
#define ATTACHLIST_HRULE_ABOVE 0x01 /* Insert <hr> above header */
13081324
#define ATTACHLIST_TARGET_BLANK 0x02 /* use target=_blank for links */
13091325
#define ATTACHLIST_SIZE 0x04 /* add size */
13101326
#define ATTACHLIST_HIDE_UNAPPROVED 0x08 /* Hide pending-moderation files */
1327
+#define ATTACHLIST_DETAILS_CLOSED 0x10 /* Wrap in a closed DETAILS element */
1328
+#define ATTACHLIST_DETAILS_OPEN 0x20 /* Wrap in an open DETAILS element */
13111329
#endif
13121330
13131331
/*
13141332
** Output HTML to show a list of attachments.
13151333
*/
@@ -1320,11 +1338,14 @@
13201338
){
13211339
int cnt = 0;
13221340
char szBuf[36] = {0}; /* scratchpad for attachment size value */
13231341
const char *zLinkTgt = (ATTACHLIST_TARGET_BLANK & flags)
13241342
? " target=\"_blank\"" : "";
1343
+ const int bUseDetail = flags &
1344
+ (ATTACHLIST_DETAILS_CLOSED | ATTACHLIST_DETAILS_OPEN);
13251345
Stmt q;
1346
+
13261347
db_prepare(&q,
13271348
"SELECT datetime(mtime,toLocal()), a.filename, a.user,"
13281349
" b1.uuid, a.src, a.target, a.attachid, b2.size\n"
13291350
" FROM attachment a, blob b1, blob b2\n"
13301351
" WHERE a.isLatest\n"
@@ -1350,15 +1371,27 @@
13501371
&& moderation_pending(aid)
13511372
&& !moderation_user_could(aid, 1, 0) ){
13521373
continue;
13531374
}
13541375
if( cnt==0 ){
1355
- @ <section class='attachlist'>
1376
+ if( bUseDetail ){
1377
+ @ <details class='attachlist'
1378
+ if( ATTACHLIST_DETAILS_OPEN & flags ){
1379
+ @ open
1380
+ }
1381
+ @ >
1382
+ }else{
1383
+ @ <section class='attachlist'>
1384
+ }
13561385
if( flags & ATTACHLIST_HRULE_ABOVE ){
13571386
@ <hr>
13581387
}
1359
- @ %s(zHeader)
1388
+ if( bUseDetail ){
1389
+ @ <summary>%s(zHeader)</summary>
1390
+ }else{
1391
+ @ %s(zHeader)
1392
+ }
13601393
@ <ul>
13611394
}
13621395
cnt++;
13631396
switch( attachment_target_type(zTarget, 1) ){
13641397
case CFTYPE_TICKET: zTypeArg = "tkt"; break;
13651398
--- src/attach.c
+++ src/attach.c
@@ -215,20 +215,21 @@
215 ** At most one of technote=, tkt=, forumpost=, or page= may be supplied.
216 **
217 ** If none are given, all attachments are listed. If one is given, only
218 ** attachments for the designated technote, ticket or wiki page are shown.
219 **
220 ** HASH may be just a prefix of the relevant technical note or ticket
221 ** artifact hash, in which case all attachments of all technical notes or
222 ** tickets with the prefix will be listed. Forum posts, on the other hand,
223 ** require a unique hash prefix.
224 */
225 void attachlist_page(void){
226 const char *zPage = P("page");
227 const char *zTkt = P("tkt");
228 const char *zTechNote = P("technote");
229 const char *zForumPost = P("forumpost");
 
230 Blob sql;
231 Stmt q;
232
233 if( zPage && zTkt ) zTkt = 0;
234 login_check_credentials();
@@ -248,32 +249,47 @@
248 if( fnid<=0 ){
249 webpage_error("Invalid forum post ID: %h", zForumPost);
250 }
251 blob_append_sql(&sql, " WHERE target="
252 "(SELECT uuid FROM blob WHERE rid=%d)", fnid);
 
 
253 }else if( zPage ){
254 if( g.perm.RdWiki==0 ){ login_needed(g.anon.RdWiki); return; }
255 style_header("Attachments To Wiki page %h", zPage);
256 blob_append_sql(&sql, " WHERE target=%Q", zPage);
 
 
257 }else if( zTkt ){
258 if( g.perm.RdTkt==0 ){ login_needed(g.anon.RdTkt); return; }
259 style_header("Attachments To Ticket %S", zTkt);
260 blob_append_sql(&sql, " WHERE target GLOB '%q*'", zTkt);
 
 
261 }else if( zTechNote ){
262 if( g.perm.RdWiki==0 ){ login_needed(g.anon.RdWiki); return; }
263 style_header("Attachments To Tech Note %S", zTechNote);
264 blob_append_sql(&sql, " WHERE target GLOB '%q*'",
265 zTechNote);
 
 
266 }else{
267 if( g.perm.RdTkt==0 && g.perm.RdWiki==0 ){
268 login_needed(g.anon.RdTkt || g.anon.RdWiki);
269 return;
270 }
271 style_header("All Attachments");
272 }
273 blob_append_sql(&sql, " ORDER BY mtime DESC");
274 db_prepare(&q, "%s", blob_sql_text(&sql));
 
 
 
 
 
 
 
275 @ <ol>
276 while( db_step(&q)==SQLITE_ROW ){
277 const char *zDate;
278 const char *zSrc;
279 const char *zTarget;
@@ -954,11 +970,11 @@
954 zTarget = db_text(0, "SELECT substr(tagname,7) FROM tag"
955 " WHERE tagname GLOB 'event-%q*'", zTarget);
956 if( zTarget==0) fossil_redirect_home();
957 }
958 zTo = zFrom ? 0 : mprintf("%R/technote?name=%T", zTarget);
959 zTargetType = mprintf("Tech Note <a href=\"%R/technote/%s\">%S</a>",
960 zTarget, zTarget);
961 noJsArgs[1] = zTarget;
962 break;
963 }
964 case CFTYPE_TICKET:{
@@ -984,11 +1000,11 @@
984 }
985 if( !db_exists("SELECT 1 FROM tag WHERE tagname='wiki-%q'", zTarget) ){
986 fossil_redirect_home();
987 }
988 zTo = zFrom ? 0 : mprintf("%R/wiki?name=%T", zTarget);
989 zTargetType = mprintf("Wiki Page <a href=\"%R/wiki?name=%h\">%h</a>",
990 zTarget, zTarget);
991 noJsArgs[3] = zTarget;
992 break;
993 }
994 }
@@ -1306,10 +1322,12 @@
1306 */
1307 #define ATTACHLIST_HRULE_ABOVE 0x01 /* Insert <hr> above header */
1308 #define ATTACHLIST_TARGET_BLANK 0x02 /* use target=_blank for links */
1309 #define ATTACHLIST_SIZE 0x04 /* add size */
1310 #define ATTACHLIST_HIDE_UNAPPROVED 0x08 /* Hide pending-moderation files */
 
 
1311 #endif
1312
1313 /*
1314 ** Output HTML to show a list of attachments.
1315 */
@@ -1320,11 +1338,14 @@
1320 ){
1321 int cnt = 0;
1322 char szBuf[36] = {0}; /* scratchpad for attachment size value */
1323 const char *zLinkTgt = (ATTACHLIST_TARGET_BLANK & flags)
1324 ? " target=\"_blank\"" : "";
 
 
1325 Stmt q;
 
1326 db_prepare(&q,
1327 "SELECT datetime(mtime,toLocal()), a.filename, a.user,"
1328 " b1.uuid, a.src, a.target, a.attachid, b2.size\n"
1329 " FROM attachment a, blob b1, blob b2\n"
1330 " WHERE a.isLatest\n"
@@ -1350,15 +1371,27 @@
1350 && moderation_pending(aid)
1351 && !moderation_user_could(aid, 1, 0) ){
1352 continue;
1353 }
1354 if( cnt==0 ){
1355 @ <section class='attachlist'>
 
 
 
 
 
 
 
 
1356 if( flags & ATTACHLIST_HRULE_ABOVE ){
1357 @ <hr>
1358 }
1359 @ %s(zHeader)
 
 
 
 
1360 @ <ul>
1361 }
1362 cnt++;
1363 switch( attachment_target_type(zTarget, 1) ){
1364 case CFTYPE_TICKET: zTypeArg = "tkt"; break;
1365
--- src/attach.c
+++ src/attach.c
@@ -215,20 +215,21 @@
215 ** At most one of technote=, tkt=, forumpost=, or page= may be supplied.
216 **
217 ** If none are given, all attachments are listed. If one is given, only
218 ** attachments for the designated technote, ticket or wiki page are shown.
219 **
220 ** HASH may be just a prefix of the relevant forum post, technical
221 ** note, or ticket artifact hash, in which case all attachments of all
222 ** technical notes or tickets with the prefix will be listed. Forum
223 ** posts, on the other hand, require a unique hash or hash prefix.
224 */
225 void attachlist_page(void){
226 const char *zPage = P("page");
227 const char *zTkt = P("tkt");
228 const char *zTechNote = P("technote");
229 const char *zForumPost = P("forumpost");
230 char *zLink = 0;
231 Blob sql;
232 Stmt q;
233
234 if( zPage && zTkt ) zTkt = 0;
235 login_check_credentials();
@@ -248,32 +249,47 @@
249 if( fnid<=0 ){
250 webpage_error("Invalid forum post ID: %h", zForumPost);
251 }
252 blob_append_sql(&sql, " WHERE target="
253 "(SELECT uuid FROM blob WHERE rid=%d)", fnid);
254 zLink = mprintf("forum post <a href='%R/forumpost/%t'>%#h</a>",
255 zForumPost, hash_digits(0), zForumPost);
256 }else if( zPage ){
257 if( g.perm.RdWiki==0 ){ login_needed(g.anon.RdWiki); return; }
258 style_header("Attachments To Wiki page %h", zPage);
259 blob_append_sql(&sql, " WHERE target=%Q", zPage);
260 zLink = mprintf("wiki page <a href='%R/wiki?name=%t'>%h</a>",
261 zPage, zPage);
262 }else if( zTkt ){
263 if( g.perm.RdTkt==0 ){ login_needed(g.anon.RdTkt); return; }
264 style_header("Attachments To Ticket %S", zTkt);
265 blob_append_sql(&sql, " WHERE target GLOB '%q*'", zTkt);
266 zLink = mprintf("ticket <a href='%R/tktview?name=%t'>%#h</a>",
267 zTkt, hash_digits(0), zTkt);
268 }else if( zTechNote ){
269 if( g.perm.RdWiki==0 ){ login_needed(g.anon.RdWiki); return; }
270 style_header("Attachments To Tech Note %S", zTechNote);
271 blob_append_sql(&sql, " WHERE target GLOB '%q*'",
272 zTechNote);
273 zLink = mprintf("tech-note <a href='%R/technote?name=%t'>%#h</a>",
274 zTechNote, hash_digits(0), zTechNote);
275 }else{
276 if( g.perm.RdTkt==0 && g.perm.RdWiki==0 ){
277 login_needed(g.anon.RdTkt || g.anon.RdWiki);
278 return;
279 }
280 style_header("All Attachments");
281 }
282 blob_append_sql(&sql, " ORDER BY mtime DESC");
283 db_prepare(&q, "%s", blob_sql_text(&sql));
284
285 if( zLink ){
286 @ <h2>Attachments for %s(zLink)</h2>
287 fossil_free(zLink);
288 zLink = 0;
289 }
290
291 @ <ol>
292 while( db_step(&q)==SQLITE_ROW ){
293 const char *zDate;
294 const char *zSrc;
295 const char *zTarget;
@@ -954,11 +970,11 @@
970 zTarget = db_text(0, "SELECT substr(tagname,7) FROM tag"
971 " WHERE tagname GLOB 'event-%q*'", zTarget);
972 if( zTarget==0) fossil_redirect_home();
973 }
974 zTo = zFrom ? 0 : mprintf("%R/technote?name=%T", zTarget);
975 zTargetType = mprintf("Tech-note <a href=\"%R/technote/%s\">%S</a>",
976 zTarget, zTarget);
977 noJsArgs[1] = zTarget;
978 break;
979 }
980 case CFTYPE_TICKET:{
@@ -984,11 +1000,11 @@
1000 }
1001 if( !db_exists("SELECT 1 FROM tag WHERE tagname='wiki-%q'", zTarget) ){
1002 fossil_redirect_home();
1003 }
1004 zTo = zFrom ? 0 : mprintf("%R/wiki?name=%T", zTarget);
1005 zTargetType = mprintf("Wiki page <a href=\"%R/wiki?name=%h\">%h</a>",
1006 zTarget, zTarget);
1007 noJsArgs[3] = zTarget;
1008 break;
1009 }
1010 }
@@ -1306,10 +1322,12 @@
1322 */
1323 #define ATTACHLIST_HRULE_ABOVE 0x01 /* Insert <hr> above header */
1324 #define ATTACHLIST_TARGET_BLANK 0x02 /* use target=_blank for links */
1325 #define ATTACHLIST_SIZE 0x04 /* add size */
1326 #define ATTACHLIST_HIDE_UNAPPROVED 0x08 /* Hide pending-moderation files */
1327 #define ATTACHLIST_DETAILS_CLOSED 0x10 /* Wrap in a closed DETAILS element */
1328 #define ATTACHLIST_DETAILS_OPEN 0x20 /* Wrap in an open DETAILS element */
1329 #endif
1330
1331 /*
1332 ** Output HTML to show a list of attachments.
1333 */
@@ -1320,11 +1338,14 @@
1338 ){
1339 int cnt = 0;
1340 char szBuf[36] = {0}; /* scratchpad for attachment size value */
1341 const char *zLinkTgt = (ATTACHLIST_TARGET_BLANK & flags)
1342 ? " target=\"_blank\"" : "";
1343 const int bUseDetail = flags &
1344 (ATTACHLIST_DETAILS_CLOSED | ATTACHLIST_DETAILS_OPEN);
1345 Stmt q;
1346
1347 db_prepare(&q,
1348 "SELECT datetime(mtime,toLocal()), a.filename, a.user,"
1349 " b1.uuid, a.src, a.target, a.attachid, b2.size\n"
1350 " FROM attachment a, blob b1, blob b2\n"
1351 " WHERE a.isLatest\n"
@@ -1350,15 +1371,27 @@
1371 && moderation_pending(aid)
1372 && !moderation_user_could(aid, 1, 0) ){
1373 continue;
1374 }
1375 if( cnt==0 ){
1376 if( bUseDetail ){
1377 @ <details class='attachlist'
1378 if( ATTACHLIST_DETAILS_OPEN & flags ){
1379 @ open
1380 }
1381 @ >
1382 }else{
1383 @ <section class='attachlist'>
1384 }
1385 if( flags & ATTACHLIST_HRULE_ABOVE ){
1386 @ <hr>
1387 }
1388 if( bUseDetail ){
1389 @ <summary>%s(zHeader)</summary>
1390 }else{
1391 @ %s(zHeader)
1392 }
1393 @ <ul>
1394 }
1395 cnt++;
1396 switch( attachment_target_type(zTarget, 1) ){
1397 case CFTYPE_TICKET: zTypeArg = "tkt"; break;
1398
--- src/default.css
+++ src/default.css
@@ -2009,10 +2009,14 @@
20092009
div.helpPage blockquote {
20102010
margin-left: 0.2em;
20112011
}
20122012
20132013
/* .attach* = styles for file attachments */
2014
+section.attachlist {}
2015
+details.attachlist > summary {
2016
+ cursor: pointer;
2017
+}
20142018
.attach-widget {
20152019
margin-bottom: 1em;
20162020
display: flex;
20172021
flex-direction: column;
20182022
gap: 0.75em;
20192023
--- src/default.css
+++ src/default.css
@@ -2009,10 +2009,14 @@
2009 div.helpPage blockquote {
2010 margin-left: 0.2em;
2011 }
2012
2013 /* .attach* = styles for file attachments */
 
 
 
 
2014 .attach-widget {
2015 margin-bottom: 1em;
2016 display: flex;
2017 flex-direction: column;
2018 gap: 0.75em;
2019
--- src/default.css
+++ src/default.css
@@ -2009,10 +2009,14 @@
2009 div.helpPage blockquote {
2010 margin-left: 0.2em;
2011 }
2012
2013 /* .attach* = styles for file attachments */
2014 section.attachlist {}
2015 details.attachlist > summary {
2016 cursor: pointer;
2017 }
2018 .attach-widget {
2019 margin-bottom: 1em;
2020 display: flex;
2021 flex-direction: column;
2022 gap: 0.75em;
2023
+8 -1
--- src/event.c
+++ src/event.c
@@ -229,11 +229,18 @@
229229
}else{
230230
@ <pre>
231231
@ %h(blob_str(&fullbody))
232232
@ </pre>
233233
}
234
- attachment_list(zFullId, "<h2>Attachments:</h2>", 1);
234
+ {
235
+ char * z = mprintf(
236
+ "<h2><a href='%R/attachlist?technote=%t'>Attachments</a>:</h2>",
237
+ zFullId
238
+ );
239
+ attachment_list(zFullId, z, 1);
240
+ fossil_free(z);
241
+ }
235242
document_emit_js();
236243
style_finish_page();
237244
manifest_destroy(pTNote);
238245
}
239246
240247
--- src/event.c
+++ src/event.c
@@ -229,11 +229,18 @@
229 }else{
230 @ <pre>
231 @ %h(blob_str(&fullbody))
232 @ </pre>
233 }
234 attachment_list(zFullId, "<h2>Attachments:</h2>", 1);
 
 
 
 
 
 
 
235 document_emit_js();
236 style_finish_page();
237 manifest_destroy(pTNote);
238 }
239
240
--- src/event.c
+++ src/event.c
@@ -229,11 +229,18 @@
229 }else{
230 @ <pre>
231 @ %h(blob_str(&fullbody))
232 @ </pre>
233 }
234 {
235 char * z = mprintf(
236 "<h2><a href='%R/attachlist?technote=%t'>Attachments</a>:</h2>",
237 zFullId
238 );
239 attachment_list(zFullId, z, 1);
240 fossil_free(z);
241 }
242 document_emit_js();
243 style_finish_page();
244 manifest_destroy(pTNote);
245 }
246
247
+14 -7
--- src/forum.c
+++ src/forum.c
@@ -1045,17 +1045,24 @@
10451045
/*
10461046
** Renders the attachment list for the given forum post.
10471047
** Emits no output if there are no attachments.
10481048
*/
10491049
static void forum_render_attachment_list(const char *zUuid){
1050
- char * zLbl = mprintf("<a href='%R/attachlist?forumpost=%!S'>"
1051
- "Attachments</a>:", zUuid);
1052
- attachment_list(zUuid, zLbl,
1053
- ATTACHLIST_HRULE_ABOVE
1054
- | ATTACHLIST_SIZE
1055
- | ATTACHLIST_HIDE_UNAPPROVED);
1056
- fossil_free(zLbl);
1050
+#if 1
1051
+ attachment_list(zUuid, "&#128206; Attachments", 0
1052
+ | ATTACHLIST_SIZE
1053
+ | ATTACHLIST_HIDE_UNAPPROVED
1054
+ | ATTACHLIST_DETAILS_CLOSED);
1055
+#else
1056
+ char * zLbl = mprintf("<a href='%R/attachlist?forumpost=%!S'>"
1057
+ "Attachments</a>:", zUuid);
1058
+ attachment_list(zUuid, zLbl,
1059
+ ATTACHLIST_HRULE_ABOVE
1060
+ | ATTACHLIST_SIZE
1061
+ | ATTACHLIST_HIDE_UNAPPROVED);
1062
+ fossil_free(zLbl);
1063
+#endif
10571064
}
10581065
10591066
/*
10601067
** Renders the attachment list for p or (if not NULL) pEditHead.
10611068
*/
10621069
--- src/forum.c
+++ src/forum.c
@@ -1045,17 +1045,24 @@
1045 /*
1046 ** Renders the attachment list for the given forum post.
1047 ** Emits no output if there are no attachments.
1048 */
1049 static void forum_render_attachment_list(const char *zUuid){
1050 char * zLbl = mprintf("<a href='%R/attachlist?forumpost=%!S'>"
1051 "Attachments</a>:", zUuid);
1052 attachment_list(zUuid, zLbl,
1053 ATTACHLIST_HRULE_ABOVE
1054 | ATTACHLIST_SIZE
1055 | ATTACHLIST_HIDE_UNAPPROVED);
1056 fossil_free(zLbl);
 
 
 
 
 
 
 
1057 }
1058
1059 /*
1060 ** Renders the attachment list for p or (if not NULL) pEditHead.
1061 */
1062
--- src/forum.c
+++ src/forum.c
@@ -1045,17 +1045,24 @@
1045 /*
1046 ** Renders the attachment list for the given forum post.
1047 ** Emits no output if there are no attachments.
1048 */
1049 static void forum_render_attachment_list(const char *zUuid){
1050 #if 1
1051 attachment_list(zUuid, "&#128206; Attachments", 0
1052 | ATTACHLIST_SIZE
1053 | ATTACHLIST_HIDE_UNAPPROVED
1054 | ATTACHLIST_DETAILS_CLOSED);
1055 #else
1056 char * zLbl = mprintf("<a href='%R/attachlist?forumpost=%!S'>"
1057 "Attachments</a>:", zUuid);
1058 attachment_list(zUuid, zLbl,
1059 ATTACHLIST_HRULE_ABOVE
1060 | ATTACHLIST_SIZE
1061 | ATTACHLIST_HIDE_UNAPPROVED);
1062 fossil_free(zLbl);
1063 #endif
1064 }
1065
1066 /*
1067 ** Renders the attachment list for p or (if not NULL) pEditHead.
1068 */
1069
+6 -1
--- src/tkt.c
+++ src/tkt.c
@@ -789,11 +789,16 @@
789789
safe_html_context(DOCSRC_TICKET);
790790
Th_Render(zScript);
791791
if( g.thTrace ) Th_Trace("END_TKTVIEW<br>\n", -1);
792792
793793
if( zFullName ){
794
- attachment_list(zFullName, "<h2>Attachments:</h2>", 1);
794
+ char * z = mprintf(
795
+ "<h2><a href='%R/attachlist?tkt=%t'>Attachments</a>:</h2>",
796
+ zFullName
797
+ );
798
+ attachment_list(zFullName, z, 1);
799
+ fossil_free(z);
795800
}
796801
797802
builtin_fossil_js_bundle_or("dom", "storage", NULL);
798803
builtin_request_js("fossil.page.ticket.js");
799804
builtin_fulfill_js_requests();
800805
--- src/tkt.c
+++ src/tkt.c
@@ -789,11 +789,16 @@
789 safe_html_context(DOCSRC_TICKET);
790 Th_Render(zScript);
791 if( g.thTrace ) Th_Trace("END_TKTVIEW<br>\n", -1);
792
793 if( zFullName ){
794 attachment_list(zFullName, "<h2>Attachments:</h2>", 1);
 
 
 
 
 
795 }
796
797 builtin_fossil_js_bundle_or("dom", "storage", NULL);
798 builtin_request_js("fossil.page.ticket.js");
799 builtin_fulfill_js_requests();
800
--- src/tkt.c
+++ src/tkt.c
@@ -789,11 +789,16 @@
789 safe_html_context(DOCSRC_TICKET);
790 Th_Render(zScript);
791 if( g.thTrace ) Th_Trace("END_TKTVIEW<br>\n", -1);
792
793 if( zFullName ){
794 char * z = mprintf(
795 "<h2><a href='%R/attachlist?tkt=%t'>Attachments</a>:</h2>",
796 zFullName
797 );
798 attachment_list(zFullName, z, 1);
799 fossil_free(z);
800 }
801
802 builtin_fossil_js_bundle_or("dom", "storage", NULL);
803 builtin_request_js("fossil.page.ticket.js");
804 builtin_fulfill_js_requests();
805

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button