Skip to content

Commit

Permalink
Merge branch 'main' into 3715-health-check-interval
Browse files Browse the repository at this point in the history
  • Loading branch information
Steve-Mcl authored May 2, 2024
2 parents 4479eb4 + 2c2a7aa commit 214d704
Show file tree
Hide file tree
Showing 33 changed files with 759 additions and 160 deletions.
4 changes: 2 additions & 2 deletions .github/ISSUE_TEMPLATE/06-story.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ body:
- type: dropdown
id: pricing
attributes:
label: Which customers would this be availble to
label: Which customers would this be available to
description: Based on our [pricing principles](https://flowfuse.com/handbook/product/pricing/) features should be aligned between Cloud and CE/EE
multiple: false
options:
Expand Down Expand Up @@ -58,4 +58,4 @@ body:
- I am not a FlowFuse team member
- I can not provide an initial effort estimate
validations:
required: true
required: true
12 changes: 6 additions & 6 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ jobs:
- name: Run Linting Tests
run: npm run lint
- name: Run UI Unit Tests
run: npm run cover:unit:frontend
run: npm run test:unit:frontend
- name: Run UI E2E (Cypress) Tests - OS
uses: cypress-io/github-action@v4
with:
Expand All @@ -169,11 +169,11 @@ jobs:
path: |
test/e2e/frontend/cypress/screenshots
test/e2e/frontend/cypress/videos
- name: Upload coverage reports to Codecov
uses: codecov/codecov-action@v3
with:
token: ${{ secrets.CODECOV_TOKEN }}
flags: frontend
# - name: Upload coverage reports to Codecov
# uses: codecov/codecov-action@v3
# with:
# token: ${{ secrets.CODECOV_TOKEN }}
# flags: frontend

notify-slack:
name: Notify on failure
Expand Down
25 changes: 12 additions & 13 deletions forge/db/controllers/ProjectSnapshot.js
Original file line number Diff line number Diff line change
Expand Up @@ -500,30 +500,29 @@ module.exports = {
* @param {Object} [options.credentials] (Optional) credentials to export. If omitted, credentials of the current project will be re-encrypted, with credentialSecret.
*/
exportSnapshot: async function (app, project, snapshot, options) {
let snapshotObj = snapshot.get()
if (!options.credentialSecret) {
return null
}
const user = await snapshot.getUser()
if (user) {
snapshotObj.user = app.db.views.User.userSummary(user)
const { UserId, id, ...newSnapshotObj } = snapshotObj
snapshotObj = newSnapshotObj
snapshotObj.id = snapshotObj.hashid
if (snapshot.UserId && !snapshot.User) {
await snapshot.reload({ include: [app.db.models.User] })
}

const result = {
...snapshot.toJSON()
}

const serviceEnv = ['FF_INSTANCE_ID', 'FF_INSTANCE_NAME', 'FF_PROJECT_ID', 'FF_PROJECT_NAME']
serviceEnv.forEach((key) => {
delete snapshotObj.settings.env[key]
delete result.settings.env[key]
})
const result = {
...snapshotObj
}
const projectSecret = await project.getCredentialSecret()

// use the secret stored in the snapshot, if available...
const projectSecret = result.credentialSecret || await project.getCredentialSecret()
const credentials = options.credentials ? options.credentials : result.flows.credentials

// if provided credentials already encrypted: "exportCredentials" will just return the same credentials
// if provided credentials are raw: "exportCredentials" will encrypt them with the secret provided
// if credentials are not provided: project's flows credentials will be used, they will be encrypted with the provided secret
// if credentials are not provided: project's flows credentials will be used, they will be encrypted with either the provided secret or a new one
const keyToDecrypt = (options.credentials && options.credentials.$) ? options.credentialSecret : projectSecret
result.flows.credentials = app.db.controllers.Project.exportCredentials(credentials || {}, keyToDecrypt, options.credentialSecret)

Expand Down
27 changes: 25 additions & 2 deletions forge/db/views/ProjectSnapshot.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,14 +80,37 @@ module.exports = function (app) {
updatedAt: { type: 'string' },
user: { $ref: 'UserSummary' },
exportedBy: { $ref: 'UserSummary' },
modules: { type: 'object', additionalProperties: true },
flows: { type: 'object', additionalProperties: true },
settings: { type: 'object', additionalProperties: true }
}
})
function snapshotExport (snapshot) {
if (snapshot) {
const result = snapshot.toJSON ? snapshot.toJSON() : snapshot
const filtered = {
id: result.hashid,
name: result.name,
description: result.description || '',
createdAt: result.createdAt,
updatedAt: result.updatedAt,
flows: result.flows,
settings: result.settings
}
if (snapshot.User) {
filtered.user = app.db.views.User.userSummary(snapshot.User)
}
if (snapshot.exportedBy) {
filtered.exportedBy = app.db.views.User.userSummary(snapshot.exportedBy)
}
return filtered
} else {
return null
}
}

return {
snapshot,
snapshotSummary
snapshotSummary,
snapshotExport
}
}
11 changes: 6 additions & 5 deletions forge/routes/api/projectSnapshots.js
Original file line number Diff line number Diff line change
Expand Up @@ -248,15 +248,16 @@ module.exports = async function (app) {
reply.code(400).send({ code: 'bad_request', error: 'credentialSecret is mandatory in the body' })
}

const snapShot = await app.db.controllers.ProjectSnapshot.exportSnapshot(
const snapshot = await app.db.controllers.ProjectSnapshot.exportSnapshot(
request.project,
request.snapshot,
request.body
)
if (snapShot) {
await app.auditLog.Project.project.snapshot.exported(request.session.User, null, request.project, snapShot)
snapShot.exportedBy = request.session.User
reply.send(snapShot)
if (snapshot) {
const snapshotExport = app.db.views.ProjectSnapshot.snapshotExport(snapshot)
snapshotExport.exportedBy = app.db.views.User.userSummary(request.session.User)
await app.auditLog.Project.project.snapshot.exported(request.session.User, null, request.project, snapshot)
reply.send(snapshotExport)
} else {
reply.send({})
}
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/CodePreviewer.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<template>
<pre class="ff-code-previewer"><code>{{ strippedSnippet }}</code></pre>
<pre class="ff-code-previewer" data-el="ff-code-previewer"><code>{{ strippedSnippet }}</code></pre>
</template>

<script>
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/SectionNavigationHeader.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<div class="inline-flex flex-wrap gap-1">
<div class="flex items-center mr-6">
<slot name="breadcrumbs" />
<ff-nav-breadcrumb data-el="page-name">{{ title }}</ff-nav-breadcrumb>
<ff-nav-breadcrumb data-el="page-name" data-cy="page-name">{{ title }}</ff-nav-breadcrumb>
<InformationCircleIcon v-if="hasInfoDialog" class="ml-3 min-w-[20px] ff-icon text-gray-800 cursor-pointer hover:text-blue-700" @click="openInfoDialog()" />
</div>
<slot name="status" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import { CheckCircleIcon, QuestionMarkCircleIcon } from '@heroicons/vue/outline'
import { defineAsyncComponent } from 'vue'
import { mapState } from 'vuex'
import product from '../../../services/product.js'
import product from '../../services/product.js'
export default {
name: 'BlueprintTile',
Expand Down
34 changes: 34 additions & 0 deletions frontend/src/components/flow-viewer/FlowViewer.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<template>
<div ref="viewer" data-el="ff-flow-previewer" class="ff-flow-viewer">
{{ flow }}
</div>
</template>

<script>
import FlowRenderer from '@flowfuse/flow-renderer'
export default {
name: 'FlowViewer',
props: {
flow: { required: true, type: Object }
},
mounted () {
this.render()
},
methods: {
render () {
const flowRenderer = new FlowRenderer()
flowRenderer.renderFlows(this.flow, {
container: this.$refs.viewer
})
}
}
}
</script>

<style scoped>
.ff-flow-viewer {
height: 600px;
}
</style>
17 changes: 17 additions & 0 deletions frontend/src/mixins/Features.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { mapState } from 'vuex'

export default {
computed: {
...mapState('account', ['features']),
isSharedLibraryFeatureEnabledForTeam () {
const flag = this.team.type.properties.features?.['shared-library']
return flag === undefined || flag
},
isSharedLibraryFeatureEnabledForPlatform () {
return this.features['shared-library']
},
isSharedLibraryFeatureEnabled () {
return this.isSharedLibraryFeatureEnabledForTeam && this.isSharedLibraryFeatureEnabledForPlatform
}
}
}
3 changes: 1 addition & 2 deletions frontend/src/pages/admin/FlowBlueprints/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,10 @@ import teamTypesApi from '../../../api/teamTypes.js'
import SectionTopMenu from '../../../components/SectionTopMenu.vue'
import BlueprintTile from '../../../components/blueprints/BlueprintTile.vue'
import MarkdownCell from '../../../components/tables/cells/MarkdownCell.vue'
import Dialog from '../../../services/dialog.js'
import BlueprintTile from '../../instance/Blueprints/BlueprintTile.vue'
import FlowBlueprintFormDialog from './dialogs/FlowBlueprintFormDialog.vue'
const marked = require('marked')
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/pages/admin/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ export default [
]
},
{
name: 'Admin Flow Blueprints',
name: 'AdminFlowBlueprints',
path: 'flow-blueprints',
component: AdminFlowBlueprints,
meta: {
Expand Down
5 changes: 2 additions & 3 deletions frontend/src/pages/instance/Blueprints/BlueprintSelection.vue
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
<script>
import flowBlueprintsApi from '../../../api/flowBlueprints.js'
import BlueprintTile from './BlueprintTile.vue'
import BlueprintTile from '../../../components/blueprints/BlueprintTile.vue'
export default {
name: 'BlueprintSelection',
Expand Down Expand Up @@ -54,9 +54,8 @@ export default {
methods: {
async loadBlueprints () {
const response = await flowBlueprintsApi.getFlowBlueprints()
const blueprints = response.blueprints
this.localBlueprints = blueprints
this.localBlueprints = response.blueprints
}
}
}
Expand Down
2 changes: 0 additions & 2 deletions frontend/src/pages/instance/Editor/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ import InstanceActionsButton from '../../../components/instance/ActionButton.vue
import FfPage from '../../../layouts/Page.vue'
import instanceMixin from '../../../mixins/Instance.js'
import FfTabs from '../../../ui-components/components/tabs/Tabs.vue'
import DashboardLink from '../components/DashboardLink.vue'
import EditorWrapper from './components/EditorWrapper.vue'
Expand All @@ -82,7 +81,6 @@ export default {
DashboardLink,
MiddleCloseButton,
DrawerTrigger,
FfTabs,
EditorWrapper,
InstanceStatusPolling,
ExternalLinkIcon,
Expand Down
18 changes: 14 additions & 4 deletions frontend/src/pages/instance/components/InstanceForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,6 @@ export default {
required: true,
type: Object
},
// EE Features
billingEnabled: {
default: false,
Expand All @@ -316,7 +315,6 @@ export default {
default: false,
type: Boolean
},
// Instance
instance: {
default: null,
Expand Down Expand Up @@ -347,6 +345,11 @@ export default {
applicationFieldsVisible: {
default: false,
type: Boolean
},
// allows setting predefined values when the component is created
preDefinedInputs: {
default: null,
type: Object
}
},
emits: ['on-submit'],
Expand Down Expand Up @@ -483,14 +486,14 @@ export default {
}
},
watch: {
'input.name': function (value, oldValue) {
'input.name': function (value) {
if (/^[a-zA-Z][a-zA-Z0-9-]*$/.test(value)) {
this.errors.name = ''
} else {
this.errors.name = 'Names must only include a→z, A→Z, -, 0→9 and can not start with 0→9'
}
},
'input.projectType': async function (value, oldValue) {
'input.projectType': async function (value) {
if (value) {
await this.updateInstanceType(value)
} else {
Expand Down Expand Up @@ -612,6 +615,13 @@ export default {
// Falls back to the default blueprint server side no error needed
console.warn('Flow Blueprints enabled but none available')
}
if (this.preDefinedInputs) {
this.input = {
...this.input,
...this.preDefinedInputs
}
}
},
async beforeMount () {
// Billing feature must be enabled
Expand Down
6 changes: 6 additions & 0 deletions frontend/src/pages/instance/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,12 @@ const children = [
export { children }

export default [
{
path: '/project/:id/:remaining*',
redirect: to => {
return { name: 'Instance', params: to.params }
}
},
{
path: '/instance/:id/:remaining*',
redirect: to => {
Expand Down
Loading

0 comments on commit 214d704

Please sign in to comment.