Repository: CSCfi/swift-browser-ui

Issue:
Deleting the last bucket does not refresh the browser view
#### Describe the bug
If you delete the last bucket in the project a notification is shown that the bucket is deleted, but the view does not get updated and the bucket is still visible and you can still open the bucket.

#### To Reproduce
Steps to reproduce the behaviour:
1. Select a project with one bucket (or one without any and create a new bucket).
2. Select the bucket and click "Delete".
3. A notification pops up saying bucket was deleted.
4. The bucket is still visible the browser and is still accessible, you can click "Delete" again and you can even open the bucket.

#### Expected behavior
Along with the notification in step 3 above, the browser view should be refreshed so that the bucket disappears.

#### Screenshots
![image](https://user-images.githubusercontent.com/10267750/137113134-65433be8-0810-4da0-be9f-1752998a71c1.png)


#### Additional context
Tested with latest Firefox (93.0 for macOS).

Discussion:

Patch:
diff --git a/swift_browser_ui/ui/api.py b/swift_browser_ui/ui/api.py
index 9fa283b5..0da1405b 100644
--- a/swift_browser_ui/ui/api.py
+++ b/swift_browser_ui/ui/api.py
@@ -67,11 +67,6 @@ async def swift_list_buckets(request: aiohttp.web.Request) -> aiohttp.web.Respon
         # response at once
         serv = request.app["Sessions"][session]["ST_conn"].list()
         [_unpack(i, cont, request) for i in serv]
-        # for a bucket with no objects
-        if not cont:
-            # return empty object
-            request.app["Log"].debug("Empty container list.")
-            raise aiohttp.web.HTTPNotFound()
         return aiohttp.web.json_response(cont)
     except SwiftError:
         request.app["Log"].error("SwiftError occured return empty container list.")
diff --git a/swift_browser_ui_frontend/src/components/Breadcrumb.vue b/swift_browser_ui_frontend/src/components/Breadcrumb.vue
new file mode 100644
index 00000000..457defe0
--- /dev/null
+++ b/swift_browser_ui_frontend/src/components/Breadcrumb.vue
@@ -0,0 +1,22 @@
+<template>
+  <li class="breadcrumb-element">
+    <router-link
+      class="breadcrumb-link"
+      :to="address"
+    >
+      {{ alias | truncate(100) }}
+    </router-link>
+  </li>
+</template>
+
+<script>
+export default {
+  name: "BreadcrumbListElement",
+  filters: {
+    truncate(value, length) {
+      return value.length > length ? value.substr(0, length) + "..." : value;
+    },
+  },
+  props: ["address", "alias"],
+};
+</script>
diff --git a/swift_browser_ui_frontend/src/entries/main.js b/swift_browser_ui_frontend/src/entries/main.js
index 64e708db..9e8579e8 100644
--- a/swift_browser_ui_frontend/src/entries/main.js
+++ b/swift_browser_ui_frontend/src/entries/main.js
@@ -7,6 +7,7 @@ import VueI18n from "vue-i18n";
 
 // Project Vue components
 import BrowserNavbar from "@/components/BrowserNavbar.vue";
+import BreadcrumbListElement from "@/components/Breadcrumb.vue";
 
 // Project JS functions
 import getLangCookie from "@/common/conv";
@@ -48,6 +49,7 @@ new Vue({
   store,
   components: {
     BrowserNavbar,
+    BreadcrumbListElement,
     ProgressBar,
   },
   computed: {
diff --git a/swift_browser_ui_frontend/src/pages/BrowserPage.vue b/swift_browser_ui_frontend/src/pages/BrowserPage.vue
index 70f25229..e2e82dc7 100644
--- a/swift_browser_ui_frontend/src/pages/BrowserPage.vue
+++ b/swift_browser_ui_frontend/src/pages/BrowserPage.vue
@@ -6,18 +6,22 @@
       :projects="projects"
     />
     <ProgressBar v-if="isUploading || isChunking" />
-    <b-breadcrumb
-      style="margin-left:5%;margin-top:1%;font-size:1rem;"
+    <div
+      class="breadcrumb"
+      aria-label="breadcrumbs"
     >
-      <b-breadcrumb-item
-        v-for="item in getRouteAsList ()"
-        :key="item.alias"
-        :to="item.address"
-        tag="router-link"
+      <ul
+        id="breadcrumb-list"
+        style="margin-left:5%;margin-top:1%;"
       >
-        {{ item.alias | truncate(100) }}
-      </b-breadcrumb-item>
-    </b-breadcrumb>
+        <BreadcrumbListElement
+          v-for="item in getRouteAsList ()"
+          :key="item.alias"
+          :alias="item.alias"
+          :address="item.address"
+        />
+      </ul>
+    </div>
     <router-view />
     <b-loading
       :is-full-page="isFullPage"
@@ -43,17 +47,6 @@
   </div>
 </template>
 
-<script>
-export default {
-  name: "BrowserPage",
-  filters: {
-    truncate(value, length) {
-      return value.length > length ? value.substr(0, length) + "..." : value;
-    },
-  },
-};
-</script>
-
 <style>
 html, body {
   height: 100%;


Test patch:
diff --git a/tests/ui_unit/test_api.py b/tests/ui_unit/test_api.py
index 5348e7d0..f116ab0f 100644
--- a/tests/ui_unit/test_api.py
+++ b/tests/ui_unit/test_api.py
@@ -107,10 +107,11 @@ class APITestClass(asynctest.TestCase):
         )
 
     async def test_list_without_containers(self):
-        """Test function list buckets on a project without object storage."""
+        """Test function list buckets on a project without containers."""
         self.request.app["Sessions"][self.cookie]["ST_conn"].init_with_data(containers=0)
-        with self.assertRaises(HTTPNotFound):
-            _ = await swift_list_buckets(self.request)
+        response = await swift_list_buckets(self.request)
+        objects = json.loads(response.text)
+        self.assertEqual(objects, [])
 
     async def test_list_with_invalid_container(self):
         """Test function list objects with an invalid container id."""