Skip to content
Snippets Groups Projects
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
SidebarMenu.vue 9.64 KiB
<template>
  <sidebar-menu
    :menu="menu"
    :collapsed="collapsed"
    :relative="true"
    :show-one-child="true"
    :disable-hover="false"
    theme="white-theme"
    @toggle-collapse="collapse"
  >
    <template #toggle-icon>
      <b-icon v-if="!collapsed" icon="arrow-bar-left" />
      <b-icon v-else icon="arrow-bar-right" />
    </template>

    <template #dropdown-icon>
      <b-icon icon="caret-right" />
    </template>
  </sidebar-menu>
</template>

<script lang="ts">
import Vue from "vue";
import { defineComponent } from "vue-demi";
import "bootstrap-icons/font/bootstrap-icons.css";
import "bootstrap-icons/font/fonts/bootstrap-icons.woff";
import "bootstrap-icons/font/fonts/bootstrap-icons.woff2";

// import the main store
import useMainStore from "@/store/index";
// import the project store
import useProjectStore from "@/modules/project/store";
// import the resource store
import useResourceStore from "@/modules/resource/store";

import type {
  ProjectObject,
  ResourceObject,
  RoleObject,
} from "@coscine/api-client/dist/types/Coscine.Api.Project";

import VueSidebarMenu from "vue-sidebar-menu";
import "vue-sidebar-menu/dist/vue-sidebar-menu.css";
import type {
  SidebarItem,
  SidebarComponentItem,
  SidebarHeaderItem,
} from "vue-sidebar-menu";

Vue.use(VueSidebarMenu);

// TODO: Waiting for role implementation (is owner for showing e.g. settings)

export default defineComponent({
  setup() {
    const mainStore = useMainStore();
    const projectStore = useProjectStore();
    const resourceStore = useResourceStore();

    return { mainStore, projectStore, resourceStore };
  },
  data() {
    return {
      collapsed: false,
    };
  },
  computed: {
    currentUserRole(): RoleObject | undefined | null {
      return this.projectStore.currentUserRole;
    },
    menu(): Array<SidebarItem | SidebarComponentItem | SidebarHeaderItem> {
      return [
        {
          href: "/",
          title: this.$t("sidebar.home").toString(),
          icon: "bi bi-house",
        },
        ...this.projectsMenu,
        ...this.projectMenu,
        ...this.resourcesMenu,
        ...this.subProjectsMenu,
        ...this.settingsMenu,
      ];
    },
    project(): ProjectObject | null {
      return this.projectStore.currentProject;
    },
    projects(): ProjectObject[] | null {
      return this.projectStore.topLevelProjects;
    },
    projectMenu(): Array<SidebarItem> {
      if (this.project && this.project.slug) {
        return [
          {
            href: {
              name: "project-page",
              params: { slug: this.project.slug },
            },
            title:
              this.$tc("sidebar.project", 1).toString() +
              ": " +
              this.project.displayName,

            icon: "bi bi-folder-symlink",
            attributes: {
              title:
                this.$tc("sidebar.project", 1).toString() +
                ": " +
                this.project.displayName,
            },
          },
        ];
      }
      return [];
    },
    projectsMenu(): Array<SidebarItem> {
      if (this.projects && this.projects.length && !this.project) {
        return [
          {
            title: this.$tc("sidebar.project", 2).toString(),
            href: "",
            icon: "bi bi-folder2-open",
            child: this.projects.map((project) => {
              return {
                title: project.displayName,
                href: {
                  name: "project-page",
                  params: { slug: project.slug },
                },
                icon: "bi bi-folder2-open",
              };
            }) as Array<SidebarItem>,
          },
        ];
      }
      return [];
    },
    resources(): ResourceObject[] | null {
      return this.projectStore.currentResources;
    },
    resourcesMenu(): Array<SidebarItem> {
      if (
        this.resources &&
        this.resources.length &&
        this.project &&
        this.project.slug
      ) {
        return [
          {
            title: this.$tc("sidebar.resource", 2).toString(),
            href: "",
            icon: "bi bi-archive",
            child: this.resources.map((resource) => {
              return {
                title:
                  (resource.type
                    ? `${this.$t(
                        "resourceTypes." +
                          resource.type.displayName +
                          ".displayName"
                      )}: `
                    : "") + resource.displayName,
                href: {
                  name: "resource-page",
                  params: {
                    slug: this.project ? this.project.slug : undefined,
                    guid: resource.id,
                  },
                },
                icon: "bi bi-archive",
                attributes: {
                  title:
                    (resource.type
                      ? `${this.$t(
                          "resourceTypes." +
                            resource.type.displayName +
                            ".displayName"
                        )}: `
                      : "") + resource.displayName,
                },
                badge: resource.archived
                  ? {
                      text: this.$t("default.archived").toString(),
                      class: "vsm--badge_default",
                    }
                  : undefined,
                exactPath: true,
              };
            }) as Array<SidebarItem>,
          },
        ];
      }
      return [];
    },
    settingsMenu(): Array<SidebarItem> {
      if (
        this.project &&
        this.project.slug &&
        this.currentUserRole &&
        this.currentUserRole.displayName === "Owner"
      ) {
        return [
          {
            title: this.$t("sidebar.settings").toString(),
            href: "",
            icon: "bi bi-gear",
            child: [
              {
                title: this.$t("sidebar.projectSettings").toString(),
                href: {
                  name: "project-settings",
                  params: { slug: this.project.slug },
                },
                icon: "bi bi-pencil",
              },
              {
                title: this.$t("sidebar.manageUsers").toString(),
                href: {
                  name: "project-members",
                  params: { slug: this.project.slug },
                },
                icon: "bi bi-people",
              },
              {
                title: this.$t("sidebar.manageQuota").toString(),
                href: {
                  name: "project-quota",
                  params: { slug: this.project.slug },
                },
                icon: "bi bi-sliders",
              },
            ],
          },
        ];
      }
      return [];
    },
    sidebarActive(): boolean {
      return this.mainStore.sidebarActive;
    },
    subProjects(): ProjectObject[] | null {
      return this.projectStore.currentSubProjects;
    },
    subProjectsMenu(): Array<SidebarItem> {
      if (this.subProjects && this.subProjects.length) {
        return [
          {
            title: this.$tc("sidebar.subProject", 2).toString(),
            href: "",
            icon: "bi bi-folder2-open",
            child: this.subProjects.map((project) => {
              return {
                title: project.displayName,
                href: {
                  name: "project-page",
                  params: { slug: project.slug },
                },
                icon: "bi bi-folder2-open",
                attributes: {
                  title:
                    this.$tc("sidebar.subProject", 2).toString() +
                    ": " +
                    project.displayName,
                },
              };
            }) as Array<SidebarItem>,
          },
        ];
      }
      return [];
    },
  },
  watch: {
    collapsed() {
      this.mainStore.sidebarActive = !this.collapsed;
    },
    sidebarActive() {
      this.collapsed = !this.sidebarActive;
    },
  },
  created() {
    this.collapsed = !this.sidebarActive;
  },
  methods: {
    collapse(collapsed: boolean) {
      this.collapsed = collapsed;
    },
  },
});
</script>

