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

User/group details and edit panel #6724

Merged
merged 26 commits into from
Apr 12, 2022
Merged
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<template>
<div class="compare-save-dialog oc-p-s oc-width-1-1">
<div class="oc-flex oc-flex-between oc-flex-middle oc-width-1-1">
<span>{{ unsavedChangesText }}</span>
<div>
<oc-button :disabled="!unsavedChanges" @click="$emit('revert')">
<translate>Revert</translate>
</oc-button>
<oc-button
appearance="filled"
variation="primary"
:disabled="!unsavedChanges || confirmButtonDisabled"
@click="$emit('confirm')"
>
<translate>Save</translate>
</oc-button>
</div>
</div>
</div>
</template>

<script lang="js">
import isEqual from 'lodash-es/isEqual'

export default {
name: 'CompareSaveDialog',
props: {
originalObject: {
type: Object,
required: true
},
compareObject: {
type: Object,
required: true
},
confirmButtonDisabled: {
type: Boolean,
default: () => {
return false
}
},
},
computed: {
unsavedChanges(){
return !isEqual(this.originalObject, this.compareObject)
},
unsavedChangesText(){
return this.unsavedChanges ? this.$gettext('Unsaved changes') : this.$gettext('No changes')
}
}
}
</script>
<style lang="scss">
.compare-save-dialog {
background: var(--oc-color-background-muted);
}
</style>
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@
:button-cancel-text="$gettext('Cancel')"
:button-confirm-text="$gettext('Create')"
:button-confirm-disabled="buttonConfirmDisabled"
focus-trap-initial="#input-display-name"
focus-trap-initial="#create-group-input-display-name"
@cancel="$emit('cancel')"
@confirm="$emit('confirm', group)"
>
<template #content>
<oc-text-input
id="input-display-name"
id="create-group-input-display-name"
v-model="group.displayName"
class="oc-mb-s"
:label="$gettext('Group name') + '*'"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,16 @@
<template #avatar="rowData">
<avatar-image :width="32" :userid="rowData.item.id" :user-name="rowData.item.displayName" />
</template>
<template #actions="{ item }">
<oc-button v-oc-tooltip="$gettext('Details')" @click="$emit('clickDetails', item)">
<oc-icon size="small" name="information" />
</oc-button>
<!-- Editing groups is currently not supported by backend
<oc-button v-oc-tooltip="$gettext('Edit')" class="oc-ml-s" @click="$emit('clickEdit', item)">
<oc-icon size="small" name="pencil" />
</oc-button>
-->
</template>
<template #footer>
<div class="oc-text-nowrap oc-text-center oc-width-1-1 oc-my-s">
<p class="oc-text-muted">{{ footerText }}</p>
Expand All @@ -42,8 +52,8 @@
<script>
const orderBy = (list, prop, desc) => {
return [...list].sort((a, b) => {
a = a[prop]
b = b[prop]
a = a[prop] || ''
b = b[prop] || ''
return desc ? b.localeCompare(a) : a.localeCompare(b)
})
}
Expand Down Expand Up @@ -88,14 +98,11 @@ export default {
sortable: true
},
{
name: 'role',
title: this.$gettext('Your role'),
sortable: true
},
{
name: 'members',
title: this.$gettext('Members'),
sortable: true
name: 'actions',
title: this.$gettext('Actions'),
sortable: false,
type: 'slot',
alignH: 'right'
}
]
},
Expand All @@ -107,7 +114,7 @@ export default {
return this.$gettextInterpolate(translated, { groupCount: this.groups.length })
},
data() {
return orderBy([...this.groups], this.sortBy, this.sortDir === 'desc')
return orderBy(this.groups, this.sortBy, this.sortDir === 'desc')
},
highlighted() {
return this.selectedGroups.map((group) => group.id)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<template>
<div class="oc-mt-xl">
<div v-if="noGroups" class="oc-flex group-info">
<oc-icon name="group-2" size="xxlarge" />
<p v-translate>Select a group to view details</p>
</div>
<div v-if="multipleGroups" class="oc-flex group-info">
<oc-icon name="group-2" size="xxlarge" />
<p>{{ multipleGroupsSelectedText }}</p>
</div>
<div v-if="group">
<div class="oc-flex group-info oc-mb-l">
<avatar-image
class="oc-mb-m"
:width="80"
:userid="group.id"
:user-name="group.displayName"
/>
<span class="oc-text-muted group-info-display-name" v-text="group.displayName"></span>
</div>
<table
class="details-table"
:aria-label="$gettext('Overview of the information about the selected group')"
>
<tr>
<th scope="col" class="oc-pr-s" v-text="$gettext('Group name')" />
<td v-text="group.displayName" />
</tr>
</table>
</div>
</div>
</template>
<script>
export default {
name: 'DetailsPanel',
props: {
groups: {
type: Array,
required: true
}
},
computed: {
group() {
return this.groups.length === 1 ? this.groups[0] : null
fschade marked this conversation as resolved.
Show resolved Hide resolved
},
noGroups() {
return !this.groups.length
},
multipleGroups() {
return this.groups.length > 1
},
multipleGroupsSelectedText() {
return this.$gettextInterpolate('%{count} groups selected', {
count: this.groups.length
})
}
}
}
</script>
<style lang="scss">
.group-info {
align-items: center;
flex-direction: column;
}
.group-info-display-name {
font-size: 1.5rem;
}
.details-table {
text-align: left;

tr {
height: 1.5rem;
}

th {
font-weight: 600;
}
}
</style>
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
<template>
<div v-if="group" class="oc-mt-xl">
<div class="oc-flex group-info oc-mb-l">
<avatar-image class="oc-mb-m" :width="80" :userid="group.id" :user-name="group.displayName" />
<span class="oc-text-muted group-info-display-name" v-text="group.displayName"></span>
</div>
<div v-if="editGroup" class="oc-background-highlight oc-p-m">
<oc-text-input
v-model="editGroup.displayName"
class="oc-mb-s"
:label="$gettext('Group name')"
:error-message="formData.displayName.errorMessage"
:fix-message-line="true"
@input="validateDisplayName"
/>
</div>
<compare-save-dialog
class="edit-compare-save-dialog"
:original-object="group"
:compare-object="editGroup"
:confirm-button-disabled="invalidFormData"
@revert="revertChanges"
@confirm="$emit('confirm', editGroup)"
></compare-save-dialog>
</div>
</template>
<script>
import CompareSaveDialog from '../../CompareSaveDialog.vue'

export default {
name: 'EditPanel',
components: {
CompareSaveDialog
},
props: {
groups: {
type: Array,
required: true
}
},
data() {
return {
editGroup: {},
formData: {
displayName: {
errorMessage: '',
valid: true
}
}
}
},
computed: {
group() {
return this.groups.length === 1 ? this.groups[0] : null
},

invalidFormData() {
return Object.values(this.formData)
.map((v) => !!v.valid)
.includes(false)
}
},
watch: {
group: {
handler: function () {
this.editGroup = { ...this.group }
},
deep: true,
immediate: true
}
},
methods: {
validateDisplayName() {
this.formData.displayName.valid = false
Comment on lines +73 to +74
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can be simplified

const valid = this.editGroup.displayName.trim() === ''
const messsage = valid ? this.$gettext('Display name cannot be empty') : ''

this.formData.displayName.errorMessage = message
this.formData.displayName.valid = valid

return valid

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, let me do the validation adjustments in a separate pr


if (this.editGroup.displayName.trim() === '') {
this.formData.displayName.errorMessage = this.$gettext('Display name cannot be empty')
return false
}

this.formData.displayName.errorMessage = ''
this.formData.displayName.valid = true
return true
},

revertChanges() {
this.editGroup = { ...this.group }
Object.values(this.formData).forEach((formDataValue) => {
formDataValue.valid = true
formDataValue.errorMessage = ''
})
}
}
}
</script>
<style lang="scss">
.edit-compare-save-dialog {
position: absolute;
bottom: 0;
left: 0;
}

.group-info {
align-items: center;
flex-direction: column;
}
.group-info-display-name {
font-size: 1.5rem;
}
</style>
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@
:button-cancel-text="$gettext('Cancel')"
:button-confirm-text="$gettext('Create')"
:button-confirm-disabled="buttonConfirmDisabled"
focus-trap-initial="#input-user-name"
focus-trap-initial="#create-user-input-display-name"
@cancel="$emit('cancel')"
@confirm="$emit('confirm', user)"
>
<template #content>
<oc-text-input
id="input-user-name"
id="create-user-input-display-name"
v-model="user.onPremisesSamAccountName"
class="oc-mb-s"
:label="$gettext('User name') + '*'"
Expand All @@ -19,7 +19,6 @@
@input="validateUserName"
/>
<oc-text-input
id="input-display-name"
v-model="user.displayName"
class="oc-mb-s"
:label="$gettext('First and last name') + '*'"
Expand All @@ -28,7 +27,6 @@
@input="validateDisplayName"
/>
<oc-text-input
id="input-mail"
v-model="user.mail"
class="oc-mb-s"
:label="$gettext('Email') + '*'"
Expand All @@ -38,7 +36,6 @@
@change="validateEmail"
/>
<oc-text-input
id="input-password"
v-model="user.passwordProfile.password"
class="oc-mb-s"
:label="$gettext('Password') + '*'"
Expand Down
Loading