Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Visual timeline of version history #4647

Merged
merged 54 commits into from
Oct 22, 2024
Merged
Changes from 1 commit
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
49f1446
detach snapshots from the main instance panel and nest it under versi…
cstns Oct 15, 2024
1cf9186
fix failing e2e editor test
cstns Oct 15, 2024
4649fc3
fix missing component property, failing e2e test due to multiple crea…
cstns Oct 15, 2024
ea20ca1
force instance update event to reload snapshot list after sucessfull …
cstns Oct 15, 2024
d0df0d4
qf failing linter caused by invalid characters
cstns Oct 15, 2024
b1fc4a8
add an api client for the timeline history endpoint
cstns Oct 16, 2024
4e0b3a8
adding timeline scaffolding
cstns Oct 16, 2024
f02b6ea
adding timeline event boilerplate
cstns Oct 16, 2024
5e1889e
adding timeline graph ui
cstns Oct 16, 2024
a60d6d9
extract graph into separate component and add settings update event
cstns Oct 16, 2024
8f7854e
add the ability to preview snapshots from history timeline and naviga…
cstns Oct 17, 2024
f525c9f
extract snapshot methods into a separate mixin to be used in the new …
cstns Oct 17, 2024
d0f2e22
use the snapshot response date as base for new date when exporting sn…
cstns Oct 17, 2024
eaf1e56
add a kebab context menu for snapshot events
cstns Oct 17, 2024
4e489f8
view toggle styling
cstns Oct 17, 2024
8779960
fix timeline/snapshot tab routing to work in the immersive editor as …
cstns Oct 17, 2024
4829c5e
add a timeline description
cstns Oct 17, 2024
bcb1d15
patchwork fix for a quick in vue's router-link not recognizing the ac…
cstns Oct 17, 2024
db0de6d
cleanup
cstns Oct 17, 2024
3f0dc5f
adding timeline loading screen, transitions between snapshot/timeline…
cstns Oct 17, 2024
b72f24f
trigger loading screen on snapshot rollback
cstns Oct 17, 2024
91bedca
styling in order to make the timeline page fit entire space available
cstns Oct 17, 2024
fcac56d
fix double fetching timeline data when navigating back from another i…
cstns Oct 17, 2024
10ccc8d
qf timeline list height when not enough events to fill the list
cstns Oct 17, 2024
40bf036
fix failing e2e tests
cstns Oct 18, 2024
2936fad
move instance snapshot.spec.js folder structure to reflect new versio…
cstns Oct 18, 2024
b2aa87c
force load history data after snapshot create or import to refresh th…
cstns Oct 18, 2024
071af6c
adding e2e test selector
cstns Oct 18, 2024
e3918c7
Differentiate between imported snapshot adn pipeline deployed snapsho…
cstns Oct 18, 2024
b24aff8
fix multiple history requests being made due to instance update, rely…
cstns Oct 18, 2024
3552976
fix snapshots ui after previous fix
cstns Oct 18, 2024
9e17a54
add feature mixin convenience methods to check for the timeline feature
cstns Oct 18, 2024
8733e34
add timeline empty state and disable feature for non licensed or feat…
cstns Oct 18, 2024
4c1775d
add the projectHistory as an admin team type feature option
cstns Oct 18, 2024
adbf8fa
fix timeline banners appearing at the same time
cstns Oct 18, 2024
70e17b4
add os e2e tests
cstns Oct 18, 2024
d76c7c2
paginate the history api call, load more functionality & ui
cstns Oct 18, 2024
7ffeb4d
remove padding bottom that compensated for the github chatbox as the …
cstns Oct 18, 2024
7648855
fixes no settings found and situations where snapshot events don't ha…
cstns Oct 18, 2024
9016834
fix failing e2e tests
cstns Oct 18, 2024
df66ecc
fix timeline list height for immersive editor while maintaining it sc…
cstns Oct 18, 2024
cc4e93e
qf removed test leftover
cstns Oct 18, 2024
885b6e7
add timeline fixtures and refactor snapshots to new folder structure
cstns Oct 21, 2024
18a714c
add timeline e2e tests
cstns Oct 21, 2024
a3c7d3c
qf leftover snapshot paths after refactor
cstns Oct 21, 2024
4a3c9cd
replace vertical dots with horizontal dots on the timeline graph
cstns Oct 21, 2024
efdff9a
default to snapshots page if feature not enabled for team or platform…
cstns Oct 21, 2024
98a3dee
alter os e2e test after changing the default tab for the version hist…
cstns Oct 21, 2024
d69ded8
fix timeline refresh when creating/uploading snapshot
cstns Oct 21, 2024
2033e48
fix transition fading the app loader when switching between snapshots…
cstns Oct 21, 2024
5d9f210
fix data fetch after snapshot update
cstns Oct 21, 2024
376a38a
Merge pull request #4650 from FlowFuse/visual-timeline-ui
cstns Oct 22, 2024
59ddd87
Merge remote-tracking branch 'origin/main' into visual-timeline-of-ve…
cstns Oct 22, 2024
d9c1207
merge fix
cstns Oct 22, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Differentiate between imported snapshot adn pipeline deployed snapsho…
…t, they both have the same event but differ in payload
  • Loading branch information
