Expand 213 hidden lines 214 214 ( icon ( Icon :: File ) ) 215 215 a class="asset-name" href=( format ! ( "/release-asset/{}" , a. id) ) { ( a. name) } 216 216 span class="asset-size muted" { ( fmt_bytes ( a. size) ) } 217 - @if can_write { 218 - form method="post" action=( format ! ( "/release-asset/{}/delete" , a. id) ) class="inline-form" { 219 - input type ="hidden" name="_csrf" value=( csrf) ; 220 - button class="icon-btn" type ="submit" aria-label="Delete asset" title="Delete asset" { ( icon ( Icon :: X ) ) } 221 - } 222 - } 223 217 } 224 218 } 225 219 li class="asset-row source" { Expand 5 hidden lines 231 225 a class="asset-name" href=( format ! ( "{base}/-/archive/{}.tar.gz" , r. tag) ) { "Source code (tar.gz)" } 232 226 } 233 227 } 234 - @if can_write { 235 - form method="post" action=( format ! ( "/release/{}/asset" , r. id) ) enctype="multipart/form-data" class="asset-upload" { 236 - input type ="hidden" name="_csrf" value=( csrf) ; 237 - input type ="file" name="asset" required; 238 - button class="btn inline-btn" type ="submit" { "Upload asset" } 239 - } 240 - } 241 228 } 242 229 } 243 230 } Expand 48 hidden lines 292 279 . await ? 293 280 . map_or ( repo. owner_id. clone ( ) , |u| u. username) ; 294 281 let back = format ! ( "/{owner}/{}/-/releases/{}" , repo. path, release. tag) ; 282 + let assets = state. store. list_release_assets ( & release. id) . await ?; 295 283 let ( jar, chrome) = build_chrome ( & state, jar, Some ( user) , uri. path ( ) . to_string ( ) ) ; 296 284 let body = html ! { 297 285 p { a class="back-link" href=( back) { "← Back to release" } } 298 286 ( release_form ( & format ! ( "/release/{}/edit" , release. id) , & chrome. csrf, Some ( & release) , & [ ] , & [ ] ) ) 287 + ( assets_editor ( & release. id, & chrome. csrf, & assets) ) 299 288 } ; 300 289 Ok ( ( jar, page ( & chrome, "Edit release" , body) ) . into_response ( ) ) 301 290 } Expand 49 hidden lines 351 340 } 352 341 } 353 342 343 + 344 + 345 + fn assets_editor ( release_id : & str , csrf : & str , assets : & [ store:: ReleaseAsset ] ) -> Markup { 346 + html ! { 347 + section class="listing" { 348 + h2 { "Assets" } 349 + div class="card" { 350 + @if assets. is_empty ( ) { 351 + p class="muted" { "No uploaded assets yet." } 352 + } @else { 353 + ul class="asset-list" { 354 + @for a in assets { 355 + li class="asset-row" { 356 + ( icon ( Icon :: File ) ) 357 + a class="asset-name" href=( format ! ( "/release-asset/{}" , a. id) ) { ( a. name) } 358 + span class="asset-size muted" { ( fmt_bytes ( a. size) ) } 359 + form method="post" action=( format ! ( "/release-asset/{}/delete" , a. id) ) class="inline-form" { 360 + input type ="hidden" name="_csrf" value=( csrf) ; 361 + button class="icon-btn" type ="submit" aria-label="Delete asset" title="Delete asset" { ( icon ( Icon :: X ) ) } 362 + } 363 + } 364 + } 365 + } 366 + } 367 + form method="post" action=( format ! ( "/release/{release_id}/asset" ) ) enctype="multipart/form-data" class="asset-upload" { 368 + input type ="hidden" name="_csrf" value=( csrf) ; 369 + input type ="file" name="asset" required; 370 + button class="btn inline-btn" type ="submit" { "Upload asset" } 371 + } 372 + } 373 + } 374 + } 375 + } 376 + 354 377 355 378 # [ derive ( Debug , Deserialize ) ] 356 379 pub struct ReleaseForm { Expand 208 hidden lines 565 588 return AppError :: Forbidden . into_response ( ) ; 566 589 } 567 590 let result = async { 568 - let ( release, repo, user) = writer_release ( & state, viewer. as_ref ( ) , & id) . await ?; 591 + let ( release, _repo, _user) = writer_release ( & state, viewer. as_ref ( ) , & id) . await ?; 569 592 if let Some ( ( tmp_name, name, size, ctype) ) = saved { 570 593 let asset = state 571 594 . store Expand 7 hidden lines 579 602 return Err ( AppError :: internal ( "storage error" ) ) ; 580 603 } 581 604 } 582 - Ok :: < String , AppError > ( format ! ( 583 - "/{}/{}/-/releases/{}" , 584 - user. username, repo. path, release. tag 585 - ) ) 605 + Ok :: < String , AppError > ( format ! ( "/release/{}/edit" , release. id) ) 586 606 } 587 607 . await ; 588 608 match result { Expand 54 hidden lines 643 663 . release_asset_by_id ( & id) 644 664 . await ? 645 665 . ok_or ( AppError :: NotFound ) ?; 646 - let ( release, repo, user) = 666 + let ( release, _repo, _user) = 647 667 writer_release ( & state, viewer. as_ref ( ) , & asset. release_id) . await ?; 648 668 let _ = tokio:: fs:: remove_file ( assets_dir ( & state) . join ( & asset. id) ) . await ; 649 669 state. store. delete_release_asset ( & asset. id) . await ?; 650 - Ok :: < String , AppError > ( format ! ( 651 - "/{}/{}/-/releases/{}" , 652 - user. username, repo. path, release. tag 653 - ) ) 670 + Ok :: < String , AppError > ( format ! ( "/release/{}/edit" , release. id) ) 654 671 } 655 672 . await ; 656 673 crate :: issues:: respond_redirect ( result)