Skip to content

Commit

Permalink
fix(DavClient): Provide proper feedback for dav requests
Browse files Browse the repository at this point in the history
Before this commit there is no error handling whatsover for this requests and
the user won't get any visual feedback whatsover irrespective of what goes down
at the server level.

Signed-off-by: fenn-cs <fenn25.fn@gmail.com>
  • Loading branch information
nfebe committed Jun 17, 2024
1 parent 5fab2da commit 812e4e3
Show file tree
Hide file tree
Showing 2 changed files with 145 additions and 143 deletions.
22 changes: 20 additions & 2 deletions src/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -252,12 +252,30 @@ class AclDavService {
propPatch(model, acls) {
const aclList = []
for (const i in acls) {
aclList.push({ type: ACL_PROPERTIES.PROPERTY_ACL_ENTRY, data: acls[i].getProperties() })
aclList.push({ type: ACL_PROPERTIES.PROPERTY_ACL_ENTRY, data: acls[i].getProperties() })
}
const props = {}
props[ACL_PROPERTIES.PROPERTY_ACL_LIST] = aclList

return client._client.propPatch(client._client.baseUrl + model.path.replaceAll('#', '%23') + '/' + encodeURIComponent(model.name), props)
}
.then(response => {
if (response.status === 207) {
return response
} else if (response.status === 403) {
// Handle permission denied scenario
console.error('Permission denied:', response.status, response.statusText)
throw new Error(t('groupfolders', 'Permission denied. User does not have sufficient permissions.'))
} else {
// Handle unexpected status codes
console.error('Unexpected status:', response.status, response.statusText)
throw new Error(t('groupfolders', 'Unexpected status from server'))
}
}).catch(error => {
// Handle network errors or exceptions
console.error('Error in propPatch:', error)
throw error
})
}

}

Expand Down
266 changes: 125 additions & 141 deletions src/components/SharingSidebarView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -59,38 +59,33 @@
</td>
<td class="state-column">
<AclStateButton :state="getState(OC.PERMISSION_READ, {
permissions: model.permissions,
mask: 31,
})"
:read-only="true" />
permissions: model.permissions,
mask: 31,
})" :read-only="true" />

Check failure on line 64 in src/components/SharingSidebarView.vue

View workflow job for this annotation

GitHub Actions / NPM lint

':read-only' should be on a new line
</td>
<td class="state-column">
<AclStateButton :state="getState(OC.PERMISSION_UPDATE, {
permissions: model.permissions,
mask: 31,
})"
:read-only="true" />
permissions: model.permissions,
mask: 31,
})" :read-only="true" />

Check failure on line 70 in src/components/SharingSidebarView.vue

View workflow job for this annotation

GitHub Actions / NPM lint

':read-only' should be on a new line
</td>
<td v-if="model.type === 'dir'" class="state-column">
<AclStateButton :state="getState(OC.PERMISSION_CREATE, {
permissions: model.permissions,
mask: 31,
})"
:read-only="true" />
permissions: model.permissions,
mask: 31,
})" :read-only="true" />

Check failure on line 76 in src/components/SharingSidebarView.vue

View workflow job for this annotation

GitHub Actions / NPM lint

':read-only' should be on a new line
</td>
<td class="state-column">
<AclStateButton :state="getState(OC.PERMISSION_DELETE, {
permissions: model.permissions,
mask: 31,
})"
:read-only="true" />
permissions: model.permissions,
mask: 31,
})" :read-only="true" />

Check failure on line 82 in src/components/SharingSidebarView.vue

View workflow job for this annotation

GitHub Actions / NPM lint

':read-only' should be on a new line
</td>
<td class="state-column">
<AclStateButton :state="getState(OC.PERMISSION_SHARE, {
permissions: model.permissions,
mask: 31,
})"
:read-only="true" />
permissions: model.permissions,
mask: 31,
})" :read-only="true" />

Check failure on line 88 in src/components/SharingSidebarView.vue

View workflow job for this annotation

GitHub Actions / NPM lint

':read-only' should be on a new line
</td>
</tr>
</tbody>
Expand All @@ -103,41 +98,29 @@
{{ getFullDisplayName(item.mappingDisplayName, item.mappingType) }}
</td>
<td class="state-column">
<AclStateButton :state="getState(OC.PERMISSION_READ, item)"
:inherited="item.inherited"
:disabled="loading"
@update="changePermission(item, OC.PERMISSION_READ, $event)" />
<AclStateButton :state="getState(OC.PERMISSION_READ, item)" :inherited="item.inherited"

