From 5d343e7a31d6a6a4ed30ac14bcc55a264dca0ae8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20G=C3=B6bel?= <dgoebel@techfak.uni-bielefeld.de> Date: Mon, 22 Apr 2024 16:56:15 +0200 Subject: [PATCH] Show buckets limits in bucket list ind detail modal #112 --- Dockerfile | 2 +- package-lock.json | 305 +++++++++--------- src/client/auth/index.ts | 2 +- src/client/auth/models/OIDCProvider.ts | 4 +- src/client/s3proxy/index.ts | 2 +- src/client/s3proxy/models/BucketOut.ts | 13 +- src/client/s3proxy/models/BucketSizeLimits.ts | 15 + src/client/s3proxy/models/Constraint.ts | 11 - src/client/s3proxy/services/BucketService.ts | 36 ++- .../object-storage/BucketLimitProgressBar.vue | 48 +++ .../object-storage/BucketListItem.vue | 38 ++- .../modals/BucketDetailModal.vue | 29 +- .../object-storage/modals/CopyObjectModal.vue | 27 +- .../modals/CreateFolderModal.vue | 6 +- .../modals/UploadObjectModal.vue | 70 ++-- src/stores/buckets.ts | 25 +- src/stores/s3objects.ts | 24 +- src/views/object-storage/BucketsView.vue | 1 - 18 files changed, 400 insertions(+), 258 deletions(-) create mode 100644 src/client/s3proxy/models/BucketSizeLimits.ts delete mode 100644 src/client/s3proxy/models/Constraint.ts create mode 100644 src/components/object-storage/BucketLimitProgressBar.vue diff --git a/Dockerfile b/Dockerfile index 3293d59..d640ca8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -10,7 +10,7 @@ RUN npm run build-only # production stage FROM nginx:stable-alpine as production-stage EXPOSE 80 -HEALTHCHECK --interval=10s --timeout=2s CMD curl --head -f http://localhost || exit 1 +HEALTHCHECK --interval=5s --timeout=2s CMD curl --head -f http://localhost || exit 1 COPY nginx.conf /etc/nginx/conf.d/default.conf COPY --from=build-stage /app/dist /usr/share/nginx/html COPY --from=build-stage /app/src/assets/env.template.js /tmp diff --git a/package-lock.json b/package-lock.json index 4a18836..bd37a59 100644 --- a/package-lock.json +++ b/package-lock.json @@ -70,9 +70,9 @@ } }, "node_modules/@apidevtools/json-schema-ref-parser": { - "version": "11.5.5", - "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-11.5.5.tgz", - "integrity": "sha512-hv/aXDILyroHioVW27etFMV+IX6FyNn41YwbeGIAt5h/7fUTQvHI5w3ols8qYAT8aQt3kzexq5ZwxFDxNHIhdQ==", + "version": "11.6.0", + "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-11.6.0.tgz", + "integrity": "sha512-I+d5/XrazqY86/kGsmjVercjjJ+w6MVXJj7vnHfUgXzaoLJAl0/tPk2WXVpHUeRqHqyJ6AGkXBqx6Dc3wJkrCQ==", "dev": true, "dependencies": { "@jsdevtools/ono": "^7.1.3", @@ -1575,9 +1575,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.14.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.14.3.tgz", - "integrity": "sha512-X9alQ3XM6I9IlSlmC8ddAvMSyG1WuHk5oUnXGw+yUBs3BFoTizmG1La/Gr8fVJvDWAq+zlYTZ9DBgrlKRVY06g==", + "version": "4.16.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.16.1.tgz", + "integrity": "sha512-92/y0TqNLRYOTXpm6Z7mnpvKAG9P7qmK7yJeRJSdzElNCUnsgbpAsGqerUboYRIQKzgfq4pWu9xVkgpWLfmNsw==", "cpu": [ "arm" ], @@ -1588,9 +1588,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.14.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.14.3.tgz", - "integrity": "sha512-eQK5JIi+POhFpzk+LnjKIy4Ks+pwJ+NXmPxOCSvOKSNRPONzKuUvWE+P9JxGZVxrtzm6BAYMaL50FFuPe0oWMQ==", + "version": "4.16.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.16.1.tgz", + "integrity": "sha512-ttWB6ZCfRLuDIUiE0yiu5gcqOsYjA5F7kEV1ggHMj20FwLZ8A1FMeahZJFl/pnOmcnD2QL0z4AcDuo27utGU8A==", "cpu": [ "arm64" ], @@ -1601,9 +1601,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.14.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.14.3.tgz", - "integrity": "sha512-Od4vE6f6CTT53yM1jgcLqNfItTsLt5zE46fdPaEmeFHvPs5SjZYlLpHrSiHEKR1+HdRfxuzXHjDOIxQyC3ptBA==", + "version": "4.16.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.16.1.tgz", + "integrity": "sha512-QLDvPLetbqjHojTGFw9+nuSP3YY/iz2k1cep6crYlr97sS+ZJ0W43b8Z0zC00+lnFZj6JSNxiA4DjboNQMuh1A==", "cpu": [ "arm64" ], @@ -1614,9 +1614,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.14.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.14.3.tgz", - "integrity": "sha512-0IMAO21axJeNIrvS9lSe/PGthc8ZUS+zC53O0VhF5gMxfmcKAP4ESkKOCwEi6u2asUrt4mQv2rjY8QseIEb1aw==", + "version": "4.16.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.16.1.tgz", + "integrity": "sha512-TAUK/D8khRrRIa1KwRzo8JNKk3tcqaeXWdtsiLgA8zmACWwlWLjPCJ4DULGHQrMkeBjp1Cd3Yuwx04lZgFx5Vg==", "cpu": [ "x64" ], @@ -1627,9 +1627,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.14.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.14.3.tgz", - "integrity": "sha512-ge2DC7tHRHa3caVEoSbPRJpq7azhG+xYsd6u2MEnJ6XzPSzQsTKyXvh6iWjXRf7Rt9ykIUWHtl0Uz3T6yXPpKw==", + "version": "4.16.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.16.1.tgz", + "integrity": "sha512-KO+WGZjrh6zyFTD1alIFkfdtxf8B4BC+hqd3kBZHscPLvE5FR/6QKsyuCT0JlERxxYBSUKNUQ/UHyX5uwO1x2A==", "cpu": [ "arm" ], @@ -1640,9 +1640,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.14.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.14.3.tgz", - "integrity": "sha512-ljcuiDI4V3ySuc7eSk4lQ9wU8J8r8KrOUvB2U+TtK0TiW6OFDmJ+DdIjjwZHIw9CNxzbmXY39wwpzYuFDwNXuw==", + "version": "4.16.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.16.1.tgz", + "integrity": "sha512-NqxbllzIB1WoAo4ThUXVtd21iiM5IHMTTXmXySKBLVcZvkU0HIZmatlP7hLzb5yQubcmdIeWmncd2NdsjocEiw==", "cpu": [ "arm" ], @@ -1653,9 +1653,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.14.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.14.3.tgz", - "integrity": "sha512-Eci2us9VTHm1eSyn5/eEpaC7eP/mp5n46gTRB3Aar3BgSvDQGJZuicyq6TsH4HngNBgVqC5sDYxOzTExSU+NjA==", + "version": "4.16.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.16.1.tgz", + "integrity": "sha512-snma5NvV8y7IECQ5rq0sr0f3UUu+92NVmG/913JXJMcXo84h9ak9TA5UI9Cl2XRM9j3m37QwDBtEYnJzRkSmxA==", "cpu": [ "arm64" ], @@ -1666,9 +1666,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.14.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.14.3.tgz", - "integrity": "sha512-UrBoMLCq4E92/LCqlh+blpqMz5h1tJttPIniwUgOFJyjWI1qrtrDhhpHPuFxULlUmjFHfloWdixtDhSxJt5iKw==", + "version": "4.16.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.16.1.tgz", + "integrity": "sha512-KOvqGprlD84ueivhCi2flvcUwDRD20mAsE3vxQNVEI2Di9tnPGAfEu6UcrSPZbM+jG2w1oSr43hrPo0RNg6GGg==", "cpu": [ "arm64" ], @@ -1679,9 +1679,9 @@ ] }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.14.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.14.3.tgz", - "integrity": "sha512-5aRjvsS8q1nWN8AoRfrq5+9IflC3P1leMoy4r2WjXyFqf3qcqsxRCfxtZIV58tCxd+Yv7WELPcO9mY9aeQyAmw==", + "version": "4.16.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.16.1.tgz", + "integrity": "sha512-/gsNwtiGLqYwN4vP+EIdUC6Q6LTlpupWqokqIndvZcjn9ig/5P01WyaYCU2wvfL/2Z82jp5kX8c1mDBOvCP3zg==", "cpu": [ "ppc64" ], @@ -1692,9 +1692,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.14.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.14.3.tgz", - "integrity": "sha512-sk/Qh1j2/RJSX7FhEpJn8n0ndxy/uf0kI/9Zc4b1ELhqULVdTfN6HL31CDaTChiBAOgLcsJ1sgVZjWv8XNEsAQ==", + "version": "4.16.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.16.1.tgz", + "integrity": "sha512-uU8zuGkQfGqfD9w6VRJZI4IuG4JIfNxxJgEmLMAmPVHREKGsxFVfgHy5c6CexQF2vOfgjB33OsET3Vdn2lln9A==", "cpu": [ "riscv64" ], @@ -1705,9 +1705,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.14.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.14.3.tgz", - "integrity": "sha512-jOO/PEaDitOmY9TgkxF/TQIjXySQe5KVYB57H/8LRP/ux0ZoO8cSHCX17asMSv3ruwslXW/TLBcxyaUzGRHcqg==", + "version": "4.16.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.16.1.tgz", + "integrity": "sha512-lsjLtDgtcGFEuBP6yrXwkRN5/wKlvUZtfbKZZu0yaoNpiBL4epgnO21osAALIspVRnl4qZgyLFd8xjCYYWgwfw==", "cpu": [ "s390x" ], @@ -1718,9 +1718,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.14.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.14.3.tgz", - "integrity": "sha512-8ybV4Xjy59xLMyWo3GCfEGqtKV5M5gCSrZlxkPGvEPCGDLNla7v48S662HSGwRd6/2cSneMQWiv+QzcttLrrOA==", + "version": "4.16.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.16.1.tgz", + "integrity": "sha512-N2ZizKhUryqqrMfdCnjhJhZRgv61C6gK+hwVtCIKC8ts8J+go+vqENnGexwg21nHIOvLN5mBM8a7DI2vlyIOPg==", "cpu": [ "x64" ], @@ -1731,9 +1731,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.14.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.14.3.tgz", - "integrity": "sha512-s+xf1I46trOY10OqAtZ5Rm6lzHre/UiLA1J2uOhCFXWkbZrJRkYBPO6FhvGfHmdtQ3Bx793MNa7LvoWFAm93bg==", + "version": "4.16.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.16.1.tgz", + "integrity": "sha512-5ICeMxqg66FrOA2AbnBQ2TJVxfvZsKLxmof0ibvPLaYtbsJqnTUtJOofgWb46Gjd4uZcA4rdsp4JCxegzQPqCg==", "cpu": [ "x64" ], @@ -1744,9 +1744,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.14.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.14.3.tgz", - "integrity": "sha512-+4h2WrGOYsOumDQ5S2sYNyhVfrue+9tc9XcLWLh+Kw3UOxAvrfOrSMFon60KspcDdytkNDh7K2Vs6eMaYImAZg==", + "version": "4.16.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.16.1.tgz", + "integrity": "sha512-1vIP6Ce02L+qWD7uZYRiFiuAJo3m9kARatWmFSnss0gZnVj2Id7OPUU9gm49JPGasgcR3xMqiH3fqBJ8t00yVg==", "cpu": [ "arm64" ], @@ -1757,9 +1757,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.14.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.14.3.tgz", - "integrity": "sha512-T1l7y/bCeL/kUwh9OD4PQT4aM7Bq43vX05htPJJ46RTI4r5KNt6qJRzAfNfM+OYMNEVBWQzR2Gyk+FXLZfogGw==", + "version": "4.16.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.16.1.tgz", + "integrity": "sha512-Y3M92DcVsT6LoP+wrKpoUWPaazaP1fzbNkp0a0ZSj5Y//+pQVfVe/tQdsYQQy7dwXR30ZfALUIc9PCh9Izir6w==", "cpu": [ "ia32" ], @@ -1770,9 +1770,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.14.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.14.3.tgz", - "integrity": "sha512-/BypzV0H1y1HzgYpxqRaXGBRqfodgoBBCcsrujT6QRcakDQdfU+Lq9PENPh5jB4I44YWq+0C2eHsHya+nZY1sA==", + "version": "4.16.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.16.1.tgz", + "integrity": "sha512-x0fvpHMuF7fK5r8oZxSi8VYXkrVmRgubXpO/wcf15Lk3xZ4Jvvh5oG+u7Su1776A7XzVKZhD2eRc4t7H50gL3w==", "cpu": [ "x64" ], @@ -2704,40 +2704,40 @@ } }, "node_modules/@volar/language-core": { - "version": "2.2.0-alpha.8", - "resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-2.2.0-alpha.8.tgz", - "integrity": "sha512-Ew1Iw7/RIRNuDLn60fWJdOLApAlfTVPxbPiSLzc434PReC9kleYtaa//Wo2WlN1oiRqneW0pWQQV0CwYqaimLQ==", + "version": "2.2.0-alpha.10", + "resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-2.2.0-alpha.10.tgz", + "integrity": "sha512-njVJLtpu0zMvDaEk7K5q4BRpOgbyEUljU++un9TfJoJNhxG0z/hWwpwgTRImO42EKvwIxF3XUzeMk+qatAFy7Q==", "dev": true, "dependencies": { - "@volar/source-map": "2.2.0-alpha.8" + "@volar/source-map": "2.2.0-alpha.10" } }, "node_modules/@volar/source-map": { - "version": "2.2.0-alpha.8", - "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-2.2.0-alpha.8.tgz", - "integrity": "sha512-E1ZVmXFJ5DU4fWDcWHzi8OLqqReqIDwhXvIMhVdk6+VipfMVv4SkryXu7/rs4GA/GsebcRyJdaSkKBB3OAkIcA==", + "version": "2.2.0-alpha.10", + "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-2.2.0-alpha.10.tgz", + "integrity": "sha512-nrdWApVkP5cksAnDEyy1JD9rKdwOJsEq1B+seWO4vNXmZNcxQQCx4DULLBvKt7AzRUAQiAuw5aQkb9RBaSqdVA==", "dev": true, "dependencies": { "muggle-string": "^0.4.0" } }, "node_modules/@volar/typescript": { - "version": "2.2.0-alpha.8", - "resolved": "https://registry.npmjs.org/@volar/typescript/-/typescript-2.2.0-alpha.8.tgz", - "integrity": "sha512-RLbRDI+17CiayHZs9HhSzlH0FhLl/+XK6o2qoiw2o2GGKcyD1aDoY6AcMd44acYncTOrqoTNoY6LuCiRyiJiGg==", + "version": "2.2.0-alpha.10", + "resolved": "https://registry.npmjs.org/@volar/typescript/-/typescript-2.2.0-alpha.10.tgz", + "integrity": "sha512-GCa0vTVVdA9ULUsu2Rx7jwsIuyZQPvPVT9o3NrANTbYv+523Ao1gv3glC5vzNSDPM6bUl37r94HbCj7KINQr+g==", "dev": true, "dependencies": { - "@volar/language-core": "2.2.0-alpha.8", + "@volar/language-core": "2.2.0-alpha.10", "path-browserify": "^1.0.1" } }, "node_modules/@vue/compiler-core": { - "version": "3.4.22", - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.4.22.tgz", - "integrity": "sha512-FBDRCBE/rFPA8OfTUrARx2c49N7zoImlGT7hsFikv0pZxQlFhffQwewpEXaLynZW0/DspVXmNA+QQ9dXINpWmg==", + "version": "3.4.23", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.4.23.tgz", + "integrity": "sha512-HAFmuVEwNqNdmk+w4VCQ2pkLk1Vw4XYiiyxEp3z/xvl14aLTUBw2OfVH3vBcx+FtGsynQLkkhK410Nah1N2yyQ==", "dependencies": { "@babel/parser": "^7.24.1", - "@vue/shared": "3.4.22", + "@vue/shared": "3.4.23", "entities": "^4.5.0", "estree-walker": "^2.0.2", "source-map-js": "^1.2.0" @@ -2749,24 +2749,24 @@ "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" }, "node_modules/@vue/compiler-dom": { - "version": "3.4.22", - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.4.22.tgz", - "integrity": "sha512-YkAS+jZc6Ip360kT3lZbMQZteiYBbHDSVKr94Jdd8Zjr7VjSkkXKAFFR/FW+2tNtBYXOps6xrWlOquy3GeYB0w==", + "version": "3.4.23", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.4.23.tgz", + "integrity": "sha512-t0b9WSTnCRrzsBGrDd1LNR5HGzYTr7LX3z6nNBG+KGvZLqrT0mY6NsMzOqlVMBKKXKVuusbbB5aOOFgTY+senw==", "dependencies": { - "@vue/compiler-core": "3.4.22", - "@vue/shared": "3.4.22" + "@vue/compiler-core": "3.4.23", + "@vue/shared": "3.4.23" } }, "node_modules/@vue/compiler-sfc": { - "version": "3.4.22", - "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.4.22.tgz", - "integrity": "sha512-Pncp5Vc8E2Ef1o5uveO8WA1IqM7rt0R1jN8D4qitQYOUxC97iITGYA8oMInQ3UcDS7ip+SegyA2HbAEB4V6NMQ==", + "version": "3.4.23", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.4.23.tgz", + "integrity": "sha512-fSDTKTfzaRX1kNAUiaj8JB4AokikzStWgHooMhaxyjZerw624L+IAP/fvI4ZwMpwIh8f08PVzEnu4rg8/Npssw==", "dependencies": { "@babel/parser": "^7.24.1", - "@vue/compiler-core": "3.4.22", - "@vue/compiler-dom": "3.4.22", - "@vue/compiler-ssr": "3.4.22", - "@vue/shared": "3.4.22", + "@vue/compiler-core": "3.4.23", + "@vue/compiler-dom": "3.4.23", + "@vue/compiler-ssr": "3.4.23", + "@vue/shared": "3.4.23", "estree-walker": "^2.0.2", "magic-string": "^0.30.8", "postcss": "^8.4.38", @@ -2779,23 +2779,20 @@ "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" }, "node_modules/@vue/compiler-sfc/node_modules/magic-string": { - "version": "0.30.9", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.9.tgz", - "integrity": "sha512-S1+hd+dIrC8EZqKyT9DstTH/0Z+f76kmmvZnkfQVmOpDEF9iVgdYif3Q/pIWHmCoo59bQVGW0kVL3e2nl+9+Sw==", + "version": "0.30.10", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.10.tgz", + "integrity": "sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==", "dependencies": { "@jridgewell/sourcemap-codec": "^1.4.15" - }, - "engines": { - "node": ">=12" } }, "node_modules/@vue/compiler-ssr": { - "version": "3.4.22", - "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.4.22.tgz", - "integrity": "sha512-ycb2sL0SW6AkgVMrvaU/TIAEk7FQWyv/oYya44E/V9xURM+ij9Oev5bVobSS7GLJzkUieWW3SrYcK/PZpb5i4A==", + "version": "3.4.23", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.4.23.tgz", + "integrity": "sha512-hb6Uj2cYs+tfqz71Wj6h3E5t6OKvb4MVcM2Nl5i/z1nv1gjEhw+zYaNOV+Xwn+SSN/VZM0DgANw5TuJfxfezPg==", "dependencies": { - "@vue/compiler-dom": "3.4.22", - "@vue/shared": "3.4.22" + "@vue/compiler-dom": "3.4.23", + "@vue/shared": "3.4.23" } }, "node_modules/@vue/devtools-api": { @@ -2842,12 +2839,12 @@ } }, "node_modules/@vue/language-core": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-2.0.13.tgz", - "integrity": "sha512-oQgM+BM66SU5GKtUMLQSQN0bxHFkFpLSSAiY87wVziPaiNQZuKVDt/3yA7GB9PiQw0y/bTNL0bOc0jM/siYjKg==", + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-2.0.14.tgz", + "integrity": "sha512-3q8mHSNcGTR7sfp2X6jZdcb4yt8AjBXAfKk0qkZIh7GAJxOnoZ10h5HToZglw4ToFvAnq+xu/Z2FFbglh9Icag==", "dev": true, "dependencies": { - "@volar/language-core": "2.2.0-alpha.8", + "@volar/language-core": "2.2.0-alpha.10", "@vue/compiler-dom": "^3.4.0", "@vue/shared": "^3.4.0", "computeds": "^0.0.1", @@ -2865,48 +2862,48 @@ } }, "node_modules/@vue/reactivity": { - "version": "3.4.22", - "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.4.22.tgz", - "integrity": "sha512-+golHRRfcGoahBrhoTauFNIIAhxntRV3BI8HHqVvCdsuWivxW1MI0E9AOXVsz4H/ZlWM1ahudWTX6PhUrNR2yQ==", + "version": "3.4.23", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.4.23.tgz", + "integrity": "sha512-GlXR9PL+23fQ3IqnbSQ8OQKLodjqCyoCrmdLKZk3BP7jN6prWheAfU7a3mrltewTkoBm+N7qMEb372VHIkQRMQ==", "dependencies": { - "@vue/shared": "3.4.22" + "@vue/shared": "3.4.23" } }, "node_modules/@vue/runtime-core": { - "version": "3.4.22", - "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.4.22.tgz", - "integrity": "sha512-cbA8lcL4g1907EdY1a1KmP5IRWfbqjgBRcgJPkF//yn96XSC1/VAJBZiAGLiyw0P77Rw2Ao7d9U51vU1GC6yUQ==", + "version": "3.4.23", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.4.23.tgz", + "integrity": "sha512-FeQ9MZEXoFzFkFiw9MQQ/FWs3srvrP+SjDKSeRIiQHIhtkzoj0X4rWQlRNHbGuSwLra6pMyjAttwixNMjc/xLw==", "dependencies": { - "@vue/reactivity": "3.4.22", - "@vue/shared": "3.4.22" + "@vue/reactivity": "3.4.23", + "@vue/shared": "3.4.23" } }, "node_modules/@vue/runtime-dom": { - "version": "3.4.22", - "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.4.22.tgz", - "integrity": "sha512-AXxRHrFkLX1y2+70CO2wDKRxW0WZcQKTOXS31AK+jZ1RLPtI6sEHVpYNfyE9WgbgXOqPtX4gfIfuoFYi8iCu2w==", + "version": "3.4.23", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.4.23.tgz", + "integrity": "sha512-RXJFwwykZWBkMiTPSLEWU3kgVLNAfActBfWFlZd0y79FTUxexogd0PLG4HH2LfOktjRxV47Nulygh0JFXe5f9A==", "dependencies": { - "@vue/runtime-core": "3.4.22", - "@vue/shared": "3.4.22", + "@vue/runtime-core": "3.4.23", + "@vue/shared": "3.4.23", "csstype": "^3.1.3" } }, "node_modules/@vue/server-renderer": { - "version": "3.4.22", - "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.4.22.tgz", - "integrity": "sha512-okiNxiCOhJlx6IOrTZvhIVwf2UYKay0hnIPqWu4h19bkNv1gmG4Ic6U3zXY287AWF26lQuFMa515Qzc+R0aAYg==", + "version": "3.4.23", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.4.23.tgz", + "integrity": "sha512-LDwGHtnIzvKFNS8dPJ1SSU5Gvm36p2ck8wCZc52fc3k/IfjKcwCyrWEf0Yag/2wTFUBXrqizfhK9c/mC367dXQ==", "dependencies": { - "@vue/compiler-ssr": "3.4.22", - "@vue/shared": "3.4.22" + "@vue/compiler-ssr": "3.4.23", + "@vue/shared": "3.4.23" }, "peerDependencies": { - "vue": "3.4.22" + "vue": "3.4.23" } }, "node_modules/@vue/shared": { - "version": "3.4.22", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.22.tgz", - "integrity": "sha512-cg7R9XNk4ovV3bKka/1a464O2oY0l5Fyt0rwGR4hSJRPjUJ0WVjrPdsr4W0JbUriwiM8EKcCcCjeKN5pRMs2Zg==" + "version": "3.4.23", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.23.tgz", + "integrity": "sha512-wBQ0gvf+SMwsCQOyusNw/GoXPV47WGd1xB5A1Pgzy0sQ3Bi5r5xm3n+92y3gCnB3MWqnRDdvfkRGxhKtbBRNgg==" }, "node_modules/@vue/tsconfig": { "version": "0.5.1", @@ -5912,9 +5909,9 @@ } }, "node_modules/rollup": { - "version": "4.14.3", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.14.3.tgz", - "integrity": "sha512-ag5tTQKYsj1bhrFC9+OEWqb5O6VYgtQDO9hPDBMmIbePwhfSr+ExlcU741t8Dhw5DkPCQf6noz0jb36D6W9/hw==", + "version": "4.16.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.16.1.tgz", + "integrity": "sha512-5CaD3MPDlPKfhqzRvWXK96G6ELJfPZNb3LHiZxTHgDdC6jvwfGz2E8nY+9g1ONk4ttHsK1WaFP19Js4PSr1E3g==", "dev": true, "dependencies": { "@types/estree": "1.0.5" @@ -5927,22 +5924,22 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.14.3", - "@rollup/rollup-android-arm64": "4.14.3", - "@rollup/rollup-darwin-arm64": "4.14.3", - "@rollup/rollup-darwin-x64": "4.14.3", - "@rollup/rollup-linux-arm-gnueabihf": "4.14.3", - "@rollup/rollup-linux-arm-musleabihf": "4.14.3", - "@rollup/rollup-linux-arm64-gnu": "4.14.3", - "@rollup/rollup-linux-arm64-musl": "4.14.3", - "@rollup/rollup-linux-powerpc64le-gnu": "4.14.3", - "@rollup/rollup-linux-riscv64-gnu": "4.14.3", - "@rollup/rollup-linux-s390x-gnu": "4.14.3", - "@rollup/rollup-linux-x64-gnu": "4.14.3", - "@rollup/rollup-linux-x64-musl": "4.14.3", - "@rollup/rollup-win32-arm64-msvc": "4.14.3", - "@rollup/rollup-win32-ia32-msvc": "4.14.3", - "@rollup/rollup-win32-x64-msvc": "4.14.3", + "@rollup/rollup-android-arm-eabi": "4.16.1", + "@rollup/rollup-android-arm64": "4.16.1", + "@rollup/rollup-darwin-arm64": "4.16.1", + "@rollup/rollup-darwin-x64": "4.16.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.16.1", + "@rollup/rollup-linux-arm-musleabihf": "4.16.1", + "@rollup/rollup-linux-arm64-gnu": "4.16.1", + "@rollup/rollup-linux-arm64-musl": "4.16.1", + "@rollup/rollup-linux-powerpc64le-gnu": "4.16.1", + "@rollup/rollup-linux-riscv64-gnu": "4.16.1", + "@rollup/rollup-linux-s390x-gnu": "4.16.1", + "@rollup/rollup-linux-x64-gnu": "4.16.1", + "@rollup/rollup-linux-x64-musl": "4.16.1", + "@rollup/rollup-win32-arm64-msvc": "4.16.1", + "@rollup/rollup-win32-ia32-msvc": "4.16.1", + "@rollup/rollup-win32-x64-msvc": "4.16.1", "fsevents": "~2.3.2" } }, @@ -6643,9 +6640,9 @@ } }, "node_modules/vite": { - "version": "5.2.9", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.2.9.tgz", - "integrity": "sha512-uOQWfuZBlc6Y3W/DTuQ1Sr+oIXWvqljLvS881SVmAj00d5RdgShLcuXWxseWPd4HXwiYBFW/vXHfKFeqj9uQnw==", + "version": "5.2.10", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.2.10.tgz", + "integrity": "sha512-PAzgUZbP7msvQvqdSD+ErD5qGnSFiGOoWmV5yAKUEI0kdhjbH6nMWVyZQC/hSc4aXwc0oJ9aEdIiF9Oje0JFCw==", "dev": true, "dependencies": { "esbuild": "^0.20.1", @@ -6698,15 +6695,15 @@ } }, "node_modules/vue": { - "version": "3.4.22", - "resolved": "https://registry.npmjs.org/vue/-/vue-3.4.22.tgz", - "integrity": "sha512-CIx7NiP+n5WHBCG/fDNaUPP4qbQ5CIa8XIHZE3HpfS/rb2vmSIsp74BxsZyrrGKF0vHW3GoToqP3l0hzrMTecw==", + "version": "3.4.23", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.4.23.tgz", + "integrity": "sha512-X1y6yyGJ28LMUBJ0k/qIeKHstGd+BlWQEOT40x3auJFTmpIhpbKLgN7EFsqalnJXq1Km5ybDEsp6BhuWKciUDg==", "dependencies": { - "@vue/compiler-dom": "3.4.22", - "@vue/compiler-sfc": "3.4.22", - "@vue/runtime-dom": "3.4.22", - "@vue/server-renderer": "3.4.22", - "@vue/shared": "3.4.22" + "@vue/compiler-dom": "3.4.23", + "@vue/compiler-sfc": "3.4.23", + "@vue/runtime-dom": "3.4.23", + "@vue/server-renderer": "3.4.23", + "@vue/shared": "3.4.23" }, "peerDependencies": { "typescript": "*" @@ -6751,9 +6748,9 @@ } }, "node_modules/vue-router": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.3.0.tgz", - "integrity": "sha512-dqUcs8tUeG+ssgWhcPbjHvazML16Oga5w34uCUmsk7i0BcnskoLGwjpa15fqMr2Fa5JgVBrdL2MEgqz6XZ/6IQ==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.3.2.tgz", + "integrity": "sha512-hKQJ1vDAZ5LVkKEnHhmm1f9pMiWIBNGF5AwU67PdH7TyXCj/a4hTccuUuYCAMgJK6rO/NVYtQIEN3yL8CECa7Q==", "dependencies": { "@vue/devtools-api": "^6.5.1" }, @@ -6775,13 +6772,13 @@ } }, "node_modules/vue-tsc": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-2.0.13.tgz", - "integrity": "sha512-a3nL3FvguCWVJUQW/jFrUxdeUtiEkbZoQjidqvMeBK//tuE2w6NWQAbdrEpY2+6nSa4kZoKZp8TZUMtHpjt4mQ==", + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-2.0.14.tgz", + "integrity": "sha512-DgAO3U1cnCHOUO7yB35LENbkapeRsBZ7Ugq5hGz/QOHny0+1VQN8eSwSBjYbjLVPfvfw6EY7sNPjbuHHUhckcg==", "dev": true, "dependencies": { - "@volar/typescript": "2.2.0-alpha.8", - "@vue/language-core": "2.0.13", + "@volar/typescript": "2.2.0-alpha.10", + "@vue/language-core": "2.0.14", "semver": "^7.5.4" }, "bin": { diff --git a/src/client/auth/index.ts b/src/client/auth/index.ts index 016081e..1995035 100644 --- a/src/client/auth/index.ts +++ b/src/client/auth/index.ts @@ -9,7 +9,7 @@ export type { OpenAPIConfig } from './core/OpenAPI'; export type { ErrorDetail } from './models/ErrorDetail'; export type { HTTPValidationError } from './models/HTTPValidationError'; -export type { OIDCProvider } from './models/OIDCProvider'; +export { OIDCProvider } from './models/OIDCProvider'; export { RoleEnum } from './models/RoleEnum'; export type { User } from './models/User'; export type { ValidationError } from './models/ValidationError'; diff --git a/src/client/auth/models/OIDCProvider.ts b/src/client/auth/models/OIDCProvider.ts index 55d0ffe..b8e466e 100644 --- a/src/client/auth/models/OIDCProvider.ts +++ b/src/client/auth/models/OIDCProvider.ts @@ -2,4 +2,6 @@ /* istanbul ignore file */ /* tslint:disable */ /* eslint-disable */ -export type OIDCProvider = string; +export enum OIDCProvider { + LIFESCIENCE = 'lifescience', +} diff --git a/src/client/s3proxy/index.ts b/src/client/s3proxy/index.ts index 69ca124..37a68b1 100644 --- a/src/client/s3proxy/index.ts +++ b/src/client/s3proxy/index.ts @@ -13,8 +13,8 @@ export type { BucketOut } from './models/BucketOut'; export type { BucketPermissionIn } from './models/BucketPermissionIn'; export type { BucketPermissionOut } from './models/BucketPermissionOut'; export type { BucketPermissionParameters } from './models/BucketPermissionParameters'; +export type { BucketSizeLimits } from './models/BucketSizeLimits'; export { BucketType } from './models/BucketType'; -export { Constraint } from './models/Constraint'; export type { ErrorDetail } from './models/ErrorDetail'; export type { HTTPValidationError } from './models/HTTPValidationError'; export { Permission } from './models/Permission'; diff --git a/src/client/s3proxy/models/BucketOut.ts b/src/client/s3proxy/models/BucketOut.ts index 87a20c6..be48294 100644 --- a/src/client/s3proxy/models/BucketOut.ts +++ b/src/client/s3proxy/models/BucketOut.ts @@ -2,11 +2,18 @@ /* istanbul ignore file */ /* tslint:disable */ /* eslint-disable */ -import type { Constraint } from './Constraint'; /** * Schema for answering a request with a bucket. */ export type BucketOut = { + /** + * Size limit of the bucket in KiB + */ + size_limit?: (number | null); + /** + * Number of objects limit of the bucket + */ + object_limit?: (number | null); /** * Name of the bucket */ @@ -23,10 +30,6 @@ export type BucketOut = { * UID of the owner */ owner_id: string; - /** - * Constraint for the owner of the bucket - */ - owner_constraint?: (Constraint | null); /** * Flag if the bucket is anonymously readable */ diff --git a/src/client/s3proxy/models/BucketSizeLimits.ts b/src/client/s3proxy/models/BucketSizeLimits.ts new file mode 100644 index 0000000..22e59a7 --- /dev/null +++ b/src/client/s3proxy/models/BucketSizeLimits.ts @@ -0,0 +1,15 @@ +/* generated using openapi-typescript-codegen -- do not edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +export type BucketSizeLimits = { + /** + * Size limit of the bucket in KiB + */ + size_limit?: (number | null); + /** + * Number of objects limit of the bucket + */ + object_limit?: (number | null); +}; + diff --git a/src/client/s3proxy/models/Constraint.ts b/src/client/s3proxy/models/Constraint.ts deleted file mode 100644 index f33ad3b..0000000 --- a/src/client/s3proxy/models/Constraint.ts +++ /dev/null @@ -1,11 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -/** - * Enumeration for the possible permission on a bucket. - */ -export enum Constraint { - READ = 'READ', - WRITE = 'WRITE', -} diff --git a/src/client/s3proxy/services/BucketService.ts b/src/client/s3proxy/services/BucketService.ts index 1984645..b30e775 100644 --- a/src/client/s3proxy/services/BucketService.ts +++ b/src/client/s3proxy/services/BucketService.ts @@ -5,6 +5,7 @@ import type { Body_Bucket_update_bucket_public_state } from '../models/Body_Bucket_update_bucket_public_state'; import type { BucketIn } from '../models/BucketIn'; import type { BucketOut } from '../models/BucketOut'; +import type { BucketSizeLimits } from '../models/BucketSizeLimits'; import type { BucketType } from '../models/BucketType'; import type { CancelablePromise } from '../core/CancelablePromise'; import { OpenAPI } from '../core/OpenAPI'; @@ -133,8 +134,8 @@ export class BucketService { }); } /** - * update public status - * Toggle the buckets public state. A bucket with an owner constraint can't be made public. + * Update public status + * Update the buckets public state. * * Permission `bucket:update` required if the current user is the owner of the bucket, * otherwise `bucket:update_any` required. @@ -164,4 +165,35 @@ export class BucketService { }, }); } + /** + * Update bucket limits + * Update the buckets size limits. + * + * Permission `bucket:update_any` required. + * @param bucketName Name of bucket + * @param requestBody + * @returns BucketOut Successful Response + * @throws ApiError + */ + public static bucketUpdateBucketLimits( + bucketName: string, + requestBody: BucketSizeLimits, + ): CancelablePromise<BucketOut> { + return __request(OpenAPI, { + method: 'PATCH', + url: '/buckets/{bucket_name}/limits', + path: { + 'bucket_name': bucketName, + }, + body: requestBody, + mediaType: 'application/json', + errors: { + 400: `Error decoding JWT Token`, + 401: `Not authenticated`, + 403: `Not authorized`, + 404: `Entity not Found`, + 422: `Validation Error`, + }, + }); + } } diff --git a/src/components/object-storage/BucketLimitProgressBar.vue b/src/components/object-storage/BucketLimitProgressBar.vue new file mode 100644 index 0000000..e0ebc5a --- /dev/null +++ b/src/components/object-storage/BucketLimitProgressBar.vue @@ -0,0 +1,48 @@ +<script setup lang="ts"> +import { computed } from "vue"; + +const props = defineProps<{ + currentVal: number; + maximum: number; + label?: string; +}>(); + +const percentage = computed<number>( + () => (100 * props.currentVal) / props.maximum, +); + +const cssWidth = computed<number>(() => + Math.min(100, Math.round(percentage.value)), +); + +const colorClass = computed(() => { + if (percentage.value > 90) { + return "text-bg-danger"; + } else if (percentage.value > 75) { + return "text-bg-warning"; + } + return "text-bg-success text-dark"; +}); +</script> + +<template> + <div + class="progress" + role="progressbar" + aria-label="Warning example" + :aria-valuenow="cssWidth" + aria-valuemin="0" + aria-valuemax="100" + > + <div + class="progress-bar overflow-visible" + :class="colorClass" + :style="{ width: cssWidth + '%' }" + > + <template v-if="label">{{ label }}</template> + <template v-else> {{ percentage.toFixed(2) }}% </template> + </div> + </div> +</template> + +<style scoped></style> diff --git a/src/components/object-storage/BucketListItem.vue b/src/components/object-storage/BucketListItem.vue index 4a5bdcd..8798943 100644 --- a/src/components/object-storage/BucketListItem.vue +++ b/src/components/object-storage/BucketListItem.vue @@ -1,6 +1,5 @@ <script setup lang="ts"> import type { BucketOut, BucketPermissionOut } from "@/client/s3proxy"; -import { Constraint } from "@/client/s3proxy"; import FontAwesomeIcon from "@/components/FontAwesomeIcon.vue"; import PermissionModal from "@/components/object-storage/modals/PermissionModal.vue"; import BucketDetailModal from "@/components/object-storage/modals/BucketDetailModal.vue"; @@ -16,6 +15,7 @@ import { environment } from "@/environment"; import { useS3ObjectStore } from "@/stores/s3objects"; import { filesize } from "filesize"; import BootstrapToast from "@/components/BootstrapToast.vue"; +import BucketLimitProgressBar from "@/components/object-storage/BucketLimitProgressBar.vue"; const props = defineProps<{ active: boolean; @@ -154,13 +154,7 @@ onMounted(() => { }" > <span class="text-truncate flex-grow-3"> - <template v-if="bucket.owner_constraint === Constraint.READ" - >download-bucket</template - > - <template v-else-if="bucket.owner_constraint === Constraint.WRITE" - >upload-bucket</template - > - <template v-else>{{ bucket.name }}</template> + {{ bucket.name }} </span> <div class="text-nowrap"> <font-awesome-icon @@ -211,7 +205,7 @@ onMounted(() => { class="px-2 rounded-bottom border shadow-sm border-3 border-top-0 border-primary" > <div v-if="permission" class="ms-1 pt-1 text-info">Foreign Bucket</div> - <table class="table table-sm table-borderless mb-0"> + <table class="table table-sm table-borderless mb-0 align-middle"> <tbody> <tr v-if="permission"> <th scope="row" class="fw-bold">Permission:</th> @@ -264,15 +258,33 @@ onMounted(() => { </tr> <tr> <th scope="row" class="fw-bold">Objects:</th> - <td>{{ bucketMeta[0] }}</td> + <td v-if="bucket.object_limit"> + <bucket-limit-progress-bar + :maximum="bucket.object_limit" + :current-val="bucketMeta[0]" + :label="bucketMeta[0] + '/' + bucket.object_limit" + /> + </td> + <td v-else>{{ bucketMeta[0] }}</td> </tr> <tr> <th scope="row" class="fw-bold">Size:</th> - <td> - {{ filesize(bucketMeta[1], { base: 2, standard: "jedec" }) }} + <td v-if="bucket.size_limit"> + <bucket-limit-progress-bar + :maximum="1024 * bucket.size_limit" + :current-val="bucketMeta[1]" + :label=" + filesize(bucketMeta[1], { base: 2 }) + + '/' + + filesize(1024 * bucket.size_limit, { + base: 2, + }) + " + /> </td> + <td v-else>{{ filesize(bucketMeta[1], { base: 2 }) }}</td> </tr> - <tr v-if="bucket.owner_constraint == undefined"> + <tr> <th scope="row"> <div :class="{ 'form-check': !loading && permission == undefined }" diff --git a/src/components/object-storage/modals/BucketDetailModal.vue b/src/components/object-storage/modals/BucketDetailModal.vue index 7115147..7b56297 100644 --- a/src/components/object-storage/modals/BucketDetailModal.vue +++ b/src/components/object-storage/modals/BucketDetailModal.vue @@ -7,6 +7,7 @@ import { useS3ObjectStore } from "@/stores/s3objects"; import { computed } from "vue"; import { environment } from "../../../environment"; import FontAwesomeIcon from "@/components/FontAwesomeIcon.vue"; +import BucketLimitProgressBar from "@/components/object-storage/BucketLimitProgressBar.vue"; const props = defineProps<{ modalId: string; @@ -40,7 +41,7 @@ const s3Link = computed<string>(() => "s3://" + props.bucket.name); <template v-slot:body> <div class="container-fluid"> - <table class="table table-hover table-sm table-borderless"> + <table class="table table-sm table-borderless"> <tbody> <tr> <th scope="row" class="col-3">Name</th> @@ -58,12 +59,34 @@ const s3Link = computed<string>(() => "s3://" + props.bucket.name); </tr> <tr> <th scope="row">Objects</th> - <td>{{ bucketMeta[0] }}</td> + <td> + {{ bucketMeta[0] + }}<span v-if="bucket.object_limit" + >/{{ bucket.object_limit }}</span + > + <bucket-limit-progress-bar + v-if="bucket.object_limit" + :maximum="bucket.object_limit" + :current-val="bucketMeta[0]" + /> + </td> </tr> <tr> <th scope="row">Size</th> <td> - {{ filesize(bucketMeta[1], { base: 2, standard: "jedec" }) }} + {{ filesize(bucketMeta[1], { base: 2 }) + }}<span v-if="bucket.size_limit" + >/{{ + filesize(1024 * bucket.size_limit, { + base: 2, + }) + }}</span + > + <bucket-limit-progress-bar + v-if="bucket.size_limit" + :maximum="1024 * bucket.size_limit" + :current-val="bucketMeta[1]" + /> </td> </tr> <tr> diff --git a/src/components/object-storage/modals/CopyObjectModal.vue b/src/components/object-storage/modals/CopyObjectModal.vue index ca3b28d..d03cfcb 100644 --- a/src/components/object-storage/modals/CopyObjectModal.vue +++ b/src/components/object-storage/modals/CopyObjectModal.vue @@ -6,6 +6,7 @@ import type { _Object as S3Object } from "@aws-sdk/client-s3"; import { useBucketStore } from "@/stores/buckets"; import { useS3ObjectStore } from "@/stores/s3objects"; import BootstrapToast from "@/components/BootstrapToast.vue"; +import type { AbortController } from "@smithy/types"; const objectRepository = useS3ObjectStore(); @@ -19,10 +20,14 @@ const formState = reactive<{ destKey: string; destBucket: string; uploading: boolean; + err: string; + abortController?: AbortController; }>({ destKey: "", destBucket: "", uploading: false, + err: "", + abortController: undefined, }); const bucketRepository = useBucketStore(); @@ -43,6 +48,7 @@ function copyObject() { if (props.srcObject.Key == undefined) { return; } + formState.abortController = new AbortController(); formState.uploading = true; objectRepository .copyObject( @@ -50,6 +56,7 @@ function copyObject() { props.srcObject, formState.destBucket, formState.destKey, + formState.abortController, ) .then(() => { copyModal?.hide(); @@ -57,11 +64,12 @@ function copyObject() { formState.destBucket = ""; }) .catch((e) => { - console.error(e); + formState.err = e.Code; errorToast?.show(); }) .finally(() => { formState.uploading = false; + formState.abortController = undefined; }); } @@ -92,7 +100,7 @@ onMounted(() => { color-class="danger" > There has been some Error.<br /> - Try again later + Code: {{ formState.err }} </bootstrap-toast> <bootstrap-modal :modalId="modalId" @@ -164,17 +172,18 @@ onMounted(() => { Close </button> <button - :disabled="formState.uploading" + v-if="formState.uploading" + class="btn btn-danger" + @click="formState.abortController?.abort()" + > + Cancel + </button> + <button + v-else type="submit" :form="'copyObjectForm' + randomIDSuffix" class="btn btn-primary" > - <span - v-if="formState.uploading" - class="spinner-border spinner-border-sm" - role="status" - aria-hidden="true" - ></span> Copy </button> </template> diff --git a/src/components/object-storage/modals/CreateFolderModal.vue b/src/components/object-storage/modals/CreateFolderModal.vue index e0b5b39..b7c5b48 100644 --- a/src/components/object-storage/modals/CreateFolderModal.vue +++ b/src/components/object-storage/modals/CreateFolderModal.vue @@ -24,9 +24,11 @@ const currentFolders = computed<string[]>(() => props.keyPrefix.split("/")); const formState = reactive<{ folderName: string; uploading: boolean; + err: string; }>({ folderName: "", uploading: false, + err: "", }); function uploadFolder() { @@ -52,7 +54,7 @@ function uploadFolder() { formState.folderName = ""; }) .catch((e) => { - console.error(e); + formState.err = e.name; errorToast?.show(); }) .finally(() => { @@ -76,7 +78,7 @@ onMounted(() => { color-class="danger" > There has been some Error.<br /> - Try again later + Code: {{ formState.err }} </bootstrap-toast> <bootstrap-modal :modalId="modalId" diff --git a/src/components/object-storage/modals/UploadObjectModal.vue b/src/components/object-storage/modals/UploadObjectModal.vue index eca85fd..c239510 100644 --- a/src/components/object-storage/modals/UploadObjectModal.vue +++ b/src/components/object-storage/modals/UploadObjectModal.vue @@ -5,6 +5,7 @@ import { Modal, Toast } from "bootstrap"; import { partial } from "filesize"; import { useS3ObjectStore } from "@/stores/s3objects"; import BootstrapToast from "@/components/BootstrapToast.vue"; +import type { AbortController } from "@smithy/types"; const fsize = partial({ base: 2, standard: "jedec" }); const objectRepository = useS3ObjectStore(); @@ -31,18 +32,22 @@ watch( }, ); -const formState = reactive({ - file: {}, - key: "", - uploading: false, - uploadDone: 0, - uploadTotal: 1, -} as { - file: File; +const formState = reactive<{ + file?: File; key: string; uploading: boolean; uploadDone: number; uploadTotal: number; + err: string; + abortController?: AbortController; +}>({ + file: undefined, + key: "", + uploading: false, + uploadDone: 0, + uploadTotal: 1, + err: "", + abortController: undefined, }); const uploadProgress = computed<number>(() => @@ -54,19 +59,32 @@ const editObject = computed<boolean>( ); function uploadObject() { + if (formState.file == undefined) { + return; + } const key = props.keyPrefix.length > 0 ? props.keyPrefix + "/" + formState.key : formState.key; formState.uploadDone = 0; formState.uploading = true; + formState.abortController = new AbortController(); + formState.uploadTotal = formState.file.size; objectRepository - .uploadObjectFile(props.bucketName, key, formState.file, (progress) => { - if (progress.loaded != null && progress.total != null) { - formState.uploadDone = progress.loaded; - formState.uploadTotal = progress.total; - } - }) + .uploadObjectFile( + props.bucketName, + key, + formState.file, + (progress) => { + if (progress.loaded != null) { + formState.uploadDone = progress.loaded; + } + if (progress.total != null) { + formState.uploadTotal = progress.total; + } + }, + formState.abortController, + ) .then(() => { uploadModal?.hide(); successToast?.show(); @@ -76,11 +94,12 @@ function uploadObject() { } }) .catch((e) => { - console.error(e); + formState.err = e.name; errorToast?.show(); }) .finally(() => { formState.uploading = false; + formState.abortController = undefined; }); } @@ -110,7 +129,7 @@ onMounted(() => { color-class="danger" > There has been some Error.<br /> - Try again later + Code: {{ formState.err }} </bootstrap-toast> <bootstrap-modal :modal-id="modalId" @@ -135,6 +154,7 @@ onMounted(() => { </template> <template #body> <div class="container-fluid"> + <p>{{ formState.err }}</p> <div class="row"> <form class="col-7" @@ -207,7 +227,7 @@ onMounted(() => { {{ uploadProgress }}% </div> </div> - <span v-if="formState.uploadDone > 0"> + <span> {{ fsize(formState.uploadDone) }} / {{ fsize(formState.uploadTotal) }} </span> @@ -216,17 +236,19 @@ onMounted(() => { Close </button> <button - :disabled="formState.uploading" + v-if="formState.uploading" + type="button" + class="btn btn-danger" + @click="formState.abortController?.abort()" + > + Cancel + </button> + <button + v-else type="submit" :form="'uploadObjectForm' + randomIDSuffix" class="btn btn-primary" > - <span - v-if="formState.uploading" - class="spinner-border spinner-border-sm" - role="status" - aria-hidden="true" - ></span> Upload </button> </template> diff --git a/src/stores/buckets.ts b/src/stores/buckets.ts index 6c13662..d450eea 100644 --- a/src/stores/buckets.ts +++ b/src/stores/buckets.ts @@ -2,7 +2,6 @@ import { defineStore } from "pinia"; import { BucketPermissionService, BucketService, - Constraint, Permission, } from "@/client/s3proxy"; import type { @@ -30,12 +29,6 @@ export const useBucketStore = defineStore({ buckets(): BucketOut[] { const tempList = Object.values(this.bucketMapping); tempList.sort((bucketA, bucketB) => { - if (bucketA.owner_constraint) { - return -1; - } - if (bucketB.owner_constraint) { - return 1; - } return bucketA.name > bucketB.name ? 1 : -1; }); return tempList; @@ -67,7 +60,7 @@ export const useBucketStore = defineStore({ return false; } // If there is a constraint on the bucket, then false otherwise true - return this.bucketMapping[bucketName].owner_constraint == null; + return true; }; }, writableBuckets(): BucketOut[] { @@ -75,11 +68,7 @@ export const useBucketStore = defineStore({ if (this.ownPermissions[bucket.name] != undefined) { return this.ownPermissions[bucket.name].permission !== "READ"; } - // If the user owns the bucket, check the bucket constraint - return ( - bucket.owner_constraint == null || - bucket.owner_constraint == Constraint.WRITE - ); + return true; }); }, writableBucket(): (bucketName: string) => boolean { @@ -90,10 +79,7 @@ export const useBucketStore = defineStore({ } // If the user owns the bucket, check the bucket constraint if (this.bucketMapping[bucketName] != undefined) { - return ( - this.bucketMapping[bucketName].owner_constraint == null || - this.bucketMapping[bucketName].owner_constraint == Constraint.WRITE - ); + return true; } return false; }; @@ -106,10 +92,7 @@ export const useBucketStore = defineStore({ } // If the user owns the bucket, check the bucket constraint if (this.bucketMapping[bucketName] != null) { - return ( - this.bucketMapping[bucketName].owner_constraint == null || - this.bucketMapping[bucketName].owner_constraint == Constraint.READ - ); + return true; } return false; }; diff --git a/src/stores/s3objects.ts b/src/stores/s3objects.ts index e314ae5..149a3eb 100644 --- a/src/stores/s3objects.ts +++ b/src/stores/s3objects.ts @@ -19,6 +19,7 @@ import { getSignedUrl } from "@aws-sdk/s3-request-presigner"; import dayjs from "dayjs"; import { Upload } from "@aws-sdk/lib-storage"; import type { Progress } from "@aws-sdk/lib-storage"; +import type { AbortController } from "@smithy/types"; export const useS3ObjectStore = defineStore({ id: "s3objects", @@ -192,6 +193,7 @@ export const useS3ObjectStore = defineStore({ srcObject: S3Object, destBucket: string, destKey: string, + abortController?: AbortController, ): Promise<S3Object> { if (srcObject.Key == undefined) { return Promise.resolve({}); @@ -201,21 +203,24 @@ export const useS3ObjectStore = defineStore({ CopySource: encodeURI(`/${srcBucket}/${srcObject.Key}`), Key: destKey, }); - return this.client.send(command).then(() => { - const newObj = { - Key: destKey, - Size: srcObject.Size, - LastModified: dayjs().toDate(), - }; - this._pushObject(destBucket, newObj); - return newObj; - }); + return this.client + .send(command, { abortSignal: abortController?.signal }) + .then(() => { + const newObj = { + Key: destKey, + Size: srcObject.Size, + LastModified: dayjs().toDate(), + }; + this._pushObject(destBucket, newObj); + return newObj; + }); }, async uploadObjectFile( bucketName: string, key: string, file: File, onProgress?: (progress: Progress) => void, + abortController?: AbortController, ): Promise<S3Object> { const parallelUploads3 = new Upload({ client: this.client, @@ -227,6 +232,7 @@ export const useS3ObjectStore = defineStore({ }, queueSize: 4, // optional concurrency configuration leavePartsOnError: false, // optional manually handle dropped parts + abortController: abortController, }); if (onProgress != undefined) { parallelUploads3.on("httpUploadProgress", onProgress); diff --git a/src/views/object-storage/BucketsView.vue b/src/views/object-storage/BucketsView.vue index fc18443..a9cb8d4 100644 --- a/src/views/object-storage/BucketsView.vue +++ b/src/views/object-storage/BucketsView.vue @@ -176,7 +176,6 @@ onMounted(() => { created_at: 0, owner_id: '', public: false, - owner_constraint: null, }" ></bucket-list-item> </div> -- GitLab