refactor(editor): Rename CollectionCard and CollectionCardCarousel (#7994)
## Summary As part of the plan to reuse current `CollectionCarousel` component, this PR makes it, and the cards it uses, more generic by renaming them and adds a new property to card component which can be used to hide the item count. #### How to test the change: Until the component that will use this is implmeneted, this can be tested manually: 1. Run n8n 2. Set `showItemCount` property for workflow collection cards to `false` 3. Check if workflow count is showing (it shouldn't) and if everything rendering correctly ## Issues fixed Fixes ADO-1567 ## Review / Merge checklist - [ ] PR title and summary are descriptive. **Remember, the title automatically goes into the changelog. Use `(no-changelog)` otherwise.** ([conventions](https://github.com/n8n-io/n8n/blob/master/.github/pull_request_title_conventions.md)) - [ ] [Docs updated](https://github.com/n8n-io/n8n-docs) or follow-up ticket created. - [ ] Tests included. > A bug is not considered fixed, unless a test is added to prevent it from happening again. A feature is not complete without tests. > > *(internal)* You can use Slack commands to trigger [e2e tests](https://www.notion.so/n8n/How-to-use-Test-Instances-d65f49dfc51f441ea44367fb6f67eb0a?pvs=4#a39f9e5ba64a48b58a71d81c837e8227) or [deploy test instance](https://www.notion.so/n8n/How-to-use-Test-Instances-d65f49dfc51f441ea44367fb6f67eb0a?pvs=4#f6a177d32bde4b57ae2da0b8e454bfce) or [deploy early access version on Cloud](https://www.notion.so/n8n/Cloudbot-3dbe779836004972b7057bc989526998?pvs=4#fef2d36ab02247e1a0f65a74f6fb534e).
This commit is contained in:
committed by
GitHub
parent
435392cbfe
commit
240d259260
212
packages/editor-ui/src/components/TemplatesInfoCarousel.vue
Normal file
212
packages/editor-ui/src/components/TemplatesInfoCarousel.vue
Normal file
@@ -0,0 +1,212 @@
|
||||
<template>
|
||||
<div :class="$style.container" v-show="loading || collections.length">
|
||||
<agile
|
||||
ref="slider"
|
||||
:dots="false"
|
||||
:navButtons="false"
|
||||
:infinite="false"
|
||||
:slides-to-show="4"
|
||||
@after-change="updateCarouselScroll"
|
||||
>
|
||||
<Card v-for="n in loading ? 4 : 0" :key="`loading-${n}`" :loading="loading" />
|
||||
<TemplatesInfoCard
|
||||
v-for="collection in loading ? [] : collections"
|
||||
:key="collection.id"
|
||||
:collection="collection"
|
||||
@click="(e) => onCardClick(e, collection.id)"
|
||||
/>
|
||||
</agile>
|
||||
<button v-show="carouselScrollPosition > 0" :class="$style.leftButton" @click="scrollLeft">
|
||||
<font-awesome-icon icon="chevron-left" />
|
||||
</button>
|
||||
<button v-show="!scrollEnd" :class="$style.rightButton" @click="scrollRight">
|
||||
<font-awesome-icon icon="chevron-right" />
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import type { PropType } from 'vue';
|
||||
import type { ITemplatesCollection } from '@/Interface';
|
||||
import Card from '@/components/CollectionWorkflowCard.vue';
|
||||
import TemplatesInfoCard from '@/components/TemplatesInfoCard.vue';
|
||||
import { VueAgile } from 'vue-agile';
|
||||
|
||||
import { genericHelpers } from '@/mixins/genericHelpers';
|
||||
|
||||
type SliderRef = InstanceType<typeof VueAgile>;
|
||||
|
||||
export default defineComponent({
|
||||
name: 'TemplatesInfoCarousel',
|
||||
mixins: [genericHelpers],
|
||||
props: {
|
||||
collections: {
|
||||
type: Array as PropType<ITemplatesCollection[]>,
|
||||
},
|
||||
loading: {
|
||||
type: Boolean,
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
collections() {
|
||||
setTimeout(() => {
|
||||
this.updateCarouselScroll();
|
||||
}, 0);
|
||||
},
|
||||
loading() {
|
||||
setTimeout(() => {
|
||||
this.updateCarouselScroll();
|
||||
}, 0);
|
||||
},
|
||||
},
|
||||
components: {
|
||||
Card,
|
||||
TemplatesInfoCard,
|
||||
agile: VueAgile,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
carouselScrollPosition: 0,
|
||||
cardWidth: 240,
|
||||
scrollEnd: false,
|
||||
listElement: null as null | Element,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
updateCarouselScroll() {
|
||||
if (this.listElement) {
|
||||
this.carouselScrollPosition = Number(this.listElement.scrollLeft.toFixed());
|
||||
|
||||
const width = this.listElement.clientWidth;
|
||||
const scrollWidth = this.listElement.scrollWidth;
|
||||
const scrollLeft = this.carouselScrollPosition;
|
||||
this.scrollEnd = scrollWidth - width <= scrollLeft + 7;
|
||||
}
|
||||
},
|
||||
onCardClick(event: MouseEvent, id: string) {
|
||||
this.$emit('openCollection', { event, id });
|
||||
},
|
||||
scrollLeft() {
|
||||
if (this.listElement) {
|
||||
this.listElement.scrollBy({ left: -(this.cardWidth * 2), top: 0, behavior: 'smooth' });
|
||||
}
|
||||
},
|
||||
scrollRight() {
|
||||
if (this.listElement) {
|
||||
this.listElement.scrollBy({ left: this.cardWidth * 2, top: 0, behavior: 'smooth' });
|
||||
}
|
||||
},
|
||||
},
|
||||
async mounted() {
|
||||
await this.$nextTick();
|
||||
const sliderRef = this.$refs.slider as SliderRef | undefined;
|
||||
if (!sliderRef) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.listElement = sliderRef.$el.querySelector('.agile__list');
|
||||
if (this.listElement) {
|
||||
this.listElement.addEventListener('scroll', this.updateCarouselScroll);
|
||||
}
|
||||
},
|
||||
beforeUnmount() {
|
||||
const sliderRef = this.$refs.slider as SliderRef | undefined;
|
||||
if (sliderRef) {
|
||||
sliderRef.destroy();
|
||||
}
|
||||
|
||||
window.removeEventListener('scroll', this.updateCarouselScroll);
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" module>
|
||||
.container {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.button {
|
||||
width: 28px;
|
||||
height: 37px;
|
||||
position: absolute;
|
||||
top: 35%;
|
||||
border-radius: var(--border-radius-large);
|
||||
border: var(--border-base);
|
||||
background-color: #fbfcfe;
|
||||
cursor: pointer;
|
||||
|
||||
&:after {
|
||||
content: '';
|
||||
width: 40px;
|
||||
height: 140px;
|
||||
top: -55px;
|
||||
position: absolute;
|
||||
}
|
||||
svg {
|
||||
color: var(--color-foreground-xdark);
|
||||
}
|
||||
}
|
||||
|
||||
.leftButton {
|
||||
composes: button;
|
||||
left: -30px;
|
||||
|
||||
&:after {
|
||||
left: 27px;
|
||||
background: linear-gradient(
|
||||
270deg,
|
||||
hsla(
|
||||
var(--color-background-light-h),
|
||||
var(--color-background-light-s),
|
||||
var(--color-background-light-l),
|
||||
50%
|
||||
),
|
||||
hsla(
|
||||
var(--color-background-light-h),
|
||||
var(--color-background-light-s),
|
||||
var(--color-background-light-l),
|
||||
100%
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
.rightButton {
|
||||
composes: button;
|
||||
right: -30px;
|
||||
&:after {
|
||||
right: 27px;
|
||||
background: linear-gradient(
|
||||
90deg,
|
||||
hsla(
|
||||
var(--color-background-light-h),
|
||||
var(--color-background-light-s),
|
||||
var(--color-background-light-l),
|
||||
50%
|
||||
),
|
||||
hsla(
|
||||
var(--color-background-light-h),
|
||||
var(--color-background-light-s),
|
||||
var(--color-background-light-l),
|
||||
100%
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="scss">
|
||||
.agile {
|
||||
&__list {
|
||||
width: 100%;
|
||||
padding-bottom: var(--spacing-2xs);
|
||||
overflow-x: auto;
|
||||
transition: all 1s ease-in-out;
|
||||
}
|
||||
|
||||
&__track {
|
||||
width: 50px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user