Skip to content

Commit d45bbf7

Browse files
authored
Merge pull request #6684 from FlowFuse/reenable-immersive-mode-for-remote-instances
Reenable immersive mode for remote instances
2 parents ba2ffcc + ccab690 commit d45bbf7

6 files changed

Lines changed: 153 additions & 20 deletions

File tree

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
<template>
2+
<div>
3+
<slot name="default">
4+
<!-- Minimal view: simple icon-only button (used in InstanceTile) -->
5+
<ff-button
6+
v-if="minimalView"
7+
:title="(editorDisabled || disabled) ? disabledReason : undefined"
8+
kind="tertiary"
9+
data-action="open-editor"
10+
:disabled="buttonDisabled"
11+
class="whitespace-nowrap ff-btn-icon editor-link-minimal"
12+
:emit-instead-of-navigate="true"
13+
@click.stop.prevent="openImmersiveEditor"
14+
@click.middle.stop.prevent="openImmersiveEditor"
15+
>
16+
<template #icon-left>
17+
<ProjectIcon />
18+
</template>
19+
</ff-button>
20+
21+
<!-- Full view: split dropdown button -->
22+
<div v-else class="editor-link-split" :class="{ 'editor-link-split--primary': primary }">
23+
<button
24+
:title="buttonDisabled ? disabledReason : undefined"
25+
class="editor-link-split__action"
26+
:class="{ 'editor-link-split--disabled': buttonDisabled }"
27+
data-action="open-editor"
28+
:disabled="buttonDisabled"
29+
@click.stop.prevent="openImmersiveEditor"
30+
@click.middle.stop.prevent="openImmersiveEditor"
31+
>
32+
<ProjectIcon class="ff-btn--icon mr-2" />
33+
<span class="hidden sm:inline editor-link-text">{{ editorDisabled ? 'Editor Disabled' : 'Open Editor' }}</span>
34+
</button>
35+
<DropdownMenu
36+
class="editor-link-split__dropdown"
37+
:buttonClass="'editor-link-split__toggle' + (buttonDisabled ? ' editor-link-split--disabled' : '')"
38+
:options="dropdownOptions"
39+
:disabled="buttonDisabled"
40+
@click.stop
41+
/>
42+
</div>
43+
</slot>
44+
</div>
45+
</template>
46+
47+
<script>
48+
import DropdownMenu from '../../../components/DropdownMenu.vue'
49+
import ProjectIcon from '../../../components/icons/Projects.js'
50+
51+
export default {
52+
name: 'DeviceEditorLink',
53+
components: {
54+
ProjectIcon,
55+
DropdownMenu
56+
},
57+
props: {
58+
editorDisabled: {
59+
default: false,
60+
type: Boolean
61+
},
62+
disabled: {
63+
default: false,
64+
type: Boolean
65+
},
66+
disabledReason: {
67+
default: null,
68+
type: String
69+
},
70+
device: {
71+
type: Object,
72+
required: true
73+
},
74+
showText: {
75+
default: true,
76+
type: Boolean
77+
},
78+
minimalView: {
79+
type: Boolean,
80+
default: false
81+
},
82+
primary: {
83+
type: Boolean,
84+
default: false
85+
}
86+
},
87+
emits: ['open-immersive-editor', 'open-editor'],
88+
computed: {
89+
buttonDisabled () {
90+
return !!(this.disabled && !this.device?.editor?.url)
91+
},
92+
dropdownOptions () {
93+
return [
94+
{ name: 'Open Direct URL', action: this.openEditor }
95+
]
96+
}
97+
},
98+
methods: {
99+
openImmersiveEditor (event) {
100+
this.$emit('open-immersive-editor', event)
101+
},
102+
openEditor (event) {
103+
this.$emit('open-editor', event)
104+
}
105+
}
106+
}
107+
</script>
108+
109+
<style scoped lang="scss">
110+
111+
</style>

frontend/src/pages/device/index.vue

