Files
enviPy-bayer/templates/modals/objects/edit_package_permissions_modal.html

378 lines
13 KiB
HTML

{% load static %}
<!-- Edit Package Permissions -->
<dialog
id="edit_package_permissions_modal"
class="modal"
x-data="{
updatePermissions(checkbox) {
const parts = checkbox.id.split('_');
const perm = parts[0];
const id = parts[1];
const readBox = document.getElementById('read_' + id);
const writeBox = document.getElementById('write_' + id);
const ownerBox = document.getElementById('owner_' + id);
if (perm === 'read' && !readBox.checked) {
writeBox.checked = false;
ownerBox.checked = false;
}
if (perm === 'write') {
if (writeBox.checked) {
readBox.checked = true;
} else {
ownerBox.checked = false;
}
}
if (perm === 'owner' && ownerBox.checked) {
readBox.checked = true;
writeBox.checked = true;
}
}
}"
>
<div class="modal-box max-w-2xl">
<!-- Header -->
<h3 class="text-lg font-bold">Grant or Revoke Permissions</h3>
<!-- Close button (X) -->
<form method="dialog">
<button class="btn btn-sm btn-circle btn-ghost absolute top-2 right-2">
</button>
</form>
<!-- Body -->
<div class="py-4">
<p class="mb-4">
Modify permissions for this package. Note that if you give
<code class="badge badge-ghost">write</code> permissions to a user or
group, <code class="badge badge-ghost">read</code> permissions will be
granted automatically.
<br />
To allow users to perform destructive actions, such as deleting the
package, <code class="badge badge-ghost">owner</code> permissions must
be granted.
</p>
<!-- Add New Permission -->
<form
id="modal-form-permissions"
accept-charset="UTF-8"
action=""
method="post"
class="mb-4"
>
{% csrf_token %}
<div class="grid grid-cols-12 gap-2 items-end">
<div class="col-span-5">
<label class="label">
<span class="label-text">User or Group</span>
</label>
<div
class="relative"
x-data="{
searchQuery: '',
selectedItem: null,
showResults: false,
filteredResults: [],
allItems: [
{% for u in users %}
{ type: 'user', name: '{{ u.username }}', url: '{{ u.url }}',
display: '{{ u.username }}' },
{% endfor %}
{% for g in groups %}
{ type: 'group', name: '{{ g.name|safe }}', url: '{{ g.url }}',
display: '{{ g.name|safe }}' },
{% endfor %}
],
init() {
this.filteredResults = this.allItems;
},
search() {
if (this.searchQuery.length === 0) {
this.filteredResults = this.allItems;
} else {
this.filteredResults = this.allItems.filter(item =>
item.name.toLowerCase().includes(this.searchQuery.toLowerCase())
);
}
this.showResults = true;
},
selectItem(item) {
this.selectedItem = item;
this.searchQuery = item.display;
this.showResults = false;
},
clearSelection() {
this.selectedItem = null;
this.searchQuery = '';
this.showResults = false;
}
}"
@click.away="showResults = false"
>
<input
type="text"
x-model="searchQuery"
@input="search()"
@focus="showResults = true; search()"
@keydown.escape="showResults = false"
@keydown.arrow-down.prevent="$refs.resultsList?.children[0]?.focus()"
class="input input-bordered w-full input-sm"
placeholder="Search users or groups..."
autocomplete="off"
required
/>
<!-- Clear button -->
<button
type="button"
x-show="searchQuery.length > 0"
@click="clearSelection()"
class="absolute right-2 top-1/2 transform -translate-y-1/2 text-gray-400 hover:text-gray-600"
>
</button>
<!-- Hidden input for form submission -->
<input
type="hidden"
name="grantee"
x-bind:value="selectedItem?.url || ''"
required
/>
<!-- Search results dropdown -->
<div
x-show="showResults && filteredResults.length > 0"
x-transition
class="absolute z-50 w-full mt-1 bg-base-100 border border-base-300 rounded-lg shadow-lg max-h-60 overflow-y-auto"
>
<ul x-ref="resultsList" id="resultsList" class="py-1">
<template
x-for="(item, index) in filteredResults"
:key="item.url"
>
<li>
<button
type="button"
@click="selectItem(item)"
@keydown.enter="selectItem(item)"
@keydown.escape="showResults = false"
@keydown.arrow-up.prevent="index > 0 ? $event.target.parentElement.previousElementSibling?.children[0]?.focus() : null"
@keydown.arrow-down.prevent="index < filteredResults.length - 1 ? $event.target.parentElement.nextElementSibling?.children[0]?.focus() : null"
class="w-full px-4 py-2 text-left hover:bg-base-200 focus:bg-base-200 focus:outline-none flex items-center space-x-2"
>
<span
x-text="item.type === 'user' ? '👤' : '👥'"
class="text-sm opacity-60"
></span>
<span x-text="item.display"></span>
<span
x-text="item.type === 'user' ? '(User)' : '(Group)'"
class="text-xs opacity-50 ml-auto"
></span>
</button>
</li>
</template>
</ul>
</div>
<!-- No results message -->
<div
x-show="showResults && filteredResults.length === 0 && searchQuery.length > 0"
x-transition
class="absolute z-50 w-full mt-1 bg-base-100 border border-base-300 rounded-lg shadow-lg"
>
<div class="px-4 py-2 text-gray-500 text-sm">
No users or groups found
</div>
</div>
</div>
</div>
<div class="col-span-2 text-center">
<label class="label justify-center">
<span class="label-text">Read</span>
</label>
<input
type="checkbox"
name="read"
id="read_new"
class="checkbox"
@click="updatePermissions($el)"
/>
</div>
<div class="col-span-2 text-center">
<label class="label justify-center">
<span class="label-text">Write</span>
</label>
<input
type="checkbox"
name="write"
id="write_new"
class="checkbox"
@click="updatePermissions($el)"
/>
</div>
<div class="col-span-2 text-center">
<label class="label justify-center">
<span class="label-text">Owner</span>
</label>
<input
type="checkbox"
name="owner"
id="owner_new"
class="checkbox"
@click="updatePermissions($el)"
/>
</div>
<div class="col-span-1">
<button type="submit" class="btn btn-primary btn-sm">+</button>
</div>
</div>
</form>
<!-- User Permissions -->
{% if user_permissions %}
<div class="divider">User Permissions</div>
<div class="space-y-2">
{% for up in user_permissions %}
<form
id="modal-form-permissions_{{ up.user.uuid }}"
accept-charset="UTF-8"
action=""
method="post"
>
{% csrf_token %}
<div class="grid grid-cols-12 gap-2 items-center">
<div class="col-span-5 truncate">
{{ up.user.username }}
{% if not up.user.is_active %}<i>(inactive)</i>{% endif %}
<input
type="hidden"
name="grantee"
value="{{ up.user.url }}"
/>
</div>
<div class="col-span-2 text-center">
<input
type="checkbox"
name="read"
id="read_{{ up.user.uuid }}"
class="checkbox"
{% if up.has_read %}checked{% endif %}
@click="updatePermissions($el)"
/>
</div>
<div class="col-span-2 text-center">
<input
type="checkbox"
name="write"
id="write_{{ up.user.uuid }}"
class="checkbox"
{% if up.has_write %}checked{% endif %}
@click="updatePermissions($el)"
/>
</div>
<div class="col-span-2 text-center">
<input
type="checkbox"
name="owner"
id="owner_{{ up.user.uuid }}"
class="checkbox"
{% if up.has_all %}checked{% endif %}
@click="updatePermissions($el)"
/>
</div>
<div class="col-span-1">
<button type="submit" class="btn btn-sm btn-ghost"></button>
</div>
</div>
</form>
{% endfor %}
</div>
{% endif %}
<!-- Group Permissions -->
{% if group_permissions %}
<div class="divider">Group Permissions</div>
<div class="space-y-2">
{% for gp in group_permissions %}
<form
id="modal-form-permissions_{{ gp.group.uuid }}"
accept-charset="UTF-8"
action=""
method="post"
>
{% csrf_token %}
<div class="grid grid-cols-12 gap-2 items-center">
<div class="col-span-5 truncate">
{{ gp.group.name|safe }}
<input
type="hidden"
name="grantee"
value="{{ gp.group.url }}"
/>
</div>
<div class="col-span-2 text-center">
<input
type="checkbox"
name="read"
id="read_{{ gp.group.uuid }}"
class="checkbox"
{% if gp.has_read %}checked{% endif %}
@click="updatePermissions($el)"
/>
</div>
<div class="col-span-2 text-center">
<input
type="checkbox"
name="write"
id="write_{{ gp.group.uuid }}"
class="checkbox"
{% if gp.has_write %}checked{% endif %}
@click="updatePermissions($el)"
/>
</div>
<div class="col-span-2 text-center">
<input
type="checkbox"
name="owner"
id="owner_{{ gp.group.uuid }}"
class="checkbox"
{% if gp.has_all %}checked{% endif %}
@click="updatePermissions($el)"
/>
</div>
<div class="col-span-1">
<button type="submit" class="btn btn-sm btn-ghost"></button>
</div>
</div>
</form>
{% endfor %}
</div>
{% endif %}
</div>
<!-- Footer -->
<div class="modal-action">
<button
type="button"
class="btn"
onclick="this.closest('dialog').close()"
>
Close
</button>
</div>
</div>
<!-- Backdrop -->
<form method="dialog" class="modal-backdrop">
<button>close</button>
</form>
</dialog>