cstns committed Oct 18, 2024
commit e3918c79d6e1932b0018806cf9233c445c7424fa
Original file line number Diff line number Diff line change
@@ -99,10 +99,34 @@ export default {
return daysSince(this.event.createdAt, true)
},
title () {
let name
const data = this.event.data

switch (true) {
case this.event.event === 'project.snapshot.imported':
// eslint-disable-next-line no-case-declarations
const splitName = this.event.data.snapshot.name.split(' - Deploy')[0] ?? ''
name = data.snapshot.name.split(' - Deploy')[0] ?? ''

if (Object.prototype.hasOwnProperty.call(data ?? {}, 'sourceProject')) {
// we can only differentiate between a plain snapshot import and a devops deployment history event
// by its data payload (i.e. if the event has a data.sourceProject attr, we know it's from a devops pipeline)

return defineComponent({
emits: ['preview-snapshot', 'preview-instance'],
methods: {
previewSnapshot () { this.$emit('preview-snapshot') },
previewInstance () { this.$emit('preview-instance') }
},
template: `
<span>
<a href="#" @click.prevent.stop="previewSnapshot">
${name}
</a>
Snapshot deployed from
<a href="#" @click.stop.prevent="previewInstance">${this.event.data.sourceProject.name}</a>
</span>`
})
}

return defineComponent({
emits: ['preview-snapshot', 'preview-instance'],
methods: {
@@ -111,11 +135,11 @@ export default {
},
template: `
<span>
Imported
<a href="#" @click.prevent.stop="previewSnapshot">
${splitName}
${name}
</a>
Snapshot deployed from
<a href="#" @click.stop.prevent="previewInstance">${this.event.data.sourceProject.name}</a>
snapshot
</span>`
})

@@ -128,7 +152,7 @@ export default {
template: `
<span>
Snapshot Restored:
<a href="#" @click.stop.prevent="previewSnapshot">${this.event.data.snapshot.name}</a>
<a href="#" @click.stop.prevent="previewSnapshot">${data.snapshot.name}</a>
</span>`
})
case this.event.event === 'project.snapshot.created':
@@ -140,8 +164,8 @@ export default {
template: `
<span>
Snapshot Captured:
<i v-if="${!this.event.data.info.snapshotExists}">${this.event.data.snapshot.name}</i>
<a href="#" v-else @click.stop.prevent="previewSnapshot">${this.event.data.snapshot.name}</a>
<i v-if="${!data.info.snapshotExists}">${data.snapshot.name}</i>
<a href="#" v-else @click.stop.prevent="previewSnapshot">${data.snapshot.name}</a>
</span>`
})
case this.event.event === 'flows.set':
@@ -165,7 +189,11 @@ export default {
shortTitle () {
switch (true) {
case this.event.event === 'project.snapshot.imported':
return 'Pipeline Stage Pushed'
if (Object.prototype.hasOwnProperty.call(this.event.data, 'sourceProject')) {
// we can only differentiate between a plain snapshot import and a devops deployment history events
// by its data payload (i.e. if the event has a data.sourceProject attr, we know it's from a devops pipeline)
return 'Pipeline Stage Pushed'
} else return 'Snapshot Imported'
case this.event.event === 'project.snapshot.rolled-back':
return 'Snapshot Restored'
case this.event.event === 'flows.set':
@@ -181,7 +209,12 @@ export default {
}
},
isSnapshot () {
return this.event.event === 'project.snapshot.created'
// we can only differentiate between a plain snapshot import and a devops deployment history events
// by its data payload (i.e. if the event has a data.sourceProject attr, we know it's from a devops pipeline)
const isImportedSnapshot = this.event.event === 'project.snapshot.imported' &&
!Object.prototype.hasOwnProperty.call(this.event.data, 'sourceProject')

return this.event.event === 'project.snapshot.created' || isImportedSnapshot
},
snapshotExists () {
return this.isSnapshot && this.event.data.info.snapshotExists
Original file line number Diff line number Diff line change
@@ -17,7 +17,7 @@
</template>

<script>
import { AdjustmentsIcon, CameraIcon, PlusIcon } from '@heroicons/vue/outline'
import { AdjustmentsIcon, CameraIcon, DownloadIcon, PlusIcon } from '@heroicons/vue/outline'

import PipelinesIcon from '../../../../../components/icons/Pipelines.js'
import ProjectsIcon from '../../../../../components/icons/Projects.js'
@@ -39,7 +39,11 @@ export default {
icon () {
switch (true) {
case this.event.event === 'project.snapshot.imported':
return PipelinesIcon
// we can only differentiate between a plain snapshot import and a devops deployment history events
// by its data payload (i.e. if the event has a data.sourceProject attr, we know it's from a devops pipeline)
if (Object.prototype.hasOwnProperty.call(this.event.data, 'sourceProject')) {
return PipelinesIcon
} else return DownloadIcon
case this.event.event === 'project.snapshot.rolled-back':
return UndoIcon
case this.event.event === 'flows.set':
@@ -65,23 +69,42 @@ export default {
return this.timeline[currentIndex + 1]
},
isPrecededBySnapshot () {
return this.isPrecededBy?.event === 'project.snapshot.created'
// we can only differentiate between a plain snapshot import and a devops deployment history events
// by its data payload (i.e. if the event has a data.sourceProject attr, we know it's from a devops pipeline)
const isPrecededByImportedSnapshot = this.isPrecededBy?.event === 'project.snapshot.imported' &&
!Object.prototype.hasOwnProperty.call(this.isPrecededBy?.data, 'sourceProject')

return this.isPrecededBy?.event === 'project.snapshot.created' || isPrecededByImportedSnapshot
},
isSucceededBy () {
const currentIndex = this.timeline.findIndex(event => event.id === this.event.id)
return this.timeline[currentIndex - 1]
},
isSucceededBySnapshot () {
return this.isSucceededBy?.event === 'project.snapshot.created'
// we can only differentiate between a plain snapshot import and a devops deployment history events
// by its data payload (i.e. if the event has a data.sourceProject attr, we know it's from a devops pipeline)
const isSucceededByImportedSnapshot = this.isSucceededBy?.event === 'project.snapshot.imported' &&
!Object.prototype.hasOwnProperty.call(this.isSucceededBy?.data, 'sourceProject')

return this.isSucceededBy?.event === 'project.snapshot.created' || isSucceededByImportedSnapshot
},
isSnapshot () {
return this.event.event === 'project.snapshot.created'
// we can only differentiate between a plain snapshot import and a devops deployment history events
// by its data payload (i.e. if the event has a data.sourceProject attr, we know it's from a devops pipeline)
const isImportedSnapshot = this.event.event === 'project.snapshot.imported' &&
!Object.prototype.hasOwnProperty.call(this.event.data, 'sourceProject')

return this.event.event === 'project.snapshot.created' || isImportedSnapshot
},
hasSomethingToChainTo () {
const currentIndex = this.timeline.findIndex(event => event.id === this.event.id)
for (const id in this.timeline.slice(0, currentIndex)) {
if ([
'project.snapshot.imported',
if ((this.timeline[id]?.event) === 'project.snapshot.imported') {
// we can only differentiate between a plain snapshot import and a devops deployment history events
// by its data payload (i.e. if the event has a data.sourceProject attr, we know it's from a devops pipeline)
const isPipelineDeployment = Object.prototype.hasOwnProperty.call(this.timeline[id]?.data, 'sourceProject')
if (isPipelineDeployment) return true
} else if ([
'project.snapshot.rolled-back',
'flows.set',
'project.created',