Lines changed: 38 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -38,15 +38,26 @@
3838
<div class="flex gap-2 align-center" style="height: 34px;">
3939
<template v-if="isDevModeAvailable">
4040
<DeveloperModeToggle data-el="device-devmode-toggle" :device="device" :disabled="disableModeToggle" :disabledReason="disableModeToggleReason" @mode-change="setDeviceMode" />
41-
<button v-if="!isVisitingAdmin" v-ff-tooltip:left="!editorAvailable ? 'You can edit flows directly when Developer Mode is enabled, and your Edge Instance is connected.' : 'Open Edge Instance Editor'" data-action="open-editor" class="ff-btn transition-fade--color ff-btn--secondary ff-btn-icon h-9" :disabled="!editorAvailable" @click="openTunnel(true)">
42-
Open Editor
43-
<span class="ff-btn--icon ff-btn--icon-right">
44-
<ExternalLinkIcon />
45-
</span>
46-
</button>
41+
<device-editor-link
42+
:device="device"
43+
:title="!editorAvailable ? 'You can edit flows directly when Developer Mode is enabled, and your Edge Instance is connected.' : 'Open Edge Instance Editor'"
44+
:disabled="!editorAvailable"
45+
:primary="editorAvailable"
46+
data-action="open-editor"
47+
@open-immersive-editor="openTunnel({launchEditor: true, event: $event, immersive: true})"
48+
@open-editor="openTunnel({launchEditor: true, event: $event, immersive: false})"
49+
/>
4750
</template>
4851
<FinishSetupButton v-if="hasPermission('device:create', {application: device.application}) && neverConnected" :device="device" />
49-
<DropdownMenu v-if="hasPermission('device:change-status', permissionContext) && actionsDropdownOptions.length" data-el="device-actions-dropdown" buttonClass="ff-btn ff-btn--primary" :options="actionsDropdownOptions">Actions</DropdownMenu>
52+
<DropdownMenu
53+
v-if="hasPermission('device:change-status', permissionContext) && actionsDropdownOptions.length"
54+
data-el="device-actions-dropdown"
55+
:buttonClass="`ff-btn ff-btn-icon ${ editorAvailable ? 'ff-btn--secondary' : 'ff-btn--primary'}`"
56+
:options="actionsDropdownOptions"
57+
>
58+
<CogIcon class="ff-btn--icon ff-btn--icon-left" />
59+
Actions
60+
</DropdownMenu>
5061
</div>
5162
</template>
5263
</SectionNavigationHeader>
@@ -110,8 +121,7 @@
110121

