Skip to content

Commit cd8da97

Browse files
committed
Add spinner support
1 parent c9de983 commit cd8da97

File tree

5 files changed

+75
-55
lines changed

5 files changed

+75
-55
lines changed

README.md

+6-8
Original file line numberDiff line numberDiff line change
@@ -47,19 +47,16 @@ export default Vue.extend({
4747
{
4848
timestamp: Date.parse('2021-05-29T20:20:46.444Z'),
4949
title: 'Dolore ullamco exercitation commodo',
50-
content: 'Esse dolore consectetur aliqua laboris sunt aliqua do non.',
51-
link: 'https://example1.com'
50+
content: 'Esse dolore consectetur aliqua laboris sunt aliqua do non.'
5251
},
5352
{
5453
timestamp: Date.parse('2021-05-28T20:20:46.444Z'),
55-
title: 'Voluptate pariatur dolore laborum eu',
56-
link: '#'
54+
title: 'Voluptate pariatur dolore laborum eu'
5755
},
5856
{
5957
timestamp: Date.parse('2021-01-28T20:20:46.444Z'),
6058
title: 'Mollit aliqua velit nostrud ipsum',
61-
content: 'Magna officia est fugiat sit esse consectetur labore elit nulla duis consectetur. Et sit velit ad ipsum officia.',
62-
link: '#'
59+
content: 'Magna officia est fugiat sit esse consectetur labore elit nulla duis consectetur. Et sit velit ad ipsum officia.'
6360
}
6461
]
6562
}
@@ -74,15 +71,16 @@ export default Vue.extend({
7471
>
7572
<b-timeline
7673
:items="timelineItems"
77-
:reverse="false"
74+
:reverse="true"
75+
:loading="true"
7876
/>
7977
</b-card>
8078
</div>
8179
</template>
8280
```
8381

8482
## Features
85-
- [ ] Loading spinner
83+
- [x] Loading spinner
8684
- [ ] Support item head color variants
8785
- [x] Support `reverse` props
8886
- [ ] Support custom icons

babel.config.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,5 @@ const buildPresets = [
1212
],
1313
];
1414
module.exports = {
15-
presets: (process.env.NODE_ENV === 'development' ? devPresets : buildPresets),
15+
presets: buildPresets,
1616
};

dev/serve.vue

+2-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@ export default Vue.extend({
4545
>
4646
<bootstrap-vue-timeline
4747
:items="timelineItems"
48-
:reverse="true"
48+
:reverse="false"
49+
:loading="true"
4950
/>
5051
</b-card>
5152
</div>
+36-34
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,58 @@
1-
import { createLocalVue, mount } from '@vue/test-utils'
2-
import { BootstrapVue } from 'bootstrap-vue'
1+
import { createLocalVue, shallowMount } from '@vue/test-utils'
2+
import { BootstrapVue, BSpinner } from 'bootstrap-vue'
33
import BootstrapVueTimeline from '../bootstrap-vue-timeline.vue'
44

55
const sampleItems = [
66
{
77
timestamp: Date.parse('2021-01-28T20:20:46.123Z'),
88
title: 'title 1',
9-
content: 'content 1',
10-
link: 'link 1'
9+
content: 'content 1'
1110
},
1211
{
1312
timestamp: Date.parse('2021-01-28T20:20:46.456Z'),
1413
title: 'title 2',
15-
content: 'content 2',
16-
link: 'link 1'
14+
content: 'content 2'
1715
},
1816
{
1917
timestamp: Date.parse('2021-01-28T20:20:46.444Z'),
2018
title: 'title 3',
21-
content: 'content 3',
22-
link: 'link 3'
19+
content: 'content 3'
2320
}
2421
]
2522

26-
test('renders a timeline with items', () => {
27-
const localVue = createLocalVue()
28-
localVue.use(BootstrapVue)
23+
describe('bootstrap vue timeline component', () => {
24+
let localVue
2925

30-
const wrapper = mount(BootstrapVueTimeline, {
31-
localVue,
32-
attachTo: document.body,
33-
propsData: {
34-
items: sampleItems,
35-
reverse: false
36-
}
26+
beforeEach(() => {
27+
localVue = createLocalVue()
28+
localVue.use(BootstrapVue)
3729
})
38-
const text = wrapper.text()
39-
expect(text).toMatch(/content 1[\s\S]*content 2[\s\S]*content 3/)
40-
})
4130

42-
test('renders a timeline with items in reversed order', () => {
43-
const localVue = createLocalVue()
44-
localVue.use(BootstrapVue)
31+
test('renders a timeline with items in reversed order', () => {
32+
const wrapper = shallowMount(BootstrapVueTimeline, {
33+
localVue,
34+
propsData: {
35+
items: sampleItems,
36+
reverse: true
37+
}
38+
})
39+
const text = wrapper.text()
40+
expect(text).toMatch(/content 3[\s\S]*content 2[\s\S]*content 1/)
41+
})
42+
43+
test('renders a timeline with items with a spinner', () => {
44+
const wrapper = shallowMount(BootstrapVueTimeline, {
45+
localVue,
46+
propsData: {
47+
items: sampleItems,
48+
reverse: false,
49+
loading: true
50+
}
51+
})
52+
const text = wrapper.text()
53+
expect(text).toMatch(/content 1[\s\S]*content 2[\s\S]*content 3/)
4554

46-
const wrapper = mount(BootstrapVueTimeline, {
47-
localVue,
48-
attachTo: document.body,
49-
propsData: {
50-
items: sampleItems,
51-
reverse: true
52-
}
55+
const spinner = wrapper.findComponent(BSpinner)
56+
expect(spinner.exists()).toBe(true)
5357
})
54-
const text = wrapper.text()
55-
expect(text).toMatch(/content 3[\s\S]*content 2[\s\S]*content 1/)
56-
})
58+
})

src/bootstrap-vue-timeline.vue

+30-11
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,40 @@
11
<script>
22
import Vue from 'vue'
3-
import { BListGroup, BListGroupItem, BTooltip } from 'bootstrap-vue'
3+
import { BListGroup, BListGroupItem, BSpinner, BTooltip } from 'bootstrap-vue'
44
import { format, formatDistanceToNow } from 'date-fns'
55
66
Vue.component('b-list-group', BListGroup)
77
Vue.component('b-list-group-item', BListGroupItem)
88
Vue.component('b-tooltip', BTooltip)
9+
Vue.component('b-spinner', BSpinner)
910
1011
export default /*#__PURE__*/{
1112
name: 'BootstrapVueTimeline',
1213
props: {
1314
items: Array,
14-
reverse: Boolean
15+
reverse: Boolean,
16+
loading: Boolean
1517
},
16-
computed: {
18+
methods: {
1719
orderedItems() {
18-
const items = this.items
20+
let items = this.items
21+
if (this.loading) {
22+
items = [...items, {spinner: true, timestamp: "time", title: "loading"}]
23+
}
24+
1925
if (this.reverse) {
2026
items.reverse()
2127
}
2228
2329
return items
24-
}
25-
},
26-
methods: {
30+
},
31+
itemsCount() {
32+
if (this.loading) {
33+
return this.items.length + 1
34+
}
35+
36+
return this.items.length
37+
},
2738
formatAgo(timestamp) {
2839
return formatDistanceToNow(timestamp, { addSuffix: true })
2940
},
@@ -40,18 +51,26 @@ export default /*#__PURE__*/{
4051
<template>
4152
<b-list-group>
4253
<b-list-group-item
43-
v-for="(item, index) in orderedItems"
54+
v-for="(item, index) in orderedItems()"
4455
:key="item.timestamp + item.title"
45-
:href="item.link"
4656
class="flex-column align-items-start"
4757
>
4858
<div class="item-head" />
4959
<div
50-
v-if="index !== items.length - 1"
60+
v-if="index !== itemsCount() - 1"
5161
class="item-tail"
5262
/>
5363

54-
<div class="item-content">
64+
<b-spinner
65+
v-if="item.spinner"
66+
variant="primary"
67+
class="ml-4"
68+
/>
69+
70+
<div
71+
v-if="!item.spinner"
72+
class="item-content"
73+
>
5574
<div class="d-flex w-100 justify-content-between">
5675
<h5 class="mt-2 mb-1">
5776
{{ item.title }}

0 commit comments

Comments
 (0)