<style lang="scss" scoped>
@import "/src/assets/scss/_custom.scss";

.v-sidebar-menu {
  height: var(--sidebar-height);
  border-radius: 0rem 0.25rem 0.25rem 0rem;
  background: $light;
}
.v-sidebar-menu ::v-deep .vsm--toggle-btn {
  border-radius: 0rem 0rem 0.25rem 0rem;
  background-color: var(--secondary);
}
.v-sidebar-menu.vsm_expanded {
  overflow-y: auto;
  overflow-x: hidden;
}
.v-sidebar-menu ::v-deep .vsm--badge {
  background-color: #ffc107;
  border-radius: 10rem;
  text-transform: capitalize;
  font-weight: bold;
}
.v-sidebar-menu ::v-deep .vsm--title {
  text-overflow: ellipsis;
  white-space: nowrap;
  overflow: hidden;
}
.v-sidebar-menu.vsm_expanded ::v-deep .vsm--item_open .vsm--link_level-1 {
  background: $primary;
}
.v-sidebar-menu.vsm_expanded
  ::v-deep
  .vsm--item_open
  .vsm--link_level-1
  .vsm--icon {
  background: $primary;
}
.v-sidebar-menu.vsm_collapsed ::v-deep .vsm--mobile-item .vsm--item_open {
  background-color: $primary;
}
.v-sidebar-menu.vsm_collapsed ::v-deep .vsm--mobile-item .vsm--mobile-bg {
  background-color: $primary;
}
.v-sidebar-menu.vsm_collapsed
  ::v-deep
  .vsm--link_level-1.vsm--link_hover
  .vsm--icon {
  background-color: $primary;
}
.v-sidebar-menu.vsm_white-theme
  ::v-deep
  .vsm--link_level-1.vsm--link_exact-active,
.v-sidebar-menu ::v-deep .vsm--link_level-1.vsm--link_active {
  box-shadow: 3px 0px 0px 0px $primary inset;
  -webkit-box-shadow: 3px 0px 0px 0px $primary inset;
}
.v-sidebar-menu ::v-deep .vsm--link_level-2.vsm--link_active {
  // Use this to edit the second level element when active
  background-color: var(--primary);
  color: $white;
}
</style>