mirror of https://github.com/logos-co/open-law.git
(not ready) book settings page
This commit is contained in:
parent
5c764b3d38
commit
c3fe536e4b
|
@ -0,0 +1 @@
|
||||||
|
export declare function initContributors(): void;
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,62 @@
|
||||||
|
<!-- Edit user modal -->
|
||||||
|
<!-- prettier-ignore-->
|
||||||
|
<div id="add-contributor-modal" tabindex="-1" aria-hidden="true" class="fixed top-0 left-0 right-0 z-50 hidden w-full p-4 overflow-x-hidden overflow-y-auto md:inset-0 h-[calc(100%-1rem)] max-h-full">
|
||||||
|
<div class="relative w-full max-w-2xl max-h-full">
|
||||||
|
<!-- Modal content -->
|
||||||
|
<form action="{{ url_for('book.settings', book_id=book.id) }}" method="post" class="relative bg-white rounded-lg shadow dark:bg-gray-700">
|
||||||
|
|
||||||
|
<input type="hidden" name="user_id" id="user-edit-id" value="0" />
|
||||||
|
<input type="hidden" name="" id="user-edit-next_url" value="" />
|
||||||
|
<!-- Modal header -->
|
||||||
|
<div class="flex items-start justify-between p-4 border-b rounded-t dark:border-gray-600">
|
||||||
|
<h3 class="text-xl font-semibold text-gray-900 dark:text-white"> Add Contributor </h3>
|
||||||
|
<button id="modalAddCloseButton" data-modal-hide="add-contributor-modal" type="button" class="text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm p-1.5 ml-auto inline-flex items-center dark:hover:bg-gray-600 dark:hover:text-white"> <svg aria-hidden="true" class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"> <path fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd"></path> </svg> </button>
|
||||||
|
</div>
|
||||||
|
<!-- Modal body -->
|
||||||
|
<div class="p-6 space-y-6">
|
||||||
|
<div class="grid gap-2">
|
||||||
|
<div class="col-span-6 sm:col-span-3">
|
||||||
|
<label for="username" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Username</label >
|
||||||
|
<div class="relative">
|
||||||
|
<div class="absolute inset-y-0 left-0 flex items-center pl-3 pointer-events-none">
|
||||||
|
<svg aria-hidden="true" class="w-5 h-5 text-gray-500 dark:text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"></path></svg>
|
||||||
|
</div>
|
||||||
|
<input id="username" type="search" id="default-search" class="block w-full p-4 pl-10 text-sm text-gray-900 border border-gray-300 rounded-lg bg-gray-50 focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" placeholder="Search Mockups, Logos..." required>
|
||||||
|
<input id="search-btn" class="text-white absolute right-2.5 bottom-2.5 bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-4 py-2 dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800">Search</input>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="col-span-6 sm:col-span-3 overflow-x-auto shadow-md sm:rounded-lg" id="search-results">
|
||||||
|
<table class="w-full text-sm text-left text-gray-500 dark:text-gray-400">
|
||||||
|
<tbody id="search-results-tbody">
|
||||||
|
<tr id="tr-example" class="hidden bg-white border-b dark:bg-gray-800 dark:border-gray-700 hover:bg-gray-50 dark:hover:bg-gray-600">
|
||||||
|
<th scope="row" class="username-th px-6 py-2 font-medium text-gray-900 whitespace-nowrap dark:text-white">
|
||||||
|
</th>
|
||||||
|
<th scope="row" class="px-6 py-1.5 font-medium text-gray-900 whitespace-nowrap dark:text-white flex justify-end">
|
||||||
|
<button data-user-id type="button" class="select-user-btn text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:ring-blue-300 font-sm rounded-lg text-sm px-5 py-1.5 dark:bg-blue-600 dark:hover:bg-blue-700 focus:outline-none dark:focus:ring-blue-800">Select</button>
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label for="roles" class="mb-2 block text-sm font-medium text-gray-900 dark:text-white">Select an option</label >
|
||||||
|
<select id="roles" class="shadow-sm bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-600 focus:border-blue-600 block w-full p-2.5 dark:bg-gray-600 dark:border-gray-500 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500">
|
||||||
|
{% for role in roles if role.value %}
|
||||||
|
<option value="{{ role.value }}">{{ role.name.title() }}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- Modal footer -->
|
||||||
|
<div class="flex items-center p-6 space-x-2 border-t border-gray-200 rounded-b dark:border-gray-600">
|
||||||
|
<button name="submit" type="submit" class="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800">Add</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
|
@ -0,0 +1,45 @@
|
||||||
|
<!-- prettier-ignore -->
|
||||||
|
{% extends 'base.html' %}
|
||||||
|
{% include 'book/add_contributor_modal.html' %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<!-- Hide right_sidebar -->
|
||||||
|
<!-- prettier-ignore -->
|
||||||
|
{% block right_sidebar %} {% endblock %}
|
||||||
|
|
||||||
|
<div class="p-5">
|
||||||
|
<div class="flex justify-between ml-4 mb-2">
|
||||||
|
<h1 class="text-2xl font-extrabold dark:text-white">Contributors</h1>
|
||||||
|
<!-- prettier-ignore -->
|
||||||
|
<button
|
||||||
|
type="button" data-modal-target="add-contributor-modal" data-modal-toggle="add-contributor-modal"
|
||||||
|
class="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-4 py-2.5 text-center inline-flex items-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6 mr-1"> <path stroke-linecap="round" stroke-linejoin="round" d="M12 9v6m3-3H9m12 0a9 9 0 11-18 0 9 9 0 0118 0z" /> </svg>
|
||||||
|
Add
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="relative overflow-x-auto shadow-md sm:rounded-lg">
|
||||||
|
<table class="w-full text-sm text-left text-gray-500 dark:text-gray-400">
|
||||||
|
<thead
|
||||||
|
class="text-xs text-gray-700 uppercase bg-gray-50 dark:bg-gray-700 dark:text-gray-400">
|
||||||
|
<tr>
|
||||||
|
<th scope="col" class="px-6 py-3">Username</th>
|
||||||
|
<th scope="col" class="px-6 py-3">Role</th>
|
||||||
|
<th scope="col" class="px-6 py-3">Action</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for contributor in book.contributors %}
|
||||||
|
<tr class="bg-white border-b dark:bg-gray-900 dark:border-gray-700">
|
||||||
|
<td class="px-6 py-4">{{ contributor.username }}</td>
|
||||||
|
<td class="px-6 py-4">{{ contributor.role.name }}</td>
|
||||||
|
<td class="px-6 py-4"></td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% endblock %}
|
|
@ -23,7 +23,7 @@ def get_all():
|
||||||
# search_query=q,
|
# search_query=q,
|
||||||
# )
|
# )
|
||||||
return render_template(
|
return render_template(
|
||||||
"books/index.html",
|
"book/index.html",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -50,6 +50,16 @@ def create():
|
||||||
return redirect(url_for("book.get_all"))
|
return redirect(url_for("book.get_all"))
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route("/<int:book_id>/settings", methods=["GET", "POST"])
|
||||||
|
@login_required
|
||||||
|
def settings(book_id):
|
||||||
|
book: m.Book = db.session.get(m.Book, book_id)
|
||||||
|
|
||||||
|
return render_template(
|
||||||
|
"book/settings.html", book=book, roles=m.BookContributor.Roles
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/<int:book_id>/add_contributor", methods=["POST"])
|
@bp.route("/<int:book_id>/add_contributor", methods=["POST"])
|
||||||
@login_required
|
@login_required
|
||||||
def add_contributor(book_id):
|
def add_contributor(book_id):
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
import {Modal} from 'flowbite';
|
||||||
|
import type {ModalOptions, ModalInterface} from 'flowbite';
|
||||||
|
|
||||||
|
const searchAndShowResults = async (
|
||||||
|
userSearchBtn: any,
|
||||||
|
userSearchbar: any,
|
||||||
|
searchResultsTbody: any,
|
||||||
|
trExample: any,
|
||||||
|
) => {
|
||||||
|
searchResultsTbody.innerHTML = '';
|
||||||
|
|
||||||
|
const searchQuery = userSearchbar.value
|
||||||
|
if (!searchQuery.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const res = await fetch('/user/search?q=' + searchQuery);
|
||||||
|
const json = await res.json();
|
||||||
|
|
||||||
|
json.users.forEach((user: any) => {
|
||||||
|
let clone = trExample.cloneNode(true);
|
||||||
|
|
||||||
|
const selectUserBtn = clone.querySelector('.select-user-btn');
|
||||||
|
selectUserBtn.setAttribute('data-user-id', user.id);
|
||||||
|
selectUserBtn.addEventListener('click', (e: any) => {
|
||||||
|
console.log('e', e.target);
|
||||||
|
userSearchBtn.setAttribute('disabled', true);
|
||||||
|
userSearchbar.setAttribute('disabled', true);
|
||||||
|
});
|
||||||
|
|
||||||
|
const usernameTh = clone.querySelector('.username-th');
|
||||||
|
usernameTh.innerHTML = user.username;
|
||||||
|
|
||||||
|
clone.classList.remove('hidden');
|
||||||
|
searchResultsTbody.appendChild(clone);
|
||||||
|
});
|
||||||
|
return undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function initContributors() {
|
||||||
|
const searchBtn: HTMLButtonElement = document.querySelector('#search-btn');
|
||||||
|
const userSearchbar: HTMLInputElement = document.querySelector('#username');
|
||||||
|
|
||||||
|
const searchResultsTbody = document.querySelector('#search-results-tbody');
|
||||||
|
const trExample: HTMLTableRowElement = document.querySelector('#tr-example');
|
||||||
|
|
||||||
|
searchBtn.addEventListener('click', async e => {
|
||||||
|
await searchAndShowResults(
|
||||||
|
searchBtn,
|
||||||
|
userSearchbar
|
||||||
|
searchResultsTbody,
|
||||||
|
trExample,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
|
@ -1,4 +1,6 @@
|
||||||
import './styles.css';
|
import './styles.css';
|
||||||
import {initBooks} from './books';
|
import {initBooks} from './books';
|
||||||
|
import {initContributors} from './contributors';
|
||||||
|
|
||||||
initBooks();
|
initBooks();
|
||||||
|
initContributors();
|
||||||
|
|
Loading…
Reference in New Issue