Skip to content

Commit

Permalink
enh: Improve accessibility
Browse files Browse the repository at this point in the history
- Migrate to new @nextcloud/vue API

Signed-off-by: Christopher Ng <chrng8@gmail.com>
  • Loading branch information
Pytal committed Nov 22, 2023
1 parent d9c271f commit 47725a9
Show file tree
Hide file tree
Showing 6 changed files with 190 additions and 156 deletions.
8 changes: 7 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@
"@nextcloud/router": "^2.1.2",
"@nextcloud/vue": "^8.2.0",
"vue": "^2.7.14",
"vue-click-outside": "^1.1.0"
"vue-click-outside": "^1.1.0",
"vue-material-design-icons": "^5.2.0"
},
"browserslist": [
"extends @nextcloud/browserslist-config"
Expand Down
135 changes: 103 additions & 32 deletions src/components/Admins.vue → src/components/Access.vue
Original file line number Diff line number Diff line change
Expand Up @@ -20,43 +20,47 @@
-->

<template>
<div class="who-has-access">
<span :class="{ hidden: !isLoading }" class="icon icon-loading" />
<div v-for="admin in admins" :key="admin.id" class="admin-avatar-container">
<div class="access">
<NcLoadingIcon v-if="isLoading" :name="t('privacy', 'Loading administrators …')" />

<div v-for="admin in admins"
:key="admin.id"
class="access__admin">
<NcAvatar :user="admin.internal ? admin.id : null"
:display-name="admin.displayname"
:size="64"
:is-no-user="!admin.internal"
:show-user-status="false" />
<NcActions v-if="!admin.internal">
<NcActionButton icon="icon-close"
:aria-label="t('privacy', 'Remove external {propertyName} admin', { propertyName: admin.displayname })"
:title="t('privacy', 'Remove external {propertyName} admin', { propertyName: admin.displayname })"
@click="deleteAdditionalAdmin(admin)" />
</NcActions>
<NcButton v-if="!admin.internal"
:aria-label="t('privacy', 'Remove external {propertyName} admin', { propertyName: admin.displayname })"
:title="t('privacy', 'Remove external {propertyName} admin', { propertyName: admin.displayname })"
@click="deleteAdditionalAdmin(admin)">
<template #icon>
<Close :size="20" />
</template>
</NcButton>
</div>

<div v-if="$is_admin">
<NcActions v-if="!isAdding" class="addAdditionalAdmin">
<NcActionButton icon="icon-add"
:aria-label="t('privacy', 'Add external admin')"
:title="t('privacy', 'Add external admin')"
@click.stop.prevent="openNewAdmin" />
</NcActions>
<NcButton v-if="!isAdding"
class="access__add"
:aria-label="t('privacy', 'Add external admin')"
:title="t('privacy', 'Add external admin')"
@click.stop.prevent="openNewAdmin">
<template #icon>
<Plus :size="20" />
</template>
</NcButton>
<form v-if="isAdding"
v-click-outside="closeNewAdmin"
class="addAdditionalAdminFormContainer"
class="access__form"
@submit.prevent="addAdditionalAdmin">
<input v-model="newAdditionalAdminInputField"
type="text"
<NcTextField :value.sync="newAdmin"
:label="t('privacy', 'Name of external admin')"
maxlength="64"
autocomplete="new-password"
autocorrect="off"
autocapitalize="off"
spellcheck="false"
:placeholder="$t('privacy', 'Name of external admin')">
<input type="submit" value="" class="icon-confirm">
<!-- add icon-loading -->
spellcheck="false" />
</form>
</div>
</div>
Expand All @@ -68,29 +72,41 @@ import ClickOutside from 'vue-click-outside'
import HttpClient from '@nextcloud/axios'
import { generateUrl } from '@nextcloud/router'
import { showError } from '@nextcloud/dialogs'
import NcActions from '@nextcloud/vue/dist/Components/NcActions.js'
import NcActionButton from '@nextcloud/vue/dist/Components/NcActionButton.js'

import NcAvatar from '@nextcloud/vue/dist/Components/NcAvatar.js'
import NcButton from '@nextcloud/vue/dist/Components/NcButton.js'
import NcLoadingIcon from '@nextcloud/vue/dist/Components/NcLoadingIcon.js'
import NcTextField from '@nextcloud/vue/dist/Components/NcTextField.js'

import Close from 'vue-material-design-icons/Close.vue'
import Plus from 'vue-material-design-icons/Plus.vue'

export default {
name: 'Admins',
name: 'Access',

components: {
NcActions,
NcActionButton,
NcAvatar,
NcButton,
NcLoadingIcon,
NcTextField,
Close,
Plus,
},

directives: {
ClickOutside,
},

data() {
return {
admins: [],
newAdditionalAdminInputField: '',
newAdmin: '',
isLoading: true,
isAdding: false,
isSavingChanges: false,
}
},

/**
* This function is called on mount of the Vue component
* It sets the isAdmin property and
Expand All @@ -108,20 +124,23 @@ export default {
this.isLoading = false
}
},

methods: {
/**
* Opens the new Admin dialog
*/
openNewAdmin() {
this.isAdding = true
},

/**
* Closes the new Admin dialog and resets the input field
*/
closeNewAdmin() {
this.isAdding = false
this.newAdditionalAdminInputField = ''
this.newAdmin = ''
},

/**
* Creates an additional (virtual) admin on the server
*
Expand All @@ -132,17 +151,18 @@ export default {
this.isSavingChanges = true

try {
const response = await HttpClient.post(url, { name: this.newAdditionalAdminInputField })
const response = await HttpClient.post(url, { name: this.newAdmin })
this.admins.push(response.data)
} catch (error) {
console.error(error)
showError('Error adding new administrator.')
} finally {
this.isSavingChanges = false
this.isAdding = false
this.newAdditionalAdminInputField = ''
this.newAdmin = ''
}
},

/**
* Deletes an additional (virtual) admin from the server
*
Expand All @@ -167,3 +187,54 @@ export default {
},
}
</script>

<style lang="scss" scoped>
.access {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 0 4px;

div.admin-avatar-container {
position: relative;

> .action-item {
position: absolute;
top: -8px;
right: -8px;
}
}

&__form {
margin-top: 20px;
position: relative;
grid-row: 1;
display: inline-flex;
align-items: center;
}

span.icon.icon-loading {
display: block;
height: 32px;
width: 32px;
margin: 26px;

&.hidden {
display: none;
}
}

&__add {
min-width: 64px !important;
min-height: 64px !important;
border-radius: 32px !important;
}

&__admin {
display: flex;
flex-direction: column;
align-items: center;
gap: 4px 0;
}
}
</style>
Loading

0 comments on commit 47725a9

Please sign in to comment.