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

Move instance pages under team namespace #4905

Draft
wants to merge 15 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
9 changes: 7 additions & 2 deletions frontend/src/components/SectionSideMenu.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<template>
<ul class="mb-6 sm:mb-0 w-full pb-4 sm:pb-0 sm:w-32 border-b sm:border-b-0 sm:border-r overflow-hidden border-gray-400 mr-6 text-gray-500 space-y-2" data-el="section-side-menu">
<template v-for="item in options" :key="item.name">
<template v-for="item in filteredOptions" :key="item.name">
<li class="block">
<router-link :to="item.path" class="block text-sm px-3 py-1 sm:py-2 pl-3 ml-1" exact-active-class="text-blue-700 ml-0 border-l-4 border-blue-700" :data-nav="item.name.toLowerCase()">{{ item.name }}</router-link>
</li>
Expand All @@ -11,7 +11,12 @@

export default {
name: 'SectionSideMenu',
props: ['options']
props: ['options'],
computed: {
filteredOptions () {
return this.options.filter(option => !option.hidden ?? true)
}
}
}

</script>
8 changes: 6 additions & 2 deletions frontend/src/components/audit-log/AuditEntry.vue
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@
<router-link class="flex content-center" :to="{ name: 'Device', params: { id: entry.scope.id } }"><ChipIcon class="ff-icon relative invisible lg:visible " /> <span class="truncate ml-2 !leading-normal">{{ association.name }}</span></router-link>
</template>
<template v-else-if="association && entry.scope.type === 'project'">
<router-link class="flex content-center" :to="{ name: 'Instance', params: { id: entry.scope.id } }"><ProjectsIcon class="ff-icon relative invisible lg:visible" /> <span class="truncate ml-2 !leading-normal">{{ association.name }}</span></router-link>
<router-link class="flex content-center" :to="{ name: 'Instance', params: { id: entry.scope.id, team_slug: team.slug } }"><ProjectsIcon class="ff-icon relative invisible lg:visible" /> <span class="truncate ml-2 !leading-normal">{{ association.name }}</span></router-link>
</template>
<template v-else-if="association && entry.scope.type === 'application'">
<router-link class="flex content-center" :to="{ name: 'Application', params: { id: entry.scope.id }}"><TemplateIcon class="ff-icon relative invisible lg:visible" /> <span class="truncate ml-2 !leading-normal">{{ association.name }}</span></router-link>
<router-link class="flex content-center" :to="{ name: 'Application', params: { id: entry.scope.id, team_slug: team.slug }}"><TemplateIcon class="ff-icon relative invisible lg:visible" /> <span class="truncate ml-2 !leading-normal">{{ association.name }}</span></router-link>
</template>
<template v-else-if="entry.scope.type === 'team'">
<router-link class="flex content-center" :to="'#'"><UserGroupIcon class="ff-icon relative invisible lg:visible" /> <span class="truncate ml-2 !leading-normal">This Team</span></router-link>
Expand All @@ -41,6 +41,7 @@
<script>

import { ChipIcon, TemplateIcon, UserGroupIcon } from '@heroicons/vue/outline'
import { mapState } from 'vuex'

import ProjectsIcon from '../../components/icons/Projects.js'