111122
<script>
112123
113-
import { ExternalLinkIcon } from '@heroicons/vue/outline'
114-
// import { TerminalIcon } from '@heroicons/vue/solid'
124+
import { CogIcon } from '@heroicons/vue/solid/index.js'
115125
import semver from 'semver'
116126
import { mapState } from 'vuex'
117127
@@ -122,6 +132,7 @@ import SectionNavigationHeader from '../../components/SectionNavigationHeader.vu
122132
import StatusBadge from '../../components/StatusBadge.vue'
123133
import SubscriptionExpiredBanner from '../../components/banners/SubscriptionExpired.vue'
124134
import TeamTrialBanner from '../../components/banners/TeamTrial.vue'
135+
import { useNavigationHelper } from '../../composables/NavigationHelper.js'
125136
import usePermissions from '../../composables/Permissions.js'
126137
import deviceActionsMixin from '../../mixins/DeviceActions.js'
127138
@@ -136,6 +147,7 @@ import DeviceAssignInstanceDialog from '../team/Devices/dialogs/DeviceAssignInst
136147
import AssignDeviceDialog from './components/AssignDeviceDialog.vue'
137148
138149
import DeveloperModeToggle from './components/DeveloperModeToggle.vue'
150+
import DeviceEditorLink from './components/DeviceEditorLink.vue'
139151
import DeviceLastSeenBadge from './components/DeviceLastSeenBadge.vue'
140152
import DeviceModeBadge from './components/DeviceModeBadge.vue'
141153
@@ -155,8 +167,9 @@ const deviceTransitionStates = [
155167
export default {
156168
name: 'DevicePage',
157169
components: {
170+
CogIcon,
171+
DeviceEditorLink,
158172
FinishSetupButton,
159-
ExternalLinkIcon,
160173
DeveloperModeToggle,
161174
DeviceModeBadge,
162175
DeviceLastSeenBadge,
@@ -172,8 +185,9 @@ export default {
172185
mixins: [deviceActionsMixin],
173186
setup () {
174187
const { hasPermission, isVisitingAdmin } = usePermissions()
188+
const { navigateTo, openInANewTab } = useNavigationHelper()
175189
176-
return { hasPermission, isVisitingAdmin }
190+
return { hasPermission, isVisitingAdmin, navigateTo, openInANewTab }
177191
},
178192
data: function () {
179193
return {
@@ -425,16 +439,23 @@ export default {
425439
426440
Alerts.emit('Device successfully assigned to application.', 'confirmation')
427441
},
428-
openEditor () {
442+
openEditor ({ event = null, immersive = false } = {}) {
429443
this.$store.dispatch('ux/validateUserAction', 'hasOpenedDeviceEditor')
430-
window.open(this.deviceEditorURL, `device-editor-${this.device.id}`)
431-
// this.$router.push({ name: 'device-editor' })
444+
if (!immersive) {
445+
this.openInANewTab(this.deviceEditorURL, `device-editor-${this.device.id}`)
446+
} else {
447+
this.navigateTo('editor', event, { target: `device-editor-${this.device.id}` })
448+
}
432449
},
433-
async openTunnel (launchEditor = false) {
450+
async openTunnel ({
451+
event,
452+
immersive = true,
453+
launchEditor = false
454+
} = {}) {
434455
try {
435456
if (this.deviceRunning) {
436457
if (this.device.editor?.enabled && this.device.editor?.connected && this.device.editor?.local) {
437-
this.openEditor()
458+
this.openEditor({ event, immersive })
438459
} else {
439460
this.openingTunnel = true
440461
this.$refs.dialog.show()
@@ -448,7 +469,7 @@ export default {
448469
if (this.device.editor?.enabled && this.device.editor?.connected) {
449470
if (this.device.editor?.local) {
450471
if (launchEditor) {
451-
this.openEditor()
472+
this.openEditor({ event, immersive })
452473
}
453474
} else {
454475
pollTunnelStatus(done, attempt + 1, 200)

frontend/src/pages/instance/Overview.vue

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -161,8 +161,7 @@
161161
</template>
162162

163163
<script>
164-
import { ExternalLinkIcon, ServerIcon, TemplateIcon, TrendingUpIcon } from '@heroicons/vue/outline'
165-
import { ArrowRightIcon } from '@heroicons/vue/outline'
164+
import { ArrowRightIcon, ExternalLinkIcon, ServerIcon, TemplateIcon, TrendingUpIcon } from '@heroicons/vue/outline'
166165
import { mapState } from 'vuex'
167166
168167
import InstanceApi from '../../api/instances.js'

frontend/src/pages/instance/components/EditorLink.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
@click.stop.prevent="openEditor"
3030
@click.middle.stop.prevent="openEditor"
3131
>
32-
<ProjectIcon class="ff-btn--icon" />
32+
<ProjectIcon class="ff-btn--icon mr-2" />
3333
<span class="hidden sm:inline editor-link-text">{{ editorDisabled ? 'Editor Disabled' : 'Open Editor' }}</span>
3434
</button>
3535
<DropdownMenu

frontend/src/pages/team/Home/components/RecentlyModifiedDevices.vue

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ export default {
139139
display: flex;
140140
width: 100%;
141141
height: fit-content;
142+
min-height: 55px;
142143
justify-content: space-between;
143144
align-items: center;
144145
gap: 10px;

frontend/src/pages/team/Home/components/RecentlyModifiedInstances.vue

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ export default {
110110
display: flex;
111111
width: 100%;
112112
height: fit-content;
113+
min-height: 55px;
113114
justify-content: space-between;
114115
align-items: center;
115116
gap: 10px;

0 commit comments

Comments
 (0)