Skip to content

Commit c79a4cc

Browse files
authored
Merge branch 'main' into chore-update-prestaging-features
2 parents 5e23d60 + c5410a0 commit c79a4cc

8 files changed

Lines changed: 83 additions & 38 deletions

File tree

frontend/src/components/dialogs/EditApplicationPermissionsDialog.vue

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
@cancel="onCancel"
1111
>
1212
<template #default>
13-
<p class="mb-4">Set a new role for {{ user.name }} in {{ application.name }}</p>
13+
<p class="mb-4">Set a new role for <b>{{ user.name }}</b> in application: <b>{{ application.name }}</b></p>
1414
<ff-listbox v-model="selection" :options="options" />
1515
</template>
1616
</ff-dialog>
@@ -23,7 +23,7 @@ import { mapState } from 'vuex'
2323
import teamApi from '../../api/team.js'
2424
import { capitalize } from '../../composables/String.js'
2525
import alerts from '../../services/alerts.js'
26-
import { RoleNames } from '../../utils/roles.js'
26+
import { RoleNames, Roles } from '../../utils/roles.js'
2727
2828
export default defineComponent({
2929
name: 'EditApplicationPermissionsDialog',
@@ -44,11 +44,14 @@ export default defineComponent({
4444
.filter(key => key.toString() !== '99')
4545
.map(key => {
4646
return {
47-
label: this.capitalize(RoleNames[key]),
47+
label: this.capitalize(this.roles[key]),
4848
value: key.toString()
4949
}
5050
})
5151
},
52+
roles () {
53+
return { ...RoleNames, [Roles.None]: 'No Access' }
54+
},
5255
isDirty () {
5356
return this.selection !== this.original
5457
}

frontend/src/components/expert/ExpertChatMessage.vue

Lines changed: 45 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,33 @@
77
<!-- Regular text content (for chat messages) -->
88
<!-- eslint-disable-next-line vue/no-v-html -->
99
<div v-if="!hasRichContent" class="message-text" v-html="formattedContent" />
10+
11+
<div v-if="hasIssues" class="issues">
12+
<h4><exclamation-icon class="ff-icon" /> Issues</h4>
13+
<ul>
14+
<li v-for="issue in issues" :key="issue">{{ sanitize(issue) }}</li>
15+
</ul>
16+
</div>
17+
18+
<div v-if="hasSuggestions" class="suggestions">
19+
<h4><information-circle-icon class="ff-icon" /> Suggestions</h4>
20+
<ul>
21+
<li v-for="suggestion in suggestions" :key="suggestion">{{ sanitize(suggestion) }}</li>
22+
</ul>
23+
</div>
1024
</div>
1125
</div>
1226
</template>
1327

1428
<script>
29+
import { ExclamationIcon, InformationCircleIcon } from '@heroicons/vue/solid'
1530
import { marked } from 'marked'
1631
1732
import { sanitize } from '../../composables/String.js'
1833
1934
export default {
2035
name: 'ExpertChatMessage',
36+
components: { ExclamationIcon, InformationCircleIcon },
2137
props: {
2238
message: {
2339
type: Object,
@@ -55,16 +71,7 @@ export default {
5571
// Convert markdown to HTML
5672
const content = []
5773
content.push(this.message.content || '')
58-
if (this.message.resources?.issues?.length > 0) {
59-
content.push('\n\n')
60-
content.push('**Issues:**')
61-
content.push(this.message.resources.issues.map(issue => `\n- ${this.sanitize(issue)}`).join(''))
62-
}
63-
if (this.message.resources?.suggestions?.length > 0) {
64-
content.push('\n\n')
65-
content.push('**Suggestions:**')
66-
content.push(this.message.resources.suggestions.map(suggestion => `\n- ${this.sanitize(suggestion)}`).join(''))
67-
}
74+
6875
const html = marked(content.join('\n'), {
6976
breaks: true,
7077
gfm: true
@@ -79,16 +86,16 @@ export default {
7986
})
8087
},
8188
issues () {
82-
return this.resources.issues
89+
return this.message.resources.issues
8390
},
8491
suggestions () {
85-
return this.resources.suggestions
92+
return this.message.resources.suggestions
8693
},
8794
hasIssues () {
88-
return (this.resources.issues && this.resources.issues.length > 0)
95+
return (this.message.resources?.issues && this.message.resources?.issues.length > 0)
8996
},
9097
hasSuggestions () {
91-
return (this.resources.suggestions && this.resources.suggestions.length > 0)
98+
return (this.message.resources?.suggestions && this.message.resources?.suggestions.length > 0)
9299
}
93100
}
94101
}
@@ -120,6 +127,30 @@ export default {
120127
border-radius: 0.5rem;
121128
border-bottom-left-radius: 0.125rem;
122129
}
130+
131+
.issues, .suggestions {
132+
margin-top: 1.25rem;
133+
h4 {
134+
font-weight: bold;
135+
display: flex;
136+
align-items: center;
137+
gap: 5px;
138+
color: $ff-grey-600;
139+
140+
.ff-icon {
141+
color: $ff-grey-500;
142+
}
143+
}
144+
145+
ul {
146+
list-style: disc;
147+
padding-left: 1.4rem;
148+
149+
li {
150+
margin-top: .5rem;
151+
}
152+
}
153+
}
123154
}
124155
125156
&.message-system {

frontend/src/components/permissions/RoleCompare.vue

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,13 @@
77
:class="style.iconClass"
88
class="ff-icon ff-icon-sm"
99
/>
10-
<span :class="style.roleClass" class="capitalize">
10+
<span :class="style.roleClass" class="">
1111
{{ role }}
1212
</span>
1313
</span>
1414
<span v-if="showOverrideRole" class="text-gray-500 italic flex gap-1">
1515
<span>Team Role:</span>
16-
<span :class="style.roleClass" class="capitalize">
16+
<span :class="style.roleClass">
1717
{{ readableBaseRole }}
1818
</span>
1919
</span>
@@ -25,7 +25,7 @@ import { ArrowDownIcon, ArrowUpIcon, BanIcon } from '@heroicons/vue/outline'
2525
2626
import { capitalize } from '../../composables/String.js'
2727
28-
import { RoleNames } from '../../utils/roles.js'
28+
import { RoleNames, Roles } from '../../utils/roles.js'
2929
3030
export default {
3131
name: 'RoleCompare',
@@ -45,10 +45,13 @@ export default {
4545
},
4646
computed: {
4747
role () {
48-
return this.capitalize(RoleNames[this.overrideRole] || 'unknown')
48+
return this.capitalize(this.roles[this.overrideRole] || 'unknown')
49+
},
50+
roles () {
51+
return { ...RoleNames, [Roles.None]: 'No Access' }
4952
},
5053
readableBaseRole () {
51-
return RoleNames[this.baseRole] || 'unknown'
54+
return this.roles[this.baseRole] || 'unknown'
5255
},
5356
style () {
5457
if (parseInt(this.baseRole) === 0) {

frontend/src/components/tables/cells/UserRoleCell.vue

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
</template>
44
<script>
55
import { capitalize } from '../../../composables/String.js'
6-
import { RoleNames } from '../../../utils/roles.js'
6+
import { RoleNames, Roles } from '../../../utils/roles.js'
77
export default {
88
name: 'UserRoleCell',
99
props: ['role'],
@@ -12,11 +12,11 @@ export default {
1212
},
1313
computed: {
1414
formattedRole () {
15-
return this.capitalize(this.formatRole(this.role))
15+
return this.capitalize(this.roles[this.role])
16+
},
17+
roles () {
18+
return { ...RoleNames, [Roles.None]: 'No Access' }
1619
}
17-
},
18-
methods: {
19-
formatRole: r => RoleNames[r] || 'unknown'
2020
}
2121
}
2222
</script>

frontend/src/pages/team/Members/General.vue

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050
<script>
5151
import { UserAddIcon } from '@heroicons/vue/solid'
5252
import { markRaw } from 'vue'
53-
import { mapGetters, mapState } from 'vuex'
53+
import { mapActions, mapGetters, mapState } from 'vuex'
5454
5555
import teamApi from '../../../api/team.js'
5656
import FeatureUnavailableToTeam from '../../../components/banners/FeatureUnavailableToTeam.vue'
@@ -127,7 +127,7 @@ export default {
127127
component: { is: markRaw(UserCell) }
128128
},
129129
{
130-
label: 'Role',
130+
label: 'Access',
131131
key: 'role',
132132
sortable: true,
133133
class: ['w-40'],
@@ -177,6 +177,7 @@ export default {
177177
}
178178
},
179179
methods: {
180+
...mapActions('account', ['refreshTeamMembership']),
180181
inviteMember () {
181182
this.$refs.inviteMemberDialog.show()
182183
},
@@ -201,6 +202,8 @@ export default {
201202
this.users = response.members
202203
this.ownerCount = 0
203204
205+
this.refreshTeamMembership()
206+
204207
if (this.users) {
205208
this.users.forEach(u => {
206209
if (u.role === Roles.Owner) {

frontend/src/pages/team/Members/components/ApplicationPermissionsRow.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
</span>
1818
<RoleCompare :baseRole="data.role" :overrideRole="application.role" class="w-40" />
1919
<span class="item action w-40 pl-5" data-action="update-role">
20-
<PencilAltIcon v-if="!application.disabled" class="ff-icon ff-icon-sm ff-link" @click.prevent="onUpdateRole(application)" />
20+
<PencilAltIcon class="ff-icon ff-icon-sm ff-link" @click.prevent="onUpdateRole(application)" />
2121
</span>
2222
</li>
2323
</ul>

frontend/src/store/modules/account/index.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -579,6 +579,11 @@ const actions = {
579579
.then(user => {
580580
commit('login', user)
581581
})
582+
},
583+
async refreshTeamMembership ({ commit, state }) {
584+
const teamMembership = await teamApi.getTeamUserMembership(state.team.id)
585+
586+
commit('setTeamMembership', teamMembership)
582587
}
583588
}
584589

test/e2e/frontend/cypress/tests-ee/rbac/rbac-management.spec.js

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ describe('FlowFuse - RBAC GUI Management', () => {
117117
cy.get('[data-nav="team-members"]').click()
118118

119119
// check that bob has an owner role
120-
cy.get('[data-el="row-no-role-barry"]').contains('None')
120+
cy.get('[data-el="row-no-role-barry"]').contains('No Access')
121121

122122
// expand the row for bob
123123
cy.get('[data-el="row-no-role-barry"] [data-el="collapsible-row-toggle"]').click()
@@ -127,13 +127,13 @@ describe('FlowFuse - RBAC GUI Management', () => {
127127
// find the next collapsible row which is the application permissions row
128128
cy.get('[data-el="row-no-role-barry"]').next('.collapsible')
129129
.within(() => {
130-
cy.get('[data-el="app-item-application-6"]').contains('None')
130+
cy.get('[data-el="app-item-application-6"]').contains('No Access')
131131
cy.get('[data-el="app-item-application-6"] [data-action="update-role"] svg').click()
132132
})
133133

134134
// set the application role viewer to bob
135135
cy.get('[data-el="application-permission-dialog"]').should('be.visible')
136-
cy.get('[data-el="application-permission-dialog"] button').contains('None').click()
136+
cy.get('[data-el="application-permission-dialog"] button').contains('No Access').click()
137137
cy.get('[data-el="application-permission-dialog"] [data-action="dialog-confirm"]').should('be.disabled')
138138
cy.get('[data-el=listbox-options] [data-option="Viewer"]').click()
139139
cy.get('[data-el="application-permission-dialog"] [data-action="dialog-confirm"]').click()
@@ -150,7 +150,7 @@ describe('FlowFuse - RBAC GUI Management', () => {
150150
cy.get('[data-el="app-item-application-6"] [data-action="update-role"] svg').click()
151151
})
152152
cy.get('[data-el="application-permission-dialog"] button').contains('Viewer').click()
153-
cy.get('[data-el=listbox-options] [data-option="None"]').click()
153+
cy.get('[data-el=listbox-options] [data-option="No Access"]').click()
154154
cy.get('[data-el="application-permission-dialog"] [data-action="dialog-confirm"]').click()
155155
cy.wait('@putTeamMember')
156156
})
@@ -184,7 +184,7 @@ describe('FlowFuse - RBAC GUI Management', () => {
184184
cy.get('[data-nav="team-members"]').click()
185185

186186
// check that noRoleBarry has no role
187-
cy.get('[data-el="row-no-role-barry"]').contains('None')
187+
cy.get('[data-el="row-no-role-barry"]').contains('No Access')
188188

189189
// expand the row for noRoleBarry
190190
cy.get('[data-el="row-no-role-barry"] [data-el="collapsible-row-toggle"]').click()
@@ -194,13 +194,13 @@ describe('FlowFuse - RBAC GUI Management', () => {
194194
// find the next collapsible row which is the application permissions row
195195
cy.get('[data-el="row-no-role-barry"]').next('.collapsible')
196196
.within(() => {
197-
cy.get('[data-el="app-item-application-6"]').contains('None')
197+
cy.get('[data-el="app-item-application-6"]').contains('No Access')
198198
cy.get('[data-el="app-item-application-6"] [data-action="update-role"] svg').click()
199199
})
200200

201201
// set the application role viewer to noRoleBarry
202202
cy.get('[data-el="application-permission-dialog"]').should('be.visible')
203-
cy.get('[data-el="application-permission-dialog"] button').contains('None').click()
203+
cy.get('[data-el="application-permission-dialog"] button').contains('No Access').click()
204204
cy.get('[data-el="application-permission-dialog"] [data-action="dialog-confirm"]').should('be.disabled')
205205
cy.get('[data-el=listbox-options] [data-option="Viewer"]').click()
206206
cy.get('[data-el="application-permission-dialog"] [data-action="dialog-confirm"]').click()
@@ -217,7 +217,7 @@ describe('FlowFuse - RBAC GUI Management', () => {
217217
cy.get('[data-el="app-item-application-6"] [data-action="update-role"] svg').click()
218218
})
219219
cy.get('[data-el="application-permission-dialog"] button').contains('Viewer').click()
220-
cy.get('[data-el=listbox-options] [data-option="None"]').click()
220+
cy.get('[data-el=listbox-options] [data-option="No Access"]').click()
221221
cy.get('[data-el="application-permission-dialog"] [data-action="dialog-confirm"]').click()
222222
cy.wait('@putTeamMember')
223223
})

0 commit comments

Comments
 (0)