diff --git a/.github/workflows/branch-deploy.yaml b/.github/workflows/branch-deploy.yaml index 394881e3b4..9c85b470c5 100644 --- a/.github/workflows/branch-deploy.yaml +++ b/.github/workflows/branch-deploy.yaml @@ -22,6 +22,10 @@ on: description: 'flowfuse/nr-file-nodes branch name' required: true default: 'main' + nr_assistant_branch: + description: 'flowfuse/nr-assistant branch name' + required: true + default: 'main' pull_request: types: - opened @@ -120,16 +124,34 @@ jobs: secrets: npm_registry_token: ${{ secrets.NPM_PUBLISH_TOKEN }} + publish_nr_assistant: + name: Build and publish nr-assistant package + needs: validate-user + if: | + needs.validate-user.outputs.is_org_member == 'true' && + github.event_name == 'workflow_dispatch' && + inputs.nr_assistant_branch != 'main' + uses: 'flowfuse/github-actions-workflows/.github/workflows/publish_node_package.yml@v0.38.0' + with: + package_name: nr-assistant + publish_package: true + repository_name: 'FlowFuse/nr-assistant' + branch_name: ${{ inputs.nr_assistant_branch }} + release_name: "pre-staging-${{ inputs.nr_assistant_branch }}" + secrets: + npm_registry_token: ${{ secrets.NPM_PUBLISH_TOKEN }} + publish_nr_launcher: name: Build and publish nr-launcher package needs: - validate-user - publish_nr_project_nodes - publish_nr_file_nodes + - publish_nr_assistant if: | needs.validate-user.outputs.is_org_member == 'true' && github.event_name == 'workflow_dispatch' && - (always() && inputs.nr_launcher_branch != 'main') || needs.publish_nr_project_nodes.result == 'success' || needs.publish_nr_file_nodes.result == 'success' + (always() && inputs.nr_launcher_branch != 'main') || needs.publish_nr_project_nodes.result == 'success' || needs.publish_nr_file_nodes.result == 'success' || needs.publish_nr_assistant.result == 'success' uses: 'flowfuse/github-actions-workflows/.github/workflows/publish_node_package.yml@v0.38.0' with: package_name: flowfuse-nr-launcher @@ -140,7 +162,7 @@ jobs: package_dependencies: | @flowfuse/nr-project-nodes=${{ inputs.nr_project_nodes_branch != 'main' && needs.publish_nr_project_nodes.outputs.release_name || 'nightly' }} @flowfuse/nr-file-nodes=${{ inputs.nr_file_nodes_branch != 'main' && needs.publish_nr_file_nodes.outputs.release_name || 'nightly' }} - @flowfuse/nr-assistant=nightly + @flowfuse/nr-assistant=${{ inputs.nr_assistant_branch != 'main' && needs.publish_nr_assistant.outputs.release_name || 'nightly' }} secrets: npm_registry_token: ${{ secrets.NPM_PUBLISH_TOKEN }} diff --git a/docs/install/docker/README.md b/docs/install/docker/README.md index ff7d147cb3..91774ec9db 100644 --- a/docs/install/docker/README.md +++ b/docs/install/docker/README.md @@ -87,7 +87,7 @@ The following guide walks through a full production-ready deployment. If you wan Before you begin, ensure you have the following: 1. **Domain Name & DNS:** A domain name that you own and can configure DNS settings for (explained in [DNS](#dns)) -2. **Install Docker:** [Docker Engine](https://docs.docker.com/engine/) and [Docker Compose](https://docs.docker.com/compose/install/) must be installed on your system (either as a standalone binary or as docker plugin) +2. **Install Docker:** [Docker Engine](https://docs.docker.com/engine/) and [Docker Compose](https://docs.docker.com/compose/install/) (in `2.23.1` version or higher) must be installed on your system (either as a standalone binary or as docker plugin). For a production-ready environment, we also recommend: * **Database:** Prepare dedicated database on a external database server (see [FAQ](#how-to-use-external-database-server%3F) for more details) diff --git a/docs/quick-start/README.md b/docs/quick-start/README.md index 5ea6190e76..a54754c962 100644 --- a/docs/quick-start/README.md +++ b/docs/quick-start/README.md @@ -28,7 +28,7 @@ For a full installation guide, including how to setup FlowFuse in a production e ## Prerequisites -Before you begin, ensure you have [Docker](https://docs.docker.com/engine/install/) and [Docker Compose](https://docs.docker.com/compose/install/) installed on your system (either as a standalone binary or as docker plugin) +Before you begin, ensure you have [Docker](https://docs.docker.com/engine/install/) and [Docker Compose](https://docs.docker.com/compose/install/) (in `2.23.1` version or higher) installed on your system (either as a standalone binary or as docker plugin) ## Step 1: Configure Domain diff --git a/docs/upgrade/open-source-to-premium.md b/docs/upgrade/open-source-to-premium.md index d65e6d351c..38738eeba1 100644 --- a/docs/upgrade/open-source-to-premium.md +++ b/docs/upgrade/open-source-to-premium.md @@ -21,26 +21,3 @@ a restart of the `forge` app is required. After the forge application has restarted, the Node-RED runtimes need to be updated to leverage these features. As restarting Node-RED might need to be coordinated, FlowFuse will not automatically restart all instances. - -## Enabling FlowFuse User Authentication for @flowfuse/node-red-dashboard - -Included with the Enterprise licensed FlowFuse is the ability to use -FlowFuse Authentication to control access to Dashboards and to have the -user information passed to the Node-RED Flow. - -This is enabled by installing a Node-RED plugin `@flowfuse/node-red-dashboard-2-user-addon`. -To install this plugin you will require a npm authentication token. To request -one please contact support@flowfuse.com. - -Once you have been supplied with a authentication token please follow these steps: - -1. Under the Admin Settings page, open the Templates tab and edit the template -2. On the Palette page of the Template settings add the following to the "Node Catalogues" list `https://catalog.flowfuse.com/catalogue.json` -3. In the "NPM configuration file" section you will need to add - ``` - //registry.npmjs.org/:_authToken= - ``` - replacing `` with the token supplied earlier -4. Click on the "Save changes" button -5. Any existing Node-RED instances will need to be restarted to pick up the changes to the template -6. Once restarted you should be able to install the `@flowfuse/node-red-dashboard-2-user-addon` from the Palette Manage menu in the Node-RED instance. diff --git a/forge/routes/api/device.js b/forge/routes/api/device.js index 8eff12beed..176a3a4b41 100644 --- a/forge/routes/api/device.js +++ b/forge/routes/api/device.js @@ -646,7 +646,19 @@ module.exports = async function (app) { const currentSettings = await request.device.getAllSettings() // remove any extra properties from env to ensure they match the format of the body data // and prevent updates from being logged for unchanged values - currentSettings.env = (currentSettings.env || []).map(e => ({ name: e.name, value: e.value })) + currentSettings.env = (currentSettings.env || []).map(e => ({ name: e.name, value: e.value, hidden: e.hidden ?? false })) + if (request.body.env) { + request.body.env.map(env => { + if (env.hidden === true && env.value === '') { + // we need to re-map the hidden value so it won't get overwritten + const existingVar = currentSettings.env.find(currentEnv => currentEnv.name === env.name) + if (existingVar) { + env.value = existingVar.value + } + } + return env + }) + } const captureUpdates = (key) => { if (key === 'env') { // transform the env array to a map for better logging format diff --git a/frontend/src/components/DevicesBrowser.vue b/frontend/src/components/DevicesBrowser.vue index fa6b53cbff..d09af5ee5f 100644 --- a/frontend/src/components/DevicesBrowser.vue +++ b/frontend/src/components/DevicesBrowser.vue @@ -235,7 +235,10 @@ @device-updated="deviceUpdated" > @@ -314,7 +317,7 @@ import { ClockIcon } from '@heroicons/vue/outline' import { PlusSmIcon } from '@heroicons/vue/solid' import { markRaw } from 'vue' -import { mapState } from 'vuex' +import { mapGetters, mapState } from 'vuex' import deviceApi from '../api/devices.js' import teamApi from '../api/team.js' @@ -402,6 +405,8 @@ export default { }, computed: { ...mapState('account', ['team', 'teamMembership']), + ...mapState('ux', ['tours']), + ...mapGetters('account', ['featuresCheck']), columns () { const columns = [ { label: 'Remote Instance', key: 'name', sortable: !this.moreThanOnePage, component: { is: markRaw(DeviceLink) } }, diff --git a/frontend/src/components/NavItem.vue b/frontend/src/components/NavItem.vue index 55cf81e893..8af10fc7bf 100644 --- a/frontend/src/components/NavItem.vue +++ b/frontend/src/components/NavItem.vue @@ -7,6 +7,9 @@ + + + @@ -14,12 +17,15 @@ + + diff --git a/frontend/src/pages/application/Devices.vue b/frontend/src/pages/application/Devices.vue index d62e3e825f..9d835ccb68 100644 --- a/frontend/src/pages/application/Devices.vue +++ b/frontend/src/pages/application/Devices.vue @@ -20,9 +20,6 @@ import { mapState } from 'vuex' import DevicesBrowser from '../../components/DevicesBrowser.vue' import SectionTopMenu from '../../components/SectionTopMenu.vue' -import Tours from '../../tours/Tours.js' - -import TourFirstDevice from '../../tours/tour-first-device.json' export default { name: 'ApplicationDevices', @@ -38,12 +35,6 @@ export default { }, computed: { ...mapState('ux', ['tours']) - }, - mounted () { - if (this.tours['first-device']) { - const tour = Tours.create('first-device', TourFirstDevice, this.$store) - tour.start() - } } } diff --git a/frontend/src/pages/application/routes.js b/frontend/src/pages/application/routes.js index e1f330bd07..80a6fa746d 100644 --- a/frontend/src/pages/application/routes.js +++ b/frontend/src/pages/application/routes.js @@ -161,8 +161,16 @@ export default [ sourceInstanceId: route.query.sourceInstanceId }), meta: { - // todo add a back button - title: 'Application - Instances - Create' + title: 'Application - Instances - Create', + menu: { + type: 'back', + backTo: ({ query, params }) => { + return { + label: 'Back', + to: { name: 'ApplicationInstances', params, query } + } + } + } } }, { @@ -179,7 +187,6 @@ export default [ name: 'ApplicationDeviceGroupDevices', component: ApplicationDeviceGroupDevices, meta: { - // todo add a back button to the application device-groups title: 'Application - Device Group - Members' } }, @@ -188,7 +195,6 @@ export default [ name: 'ApplicationDeviceGroupSettings', component: ApplicationDeviceGroupSettings, meta: { - // todo add back button title: 'Application - Device Group - Settings' }, redirect: { diff --git a/frontend/src/pages/device/index.vue b/frontend/src/pages/device/index.vue index f2651ab104..57aae2cdb9 100644 --- a/frontend/src/pages/device/index.vue +++ b/frontend/src/pages/device/index.vue @@ -397,6 +397,7 @@ export default { Alerts.emit('Device successfully assigned to application.', 'confirmation') }, openEditor () { + this.$store.dispatch('ux/validateUserAction', 'hasOpenedDeviceEditor') window.open(this.deviceEditorURL, `device-editor-${this.device.id}`) }, async openTunnel (launchEditor = false) { diff --git a/frontend/src/pages/team/Applications/index.vue b/frontend/src/pages/team/Applications/index.vue index 0c8d011202..b515a85b46 100644 --- a/frontend/src/pages/team/Applications/index.vue +++ b/frontend/src/pages/team/Applications/index.vue @@ -102,7 +102,7 @@