Check failure on line 101 in src/components/SharingSidebarView.vue

View workflow job for this annotation

GitHub Actions / NPM lint

':inherited' should be on a new line
:disabled="loading" @update="changePermission(item, OC.PERMISSION_READ, $event)" />

Check failure on line 102 in src/components/SharingSidebarView.vue

View workflow job for this annotation

GitHub Actions / NPM lint

'@update' should be on a new line
</td>
<td class="state-column">
<AclStateButton :state="getState(OC.PERMISSION_UPDATE, item)"
:inherited="item.inherited"
:disabled="loading"
@update="changePermission(item, OC.PERMISSION_UPDATE, $event)" />
<AclStateButton :state="getState(OC.PERMISSION_UPDATE, item)" :inherited="item.inherited"

Check failure on line 105 in src/components/SharingSidebarView.vue

View workflow job for this annotation

GitHub Actions / NPM lint

':inherited' should be on a new line
:disabled="loading" @update="changePermission(item, OC.PERMISSION_UPDATE, $event)" />

Check failure on line 106 in src/components/SharingSidebarView.vue

View workflow job for this annotation

GitHub Actions / NPM lint

'@update' should be on a new line
</td>
<td v-if="model.type === 'dir'" class="state-column">
<AclStateButton :state="getState(OC.PERMISSION_CREATE, item)"
:inherited="item.inherited"
:disabled="loading"
@update="changePermission(item, OC.PERMISSION_CREATE, $event)" />
<AclStateButton :state="getState(OC.PERMISSION_CREATE, item)" :inherited="item.inherited"

Check failure on line 109 in src/components/SharingSidebarView.vue

View workflow job for this annotation

GitHub Actions / NPM lint

':inherited' should be on a new line
:disabled="loading" @update="changePermission(item, OC.PERMISSION_CREATE, $event)" />
</td>
<td class="state-column">
<AclStateButton :state="getState(OC.PERMISSION_DELETE, item)"
:inherited="item.inherited"
:disabled="loading"
@update="changePermission(item, OC.PERMISSION_DELETE, $event)" />
<AclStateButton :state="getState(OC.PERMISSION_DELETE, item)" :inherited="item.inherited"
:disabled="loading" @update="changePermission(item, OC.PERMISSION_DELETE, $event)" />
</td>
<td class="state-column">
<AclStateButton :state="getState(OC.PERMISSION_SHARE, item)"
:inherited="item.inherited"
:disabled="loading"
@update="changePermission(item, OC.PERMISSION_SHARE, $event)" />
<AclStateButton :state="getState(OC.PERMISSION_SHARE, item)" :inherited="item.inherited"
:disabled="loading" @update="changePermission(item, OC.PERMISSION_SHARE, $event)" />
</td>
<td class="state-column">
<NcButton v-if="item.inherited === false"
type="tertiary"
<NcButton v-if="item.inherited === false" type="tertiary"
:v-tooltip="t('groupfolders', 'Remove access rule')"
:aria-label="t('groupfolders', 'Remove access rule')"
@click="removeAcl(item)">
:aria-label="t('groupfolders', 'Remove access rule')" @click="removeAcl(item)">
<template #icon>
<Close :size="16" />
</template>
Expand All @@ -146,23 +129,15 @@
</tr>
</tbody>
</table>
<NcButton v-if="isAdmin && !loading && !showAclCreate"
@click="toggleAclCreate">
<NcButton v-if="isAdmin && !loading && !showAclCreate" @click="toggleAclCreate">
<template #icon>
<Plus :size="16" />
</template>
{{ t('groupfolders', 'Add advanced permission rule') }}
</NcButton>
<NcSelect v-if="isAdmin && !loading && showAclCreate"
ref="select"
v-model="value"
:options="options"
:loading="isSearching"
:filterable="false"
:placeholder="t('groupfolders', 'Select a user or group')"
:get-option-key="() => 'unique'"
@input="createAcl"
@search="searchMappings">
<NcSelect v-if="isAdmin && !loading && showAclCreate" ref="select" v-model="value" :options="options"
:loading="isSearching" :filterable="false" :placeholder="t('groupfolders', 'Select a user or group')"
:get-option-key="() => 'unique'" @input="createAcl" @search="searchMappings">
<template #option="option">
<NcAvatar :user="option.id" :is-no-user="option.type !== 'user'" />
{{ option.label }}
Expand All @@ -185,6 +160,7 @@ import NcSelect from '@nextcloud/vue/dist/Components/NcSelect.js'
import Tooltip from '@nextcloud/vue/dist/Directives/Tooltip.js'
import Plus from 'vue-material-design-icons/Plus.vue'
import Close from 'vue-material-design-icons/Close.vue'
import { showError } from '@nextcloud/dialogs'

