Skip to content

Commit

Permalink
Merge pull request #14802 from guerler/drop_left_panel
Browse files Browse the repository at this point in the history
Introducing the Activity Bar, initial concept and layout
  • Loading branch information
guerler authored Apr 16, 2023
2 parents 92910e6 + 508bc4b commit 6f50816
Show file tree
Hide file tree
Showing 27 changed files with 936 additions and 158 deletions.
87 changes: 87 additions & 0 deletions client/src/components/ActivityBar/ActivityBar.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
<script setup>
import { useUserStore } from "@/stores/userStore";
import UploadItem from "./Items/UploadItem.vue";
import ToolBox from "@/components/Panels/ProviderAwareToolBox.vue";
import ActivityItem from "./ActivityItem";
const userStore = useUserStore();
function sidebarIsActive(menuKey) {
return userStore.toggledSideBar === menuKey;
}
function onToggleSidebar(toggle) {
userStore.toggleSideBar(toggle);
}
</script>
<template>
<div class="d-flex">
<div class="activity-bar d-flex flex-column">
<b-nav vertical class="flex-nowrap p-1 h-100 vertical-overflow">
<upload-item />
<ActivityItem
id="activity-tools"
icon="wrench"
title="Tools"
tooltip="Search and run tools"
:is-active="sidebarIsActive('search')"
@click="onToggleSidebar('search')" />
<ActivityItem
id="activity-workflow"
title="Workflow"
icon="sitemap"
tooltip="Chain tools into workflows"
to="/workflows/list" />
<ActivityItem
id="activity-visualization"
icon="chart-bar"
title="Visualize"
tooltip="Visualize datasets"
to="/visualizations" />
</b-nav>
<b-nav vertical class="flex-nowrap p-1">
<ActivityItem
id="activity-settings"
icon="cog"
title="Settings"
tooltip="Edit preferences"
to="/user" />
</b-nav>
</div>
<div v-if="sidebarIsActive('search')" key="search" class="left-column">
<ToolBox />
</div>
</div>
</template>

<style scoped lang="scss">
@import "theme/blue.scss";
.left-column {
width: 15rem;
}
.activity-bar {
background: $panel-bg-color;
width: 4rem;
}
.activity-bar::-webkit-scrollbar {
display: none;
}
.panels-enter-active,
.panels-leave-active {
transition: all 0.3s;
}
.panels-enter,
.panels-leave-to {
transform: translateX(-100%);
}
.vertical-overflow {
overflow-y: auto;
overflow-x: hidden;
}
</style>
141 changes: 141 additions & 0 deletions client/src/components/ActivityBar/ActivityItem.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
<script setup lang="ts">
import { useRouter } from "vue-router/composables";
import Popper from "components/Popper/Popper.vue";
const router = useRouter();
interface Option {
name: string;
value: string;
}
export interface Props {
id: string;
title: string;
icon?: string;
isActive?: boolean;
tooltip?: string;
progressPercentage?: number;
progressStatus?: string;
options?: Option[];
to?: string;
}
const props = withDefaults(defineProps<Props>(), {
icon: "question",
isActive: false,
options: null,
progressPercentage: 0,
progressStatus: null,
to: null,
tooltip: null,
});
const emit = defineEmits<{
(e: "click"): void;
}>();
function onClick(): void {
if (props.to) {
router.push(props.to);
}
emit("click");
}
</script>

<template>
<div>
<Popper reference-is="span" popper-is="span" placement="right">
<template v-slot:reference>
<b-nav-item
:id="id"
class="position-relative mb-1"
:class="{ 'nav-item-active': isActive }"
:aria-label="title | l"
@click="onClick">
<span v-if="progressStatus" class="progress">
<div
class="progress-bar notransition"
:class="{
'bg-danger': progressStatus === 'danger',
'bg-success': progressStatus === 'success',
}"
:style="{
width: `${Math.round(progressPercentage)}%`,
}" />
</span>
<span class="position-relative">
<div class="nav-icon">
<Icon :icon="icon" />
</div>
<div class="nav-title">{{ title }}</div>
</span>
</b-nav-item>
</template>
<div class="px-2 py-1">
<small v-if="tooltip">{{ tooltip | l }}</small>
<small v-else>No tooltip available for this item</small>
<div v-if="options" class="nav-options p-1">
<router-link v-for="(option, index) in options" :key="index" :to="option.value">
<b-button size="sm" variant="outline-primary" class="w-100 my-1 text-break text-light">
{{ option.name }}
</b-button>
</router-link>
</div>
</div>
</Popper>
</div>
</template>

