From d4db4ede7a6f3603c076ff51703736c56e364538 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Daniel=20G=C3=B6bel?= <dgoebel@techfak.uni-bielefeld.de>
Date: Tue, 19 Jul 2022 12:17:49 +0200
Subject: [PATCH] Reorganize folder structure and add basic layout

---
 .dockerignore                                 |   1 +
 ProxyAPI-UI/.eslintrc.cjs => .eslintrc.cjs    |   0
 Dockerfile                                    |   4 +-
 ProxyAPI-UI/index.html                        |  13 --
 ProxyAPI-UI/public/favicon.ico                | Bin 4286 -> 0 bytes
 ProxyAPI-UI/src/App.vue                       |  91 ----------
 ProxyAPI-UI/src/components/HelloWorld.vue     |  40 -----
 ProxyAPI-UI/src/components/TheWelcome.vue     |  91 ----------
 ProxyAPI-UI/src/components/WelcomeItem.vue    |  86 ----------
 .../src/components/icons/IconCommunity.vue    |  12 --
 .../components/icons/IconDocumentation.vue    |  12 --
 .../src/components/icons/IconEcosystem.vue    |  12 --
 .../src/components/icons/IconSupport.vue      |  12 --
 .../src/components/icons/IconTooling.vue      |  19 ---
 ProxyAPI-UI/env.d.ts => env.d.ts              |   0
 index.html                                    |  16 ++
 package-lock.json                             | 156 +++++++++---------
 package.json                                  |   3 +-
 public/favicon.ico                            | Bin 0 -> 4286 bytes
 src/App.vue                                   |  16 ++
 {ProxyAPI-UI/src => src}/assets/base.css      |   0
 {ProxyAPI-UI/src => src}/assets/logo.svg      |   0
 {ProxyAPI-UI/src => src}/assets/main.css      |   0
 src/components/BootstrapIcon.vue              |  15 ++
 src/components/NavbarTop.vue                  |  40 +++++
 src/components/SidebarLeft.vue                |  41 +++++
 {ProxyAPI-UI/src => src}/main.ts              |   0
 {ProxyAPI-UI/src => src}/router/index.ts      |  16 +-
 {ProxyAPI-UI/src => src}/stores/counter.ts    |   0
 .../HomeView.vue => src/views/BucketsView.vue |   3 +-
 .../AboutView.vue => src/views/S3KeysView.vue |   3 +-
 ...config.config.json => tsconfig.config.json |   0
 ProxyAPI-UI/tsconfig.json => tsconfig.json    |   0
 ProxyAPI-UI/vite.config.ts => vite.config.ts  |   0
 34 files changed, 223 insertions(+), 479 deletions(-)
 rename ProxyAPI-UI/.eslintrc.cjs => .eslintrc.cjs (100%)
 delete mode 100644 ProxyAPI-UI/index.html
 delete mode 100644 ProxyAPI-UI/public/favicon.ico
 delete mode 100644 ProxyAPI-UI/src/App.vue
 delete mode 100644 ProxyAPI-UI/src/components/HelloWorld.vue
 delete mode 100644 ProxyAPI-UI/src/components/TheWelcome.vue
 delete mode 100644 ProxyAPI-UI/src/components/WelcomeItem.vue
 delete mode 100644 ProxyAPI-UI/src/components/icons/IconCommunity.vue
 delete mode 100644 ProxyAPI-UI/src/components/icons/IconDocumentation.vue
 delete mode 100644 ProxyAPI-UI/src/components/icons/IconEcosystem.vue
 delete mode 100644 ProxyAPI-UI/src/components/icons/IconSupport.vue
 delete mode 100644 ProxyAPI-UI/src/components/icons/IconTooling.vue
 rename ProxyAPI-UI/env.d.ts => env.d.ts (100%)
 create mode 100644 index.html
 create mode 100644 public/favicon.ico
 create mode 100644 src/App.vue
 rename {ProxyAPI-UI/src => src}/assets/base.css (100%)
 rename {ProxyAPI-UI/src => src}/assets/logo.svg (100%)
 rename {ProxyAPI-UI/src => src}/assets/main.css (100%)
 create mode 100644 src/components/BootstrapIcon.vue
 create mode 100644 src/components/NavbarTop.vue
 create mode 100644 src/components/SidebarLeft.vue
 rename {ProxyAPI-UI/src => src}/main.ts (100%)
 rename {ProxyAPI-UI/src => src}/router/index.ts (59%)
 rename {ProxyAPI-UI/src => src}/stores/counter.ts (100%)
 rename ProxyAPI-UI/src/views/HomeView.vue => src/views/BucketsView.vue (86%)
 rename ProxyAPI-UI/src/views/AboutView.vue => src/views/S3KeysView.vue (73%)
 rename ProxyAPI-UI/tsconfig.config.json => tsconfig.config.json (100%)
 rename ProxyAPI-UI/tsconfig.json => tsconfig.json (100%)
 rename ProxyAPI-UI/vite.config.ts => vite.config.ts (100%)

diff --git a/.dockerignore b/.dockerignore
index 651665b..762eda3 100644
--- a/.dockerignore
+++ b/.dockerignore
@@ -1,2 +1,3 @@
 node_modules
 .git
+dist
diff --git a/ProxyAPI-UI/.eslintrc.cjs b/.eslintrc.cjs
similarity index 100%
rename from ProxyAPI-UI/.eslintrc.cjs
rename to .eslintrc.cjs
diff --git a/Dockerfile b/Dockerfile
index 986fbb8..d298d74 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -5,8 +5,8 @@ WORKDIR /app
 COPY package.json ./
 COPY package-lock.json ./
 RUN npm install
-COPY ProxyAPI-UI .
-RUN npm run build
+COPY . .
+RUN npm run build-only
 
 # production stage
 FROM nginx:stable-alpine as production-stage
diff --git a/ProxyAPI-UI/index.html b/ProxyAPI-UI/index.html
deleted file mode 100644
index 11603f8..0000000
--- a/ProxyAPI-UI/index.html
+++ /dev/null
@@ -1,13 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-  <head>
-    <meta charset="UTF-8" />
-    <link rel="icon" href="/favicon.ico" />
-    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
-    <title>Vite App</title>
-  </head>
-  <body>
-    <div id="app"></div>
-    <script type="module" src="/src/main.ts"></script>
-  </body>
-</html>
diff --git a/ProxyAPI-UI/public/favicon.ico b/ProxyAPI-UI/public/favicon.ico
deleted file mode 100644
index df36fcfb72584e00488330b560ebcf34a41c64c2..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 4286
zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj
zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56
zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy
zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei
z@g6Xq-pDoPl=MANPiR7%172VA%r)kev<ISBgE$F{SFy+(=9Z)f)De0Se}ZDZW}Z3B
zElCeVrw;K0Fdl_Cg=gZOFXXc3pL)Q05CAuT+XucQ<8g~3dteP~|7s7c6QYP;fy;mF
zMN;>tV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX
zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm
zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp=
zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8
zx!=3<4seY*%=OlbCbcae?<QnEgvj4i?s}Yk=qA2z`-^*<eK3c)MS4JOdbsTQEOa0)
z0NWqlna2rzs>5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO
z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3
z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD
zsW0Ab)ZK@0cIW%W7<X*Er!BfRbvU93$DH%#v6dRt^6HBxz1xBNHx=$&_Gv<&J}Ljk
zJN<Fzx(`Oe@KgQ0F$<14=XV#WK`o#6Ku>z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6
z={Xwx{T<?%b6i9IjI)Ls)S{-*mq<@~R{?$}ZKjf;^k75i_}(2MXt}^SEBVg7AI@28
zo_uPg2V)_e-`2Ois=PYoe%9u*n9({PFR)OnHJPi{dNx>Kx<YG`4QQ>D#iCLfl2<BD
h7L=-;Q>vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S