let searchRequestCancelSource = null

Expand Down Expand Up @@ -355,7 +331,7 @@ export default {
})

},
changePermission(item, permission, $event) {
async changePermission(item, permission, $event) {
const index = this.list.indexOf(item)
const inherit = $event === STATES.INHERIT_ALLOW || $event === STATES.INHERIT_DENY || $event === STATES.INHERIT_DEFAULT
const allow = $event === STATES.SELF_ALLOW
Expand All @@ -374,109 +350,117 @@ export default {
}
item.inherited = false
Vue.set(this.list, index, item)
client.propPatch(this.model, this.list.filter(rule => !rule.inherited)).then(() => {
// TODO block UI during save
})
// TODO: Block UI during save
try {
await client.propPatch(this.model, this.list.filter(rule => !rule.inherited))
console.debug('Permissions updated successfully')
} catch (error) {
console.error('Failed to save changes:', error)
showError(error)
} finally {
// TODO: Unblock the UI after the operation completes
}
},
},
}
</script>

<style scoped>
#groupfolder-acl-container {
margin-bottom: 20px;
}
#groupfolder-acl-container {
margin-bottom: 20px;
}

.groupfolder-entry {
height: 44px;
white-space: normal;
display: inline-flex;
align-items: center;
position: relative;
}
.groupfolder-entry {
height: 44px;
white-space: normal;
display: inline-flex;
align-items: center;
position: relative;
}

.avatar.icon-group-white {
display: inline-block;
background-color: var(--color-primary-element, #0082c9);
padding: 16px;
}
.avatar.icon-group-white {
display: inline-block;
background-color: var(--color-primary-element, #0082c9);
padding: 16px;
}

.groupfolder-entry .username {
padding: 0 8px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.groupfolder-entry .username {
padding: 0 8px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}

table {
width: 100%;
margin-top: -44px;
margin-bottom: 5px;
}
table {
width: 100%;
margin-top: -44px;
margin-bottom: 5px;
}

table td, table th {
padding: 0
}
table td,
table th {
padding: 0
}

thead th {
height: 44px;
}
thead th {
height: 44px;
}

thead th:first-child,
tbody tr td:first-child {
width: 24px;
padding: 0;
padding-left: 4px;
}
thead th:first-child,
tbody tr td:first-child {
width: 24px;
padding: 0;
padding-left: 4px;
}

table .avatardiv {
margin-top: 6px;
}
table .avatardiv {
margin-top: 6px;
}

table thead th:nth-child(2),
table .username {
padding-left: 13px;
text-overflow: ellipsis;
overflow: hidden;
max-width: 0;
min-width: 50px;
}
table thead th:nth-child(2),
table .username {
padding-left: 13px;
text-overflow: ellipsis;
overflow: hidden;
max-width: 0;
min-width: 50px;
}

.state-column {
text-align: center;
width: 44px !important;
padding: 3px;
}
.state-column {
text-align: center;
width: 44px !important;
padding: 3px;
}

thead .state-column {
text-overflow: ellipsis;
overflow: hidden;
}
thead .state-column {
text-overflow: ellipsis;
overflow: hidden;
}

table button {
height: 26px;
width: 24px !important;
display: block;
border-radius: 50%;
margin: auto;
}
table button {
height: 26px;
width: 24px !important;
display: block;
border-radius: 50%;
margin: auto;
}

a.icon-close {
display: inline-block;
height: 24px;
width: 100%;
vertical-align: middle;
background-size: 12px;
opacity: .7;
float: right;
}
a.icon-close {
display: inline-block;
height: 24px;
width: 100%;
vertical-align: middle;
background-size: 12px;
opacity: .7;
float: right;
}

a.icon-close:hover {
opacity: 1;
}
a.icon-close:hover {
opacity: 1;
}

.multiselect {
margin-left: 44px;
width: calc(100% - 44px);
}
.multiselect {
margin-left: 44px;
width: calc(100% - 44px);
}
</style>

0 comments on commit 812e4e3

Please sign in to comment.