Skip to content
Snippets Groups Projects
AppHeader.vue 11.80 KiB
<script setup lang="ts">
import FontAwesomeIcon from "@/components/FontAwesomeIcon.vue";
import { useAuthStore } from "@/stores/users";
import { useRoute } from "vue-router";
import { useCookies } from "vue3-cookies";
import { watch, ref, computed } from "vue";
import BootstrapModal from "@/components/modals/BootstrapModal.vue";
import { OpenAPI as S3ProxyOpenAPI } from "@/client/s3proxy";
import { OpenAPI as AuthOpenAPI } from "@/client/auth";
import { OpenAPI as WorkflowOpenAPI } from "@/client/workflow";
import { OpenAPI as ResourceOpenAPI } from "@/client/resource";
import CopyToClipboardIcon from "@/components/CopyToClipboardIcon.vue";
import dayjs from "dayjs";

const store = useAuthStore();
const { cookies } = useCookies();
const route = useRoute();

function logout() {
  store.logout();
  cookies.remove("bearer");
}

const activeRoute = ref("");
const objectStorageActive = computed<boolean>(
  () => activeRoute.value == "buckets" || activeRoute.value == "s3_keys",
);
const workflowActive = computed<boolean>(
  () => activeRoute.value == "workflows",
);
const resourceActive = computed<boolean>(() => activeRoute.value == "resource");
const adminActive = computed<boolean>(() => activeRoute.value == "admin");

watch(
  () => route.name,
  (to) => {
    if (typeof to === "string") {
      if (to.startsWith("bucket")) {
        activeRoute.value = "buckets";
      } else if (to.startsWith("workflow")) {
        activeRoute.value = "workflows";
      } else if (to.startsWith("resource")) {
        activeRoute.value = "resource";
      } else if (to.startsWith("admin")) {
        activeRoute.value = "admin";
      } else {
        activeRoute.value = to;
      }
    } else {
      activeRoute.value = "";
    }
  },
);
</script>

