Skip to content

Commit

Permalink
add separate Histories side panel (from multiview panel)
Browse files Browse the repository at this point in the history
  • Loading branch information
ahmedhamidawan committed Feb 13, 2024
1 parent 4c852d4 commit 6d2ee60
Show file tree
Hide file tree
Showing 7 changed files with 158 additions and 56 deletions.
6 changes: 5 additions & 1 deletion client/src/components/ActivityBar/ActivityBar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import NotificationItem from "./Items/NotificationItem.vue";
import UploadItem from "./Items/UploadItem.vue";
import ContextMenu from "@/components/Common/ContextMenu.vue";
import FlexPanel from "@/components/Panels/FlexPanel.vue";
import HistoriesPanel from "@/components/Panels/HistoriesPanel.vue";
import MultiviewPanel from "@/components/Panels/MultiviewPanel.vue";
import NotificationsPanel from "@/components/Panels/NotificationsPanel.vue";
import ToolPanel from "@/components/Panels/ToolPanel.vue";
Expand Down Expand Up @@ -181,7 +182,7 @@ function toggleContextMenu(evt: MouseEvent) {
:to="activity.to"
@click="onToggleSidebar()" />
<ActivityItem
v-else-if="['tools', 'workflows', 'multiview'].includes(activity.id)"
v-else-if="['tools', 'workflows', 'multiview', 'histories'].includes(activity.id)"
:id="`activity-${activity.id}`"
:key="activity.id"
:icon="activity.icon"
Expand Down Expand Up @@ -234,6 +235,9 @@ function toggleContextMenu(evt: MouseEvent) {
<FlexPanel v-else-if="isActiveSideBar('multiview')" key="multiview" side="left" :collapsible="false">
<MultiviewPanel />
</FlexPanel>
<FlexPanel v-else-if="isActiveSideBar('histories')" key="histories" side="left" :collapsible="false">
<HistoriesPanel />
</FlexPanel>
<ContextMenu :visible="contextMenuVisible" :x="contextMenuX" :y="contextMenuY" @hide="toggleContextMenu">
<ActivitySettings />
</ContextMenu>
Expand Down
51 changes: 30 additions & 21 deletions client/src/components/History/HistoryScrollList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ const props = defineProps({
additionalOptions: { type: Array as PropType<AdditionalOptions[]>, default: () => [] },
showModal: { type: Boolean, default: false },
inModal: { type: Boolean, default: false },
inPanel: { type: Boolean, default: false },
filter: { type: String, default: "" },
loading: { type: Boolean, default: false },
});
Expand Down Expand Up @@ -124,9 +125,9 @@ const filtered: Ref<HistorySummary[]> = computed(() => {
});
}
return filteredHistories.sort((a, b) => {
if (!isMultiviewPanel.value && a.id == currentHistoryId.value) {
if (!props.inPanel && a.id == currentHistoryId.value) {
return -1;
} else if (!isMultiviewPanel.value && b.id == currentHistoryId.value) {
} else if (!props.inPanel && b.id == currentHistoryId.value) {
return 1;
} else if (a.update_time < b.update_time) {
return 1;
Expand All @@ -137,11 +138,13 @@ const filtered: Ref<HistorySummary[]> = computed(() => {
});
/** is this the selector list for Multiview that shows up in the left panel */
const isMultiviewPanel = computed(() => !props.inModal && props.multiple);
const isMultiviewPanel = computed(() => props.inPanel && props.multiple);
function isActiveItem(history: HistorySummary) {
if (isMultiviewPanel.value) {
return pinnedHistories.value.some((item: PinnedHistory) => item.id == history.id);
} else if (props.inPanel) {
return currentHistoryId.value === history.id;
} else {
return props.selectedHistories.some((item: PinnedHistory) => item.id == history.id);
}
Expand All @@ -155,6 +158,8 @@ function historyClicked(history: HistorySummary) {
} else {
openInMulti(history);
}
} else if (props.inPanel) {
setCurrentHistory(history);
}
}
Expand Down Expand Up @@ -182,6 +187,9 @@ function openInMulti(history: HistorySummary) {
router.push("/histories/view_multiple");
historyStore.pinHistory(history.id);
emit("update:show-modal", false);
if (props.inPanel && !isMultiviewPanel.value) {
useUserStore().toggleSideBar("multiview");
}
}
/** Loads (paginates) for more histories
Expand All @@ -198,7 +206,7 @@ async function loadMore(noScroll = false) {
</script>

<template>
<div :class="isMultiviewPanel ? 'unified-panel' : 'flex-column-overflow'">
<div :class="props.inPanel ? 'unified-panel' : 'flex-column-overflow'">
<div class="unified-panel-controls">
<BBadge v-if="props.filter && !validFilter" class="alert-danger w-100 mb-2">
Search string too short!
Expand All @@ -209,7 +217,7 @@ async function loadMore(noScroll = false) {
<div
class="history-list-container"
:class="{
'in-panel': isMultiviewPanel,
'in-panel': props.inPanel,
'scrolled-top': scrolledTop,
'scrolled-bottom': scrolledBottom,
}">
Expand All @@ -218,9 +226,9 @@ async function loadMore(noScroll = false) {
ref="scrollableDiv"
:class="{
'history-scroll-list': !hasNoResults,
'in-panel': isMultiviewPanel,
'in-panel': props.inPanel,
'in-modal': props.inModal,
toolMenuContainer: isMultiviewPanel,
toolMenuContainer: props.inPanel,
}"
role="list">
<BListGroup>
Expand All @@ -231,13 +239,13 @@ async function loadMore(noScroll = false) {
button
:class="{
current: history.id === currentHistoryId,
'panel-item': isMultiviewPanel,
'panel-item': props.inPanel,
}"
:active="isActiveItem(history)"
@click="() => historyClicked(history)">
<div class="overflow-auto w-100">
<div :class="!isMultiviewPanel ? 'd-flex justify-content-between align-items-center' : ''">
<div v-if="!isMultiviewPanel">
<div :class="!props.inPanel ? 'd-flex justify-content-between align-items-center' : ''">
<div v-if="!props.inPanel">
<Heading h3 inline bold size="text">
<span>{{ history.name }}</span>
<i v-if="history.id === currentHistoryId">(Current)</i>
Expand Down Expand Up @@ -267,19 +275,20 @@ async function loadMore(noScroll = false) {
</div>
</div>

<p v-if="!isMultiviewPanel && history.annotation" class="my-1">{{ history.annotation }}</p>
<p v-if="!props.inPanel && history.annotation" class="my-1">{{ history.annotation }}</p>

<StatelessTags
v-if="history.tags.length > 0"
class="my-1"
:value="history.tags"
:disabled="true"
:max-visible-tags="isMultiviewPanel ? 1 : 10"
:max-visible-tags="props.inPanel ? 1 : 10"
@tag-click="setFilterValue('tag', $event)" />

<div
v-if="props.additionalOptions.length > 0"
class="d-flex justify-content-end align-items-center mt-1">
class="d-flex align-items-center mt-1"
:class="!props.inPanel && 'justify-content-end'">
<BButtonGroup>
<BButton
v-if="
Expand All @@ -291,7 +300,7 @@ async function loadMore(noScroll = false) {
variant="link"
class="p-0 px-1"
@click.stop="() => setCurrentHistory(history)">
<FontAwesomeIcon icon="fa-sign-in-alt" />
<FontAwesomeIcon :icon="faSignInAlt" />
</BButton>

<BButton
Expand All @@ -301,7 +310,7 @@ async function loadMore(noScroll = false) {
variant="link"
class="p-0 px-1"
@click.stop="() => openInMulti(history)">
<FontAwesomeIcon icon="fa-columns" />
<FontAwesomeIcon :icon="faColumns" />
</BButton>

<BButton
Expand All @@ -311,14 +320,14 @@ async function loadMore(noScroll = false) {
variant="link"
class="p-0 px-1"
@click.stop="() => setCenterPanelHistory(history)">
<FontAwesomeIcon icon="far fa-list-alt" />
<FontAwesomeIcon :icon="faListAlt" />
</BButton>
</BButtonGroup>
</div>
</div>
<div v-if="isMultiviewPanel">
<div v-if="props.inPanel">
<FontAwesomeIcon v-if="isActiveItem(history)" :icon="['far', 'check-square']" size="lg" />
<FontAwesomeIcon v-else :icon="['far', 'square']" size="lg" />
<FontAwesomeIcon v-else :icon="isMultiviewPanel ? ['far', 'square'] : ['fa', 'sign-in-alt']" size="lg" />
</div>
</BListGroupItem>
<div>
Expand All @@ -333,11 +342,11 @@ async function loadMore(noScroll = false) {
<ScrollToTopButton :offset="scrollTop" @click="scrollToTop" />
</div>

<div :class="!isMultiviewPanel && 'd-flex flex-row mt-3'">
<div :class="!props.inPanel && 'd-flex flex-row mt-3'">
<div
v-if="!allLoaded"
class="mr-auto d-flex justify-content-center align-items-center"
:class="isMultiviewPanel && 'mt-1'">
:class="props.inPanel && 'mt-1'">
<i class="mr-1">Loaded {{ filtered.length }} out of {{ totalHistoryCount }} histories</i>
<BButton
v-if="!props.filter"
Expand All @@ -347,7 +356,7 @@ async function loadMore(noScroll = false) {
:title="localize('Load More')"
variant="link"
@click="loadMore()">
<FontAwesomeIcon icon="fa-arrow-down" />
<FontAwesomeIcon :icon="faArrowDown" />
</BButton>
</div>

Expand Down
5 changes: 3 additions & 2 deletions client/src/components/Panels/ActivityPanel.vue
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,15 @@ const emit = defineEmits(["goToAll"]);
height: 100%;
display: flex;
flex-flow: column;
padding: 0.5rem 0.25rem;
background-color: $brand-light;
.activity-panel-header {
padding-bottom: 0.5rem;
padding-left: 1rem;
padding-right: 1rem;
.activity-panel-header-top {
height: 2.5rem;
display: flex;
align-items: center;
justify-content: space-between;
Expand All @@ -64,7 +66,6 @@ const emit = defineEmits(["goToAll"]);
flex-grow: 1;
height: 100%;
overflow-y: auto;
padding: 0.2rem 0.2rem;
}
.activity-panel-footer {
Expand Down
89 changes: 89 additions & 0 deletions client/src/components/Panels/HistoriesPanel.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<script setup lang="ts">
import { library } from "@fortawesome/fontawesome-svg-core";
import { faPlus, faUpload } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
import { storeToRefs } from "pinia";
import { computed, ref } from "vue";
import { useRouter } from "vue-router/composables";
import { HistoriesFilters } from "@/components/History/HistoriesFilters";
import { useHistoryStore } from "@/stores/historyStore";
import { useUserStore } from "@/stores/userStore";
import { withPrefix } from "@/utils/redirect";
import FilterMenu from "@/components/Common/FilterMenu.vue";
import HistoryList from "@/components/History/HistoryScrollList.vue";
import ActivityPanel from "@/components/Panels/ActivityPanel.vue";
const router = useRouter();
// @ts-ignore bad library types
library.add(faPlus, faUpload);
const filter = ref("");
const showAdvanced = ref(false);
const loading = ref(false);
const isAnonymous = computed(() => useUserStore().isAnonymous);
const historyStore = useHistoryStore();
const { historiesLoading } = storeToRefs(historyStore);
function setFilter(newFilter: string, newValue: string) {
filter.value = HistoriesFilters.setFilterValue(filter.value, newFilter, newValue);
}
function userTitle(title: string) {
if (isAnonymous.value == true) {
return `Log in to ${title}`;
} else {
return title;
}
}
</script>

<template>
<ActivityPanel title="Histories" go-to-all-title="All histories" @goToAll="router.push('/histories/list')">
<template v-slot:header-buttons>
<BButtonGroup>
<BButton
v-b-tooltip.bottom.hover
data-description="create new history from histories panel"
size="sm"
variant="link"
:title="userTitle('Create new history')"
:disabled="isAnonymous"
@click="historyStore.createNewHistory()">
<FontAwesomeIcon :icon="faPlus" fixed-width />
</BButton>
<BButton
v-b-tooltip.bottom.hover
data-description="import new history from histories panel"
size="sm"
variant="link"
:title="userTitle('Import history')"
:disabled="isAnonymous"
@click="router.push('/histories/import')">
<FontAwesomeIcon :icon="faUpload" fixed-width />
</BButton>
</BButtonGroup>
</template>

<template v-slot:header>
<FilterMenu
name="Histories"
placeholder="search histories"
:filter-class="HistoriesFilters"
:filter-text.sync="filter"
:loading="historiesLoading || loading"
:show-advanced.sync="showAdvanced" />
</template>

<div v-if="isAnonymous">
<b-badge class="alert-info w-100 mx-2">
Please <a :href="withPrefix('/login')">log in or register</a> to create multiple histories.
</b-badge>
</div>

<HistoryList v-show="!showAdvanced" in-panel :filter="filter" :loading.sync="loading" :additional-options="['center', 'multi']" @setFilter="setFilter" />
</ActivityPanel>
</template>
Loading

0 comments on commit 6d2ee60

Please sign in to comment.