diff --git a/ProxyAPI-UI/src/App.vue b/ProxyAPI-UI/src/App.vue
deleted file mode 100644
index 540829f..0000000
--- a/ProxyAPI-UI/src/App.vue
+++ /dev/null
@@ -1,91 +0,0 @@
-<script setup lang="ts">
-import { RouterLink, RouterView } from "vue-router";
-import HelloWorld from "./components/HelloWorld.vue";
-</script>
-
-<template>
-  <header>
-    <img
-      alt="Vue logo"
-      class="logo"
-      src="@/assets/logo.svg"
-      width="125"
-      height="125"
-    />
-
-    <div class="wrapper">
-      <HelloWorld msg="You did it!" />
-
-      <nav>
-        <RouterLink to="/">Home</RouterLink>
-        <RouterLink to="/about">About</RouterLink>
-      </nav>
-    </div>
-  </header>
-
-  <RouterView />
-</template>
-
-<style scoped>
-header {
-  line-height: 1.5;
-  max-height: 100vh;
-}
-
-.logo {
-  display: block;
-  margin: 0 auto 2rem;
-}
-
-nav {
-  width: 100%;
-  font-size: 12px;
-  text-align: center;
-  margin-top: 2rem;
-}
-
-nav a.router-link-exact-active {
-  color: var(--color-text);
-}
-
-nav a.router-link-exact-active:hover {
-  background-color: transparent;
-}
-
-nav a {
-  display: inline-block;
-  padding: 0 1rem;
-  border-left: 1px solid var(--color-border);
-}
-
-nav a:first-of-type {
-  border: 0;
-}
-
-@media (min-width: 1024px) {
-  header {
-    display: flex;
-    place-items: center;
-    padding-right: calc(var(--section-gap) / 2);
-  }
-
-  .logo {
-    margin: 0 2rem 0 0;
-  }
-
-  header .wrapper {
-    display: flex;
-    place-items: flex-start;
-    flex-wrap: wrap;
-  }
-
-  nav {
-    text-align: left;
-    margin-left: -1rem;
-    font-size: 1rem;
-
-    padding: 1rem 0;
-    margin-top: 1rem;
-  }
-}
-</style>
diff --git a/ProxyAPI-UI/src/components/HelloWorld.vue b/ProxyAPI-UI/src/components/HelloWorld.vue
deleted file mode 100644
index e67e9e6..0000000
--- a/ProxyAPI-UI/src/components/HelloWorld.vue
+++ /dev/null
@@ -1,40 +0,0 @@
-<script setup lang="ts">
-defineProps<{
-  msg: string;
-}>();
-</script>
-
-<template>
-  <div class="greetings">
-    <h1 class="green">{{ msg }}</h1>
-    <h3>
-      You’ve successfully created a project with
-      <a target="_blank" href="https://vitejs.dev/">Vite</a> +
-      <a target="_blank" href="https://vuejs.org/">Vue 3</a>. What's next?
-    </h3>
-  </div>
-</template>
-
-<style scoped>
-h1 {
-  font-weight: 500;
-  font-size: 2.6rem;
-  top: -10px;
-}
-
-h3 {
-  font-size: 1.2rem;
-}
-
-.greetings h1,
-.greetings h3 {
-  text-align: center;
-}
-
-@media (min-width: 1024px) {
-  .greetings h1,
-  .greetings h3 {
-    text-align: left;
-  }
-}
-</style>
diff --git a/ProxyAPI-UI/src/components/TheWelcome.vue b/ProxyAPI-UI/src/components/TheWelcome.vue
deleted file mode 100644
index 35c3b0f..0000000
--- a/ProxyAPI-UI/src/components/TheWelcome.vue
+++ /dev/null
@@ -1,91 +0,0 @@
-<script setup lang="ts">
-import WelcomeItem from "./WelcomeItem.vue";
-import DocumentationIcon from "./icons/IconDocumentation.vue";
-import ToolingIcon from "./icons/IconTooling.vue";
-import EcosystemIcon from "./icons/IconEcosystem.vue";
-import CommunityIcon from "./icons/IconCommunity.vue";
-import SupportIcon from "./icons/IconSupport.vue";
-</script>
-
-<template>
-  <WelcomeItem>
-    <template #icon>
-      <DocumentationIcon />
-    </template>
-    <template #heading>Documentation</template>
-
-    Vue’s
-    <a target="_blank" href="https://vuejs.org/">official documentation</a>
-    provides you with all information you need to get started.
-  </WelcomeItem>
-
-  <WelcomeItem>
-    <template #icon>
-      <ToolingIcon />
-    </template>
-    <template #heading>Tooling</template>
-
-    This project is served and bundled with
-    <a href="https://vitejs.dev/guide/features.html" target="_blank">Vite</a>.
-    The recommended IDE setup is
-    <a href="https://code.visualstudio.com/" target="_blank">VSCode</a> +
-    <a href="https://github.com/johnsoncodehk/volar" target="_blank">Volar</a>.
-    If you need to test your components and web pages, check out
-    <a href="https://www.cypress.io/" target="_blank">Cypress</a> and
-    <a href="https://on.cypress.io/component" target="_blank"
-      >Cypress Component Testing</a
-    >.
-
-    <br />
-
-    More instructions are available in <code>README.md</code>.
-  </WelcomeItem>
-
-  <WelcomeItem>
-    <template #icon>
-      <EcosystemIcon />
-    </template>
-    <template #heading>Ecosystem</template>
-
-    Get official tools and libraries for your project:
-    <a target="_blank" href="https://pinia.vuejs.org/">Pinia</a>,
-    <a target="_blank" href="https://router.vuejs.org/">Vue Router</a>,
-    <a target="_blank" href="https://test-utils.vuejs.org/">Vue Test Utils</a>,
-    and
-    <a target="_blank" href="https://github.com/vuejs/devtools">Vue Dev Tools</a
-    >. If you need more resources, we suggest paying
-    <a target="_blank" href="https://github.com/vuejs/awesome-vue"
-      >Awesome Vue</a
-    >
-    a visit.
-  </WelcomeItem>
-
-  <WelcomeItem>
-    <template #icon>
-      <CommunityIcon />
-    </template>
-    <template #heading>Community</template>
-
-    Got stuck? Ask your question on
-    <a target="_blank" href="https://chat.vuejs.org">Vue Land</a>, our official
-    Discord server, or
-    <a target="_blank" href="https://stackoverflow.com/questions/tagged/vue.js"
-      >StackOverflow</a
-    >. You should also subscribe to
-    <a target="_blank" href="https://news.vuejs.org">our mailing list</a> and
-    follow the official
-    <a target="_blank" href="https://twitter.com/vuejs">@vuejs</a>
-    twitter account for latest news in the Vue world.
-  </WelcomeItem>
-
-  <WelcomeItem>
-    <template #icon>
-      <SupportIcon />
-    </template>
-    <template #heading>Support Vue</template>
-
-    As an independent project, Vue relies on community backing for its
-    sustainability. You can help us by
-    <a target="_blank" href="https://vuejs.org/sponsor/">becoming a sponsor</a>.
-  </WelcomeItem>
-</template>
diff --git a/ProxyAPI-UI/src/components/WelcomeItem.vue b/ProxyAPI-UI/src/components/WelcomeItem.vue
deleted file mode 100644
index 6cff194..0000000
--- a/ProxyAPI-UI/src/components/WelcomeItem.vue
+++ /dev/null
@@ -1,86 +0,0 @@
-<template>
-  <div class="item">
-    <i>
-      <slot name="icon"></slot>
-    </i>
-    <div class="details">
-      <h3>
-        <slot name="heading"></slot>
-      </h3>
-      <slot></slot>
-    </div>
-  </div>
-</template>
-
-<style scoped>
-.item {
-  margin-top: 2rem;
-  display: flex;
-}
-
-.details {
-  flex: 1;
-  margin-left: 1rem;
-}
-
-i {
-  display: flex;
-  place-items: center;
-  place-content: center;
-  width: 32px;
-  height: 32px;
-
-  color: var(--color-text);
-}
-
-h3 {
-  font-size: 1.2rem;
-  font-weight: 500;
-  margin-bottom: 0.4rem;
-  color: var(--color-heading);
-}
-
-@media (min-width: 1024px) {
-  .item {
-    margin-top: 0;
-    padding: 0.4rem 0 1rem calc(var(--section-gap) / 2);
-  }
-
-  i {
-    top: calc(50% - 25px);
-    left: -26px;
-    position: absolute;
-    border: 1px solid var(--color-border);
-    background: var(--color-background);
-    border-radius: 8px;
-    width: 50px;
-    height: 50px;
-  }
-
-  .item:before {
-    content: " ";
-    border-left: 1px solid var(--color-border);
-    position: absolute;
-    left: 0;
-    bottom: calc(50% + 25px);
-    height: calc(50% - 25px);
-  }
-
-  .item:after {
-    content: " ";
-    border-left: 1px solid var(--color-border);
-    position: absolute;
-    left: 0;
-    top: calc(50% + 25px);
-    height: calc(50% - 25px);
-  }
-
-  .item:first-of-type:before {
-    display: none;
-  }
-
-  .item:last-of-type:after {
-    display: none;
-  }
-}
-</style>
diff --git a/ProxyAPI-UI/src/components/icons/IconCommunity.vue b/ProxyAPI-UI/src/components/icons/IconCommunity.vue
deleted file mode 100644
index ea8ddef..0000000
--- a/ProxyAPI-UI/src/components/icons/IconCommunity.vue
+++ /dev/null
@@ -1,12 +0,0 @@
-<template>
-  <svg
-    xmlns="http://www.w3.org/2000/svg"
-    width="20"
-    height="20"
-    fill="currentColor"
-  >
-    <path
-      d="M15 4a1 1 0 1 0 0 2V4zm0 11v-1a1 1 0 0 0-1 1h1zm0 4l-.707.707A1 1 0 0 0 16 19h-1zm-4-4l.707-.707A1 1 0 0 0 11 14v1zm-4.707-1.293a1 1 0 0 0-1.414 1.414l1.414-1.414zm-.707.707l-.707-.707.707.707zM9 11v-1a1 1 0 0 0-.707.293L9 11zm-4 0h1a1 1 0 0 0-1-1v1zm0 4H4a1 1 0 0 0 1.707.707L5 15zm10-9h2V4h-2v2zm2 0a1 1 0 0 1 1 1h2a3 3 0 0 0-3-3v2zm1 1v6h2V7h-2zm0 6a1 1 0 0 1-1 1v2a3 3 0 0 0 3-3h-2zm-1 1h-2v2h2v-2zm-3 1v4h2v-4h-2zm1.707 3.293l-4-4-1.414 1.414 4 4 1.414-1.414zM11 14H7v2h4v-2zm-4 0c-.276 0-.525-.111-.707-.293l-1.414 1.414C5.42 15.663 6.172 16 7 16v-2zm-.707 1.121l3.414-3.414-1.414-1.414-3.414 3.414 1.414 1.414zM9 12h4v-2H9v2zm4 0a3 3 0 0 0 3-3h-2a1 1 0 0 1-1 1v2zm3-3V3h-2v6h2zm0-6a3 3 0 0 0-3-3v2a1 1 0 0 1 1 1h2zm-3-3H3v2h10V0zM3 0a3 3 0 0 0-3 3h2a1 1 0 0 1 1-1V0zM0 3v6h2V3H0zm0 6a3 3 0 0 0 3 3v-2a1 1 0 0 1-1-1H0zm3 3h2v-2H3v2zm1-1v4h2v-4H4zm1.707 4.707l.586-.586-1.414-1.414-.586.586 1.414 1.414z"
-    />
-  </svg>
-</template>
diff --git a/ProxyAPI-UI/src/components/icons/IconDocumentation.vue b/ProxyAPI-UI/src/components/icons/IconDocumentation.vue
deleted file mode 100644
index 63a8534..0000000
--- a/ProxyAPI-UI/src/components/icons/IconDocumentation.vue
+++ /dev/null
@@ -1,12 +0,0 @@
-<template>
-  <svg
-    xmlns="http://www.w3.org/2000/svg"
-    width="20"
-    height="17"
-    fill="currentColor"
-  >
-    <path
-      d="M11 2.253a1 1 0 1 0-2 0h2zm-2 13a1 1 0 1 0 2 0H9zm.447-12.167a1 1 0 1 0 1.107-1.666L9.447 3.086zM1 2.253L.447 1.42A1 1 0 0 0 0 2.253h1zm0 13H0a1 1 0 0 0 1.553.833L1 15.253zm8.447.833a1 1 0 1 0 1.107-1.666l-1.107 1.666zm0-14.666a1 1 0 1 0 1.107 1.666L9.447 1.42zM19 2.253h1a1 1 0 0 0-.447-.833L19 2.253zm0 13l-.553.833A1 1 0 0 0 20 15.253h-1zm-9.553-.833a1 1 0 1 0 1.107 1.666L9.447 14.42zM9 2.253v13h2v-13H9zm1.553-.833C9.203.523 7.42 0 5.5 0v2c1.572 0 2.961.431 3.947 1.086l1.107-1.666zM5.5 0C3.58 0 1.797.523.447 1.42l1.107 1.666C2.539 2.431 3.928 2 5.5 2V0zM0 2.253v13h2v-13H0zm1.553 13.833C2.539 15.431 3.928 15 5.5 15v-2c-1.92 0-3.703.523-5.053 1.42l1.107 1.666zM5.5 15c1.572 0 2.961.431 3.947 1.086l1.107-1.666C9.203 13.523 7.42 13 5.5 13v2zm5.053-11.914C11.539 2.431 12.928 2 14.5 2V0c-1.92 0-3.703.523-5.053 1.42l1.107 1.666zM14.5 2c1.573 0 2.961.431 3.947 1.086l1.107-1.666C18.203.523 16.421 0 14.5 0v2zm3.5.253v13h2v-13h-2zm1.553 12.167C18.203 13.523 16.421 13 14.5 13v2c1.573 0 2.961.431 3.947 1.086l1.107-1.666zM14.5 13c-1.92 0-3.703.523-5.053 1.42l1.107 1.666C11.539 15.431 12.928 15 14.5 15v-2z"
-    />
-  </svg>
-</template>
diff --git a/ProxyAPI-UI/src/components/icons/IconEcosystem.vue b/ProxyAPI-UI/src/components/icons/IconEcosystem.vue
deleted file mode 100644
index 385a202..0000000
--- a/ProxyAPI-UI/src/components/icons/IconEcosystem.vue
+++ /dev/null
@@ -1,12 +0,0 @@
-<template>
-  <svg
-    xmlns="http://www.w3.org/2000/svg"
-    width="18"
-    height="20"
-    fill="currentColor"
-  >
-    <path
-      d="M11.447 8.894a1 1 0 1 0-.894-1.789l.894 1.789zm-2.894-.789a1 1 0 1 0 .894 1.789l-.894-1.789zm0 1.789a1 1 0 1 0 .894-1.789l-.894 1.789zM7.447 7.106a1 1 0 1 0-.894 1.789l.894-1.789zM10 9a1 1 0 1 0-2 0h2zm-2 2.5a1 1 0 1 0 2 0H8zm9.447-5.606a1 1 0 1 0-.894-1.789l.894 1.789zm-2.894-.789a1 1 0 1 0 .894 1.789l-.894-1.789zm2 .789a1 1 0 1 0 .894-1.789l-.894 1.789zm-1.106-2.789a1 1 0 1 0-.894 1.789l.894-1.789zM18 5a1 1 0 1 0-2 0h2zm-2 2.5a1 1 0 1 0 2 0h-2zm-5.447-4.606a1 1 0 1 0 .894-1.789l-.894 1.789zM9 1l.447-.894a1 1 0 0 0-.894 0L9 1zm-2.447.106a1 1 0 1 0 .894 1.789l-.894-1.789zm-6 3a1 1 0 1 0 .894 1.789L.553 4.106zm2.894.789a1 1 0 1 0-.894-1.789l.894 1.789zm-2-.789a1 1 0 1 0-.894 1.789l.894-1.789zm1.106 2.789a1 1 0 1 0 .894-1.789l-.894 1.789zM2 5a1 1 0 1 0-2 0h2zM0 7.5a1 1 0 1 0 2 0H0zm8.553 12.394a1 1 0 1 0 .894-1.789l-.894 1.789zm-1.106-2.789a1 1 0 1 0-.894 1.789l.894-1.789zm1.106 1a1 1 0 1 0 .894 1.789l-.894-1.789zm2.894.789a1 1 0 1 0-.894-1.789l.894 1.789zM8 19a1 1 0 1 0 2 0H8zm2-2.5a1 1 0 1 0-2 0h2zm-7.447.394a1 1 0 1 0 .894-1.789l-.894 1.789zM1 15H0a1 1 0 0 0 .553.894L1 15zm1-2.5a1 1 0 1 0-2 0h2zm12.553 2.606a1 1 0 1 0 .894 1.789l-.894-1.789zM17 15l.447.894A1 1 0 0 0 18 15h-1zm1-2.5a1 1 0 1 0-2 0h2zm-7.447-5.394l-2 1 .894 1.789 2-1-.894-1.789zm-1.106 1l-2-1-.894 1.789 2 1 .894-1.789zM8 9v2.5h2V9H8zm8.553-4.894l-2 1 .894 1.789 2-1-.894-1.789zm.894 0l-2-1-.894 1.789 2 1 .894-1.789zM16 5v2.5h2V5h-2zm-4.553-3.894l-2-1-.894 1.789 2 1 .894-1.789zm-2.894-1l-2 1 .894 1.789 2-1L8.553.106zM1.447 5.894l2-1-.894-1.789-2 1 .894 1.789zm-.894 0l2 1 .894-1.789-2-1-.894 1.789zM0 5v2.5h2V5H0zm9.447 13.106l-2-1-.894 1.789 2 1 .894-1.789zm0 1.789l2-1-.894-1.789-2 1 .894 1.789zM10 19v-2.5H8V19h2zm-6.553-3.894l-2-1-.894 1.789 2 1 .894-1.789zM2 15v-2.5H0V15h2zm13.447 1.894l2-1-.894-1.789-2 1 .894 1.789zM18 15v-2.5h-2V15h2z"
-    />
-  </svg>
-</template>
diff --git a/ProxyAPI-UI/src/components/icons/IconSupport.vue b/ProxyAPI-UI/src/components/icons/IconSupport.vue
deleted file mode 100644
index 7db961e..0000000
--- a/ProxyAPI-UI/src/components/icons/IconSupport.vue
+++ /dev/null
@@ -1,12 +0,0 @@
-<template>
-  <svg
-    xmlns="http://www.w3.org/2000/svg"
-    width="20"
-    height="20"
-    fill="currentColor"
-  >
-    <path
-      d="M10 3.22l-.61-.6a5.5 5.5 0 0 0-7.666.105 5.5 5.5 0 0 0-.114 7.665L10 18.78l8.39-8.4a5.5 5.5 0 0 0-.114-7.665 5.5 5.5 0 0 0-7.666-.105l-.61.61z"
-    />
-  </svg>
-</template>
diff --git a/ProxyAPI-UI/src/components/icons/IconTooling.vue b/ProxyAPI-UI/src/components/icons/IconTooling.vue
deleted file mode 100644
index 660598d..0000000
--- a/ProxyAPI-UI/src/components/icons/IconTooling.vue
+++ /dev/null
@@ -1,19 +0,0 @@
-<!-- This icon is from <https://github.com/Templarian/MaterialDesign>, distributed under Apache 2.0 (https://www.apache.org/licenses/LICENSE-2.0) license-->
-<template>
-  <svg
-    xmlns="http://www.w3.org/2000/svg"
-    xmlns:xlink="http://www.w3.org/1999/xlink"
-    aria-hidden="true"
-    role="img"
-    class="iconify iconify--mdi"
-    width="24"
-    height="24"
-    preserveAspectRatio="xMidYMid meet"
-    viewBox="0 0 24 24"
-  >
-    <path
-      d="M20 18v-4h-3v1h-2v-1H9v1H7v-1H4v4h16M6.33 8l-1.74 4H7v-1h2v1h6v-1h2v1h2.41l-1.74-4H6.33M9 5v1h6V5H9m12.84 7.61c.1.22.16.48.16.8V18c0 .53-.21 1-.6 1.41c-.4.4-.85.59-1.4.59H4c-.55 0-1-.19-1.4-.59C2.21 19 2 18.53 2 18v-4.59c0-.32.06-.58.16-.8L4.5 7.22C4.84 6.41 5.45 6 6.33 6H7V5c0-.55.18-1 .57-1.41C7.96 3.2 8.44 3 9 3h6c.56 0 1.04.2 1.43.59c.39.41.57.86.57 1.41v1h.67c.88 0 1.49.41 1.83 1.22l2.34 5.39z"
-      fill="currentColor"
-    ></path>
-  </svg>
-</template>
diff --git a/ProxyAPI-UI/env.d.ts b/env.d.ts
similarity index 100%
rename from ProxyAPI-UI/env.d.ts
rename to env.d.ts
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..6ff0a14
--- /dev/null
+++ b/index.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <meta charset="UTF-8" />
+    <link rel="icon" href="/favicon.ico" />
+    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
+    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.9.1/font/bootstrap-icons.css">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+    <title>S3 Proxy</title>
+  </head>
+  <body>
+    <div id="app"></div>
+    <script type="module" src="/src/main.ts"></script>
+    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous"></script>
+  </body>
+</html>
diff --git a/package-lock.json b/package-lock.json
index 9c6ebaf..ef9b13f 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1697,14 +1697,14 @@
       "dev": true
     },
     "node_modules/@typescript-eslint/eslint-plugin": {
-      "version": "5.30.6",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.30.6.tgz",
-      "integrity": "sha512-J4zYMIhgrx4MgnZrSDD7sEnQp7FmhKNOaqaOpaoQ/SfdMfRB/0yvK74hTnvH+VQxndZynqs5/Hn4t+2/j9bADg==",
+      "version": "5.30.7",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.30.7.tgz",
+      "integrity": "sha512-l4L6Do+tfeM2OK0GJsU7TUcM/1oN/N25xHm3Jb4z3OiDU4Lj8dIuxX9LpVMS9riSXQs42D1ieX7b85/r16H9Fw==",
       "dev": true,
       "dependencies": {
-        "@typescript-eslint/scope-manager": "5.30.6",
-        "@typescript-eslint/type-utils": "5.30.6",
-        "@typescript-eslint/utils": "5.30.6",
+        "@typescript-eslint/scope-manager": "5.30.7",
+        "@typescript-eslint/type-utils": "5.30.7",
+        "@typescript-eslint/utils": "5.30.7",
         "debug": "^4.3.4",
         "functional-red-black-tree": "^1.0.1",
         "ignore": "^5.2.0",
@@ -1730,14 +1730,14 @@
       }
     },
     "node_modules/@typescript-eslint/parser": {
-      "version": "5.30.6",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.30.6.tgz",
-      "integrity": "sha512-gfF9lZjT0p2ZSdxO70Xbw8w9sPPJGfAdjK7WikEjB3fcUI/yr9maUVEdqigBjKincUYNKOmf7QBMiTf719kbrA==",
+      "version": "5.30.7",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.30.7.tgz",
+      "integrity": "sha512-Rg5xwznHWWSy7v2o0cdho6n+xLhK2gntImp0rJroVVFkcYFYQ8C8UJTSuTw/3CnExBmPjycjmUJkxVmjXsld6A==",
       "dev": true,
       "dependencies": {
-        "@typescript-eslint/scope-manager": "5.30.6",
-        "@typescript-eslint/types": "5.30.6",
-        "@typescript-eslint/typescript-estree": "5.30.6",
+        "@typescript-eslint/scope-manager": "5.30.7",
+        "@typescript-eslint/types": "5.30.7",
+        "@typescript-eslint/typescript-estree": "5.30.7",
         "debug": "^4.3.4"
       },
       "engines": {
@@ -1757,13 +1757,13 @@
       }
     },
     "node_modules/@typescript-eslint/scope-manager": {
-      "version": "5.30.6",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.30.6.tgz",
-      "integrity": "sha512-Hkq5PhLgtVoW1obkqYH0i4iELctEKixkhWLPTYs55doGUKCASvkjOXOd/pisVeLdO24ZX9D6yymJ/twqpJiG3g==",
+      "version": "5.30.7",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.30.7.tgz",
+      "integrity": "sha512-7BM1bwvdF1UUvt+b9smhqdc/eniOnCKxQT/kj3oXtj3LqnTWCAM0qHRHfyzCzhEfWX0zrW7KqXXeE4DlchZBKw==",
       "dev": true,
       "dependencies": {
-        "@typescript-eslint/types": "5.30.6",
-        "@typescript-eslint/visitor-keys": "5.30.6"
+        "@typescript-eslint/types": "5.30.7",
+        "@typescript-eslint/visitor-keys": "5.30.7"
       },
       "engines": {
         "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
@@ -1774,12 +1774,12 @@
       }
     },
     "node_modules/@typescript-eslint/type-utils": {
-      "version": "5.30.6",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.30.6.tgz",
-      "integrity": "sha512-GFVVzs2j0QPpM+NTDMXtNmJKlF842lkZKDSanIxf+ArJsGeZUIaeT4jGg+gAgHt7AcQSFwW7htzF/rbAh2jaVA==",
+      "version": "5.30.7",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.30.7.tgz",
+      "integrity": "sha512-nD5qAE2aJX/YLyKMvOU5jvJyku4QN5XBVsoTynFrjQZaDgDV6i7QHFiYCx10wvn7hFvfuqIRNBtsgaLe0DbWhw==",
       "dev": true,
       "dependencies": {
-        "@typescript-eslint/utils": "5.30.6",
+        "@typescript-eslint/utils": "5.30.7",
         "debug": "^4.3.4",
         "tsutils": "^3.21.0"
       },
@@ -1800,9 +1800,9 @@
       }
     },
     "node_modules/@typescript-eslint/types": {
-      "version": "5.30.6",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.30.6.tgz",
-      "integrity": "sha512-HdnP8HioL1F7CwVmT4RaaMX57RrfqsOMclZc08wGMiDYJBsLGBM7JwXM4cZJmbWLzIR/pXg1kkrBBVpxTOwfUg==",
+      "version": "5.30.7",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.30.7.tgz",
+      "integrity": "sha512-ocVkETUs82+U+HowkovV6uxf1AnVRKCmDRNUBUUo46/5SQv1owC/EBFkiu4MOHeZqhKz2ktZ3kvJJ1uFqQ8QPg==",
       "dev": true,
       "engines": {
         "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
@@ -1813,13 +1813,13 @@
       }
     },
     "node_modules/@typescript-eslint/typescript-estree": {
-      "version": "5.30.6",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.30.6.tgz",
-      "integrity": "sha512-Z7TgPoeYUm06smfEfYF0RBkpF8csMyVnqQbLYiGgmUSTaSXTP57bt8f0UFXstbGxKIreTwQCujtaH0LY9w9B+A==",
+      "version": "5.30.7",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.30.7.tgz",
+      "integrity": "sha512-tNslqXI1ZdmXXrHER83TJ8OTYl4epUzJC0aj2i4DMDT4iU+UqLT3EJeGQvJ17BMbm31x5scSwo3hPM0nqQ1AEA==",
       "dev": true,
       "dependencies": {
-        "@typescript-eslint/types": "5.30.6",
-        "@typescript-eslint/visitor-keys": "5.30.6",
+        "@typescript-eslint/types": "5.30.7",
+        "@typescript-eslint/visitor-keys": "5.30.7",
         "debug": "^4.3.4",
         "globby": "^11.1.0",
         "is-glob": "^4.0.3",
@@ -1840,15 +1840,15 @@
       }
     },
     "node_modules/@typescript-eslint/utils": {
-      "version": "5.30.6",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.30.6.tgz",
-      "integrity": "sha512-xFBLc/esUbLOJLk9jKv0E9gD/OH966M40aY9jJ8GiqpSkP2xOV908cokJqqhVd85WoIvHVHYXxSFE4cCSDzVvA==",
+      "version": "5.30.7",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.30.7.tgz",
+      "integrity": "sha512-Z3pHdbFw+ftZiGUnm1GZhkJgVqsDL5CYW2yj+TB2mfXDFOMqtbzQi2dNJIyPqPbx9mv2kUxS1gU+r2gKlKi1rQ==",
       "dev": true,
       "dependencies": {
         "@types/json-schema": "^7.0.9",
-        "@typescript-eslint/scope-manager": "5.30.6",
-        "@typescript-eslint/types": "5.30.6",
-        "@typescript-eslint/typescript-estree": "5.30.6",
+        "@typescript-eslint/scope-manager": "5.30.7",
+        "@typescript-eslint/types": "5.30.7",
+        "@typescript-eslint/typescript-estree": "5.30.7",
         "eslint-scope": "^5.1.1",
         "eslint-utils": "^3.0.0"
       },
@@ -1864,12 +1864,12 @@
       }
     },
     "node_modules/@typescript-eslint/visitor-keys": {
-      "version": "5.30.6",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.30.6.tgz",
-      "integrity": "sha512-41OiCjdL2mCaSDi2SvYbzFLlqqlm5v1ZW9Ym55wXKL/Rx6OOB1IbuFGo71Fj6Xy90gJDFTlgOS+vbmtGHPTQQA==",
+      "version": "5.30.7",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.30.7.tgz",
+      "integrity": "sha512-KrRXf8nnjvcpxDFOKej4xkD7657+PClJs5cJVSG7NNoCNnjEdc46juNAQt7AyuWctuCgs6mVRc1xGctEqrjxWw==",
       "dev": true,
       "dependencies": {
-        "@typescript-eslint/types": "5.30.6",
+        "@typescript-eslint/types": "5.30.7",
         "eslint-visitor-keys": "^3.3.0"
       },
       "engines": {
@@ -6781,14 +6781,14 @@
       "dev": true
     },
     "@typescript-eslint/eslint-plugin": {
-      "version": "5.30.6",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.30.6.tgz",
-      "integrity": "sha512-J4zYMIhgrx4MgnZrSDD7sEnQp7FmhKNOaqaOpaoQ/SfdMfRB/0yvK74hTnvH+VQxndZynqs5/Hn4t+2/j9bADg==",
+      "version": "5.30.7",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.30.7.tgz",
+      "integrity": "sha512-l4L6Do+tfeM2OK0GJsU7TUcM/1oN/N25xHm3Jb4z3OiDU4Lj8dIuxX9LpVMS9riSXQs42D1ieX7b85/r16H9Fw==",
       "dev": true,
       "requires": {
-        "@typescript-eslint/scope-manager": "5.30.6",
-        "@typescript-eslint/type-utils": "5.30.6",
-        "@typescript-eslint/utils": "5.30.6",
+        "@typescript-eslint/scope-manager": "5.30.7",
+        "@typescript-eslint/type-utils": "5.30.7",
+        "@typescript-eslint/utils": "5.30.7",
         "debug": "^4.3.4",
         "functional-red-black-tree": "^1.0.1",
         "ignore": "^5.2.0",
@@ -6798,52 +6798,52 @@
       }
     },
     "@typescript-eslint/parser": {
-      "version": "5.30.6",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.30.6.tgz",
-      "integrity": "sha512-gfF9lZjT0p2ZSdxO70Xbw8w9sPPJGfAdjK7WikEjB3fcUI/yr9maUVEdqigBjKincUYNKOmf7QBMiTf719kbrA==",
+      "version": "5.30.7",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.30.7.tgz",
+      "integrity": "sha512-Rg5xwznHWWSy7v2o0cdho6n+xLhK2gntImp0rJroVVFkcYFYQ8C8UJTSuTw/3CnExBmPjycjmUJkxVmjXsld6A==",
       "dev": true,
       "requires": {
-        "@typescript-eslint/scope-manager": "5.30.6",
-        "@typescript-eslint/types": "5.30.6",
-        "@typescript-eslint/typescript-estree": "5.30.6",
+        "@typescript-eslint/scope-manager": "5.30.7",
+        "@typescript-eslint/types": "5.30.7",
+        "@typescript-eslint/typescript-estree": "5.30.7",
         "debug": "^4.3.4"
       }
     },
     "@typescript-eslint/scope-manager": {
-      "version": "5.30.6",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.30.6.tgz",
-      "integrity": "sha512-Hkq5PhLgtVoW1obkqYH0i4iELctEKixkhWLPTYs55doGUKCASvkjOXOd/pisVeLdO24ZX9D6yymJ/twqpJiG3g==",
+      "version": "5.30.7",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.30.7.tgz",
+      "integrity": "sha512-7BM1bwvdF1UUvt+b9smhqdc/eniOnCKxQT/kj3oXtj3LqnTWCAM0qHRHfyzCzhEfWX0zrW7KqXXeE4DlchZBKw==",
       "dev": true,
       "requires": {
-        "@typescript-eslint/types": "5.30.6",
-        "@typescript-eslint/visitor-keys": "5.30.6"
+        "@typescript-eslint/types": "5.30.7",
+        "@typescript-eslint/visitor-keys": "5.30.7"
       }
     },
     "@typescript-eslint/type-utils": {
-      "version": "5.30.6",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.30.6.tgz",
-      "integrity": "sha512-GFVVzs2j0QPpM+NTDMXtNmJKlF842lkZKDSanIxf+ArJsGeZUIaeT4jGg+gAgHt7AcQSFwW7htzF/rbAh2jaVA==",
+      "version": "5.30.7",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.30.7.tgz",
+      "integrity": "sha512-nD5qAE2aJX/YLyKMvOU5jvJyku4QN5XBVsoTynFrjQZaDgDV6i7QHFiYCx10wvn7hFvfuqIRNBtsgaLe0DbWhw==",
       "dev": true,
       "requires": {
-        "@typescript-eslint/utils": "5.30.6",
+        "@typescript-eslint/utils": "5.30.7",
         "debug": "^4.3.4",
         "tsutils": "^3.21.0"
       }
     },
     "@typescript-eslint/types": {
-      "version": "5.30.6",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.30.6.tgz",
-      "integrity": "sha512-HdnP8HioL1F7CwVmT4RaaMX57RrfqsOMclZc08wGMiDYJBsLGBM7JwXM4cZJmbWLzIR/pXg1kkrBBVpxTOwfUg==",
+      "version": "5.30.7",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.30.7.tgz",
+      "integrity": "sha512-ocVkETUs82+U+HowkovV6uxf1AnVRKCmDRNUBUUo46/5SQv1owC/EBFkiu4MOHeZqhKz2ktZ3kvJJ1uFqQ8QPg==",
       "dev": true
     },
     "@typescript-eslint/typescript-estree": {
-      "version": "5.30.6",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.30.6.tgz",
-      "integrity": "sha512-Z7TgPoeYUm06smfEfYF0RBkpF8csMyVnqQbLYiGgmUSTaSXTP57bt8f0UFXstbGxKIreTwQCujtaH0LY9w9B+A==",
+      "version": "5.30.7",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.30.7.tgz",
+      "integrity": "sha512-tNslqXI1ZdmXXrHER83TJ8OTYl4epUzJC0aj2i4DMDT4iU+UqLT3EJeGQvJ17BMbm31x5scSwo3hPM0nqQ1AEA==",
       "dev": true,
       "requires": {
-        "@typescript-eslint/types": "5.30.6",
-        "@typescript-eslint/visitor-keys": "5.30.6",
+        "@typescript-eslint/types": "5.30.7",
+        "@typescript-eslint/visitor-keys": "5.30.7",
         "debug": "^4.3.4",
         "globby": "^11.1.0",
         "is-glob": "^4.0.3",
@@ -6852,26 +6852,26 @@
       }
     },
     "@typescript-eslint/utils": {
-      "version": "5.30.6",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.30.6.tgz",
-      "integrity": "sha512-xFBLc/esUbLOJLk9jKv0E9gD/OH966M40aY9jJ8GiqpSkP2xOV908cokJqqhVd85WoIvHVHYXxSFE4cCSDzVvA==",
+      "version": "5.30.7",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.30.7.tgz",
+      "integrity": "sha512-Z3pHdbFw+ftZiGUnm1GZhkJgVqsDL5CYW2yj+TB2mfXDFOMqtbzQi2dNJIyPqPbx9mv2kUxS1gU+r2gKlKi1rQ==",
       "dev": true,
       "requires": {
         "@types/json-schema": "^7.0.9",
-        "@typescript-eslint/scope-manager": "5.30.6",
-        "@typescript-eslint/types": "5.30.6",
-        "@typescript-eslint/typescript-estree": "5.30.6",
+        "@typescript-eslint/scope-manager": "5.30.7",
+        "@typescript-eslint/types": "5.30.7",
+        "@typescript-eslint/typescript-estree": "5.30.7",
         "eslint-scope": "^5.1.1",
         "eslint-utils": "^3.0.0"
       }
     },
     "@typescript-eslint/visitor-keys": {
-      "version": "5.30.6",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.30.6.tgz",
-      "integrity": "sha512-41OiCjdL2mCaSDi2SvYbzFLlqqlm5v1ZW9Ym55wXKL/Rx6OOB1IbuFGo71Fj6Xy90gJDFTlgOS+vbmtGHPTQQA==",
+      "version": "5.30.7",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.30.7.tgz",
+      "integrity": "sha512-KrRXf8nnjvcpxDFOKej4xkD7657+PClJs5cJVSG7NNoCNnjEdc46juNAQt7AyuWctuCgs6mVRc1xGctEqrjxWw==",
       "dev": true,
       "requires": {
-        "@typescript-eslint/types": "5.30.6",
+        "@typescript-eslint/types": "5.30.7",
         "eslint-visitor-keys": "^3.3.0"
       }
     },
diff --git a/package.json b/package.json
index 3a850b0..78fd112 100644
--- a/package.json
+++ b/package.json
@@ -7,7 +7,8 @@
     "preview": "vite preview --port 4173",
     "build-only": "vite build",
     "type-check": "vue-tsc --noEmit",
-    "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore"
+    "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore",
+    "generate-client": "openapi --input http://localhost:8000/api/openapi.json --output src/client --client axios"
   },
   "dependencies": {
     "@aws-sdk/client-s3": "^3.131.0",
diff --git a/public/favicon.ico b/public/favicon.ico
new file mode 100644
index 0000000000000000000000000000000000000000..0561d178dadb78ee5f28f65c07b6110898bed797
GIT binary patch
literal 4286
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
RT!;Q-lf&4Ar&Uj@@h@k0e$W5_

literal 0
HcmV?d00001

diff --git a/src/App.vue b/src/App.vue
new file mode 100644
index 0000000..420561b
--- /dev/null
+++ b/src/App.vue
@@ -0,0 +1,16 @@
+<script setup lang="ts">
+import NavbarTop from "./components/NavbarTop.vue";
+import SidebarLeft from "./components/SidebarLeft.vue";
+</script>
+
+<template style="height: 100%">
+  <NavbarTop />
+  <SidebarLeft />
+  <router-view class="cona"></router-view>
+</template>
+
+<style scoped>
+.cona {
+  min-height: 80vh;
+}
+</style>
diff --git a/ProxyAPI-UI/src/assets/base.css b/src/assets/base.css
similarity index 100%
rename from ProxyAPI-UI/src/assets/base.css
rename to src/assets/base.css
diff --git a/ProxyAPI-UI/src/assets/logo.svg b/src/assets/logo.svg
similarity index 100%
rename from ProxyAPI-UI/src/assets/logo.svg
rename to src/assets/logo.svg
diff --git a/ProxyAPI-UI/src/assets/main.css b/src/assets/main.css
similarity index 100%
rename from ProxyAPI-UI/src/assets/main.css
rename to src/assets/main.css
diff --git a/src/components/BootstrapIcon.vue b/src/components/BootstrapIcon.vue
new file mode 100644
index 0000000..5b33bbe
--- /dev/null
+++ b/src/components/BootstrapIcon.vue
@@ -0,0 +1,15 @@
+<template>
+  <svg class="bi">
+    <use v-bind:xlink:href="iconPath + '#' + icon" />
+  </svg>
+</template>
+
+<script setup lang="ts">
+import iconPath from "bootstrap-icons/bootstrap-icons.svg";
+
+defineProps<{
+  icon: string;
+}>();
+</script>
+
+<style scoped></style>
diff --git a/src/components/NavbarTop.vue b/src/components/NavbarTop.vue
new file mode 100644
index 0000000..040a4f6
--- /dev/null
+++ b/src/components/NavbarTop.vue
@@ -0,0 +1,40 @@
+<script setup lang="ts">
+import BootstrapIcon from "./BootstrapIcon.vue";
+</script>
+
+<template>
+  <nav class="navbar fixed-top navbar-expand-lg bg-dark">
+    <div class="container-fluid">
+      <router-link class="navbar-brand ms-3" to="/">S3 Proxy</router-link>
+      <div class="dropdown d-flex me-3">
+        <a
+          href="#"
+          class="d-flex align-items-center text-white text-decoration-none dropdown-toggle-split"
+          id="dropdownUser1"
+          data-bs-toggle="dropdown"
+          aria-expanded="false"
+        >
+          <strong class="me-2">Bilbo Baggins</strong>
+          <bootstrap-icon
+            icon="person-circle"
+            fill="white"
+            width="24"
+            height="24"
+          />
+        </a>
+        <ul
+          class="dropdown-menu dropdown-menu-dark text-small shadow"
+          aria-labelledby="dropdownUser1"
+        >
+          <li><a class="dropdown-item" href="#">New project...</a></li>
+          <li><a class="dropdown-item" href="#">Settings</a></li>
+          <li><a class="dropdown-item" href="#">Profile</a></li>
+          <li><hr class="dropdown-divider" /></li>
+          <li><a class="dropdown-item" href="#">Sign out</a></li>
+        </ul>
+      </div>
+    </div>
+  </nav>
+</template>
+
+<style scoped></style>
diff --git a/src/components/SidebarLeft.vue b/src/components/SidebarLeft.vue
new file mode 100644
index 0000000..a5d1866
--- /dev/null
+++ b/src/components/SidebarLeft.vue
@@ -0,0 +1,41 @@
+<script setup lang="ts"></script>
+
+<template>
+  <div
+    class="d-flex flex-column flex-shrink-0 p-3 text-white bg-dark"
+    style="width: 200px"
+  >
+    <ul class="nav nav-pills flex-column mb-auto">
+      <li class="nav-item">
+        <button
+          class="btn btn-toggle align-items-center rounded collapsed text-white"
+          data-bs-toggle="collapse"
+          data-bs-target="#home-collapse"
+          aria-expanded="true"
+        >
+          Object Storage
+        </button>
+        <div class="collapse show" id="home-collapse">
+          <ul class="btn-toggle-nav list-unstyled fw-normal pb-1 small">
+            <li>
+              <router-link
+                to="/object-storage/buckets"
+                class="link-light rounded"
+                >Buckets</router-link
+              >
+            </li>
+            <li>
+              <router-link
+                to="/object-storage/s3-keys"
+                class="link-light rounded"
+                >S3 Keys</router-link
+              >
+            </li>
+          </ul>
+        </div>
+      </li>
+    </ul>
+  </div>
+</template>
+
+<style scoped></style>
diff --git a/ProxyAPI-UI/src/main.ts b/src/main.ts
similarity index 100%
rename from ProxyAPI-UI/src/main.ts
rename to src/main.ts
diff --git a/ProxyAPI-UI/src/router/index.ts b/src/router/index.ts
similarity index 59%
rename from ProxyAPI-UI/src/router/index.ts
rename to src/router/index.ts
index 35612dc..3cc545e 100644
--- a/ProxyAPI-UI/src/router/index.ts
+++ b/src/router/index.ts
@@ -1,21 +1,25 @@
 import { createRouter, createWebHistory } from "vue-router";
-import HomeView from "../views/HomeView.vue";
+import BucketsView from "../views/BucketsView.vue";
 
 const router = createRouter({
   history: createWebHistory(import.meta.env.BASE_URL),
   routes: [
     {
-      path: "/",
-      name: "home",
-      component: HomeView,
+      path: "/object-storage/buckets",
+      name: "buckets",
+      component: BucketsView,
     },
     {
-      path: "/about",
+      path: "/object-storage/s3-keys",
       name: "about",
       // route level code-splitting
       // this generates a separate chunk (About.[hash].js) for this route
       // which is lazy-loaded when the route is visited.
-      component: () => import("../views/AboutView.vue"),
+      component: () => import("../views/S3KeysView.vue"),
+    },
+    {
+      path: "/",
+      redirect: { name: "buckets" },
     },
   ],
 });
diff --git a/ProxyAPI-UI/src/stores/counter.ts b/src/stores/counter.ts
similarity index 100%
rename from ProxyAPI-UI/src/stores/counter.ts
rename to src/stores/counter.ts
diff --git a/ProxyAPI-UI/src/views/HomeView.vue b/src/views/BucketsView.vue
similarity index 86%
rename from ProxyAPI-UI/src/views/HomeView.vue
rename to src/views/BucketsView.vue
index 5d558a9..94874bb 100644
--- a/ProxyAPI-UI/src/views/HomeView.vue
+++ b/src/views/BucketsView.vue
@@ -1,5 +1,4 @@
 <script setup lang="ts">
-import TheWelcome from "@/components/TheWelcome.vue";
 import { onMounted, reactive } from "vue";
 import { useCookies } from "vue3-cookies";
 
@@ -21,6 +20,6 @@ onMounted(() => {
       Cookie Present: {{ my_cookie.val }}
     </p>
     <p v-else>No Cookie set</p>
-    <TheWelcome />
+    <div>This the is the Buckets Page</div>
   </main>
 </template>
diff --git a/ProxyAPI-UI/src/views/AboutView.vue b/src/views/S3KeysView.vue
similarity index 73%
rename from ProxyAPI-UI/src/views/AboutView.vue
rename to src/views/S3KeysView.vue
index 756ad2a..cc1e83c 100644
--- a/ProxyAPI-UI/src/views/AboutView.vue
+++ b/src/views/S3KeysView.vue
@@ -1,13 +1,12 @@
 <template>
   <div class="about">
-    <h1>This is an about page</h1>
+    <h1>This is the S3 Key Page</h1>
   </div>
 </template>
 
 <style>
 @media (min-width: 1024px) {
   .about {
-    min-height: 100vh;
     display: flex;
     align-items: center;
   }
diff --git a/ProxyAPI-UI/tsconfig.config.json b/tsconfig.config.json
similarity index 100%
rename from ProxyAPI-UI/tsconfig.config.json
rename to tsconfig.config.json
diff --git a/ProxyAPI-UI/tsconfig.json b/tsconfig.json
similarity index 100%
rename from ProxyAPI-UI/tsconfig.json
rename to tsconfig.json
diff --git a/ProxyAPI-UI/vite.config.ts b/vite.config.ts
similarity index 100%
rename from ProxyAPI-UI/vite.config.ts
rename to vite.config.ts
-- 
GitLab