<template>
  <header
    class="navbar navbar-expand bd-navbar sticky-top border-bottom border-secondary"
  >
    <nav class="container-xxl bd-gutter flex-wrap flex-lg-nowrap text-light">
      <router-link
        class="navbar-brand ms-3 text-white d-flex align-items-center"
        to="/"
      >
        <img
          src="/src/assets/images/clowm.svg"
          alt="CloWM Icon"
          width="32"
          height="32"
          class="d-inline-block align-text-top me-2"
        />
        CloWM
      </router-link>

      <div class="d-flex flex-grow-1" v-if="store.authenticated">
        <ul class="navbar-nav">
          <li class="nav-item dropdown">
            <a
              class="nav-link dropdown-toggle"
              id=""
              :class="{ 'text-black': objectStorageActive }"
              href="#"
              role="button"
              data-bs-toggle="dropdown"
              aria-expanded="false"
              data-bs-auto-close="true"
            >
              Files
            </a>
            <ul
              class="dropdown-menu shadow m-0"
              aria-labelledby="objectStoreDropdown"
            >
              <li>
                <router-link class="dropdown-item" :to="{ name: 'buckets' }"
                  >My Data Buckets
                </router-link>
              </li>
              <li>
                <router-link class="dropdown-item" :to="{ name: 's3_keys' }"
                  >S3 Bucket Keys
                </router-link>
              </li>
            </ul>
          </li>
          <li class="nav-item dropdown">
            <a
              class="nav-link dropdown-toggle"
              :class="{ 'text-black': workflowActive }"
              id="workflowDropdown"
              href="#"
              role="button"
              data-bs-toggle="dropdown"
              aria-expanded="false"
              data-bs-auto-close="true"
            >
              Workflows
            </a>
            <ul
              class="dropdown-menu shadow m-0"
              aria-labelledby="workflowDropdown"
            >
              <li>
                <router-link class="dropdown-item" :to="{ name: 'workflows' }"
                  >Available Workflows
                </router-link>
              </li>
              <li>
                <router-link
                  class="dropdown-item"
                  :to="{ name: 'workflow-executions' }"
                  >My Workflow Executions
                </router-link>
              </li>
              <li v-if="store.workflowDev || store.rewiewer || store.admin">
                <hr class="dropdown-divider" />
              </li>
              <li v-if="store.workflowDev || store.admin">
                <router-link
                  class="dropdown-item"
                  :to="{ name: 'workflows-developer' }"
                  >My Workflows
                </router-link>
              </li>
              <li v-if="store.rewiewer || store.admin">
                <router-link
                  class="dropdown-item"
                  :to="{ name: 'workflows-reviewer' }"
                  >Reviews
                </router-link>
              </li>
            </ul>
          </li>
          <li class="nav-item dropdown">
            <a
              class="nav-link dropdown-toggle"
              :class="{ 'text-black': resourceActive }"
              id="resourceDropdown"
              href="#"
              role="button"
              data-bs-toggle="dropdown"
              aria-expanded="false"
              data-bs-auto-close="true"
            >
              Resources
            </a>
            <ul
              class="dropdown-menu shadow m-0"
              aria-labelledby="workflowDropdown"
            >
              <li>
                <router-link class="dropdown-item" :to="{ name: 'resources' }"
                  >Available Resources
                </router-link>
              </li>
              <li
                v-if="store.resourceMaintainer || store.rewiewer || store.admin"
              >
                <hr class="dropdown-divider" />
              </li>
              <li v-if="store.resourceMaintainer || store.admin">
                <router-link
                  class="dropdown-item"
                  :to="{ name: 'resource-maintainer' }"
                  >My Resources
                </router-link>
              </li>
              <li v-if="store.rewiewer || store.admin">
                <router-link
                  class="dropdown-item"
                  :to="{ name: 'resource-review' }"
                  >Reviews
                </router-link>
              </li>
            </ul>
          </li>
          <li v-if="store.admin">
            <a
              class="nav-link dropdown-toggle"
              :class="{ 'text-black': adminActive }"
              id="adminDropdown"
              href="#"
              role="button"
              data-bs-toggle="dropdown"
              aria-expanded="false"
              data-bs-auto-close="true"
            >
              Admin
            </a>
            <ul
              class="dropdown-menu shadow m-0"
              aria-labelledby="adminDropdown"
            >
              <li>
                <router-link class="dropdown-item" :to="{ name: 'admin-users' }"
                  >Users
                </router-link>
              </li>
              <li>
                <router-link
                  class="dropdown-item"
                  :to="{ name: 'admin-resources' }"
                  >Resources
                </router-link>
              </li>
              <li>
                <router-link
                  class="dropdown-item"
                  :to="{ name: 'admin-sync-requests' }"
                  >Resources Synchronization
                </router-link>
              </li>
            </ul>
          </li>
        </ul>
      </div>
      <div class="dropdown" v-if="store.authenticated && store.user != null">
        <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">{{ store.user?.display_name }}</strong>
          <font-awesome-icon icon="fa-solid fa-circle-user" class="fs-5" />
        </a>
        <ul
          class="dropdown-menu text-small shadow"
          aria-labelledby="dropdownUser1"
        >
          <li>
            <a
              href="#"
              class="dropdown-item"
              data-bs-toggle="modal"
              data-bs-target="#advancedUsageModal"
              >Advanced Usage</a
            >
          </li>
          <li>
            <hr class="dropdown-divider" />
          </li>
          <li><h6 class="dropdown-header">Roles</h6></li>
          <li
            v-for="role in store.roles"
            :key="role"
            class="dropdown-item text-capitalize disabled"
          >
            {{ role }}
          </li>
          <li>
            <hr class="dropdown-divider" />
          </li>
          <li>
            <router-link
              :to="{ name: 'login' }"
              class="dropdown-item"
              @click="logout"
            >
              Sign out
            </router-link>
          </li>
        </ul>
      </div>
    </nav>
  </header>
  <bootstrap-modal
    modal-id="advancedUsageModal"
    modal-label="Advanced Usage Modal"
    v-if="store.authenticated"
    size-modifier="lg"
  >
    <template v-slot:header>
      <h3>Advanced Usage</h3>
    </template>
    <template v-slot:body>
      <table class="table table-borderless table-sm">
        <tbody>
          <tr>
            <td class="text-end">Auth Service:</td>
            <td>
              <a :href="AuthOpenAPI.BASE + '/docs'" target="_blank">
                <font-awesome-icon
                  class="me-1"
                  icon="fa-solid fa-arrow-up-right-from-square"
                />
                {{ AuthOpenAPI.BASE }}</a
              >
            </td>
          </tr>
          <tr>
            <td class="text-end">S3Proxy Service:</td>
            <td>
              <a :href="S3ProxyOpenAPI.BASE + '/docs'" target="_blank">
                <font-awesome-icon
                  class="me-1"
                  icon="fa-solid fa-arrow-up-right-from-square"
                />
                {{ S3ProxyOpenAPI.BASE }}</a
              >
            </td>
          </tr>
          <tr>
            <td class="text-end">Workflow Service:</td>
            <td>
              <a :href="WorkflowOpenAPI.BASE + '/docs'" target="_blank">
                <font-awesome-icon
                  class="me-1"
                  icon="fa-solid fa-arrow-up-right-from-square"
                />
                {{ WorkflowOpenAPI.BASE }}</a
              >
            </td>
          </tr>
          <tr>
            <td class="text-end">Resource Service:</td>
            <td>
              <a :href="ResourceOpenAPI.BASE + '/docs'" target="_blank">
                <font-awesome-icon
                  class="me-1"
                  icon="fa-solid fa-arrow-up-right-from-square"
                />
                {{ ResourceOpenAPI.BASE }}</a
              >
            </td>
          </tr>
        </tbody>
      </table>
      <div class="mt-4">
        <label for="clowm-jwt" class="form-label"
          >JWT for Services (expires at
          {{
            dayjs.unix(store.decodedToken!.exp).format("DD.MM.YYYY HH:mm")
          }})</label
        >
        <div class="input-group">
          <input
            type="text"
            readonly
            class="form-control text-truncate"
            id="clowm-jwt"
            :value="store.token"
            aria-describedby="clowm-jwt-copy"
          />
          <span class="input-group-text" id="clowm-jwt-copy"
            ><copy-to-clipboard-icon :text="store.token ?? ''"
          /></span>
        </div>
      </div>
    </template>
    <template v-slot:footer>
      <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">
        Close
      </button>
    </template>
  </bootstrap-modal>
</template>

<style scoped>
header {
  background: rgb(255, 177, 45);
}
</style>