forked from enviPath/enviPy
378 lines
13 KiB
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>
|