<style scoped lang="scss">
@import "theme/blue.scss";
.nav-item {
display: flex;
align-items: center;
align-content: center;
justify-content: center;
}
.nav-item-active {
border-radius: $border-radius-extralarge;
background: $gray-300;
}
.nav-icon {
@extend .nav-item;
font-size: 1rem;
}
.nav-title {
@extend .nav-item;
margin-top: 0.7rem;
margin-bottom: 0.3rem;
line-height: 0rem;
font-size: 0.7rem;
}
.nav-options {
max-height: 20rem;
overflow-x: hidden;
overflow-y: auto;
}
.progress {
background: transparent;
border-radius: $border-radius-extralarge;
position: absolute;
width: 100%;
height: 100%;
left: 0;
top: 0;
}
.notransition {
-webkit-transition: none;
-moz-transition: none;
-ms-transition: none;
-o-transition: none;
transition: none;
}
</style>
47 changes: 47 additions & 0 deletions client/src/components/ActivityBar/Items/UploadItem.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<script setup lang="ts">
import { ref, onMounted, onUnmounted, type Ref } from "vue";
import ActivityItem from "components/ActivityBar/ActivityItem.vue";
// @ts-ignore
import Query from "utils/query-string-parsing.js";
// @ts-ignore
import { useGlobalUploadModal } from "composables/globalUploadModal.js";
// @ts-ignore
import { eventHub } from "components/plugins/eventHub.js";
const { openGlobalUploadModal } = useGlobalUploadModal();
const status: Ref<string> = ref("success");
const percentage: Ref<number> = ref(0);
onMounted(() => {
eventHub.$on("upload:status", setStatus);
eventHub.$on("upload:percentage", setPercentage);
if (Query.get("tool_id") == "upload1") {
openGlobalUploadModal();
}
});
onUnmounted(() => {
eventHub.$off("upload:status", setStatus);
eventHub.$off("upload:percentage", setPercentage);
});
function setStatus(val: string): void {
status.value = val;
}
function setPercentage(val: number): void {
percentage.value = val;
}
</script>

<template>
<ActivityItem
id="activity-upload"
title="Upload"
tooltip="Download from URL or upload files from disk"
icon="upload"
:progress-percentage="percentage"
:progress-status="status"
@click="openGlobalUploadModal" />
</template>
51 changes: 24 additions & 27 deletions client/src/components/Common/Published.vue
Original file line number Diff line number Diff line change
@@ -1,42 +1,39 @@
<template>
<div id="columns">
<div id="center">
<div class="center-container">
<div class="center-panel" style="display: block">
<slot />
</div>
</div>
<div id="columns" class="d-flex">
<div id="center" class="m-3 w-100 overflow-auto">
<slot />
</div>
<div id="right">
<div class="m-3">
<div v-if="modelTitle">
<h1 class="h-sm">About this {{ modelTitle }}</h1>
<h2 class="h-md">{{ item.title || item.name }}</h2>
<img class="float-right" :src="gravatarSource" alt="user avatar" />
<StatelessTags v-if="item.tags" class="tags mt-2" :value="item.tags" :disabled="true" />
<br />
<h2 class="h-sm">Author</h2>
<div>{{ owner }}</div>
<hr />
<h2 class="h-sm">Related Pages</h2>
<div>
<router-link :to="urlAll">All published {{ plural }}.</router-link>
</div>
<div>
<router-link :to="publishedByUser"> Published {{ plural }} by {{ owner }}. </router-link>
</div>
<FlexPanel side="right">
<div v-if="modelTitle" class="m-3">
<h1 class="h-sm">About this {{ modelTitle }}</h1>
<h2 class="h-md">{{ item.title || item.name }}</h2>
<img :src="gravatarSource" alt="user avatar" />
<StatelessTags v-if="item.tags" class="tags mt-2" :value="item.tags" :disabled="true" />
<br />
<h2 class="h-sm">Author</h2>
<div>{{ owner }}</div>
<hr />
<h2 class="h-sm">Related Pages</h2>
<div>
<router-link :to="urlAll">All published {{ plural }}.</router-link>
</div>
<div>
<router-link :to="publishedByUser"> Published {{ plural }} by {{ owner }}. </router-link>
</div>
<LoadingSpan v-else message="Loading item details" />
</div>
</div>
<LoadingSpan v-else message="Loading item details" />
<div class="flex-fill" />
</FlexPanel>
</div>
</template>

<script>
import { StatelessTags } from "components/Tags";
import LoadingSpan from "components/LoadingSpan";
import FlexPanel from "@/components/Panels/FlexPanel.vue";
export default {
components: {
FlexPanel,
LoadingSpan,
StatelessTags,
},
Expand Down
Loading

0 comments on commit 6f50816

Please sign in to comment.