Expand All @@ -63,6 +64,9 @@ export default {
default: false
}
},
computed: {
...mapState('account', ['team'])
},
components: {
AuditEntryIcon,
AuditEntryVerbose,
Expand Down
6 changes: 4 additions & 2 deletions frontend/src/components/pipelines/Stage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
<div v-if="stage.instance || stage.device || stage.deviceGroup" class="py-3">
<div>
<div v-if="stage.stageType == StageType.INSTANCE" class="ff-pipeline-stage-type">
<router-link class="flex gap-2 items-center" :to="{name: 'Instance', params: { id: stage.instance.id }}">
<router-link class="flex gap-2 items-center" :to="{name: 'Instance', params: { id: stage.instance.id, team_slug: team.slug }}">
<IconNodeRedSolid class="ff-icon ff-icon-lg text-red-800" />
<div>
<label class="flex items-center gap-2">Instance:</label>
Expand All @@ -72,7 +72,7 @@
</router-link>
</div>
<div v-if="stage.stageType == StageType.DEVICEGROUP" class="ff-pipeline-stage-type">
<router-link class="flex gap-2 items-center" :to="{name: 'ApplicationDeviceGroupDevices', params: { applicationId: application.id, deviceGroupId: stage.deviceGroup.id }}">
<router-link class="flex gap-2 items-center" :to="{name: 'ApplicationDeviceGroupDevices', params: { applicationId: application.id, deviceGroupId: stage.deviceGroup.id, team_slug: team.slug }}">
<IconDeviceGroupSolid class="ff-icon ff-icon-lg text-teal-700" />
<div>
<label class="flex items-center gap-2">Device Group:</label>
Expand Down Expand Up @@ -156,6 +156,7 @@

<script>
import { ExclamationIcon, LockClosedIcon, PencilAltIcon, PlayIcon, PlusCircleIcon, TrashIcon } from '@heroicons/vue/outline'
import { mapState } from 'vuex'

import PipelineAPI, { StageAction, StageType } from '../../api/pipeline.js'

Expand Down Expand Up @@ -213,6 +214,7 @@ export default {
},
emits: ['stage-deleted', 'stage-deploy-starting', 'stage-deploy-started', 'stage-deploy-failed'],
computed: {
...mapState('account', ['team']),
deploying () {
return this.stage.isDeploying
},
Expand Down
5 changes: 4 additions & 1 deletion frontend/src/pages/application/Logs.vue
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
value-key="id"
class="w-full"
/>
<router-link v-if="instance?.meta" :to="{ name: 'Instance', params: { id: instance.id }}">
<router-link v-if="instance?.meta" :to="{ name: 'Instance', params: { id: instance.id, team_slug: team.slug }}">
<InstanceStatusBadge :status="instance.meta?.state" :pendingStateChange="instance?.pendingStateChange" :optimisticStateChange="instance.optimisticStateChange" class="ml-2" />
</router-link>
</div>
Expand All @@ -29,6 +29,8 @@
</template>

<script>
import { mapState } from 'vuex'

import SectionTopMenu from '../../components/SectionTopMenu.vue'
import LogsShared from '../instance/components/InstanceLogs.vue'

Expand Down Expand Up @@ -56,6 +58,7 @@ export default {
}
},
computed: {
...mapState('account', ['team']),
instance () {
return this.instances.find((instance) => instance.id === this.input.instanceId)
}
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/pages/application/Overview.vue
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,8 @@ export default {
this.navigateTo({
name: 'Instance',
params: {
id: cloudInstance.id
id: cloudInstance.id,
team_slug: this.team.slug
}
}, event)
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<template>
<div>
<template v-if="ownerType==='instance'">
<router-link class="flex items-center" :to="{ name: 'Instance', params: { id: project.id }}">
<router-link class="flex items-center" :to="{ name: 'Instance', params: { id: project.id, team_slug: team.slug }}">
<IconNodeRedSolid class="ff-icon ff-icon-lg text-red-800 relative" />
<div class="flex flex-col ml-2">
<div class="text-xs text-gray-400">instance</div>
Expand All @@ -28,6 +28,8 @@

<script>

import { mapState } from 'vuex'

import IconDeviceSolid from '../../../../../components/icons/DeviceSolid.js'
import IconNodeRedSolid from '../../../../../components/icons/NodeRedSolid.js'

Expand All @@ -52,6 +54,9 @@ export default {
type: Object,
default: null
}
},
computed: {
...mapState('account', ['team'])
}
}
</script>
2 changes: 1 addition & 1 deletion frontend/src/pages/device/Overview.vue
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
</InfoCardRow>
<InfoCardRow v-if="device.ownerType!=='application'" property="Instance:">
<template #value>
<router-link v-if="device?.instance" :to="{name: 'Instance', params: { id: device.instance.id }}">
<router-link v-if="device?.instance" :to="{name: 'Instance', params: { id: device.instance.id, team_slug: team.slug }}">
{{ device.instance?.name }}
</router-link>
<span v-else>None</span>
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/pages/device/Settings/General.vue
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
<template v-else-if="hasInstance">
<div>
<label class="font-medium mr-2">Instance:</label>
<router-link :to="{name: 'Instance', params: {id: device.instance.id}}" class="ff-link">{{ device.instance.name }}</router-link>
<router-link :to="{name: 'Instance', params: {id: device.instance.id, team_slug: team.slug}}" class="ff-link">{{ device.instance.name }}</router-link>
</div>
<h3>Features:</h3>
<ul class="list-disc ml-6 space-y-2 max-w-xl">
Expand Down Expand Up @@ -103,7 +103,7 @@ export default {
}
},
computed: {
...mapState('account', ['teamMembership']),
...mapState('account', ['teamMembership', 'team']),
hasApplication () {
return this.device?.ownerType === 'application' && this.device.application
},
Expand Down
6 changes: 2 additions & 4 deletions frontend/src/pages/instance/Editor/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,14 @@ import InstanceEditor from './index.vue'

export default [
{
path: '/instance/:id/editor',
path: ':id/editor',
name: 'instance-editor',
component: InstanceEditor,
meta: {
title: 'Instance - Editor',
layout: 'plain'
},
redirect: to => {
return { name: 'instance-editor-overview', params: { id: to.params.id } }
},
redirect: { name: 'instance-editor-overview' },
children: [
...children.filter(child => !['settings', 'version-history'].includes(child.path)).map(child => {
return {
Expand Down
6 changes: 3 additions & 3 deletions frontend/src/pages/instance/Settings/Danger.vue
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ export default {
duplicateProject (parts) {
this.loading.duplicating = true
InstanceApi.create(parts).then(result => {
this.$router.push({ name: 'Instance', params: { id: result.id } })
this.$router.push({ name: 'Instance', params: { id: result.id, team_slug: this.team.slug } })
alerts.emit('Instance successfully duplicated.', 'confirmation')
}).catch(err => {
console.error(err)
Expand All @@ -217,7 +217,7 @@ export default {
importInstance (parts) {
this.loading.importing = true
InstanceApi.importInstance(this.instance.id, parts).then(result => {
this.$router.push({ name: 'Instance', params: { id: this.instance.id } })
this.$router.push({ name: 'Instance', params: { id: this.instance.id, team_slug: this.team.slug } })
alerts.emit('Instance flows imported.', 'confirmation')
}).catch(err => {
console.error(err)
Expand All @@ -230,7 +230,7 @@ export default {
if (this.instance.stack?.id !== selectedStack) {
this.loading.changingStack = true
InstanceApi.changeStack(this.instance.id, selectedStack).then(() => {
this.$router.push({ name: 'Instance', params: { id: this.instance.id } })
this.$router.push({ name: 'Instance', params: { id: this.instance.id, team_slug: this.team.slug } })
this.$emit('instance-updated')
alerts.emit('Instance Node-RED Version successfully updated.', 'confirmation')
}).catch(err => {
Expand Down
77 changes: 43 additions & 34 deletions frontend/src/pages/instance/Settings/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
</template>

<script>
import { mapState } from 'vuex'
import { mapGetters, mapState } from 'vuex'

import SectionSideMenu from '../../../components/SectionSideMenu.vue'
import SectionTopMenu from '../../../components/SectionTopMenu.vue'
Expand All @@ -38,41 +38,50 @@ export default {
}
},
emits: ['instance-updated', 'instance-confirm-delete', 'instance-confirm-suspend'],
data () {
return {
sideNavigation: []
}
},
computed: {
...mapState('account', ['team', 'teamMembership', 'features', 'settings'])
},
watch: {
teamMembership: 'checkAccess'
},
mounted () {
this.checkAccess()
},
methods: {
checkAccess: async function () {
this.sideNavigation = [
{ name: 'General', path: './general' },
{ name: 'Environment', path: './environment' }
]
if (this.hasPermission('project:edit')) {
if (this.features.ha) {
this.sideNavigation.push({ name: 'High Availability', path: './ha' })
}
if (this.features.protectedInstance && this.team.type.properties.features?.protectedInstance) {
this.sideNavigation.push({ name: 'Protect Instance', path: './protectInstance' })
...mapState('account', ['team', 'teamMembership', 'features', 'settings']),
...mapGetters('account', ['featuresCheck']),
sideNavigation () {
const hasPermissionToEditProject = this.hasPermission('project:edit')
return [
{ name: 'General', path: { name: 'instance-settings-general' } },
{ name: 'Environment', path: { name: 'instance-settings-environment' } },
{
name: 'High Availability',
path: { name: 'instance-settings-ha' },
hidden: !hasPermissionToEditProject && !this.features.ha
},
{
name: 'Protect Instance',
path: { name: 'instance-settings-protect' },
hidden: !hasPermissionToEditProject && !this.featuresCheck.isProtectedInstanceFeatureEnabled
},
{
name: 'Editor',
path: { name: 'instance-settings-editor' },
hidden: !hasPermissionToEditProject
},
{
name: 'Security',
path: { name: 'instance-settings-security' },
hidden: !hasPermissionToEditProject
},
{
name: 'Palette',
path: { name: 'instance-settings-palette' },
hidden: !hasPermissionToEditProject
},
{
name: 'Launcher',
path: { name: 'instance-settings-launcher' },
hidden: !hasPermissionToEditProject
},
{
name: 'Alerts',
path: { name: 'instance-settings-alerts' },
hidden: !hasPermissionToEditProject && !this.featuresCheck.isEmailAlertsFeatureEnabled
}
this.sideNavigation.push({ name: 'Editor', path: './editor' })
this.sideNavigation.push({ name: 'Security', path: './security' })
this.sideNavigation.push({ name: 'Palette', path: './palette' })
this.sideNavigation.push({ name: 'Launcher', path: './launcher' })
if (this.features.emailAlerts && this.team.type.properties.features?.emailAlerts) {
this.sideNavigation.push({ name: 'Alerts', path: './alerts' })
}
}
]
}
}
}
Expand Down
3 changes: 3 additions & 0 deletions frontend/src/pages/instance/VersionHistory/Timeline/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@
</template>

<script>
import { mapGetters } from 'vuex'

import projectHistoryAPI from '../../../../api/projectHistory.js'
import EmptyState from '../../../../components/EmptyState.vue'
import FeatureUnavailable from '../../../../components/banners/FeatureUnavailable.vue'
Expand Down Expand Up @@ -94,6 +96,7 @@ export default {
}
},
computed: {
...mapGetters('account', ['featuresCheck']),
canLoadMore () {
return this.next_cursor !== undefined
},
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/pages/instance/components/EditorLink.vue
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ export default {
},
url () {
if (this.isImmersiveEditor) {
return this.$router.resolve({ name: 'instance-editor', params: { id: this.instance.id } }).fullPath
return this.$router.resolve({ name: 'instance-editor', params: { id: this.instance.id, team_slug: this.team.slug } }).fullPath
}

return this.editorURL
Expand Down
27 changes: 8 additions & 19 deletions frontend/src/pages/instance/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -107,26 +107,15 @@ export default {
...mapState('account', ['teamMembership', 'team']),
navigation () {
if (!this.instance.id) return []
let versionHistoryRoute
if (!this.isTimelineFeatureEnabled) {
versionHistoryRoute = {
name: 'instance-snapshots',
params: { id: this.instance.id }
}
} else {
versionHistoryRoute = {
name: 'instance-version-history',
params: { id: this.instance.id }
}
}

return [
{ label: 'Overview', to: { name: 'instance-overview', params: { id: this.instance.id } }, tag: 'instance-overview' },
{ label: 'Devices', to: { name: 'instance-devices', params: { id: this.instance.id } }, tag: 'instance-remote' },
{ label: 'Version History', to: versionHistoryRoute, tag: 'instance-version-history' },
{ label: 'Assets', to: { name: 'instance-assets', params: { id: this.instance.id } }, tag: 'instance-assets', hidden: !this.hasAMinimumTeamRoleOf(Roles.Member) },
{ label: 'Audit Log', to: { name: 'instance-audit-log', params: { id: this.instance.id } }, tag: 'instance-activity' },
{ label: 'Node-RED Logs', to: { name: 'instance-logs', params: { id: this.instance.id } }, tag: 'instance-logs' },
{ label: 'Settings', to: { name: 'instance-settings', params: { id: this.instance.id } }, tag: 'instance-settings' }
{ label: 'Overview', to: { name: 'instance-overview', params: { id: this.instance.id, team_slug: this.team.slug } }, tag: 'instance-overview' },
{ label: 'Devices', to: { name: 'instance-devices', params: { id: this.instance.id, team_slug: this.team.slug } }, tag: 'instance-remote' },
{ label: 'Version History', to: { name: 'instance-version-history', params: { id: this.instance.id, team_slug: this.team.slug } }, tag: 'instance-version-history' },
{ label: 'Assets', to: { name: 'instance-assets', params: { id: this.instance.id, team_slug: this.team.slug } }, tag: 'instance-assets', hidden: !this.hasAMinimumTeamRoleOf(Roles.Member) },
{ label: 'Audit Log', to: { name: 'instance-audit-log', params: { id: this.instance.id, team_slug: this.team.slug } }, tag: 'instance-activity' },
{ label: 'Node-RED Logs', to: { name: 'instance-logs', params: { id: this.instance.id, team_slug: this.team.slug } }, tag: 'instance-logs' },
{ label: 'Settings', to: { name: 'instance-settings', params: { id: this.instance.id, team_slug: this.team.slug } }, tag: 'instance-settings' }
]
},
isLoading: function () {
Expand Down
Loading
Loading