mirror of https://github.com/logos-co/open-law.git
added profile page (edit-change to edit_profile)
This commit is contained in:
parent
53bc7810b2
commit
c82912d6da
File diff suppressed because one or more lines are too long
142935
app/static/js/main.js
142935
app/static/js/main.js
File diff suppressed because one or more lines are too long
|
@ -18,9 +18,10 @@
|
||||||
<!-- prettier-ignore -->
|
<!-- prettier-ignore -->
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<!-- prettier-ignore -->
|
<!-- prettier-ignore -->
|
||||||
|
<div class="flex flex-col w-4/5">
|
||||||
{% for book in books if not book.is_deleted%}
|
{% for book in books if not book.is_deleted%}
|
||||||
<!-- prettier-ignore -->
|
<!-- prettier-ignore -->
|
||||||
<dl class=" bg-white dark:bg-gray-900 h-max w-full p-5 text-gray-900 divide-y divide-gray-200 dark:text-white dark:divide-gray-700 m-3 border-2 border-gray-200 border-solid rounded-lg dark:border-gray-700">
|
<dl class="bg-white dark:bg-gray-900 h-max w-full p-5 text-gray-900 divide-y divide-gray-200 dark:text-white dark:divide-gray-700 m-3 border-2 border-gray-200 border-solid rounded-lg dark:border-gray-700">
|
||||||
<dt class="mb-2"><a class="flex flex-col pb-4" href="{{url_for('book.collection_view',book_id=book.id)}}">{{book.owner.username}}/{{book.label}}</a></dt>
|
<dt class="mb-2"><a class="flex flex-col pb-4" href="{{url_for('book.collection_view',book_id=book.id)}}">{{book.owner.username}}/{{book.label}}</a></dt>
|
||||||
<dd class="flex flex-col md:flex-row text-lg font-semibold text-gray-500 md:text-lg dark:text-gray-400">
|
<dd class="flex flex-col md:flex-row text-lg font-semibold text-gray-500 md:text-lg dark:text-gray-400">
|
||||||
{% if book.versions %}
|
{% if book.versions %}
|
||||||
|
@ -45,6 +46,7 @@
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
</div>
|
||||||
<!-- prettier-ignore -->
|
<!-- prettier-ignore -->
|
||||||
{% if current_user.is_authenticated and page.pages > 1 %}
|
{% if current_user.is_authenticated and page.pages > 1 %}
|
||||||
<div class="container content-center mt-3 flex bg-white dark:bg-gray-800">
|
<div class="container content-center mt-3 flex bg-white dark:bg-gray-800">
|
||||||
|
|
|
@ -64,7 +64,7 @@
|
||||||
<p class="text-center text-sm text-gray-900 dark:text-white" role="none"> {{current_user.username}} </p>
|
<p class="text-center text-sm text-gray-900 dark:text-white" role="none"> {{current_user.username}} </p>
|
||||||
</div>
|
</div>
|
||||||
<div class="px-4 py-3" role="none">
|
<div class="px-4 py-3" role="none">
|
||||||
<a class="text-center text-sm text-gray-900 dark:text-white" role="none" href="{{ url_for('user.profile') }}"> Edit profile </a>
|
<a class="text-center text-sm text-gray-900 dark:text-white" role="none" href="{{ url_for('user.edit_profile') }}"> Edit profile </a>
|
||||||
</div>
|
</div>
|
||||||
<ul class="py-1" role="none">
|
<ul class="py-1" role="none">
|
||||||
<li>
|
<li>
|
||||||
|
|
|
@ -13,8 +13,8 @@
|
||||||
<ul class="flex md:flex-wrap -mb-px text-xs md:text-sm font-medium text-center" id="myTab" data-tabs-toggle="#myTabContent" role="tablist">
|
<ul class="flex md:flex-wrap -mb-px text-xs md:text-sm font-medium text-center" id="myTab" data-tabs-toggle="#myTabContent" role="tablist">
|
||||||
<li class="mr-2 w-full md:w-auto" role="presentation">
|
<li class="mr-2 w-full md:w-auto" role="presentation">
|
||||||
<!-- prettier-ignore -->
|
<!-- prettier-ignore -->
|
||||||
<button class="inline-flex p-4 border-b-2 rounded-t-lg" id="last-sections-tab" data-tabs-target="#last-sections" type="button" role="tab" aria-controls="last-sections" aria-selected="false"> <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-3"> <path stroke-linecap="round" stroke-linejoin="round" d="M3.75 13.5l10.5-11.25L12 10.5h8.25L9.75 21.75 12 13.5H3.75z" /> </svg>
|
<button class="inline-flex p-4 border-b-2 rounded-t-lg" id="last-interpretations-tab" data-tabs-target="#last-interpretations" type="button" role="tab" aria-controls="last-interpretations" aria-selected="false"> <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-3"> <path stroke-linecap="round" stroke-linejoin="round" d="M3.75 13.5l10.5-11.25L12 10.5h8.25L9.75 21.75 12 13.5H3.75z" /> </svg>
|
||||||
LAtest Interpretations
|
Latest Interpretations
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
<li class="mr-2 w-full md:w-auto" role="presentation">
|
<li class="mr-2 w-full md:w-auto" role="presentation">
|
||||||
|
@ -27,7 +27,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div id="myTabContent" class="md:mr-64">
|
<div id="myTabContent" class="md:mr-64">
|
||||||
<!-- prettier-ignore -->
|
<!-- prettier-ignore -->
|
||||||
<div class="hidden p-4 rounded-lg bg-gray-50 dark:bg-gray-800" id="last-sections" role="tabpanel" aria-labelledby="last-sections-tab">
|
<div class="hidden p-4 rounded-lg bg-gray-50 dark:bg-gray-800" id="last-interpretations" role="tabpanel" aria-labelledby="last-interpretations-tab">
|
||||||
{% for interpretation in interpretations %}
|
{% for interpretation in interpretations %}
|
||||||
<!-- prettier-ignore -->
|
<!-- prettier-ignore -->
|
||||||
<dl class="bg-white dark:bg-gray-900 max-w-full p-3 text-gray-900 divide-y divide-gray-200 dark:text-white dark:divide-gray-700 m-3 border-2 border-gray-200 border-solid rounded-lg dark:border-gray-700">
|
<dl class="bg-white dark:bg-gray-900 max-w-full p-3 text-gray-900 divide-y divide-gray-200 dark:text-white dark:divide-gray-700 m-3 border-2 border-gray-200 border-solid rounded-lg dark:border-gray-700">
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
</span>
|
</span>
|
||||||
</li>
|
</li>
|
||||||
<li class="md:hidden">
|
<li class="md:hidden">
|
||||||
<a href="{{ url_for('user.profile') }}" class="flex items-center p-2 text-gray-900 rounded-lg dark:text-white hover:bg-gray-100 dark:hover:bg-gray-700">
|
<a href="{{ url_for('user.edit_profile') }}" class="flex items-center p-2 text-gray-900 rounded-lg dark:text-white hover:bg-gray-100 dark:hover:bg-gray-700">
|
||||||
<!-- prettier-ignore -->
|
<!-- prettier-ignore -->
|
||||||
<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"> <path stroke-linecap="round" stroke-linejoin="round" d="M16.862 4.487l1.687-1.688a1.875 1.875 0 112.652 2.652L10.582 16.07a4.5 4.5 0 01-1.897 1.13L6 18l.8-2.685a4.5 4.5 0 011.13-1.897l8.932-8.931zm0 0L19.5 7.125M18 14v4.75A2.25 2.25 0 0115.75 21H5.25A2.25 2.25 0 013 18.75V8.25A2.25 2.25 0 015.25 6H10" /> </svg>
|
<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"> <path stroke-linecap="round" stroke-linejoin="round" d="M16.862 4.487l1.687-1.688a1.875 1.875 0 112.652 2.652L10.582 16.07a4.5 4.5 0 01-1.897 1.13L6 18l.8-2.685a4.5 4.5 0 011.13-1.897l8.932-8.931zm0 0L19.5 7.125M18 14v4.75A2.25 2.25 0 0115.75 21H5.25A2.25 2.25 0 013 18.75V8.25A2.25 2.25 0 015.25 6H10" /> </svg>
|
||||||
<span class="ml-3">Edit profile</span>
|
<span class="ml-3">Edit profile</span>
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
<!-- prettier-ignore -->
|
||||||
|
{% extends 'base.html' %}
|
||||||
|
{% include 'user/delete_profile_modal.html' %}
|
||||||
|
{% block content %}
|
||||||
|
<!-- component -->
|
||||||
|
<section>
|
||||||
|
<div class="w-full lg:w-4/12 px-4 mx-auto pt-6">
|
||||||
|
<div>
|
||||||
|
<!-- prettier-ignore -->
|
||||||
|
<div class="w-full lg:max-w-xl p-6 space-y-8 sm:p-8 bg-white rounded-lg shadow-xl dark:bg-gray-800">
|
||||||
|
{% if current_user.is_activated %}
|
||||||
|
<!-- prettier-ignore -->
|
||||||
|
<h2 class="text-2xl font-bold text-gray-900 dark:text-white">Edit your profile</h2>
|
||||||
|
{% else %}
|
||||||
|
<!-- prettier-ignore -->
|
||||||
|
<h2 class="text-2xl font-bold text-gray-900 dark:text-white">Create your profile</h2>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<!-- prettier-ignore -->
|
||||||
|
<label class='block mb-2 text-sm font-medium text-gray-900 dark:text-white'>Account</label>
|
||||||
|
<input type="text" class='bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 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' autocomplete="off" onCopy="return false" readonly value="{{current_user.wallet_id}}">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- prettier-ignore -->
|
||||||
|
<form class="mt-8 space-y-6 from" role="form" action="{{ url_for('user.edit_profile') }}" method="post" enctype="multipart/form-data">
|
||||||
|
{{ form.hidden_tag() }}
|
||||||
|
<div>
|
||||||
|
<!-- prettier-ignore -->
|
||||||
|
{{form.name.label(class='block mb-2 text-sm font-medium text-gray-900 dark:text-white')}}
|
||||||
|
{{form.name(autocomplete="off", class='bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 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')}}
|
||||||
|
</div>
|
||||||
|
<!-- prettier-ignore -->
|
||||||
|
{{form.avatar_img.label(class='block mb-2 text-sm font-medium text-gray-900 dark:text-white')}}
|
||||||
|
<div class="flex items-center mb-3">
|
||||||
|
<div>
|
||||||
|
{% if current_user.avatar_img %}
|
||||||
|
<img class=" w-14 h-14 rounded-full mr-3" src="data:image/jpeg;base64,{{ current_user.avatar_img }}" alt="user avatar">
|
||||||
|
{% else %}
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 56 56" stroke-width="1.5" stroke="currentColor" class="w-14 h-14"> <path stroke-linecap="round" stroke-linejoin="round" d="M17.982 18.725A7.488 7.488 0 0012 15.75a7.488 7.488 0 00-5.982 2.975m11.963 0a9 9 0 10-11.963 0m11.963 0A8.966 8.966 0 0112 21a8.966 8.966 0 01-5.982-2.275M15 9.75a3 3 0 11-6 0 3 3 0 016 0z" /> </svg>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
|
||||||
|
{{form.avatar_img(type='file', class='bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 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', id="avatar_img",
|
||||||
|
value=current_user.avatar_img if current_user.avatar_img else "")}}</div>
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="w-full px-5 py-3 text-base font-medium text-center text-white bg-blue-700 rounded-lg hover:bg-blue-800 focus:ring-4 focus:ring-blue-300 sm:w-auto dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800">Save changes</button>
|
||||||
|
</form>
|
||||||
|
<button type="button" data-modal-target="delete_profile_modal" data-modal-toggle="delete_profile_modal" class="text-red-700 hover:text-white border border-red-700 hover:bg-red-800 focus:ring-4 focus:outline-none focus:ring-red-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center mr-2 mb-2 dark:border-red-500 dark:text-red-500 dark:hover:text-white dark:hover:bg-red-600 dark:focus:ring-red-900">Delete you profile</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
{% block right_sidebar %}{% endblock %}
|
||||||
|
<!-- prettier-ignore -->
|
||||||
|
{% endblock %}
|
|
@ -1,58 +1,140 @@
|
||||||
<!-- prettier-ignore -->
|
<!-- prettier-ignore -->
|
||||||
{% extends 'base.html' %}
|
{% extends 'base.html' %}
|
||||||
{% include 'user/delete_profile_modal.html' %}
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<!-- component -->
|
<div class="border-b border-gray-200 dark:border-gray-700 md:mr-64">
|
||||||
<section>
|
<div class="flex p-5 items-center">
|
||||||
<div class="w-full lg:w-4/12 px-4 mx-auto pt-6">
|
|
||||||
<div>
|
|
||||||
<!-- prettier-ignore -->
|
<!-- prettier-ignore -->
|
||||||
<div class="w-full lg:max-w-xl p-6 space-y-8 sm:p-8 bg-white rounded-lg shadow-xl dark:bg-gray-800">
|
{% if user.avatar_img %}
|
||||||
{% if current_user.is_activated %}
|
|
||||||
<!-- prettier-ignore -->
|
<!-- prettier-ignore -->
|
||||||
<h2 class="text-2xl font-bold text-gray-900 dark:text-white">Edit your profile</h2>
|
<img class=" w-10 h-10 rounded-full mr-3" src="data:image/jpeg;base64,{{ current_user.avatar_img }}" alt="user avatar">
|
||||||
{% endif %}
|
|
||||||
{% if not current_user.is_activated %}
|
|
||||||
<!-- prettier-ignore -->
|
|
||||||
<h2 class="text-2xl font-bold text-gray-900 dark:text-white">Create your profile</h2>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<!-- prettier-ignore -->
|
|
||||||
<label class='block mb-2 text-sm font-medium text-gray-900 dark:text-white'>Account</label>
|
|
||||||
<input type="text" class='bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 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' autocomplete="off" onCopy="return false" readonly value="{{current_user.wallet_id}}">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- prettier-ignore -->
|
|
||||||
<form class="mt-8 space-y-6 from" role="form" action="{{ url_for('user.profile') }}" method="post" enctype="multipart/form-data">
|
|
||||||
{{ form.hidden_tag() }}
|
|
||||||
<div>
|
|
||||||
<!-- prettier-ignore -->
|
|
||||||
{{form.name.label(class='block mb-2 text-sm font-medium text-gray-900 dark:text-white')}}
|
|
||||||
{{form.name(autocomplete="off", class='bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 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')}}
|
|
||||||
</div>
|
|
||||||
<!-- prettier-ignore -->
|
|
||||||
{{form.avatar_img.label(class='block mb-2 text-sm font-medium text-gray-900 dark:text-white')}}
|
|
||||||
<div class="flex items-center mb-3">
|
|
||||||
<div>
|
|
||||||
{% if current_user.avatar_img %}
|
|
||||||
<img class=" w-14 h-14 rounded-full mr-3" src="data:image/jpeg;base64,{{ current_user.avatar_img }}" alt="user avatar">
|
|
||||||
{% else %}
|
{% else %}
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 56 56" stroke-width="1.5" stroke="currentColor" class="w-14 h-14"> <path stroke-linecap="round" stroke-linejoin="round" d="M17.982 18.725A7.488 7.488 0 0012 15.75a7.488 7.488 0 00-5.982 2.975m11.963 0a9 9 0 10-11.963 0m11.963 0A8.966 8.966 0 0112 21a8.966 8.966 0 01-5.982-2.275M15 9.75a3 3 0 11-6 0 3 3 0 016 0z" /> </svg>
|
<!-- prettier-ignore -->
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-10 h-10"> <path stroke-linecap="round" stroke-linejoin="round" d="M17.982 18.725A7.488 7.488 0 0012 15.75a7.488 7.488 0 00-5.982 2.975m11.963 0a9 9 0 10-11.963 0m11.963 0A8.966 8.966 0 0112 21a8.966 8.966 0 01-5.982-2.275M15 9.75a3 3 0 11-6 0 3 3 0 016 0z" /> </svg>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<!-- prettier-ignore -->
|
||||||
|
<h1 class="hidden md:inline font-extrabold text-lg dark:text-white ml-4">{{user.username}}</h1>
|
||||||
|
<!-- prettier-ignore -->
|
||||||
|
<span class="hidden md:block text-sm ml-4 w-1/2 text-gray-500 text-center md:text-left dark:text-gray-400">
|
||||||
|
{{user.wallet_id}}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<!-- prettier-ignore -->
|
||||||
|
<ul class="flex md:flex-wrap -mb-px text-xs md:text-sm font-medium text-center" id="myTab" data-tabs-toggle="#myTabContent" role="tablist">
|
||||||
|
<li class="mr-2 w-full md:w-auto" role="presentation">
|
||||||
|
<!-- prettier-ignore -->
|
||||||
|
<button class="inline-flex p-4 border-b-2 rounded-t-lg" id="library-tab" data-tabs-target="#library" type="button" role="tab" aria-controls="library" aria-selected="false"><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-3"> <path stroke-linecap="round" stroke-linejoin="round" d="M11.48 3.499a.562.562 0 011.04 0l2.125 5.111a.563.563 0 00.475.345l5.518.442c.499.04.701.663.321.988l-4.204 3.602a.563.563 0 00-.182.557l1.285 5.385a.562.562 0 01-.84.61l-4.725-2.885a.563.563 0 00-.586 0L6.982 20.54a.562.562 0 01-.84-.61l1.285-5.386a.562.562 0 00-.182-.557l-4.204-3.602a.563.563 0 01.321-.988l5.518-.442a.563.563 0 00.475-.345L11.48 3.5z" /> </svg>
|
||||||
|
Library
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
<li class="mr-2 w-full md:w-auto" role="presentation">
|
||||||
|
<!-- prettier-ignore -->
|
||||||
|
<button class="inline-flex p-4 border-b-2 border-transparent rounded-t-lg hover:text-gray-600 hover:border-gray-300 dark:hover:text-gray-300" id="contributions-tab" data-tabs-target="#contributions" type="button" role="tab" aria-controls="contributions" aria-selected="false"><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-3"> <path stroke-linecap="round" stroke-linejoin="round" d="M15 19.128a9.38 9.38 0 002.625.372 9.337 9.337 0 004.121-.952 4.125 4.125 0 00-7.533-2.493M15 19.128v-.003c0-1.113-.285-2.16-.786-3.07M15 19.128v.106A12.318 12.318 0 018.624 21c-2.331 0-4.512-.645-6.374-1.766l-.001-.109a6.375 6.375 0 0111.964-3.07M12 6.375a3.375 3.375 0 11-6.75 0 3.375 3.375 0 016.75 0zm8.25 2.25a2.625 2.625 0 11-5.25 0 2.625 2.625 0 015.25 0z" /> </svg>
|
||||||
|
Contributions
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div id="myTabContent" class="md:mr-64">
|
||||||
|
<!-- prettier-ignore -->
|
||||||
|
<div class="hidden p-4 rounded-lg bg-gray-50 dark:bg-gray-800" id="library" role="tabpanel" aria-labelledby="library-tab">
|
||||||
|
{% for book in user.books if not book.is_deleted %}
|
||||||
|
<!-- prettier-ignore -->
|
||||||
|
<dl class="bg-white dark:bg-gray-900 h-max w-full p-5 text-gray-900 divide-y divide-gray-200 dark:text-white dark:divide-gray-700 m-3 border-2 border-gray-200 border-solid rounded-lg dark:border-gray-700">
|
||||||
|
<dt class="mb-2"><a class="flex flex-col pb-4" href="{{url_for('book.collection_view',book_id=book.id)}}">{{book.owner.username}}/{{book.label}}</a></dt>
|
||||||
|
<dd class="flex flex-col md:flex-row text-lg font-semibold text-gray-500 md:text-lg dark:text-gray-400">
|
||||||
|
{% if book.versions %}
|
||||||
|
<p>
|
||||||
|
Last updated on {{book.versions[-1].updated_at.strftime('%B %d, %Y')}}
|
||||||
|
</p>
|
||||||
|
{% endif %}
|
||||||
|
<div class="flex ml-auto align-center justify-center space-x-3">
|
||||||
|
<span class="space-x-0.5 flex items-center">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 22 22" stroke-width="1" stroke="currentColor" class="w-4 h-4 inline-flex mr-1"> <path stroke-linecap="round" stroke-linejoin="round" d="M11.48 3.499a.562.562 0 011.04 0l2.125 5.111a.563.563 0 00.475.345l5.518.442c.499.04.701.663.321.988l-4.204 3.602a.563.563 0 00-.182.557l1.285 5.385a.562.562 0 01-.84.61l-4.725-2.885a.563.563 0 00-.586 0L6.982 20.54a.562.562 0 01-.84-.61l1.285-5.386a.562.562 0 00-.182-.557l-4.204-3.602a.563.563 0 01.321-.988l5.518-.442a.563.563 0 00.475-.345L11.48 3.5z" /> </svg>
|
||||||
|
<p>{{ book.stars|length }}</p>
|
||||||
|
</span>
|
||||||
|
<span class="space-x-0.5 flex items-center">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 22 22" stroke-width="1" stroke="currentColor" class="w-4 h-4 inline-flex mr-1"> <path stroke-linecap="round" stroke-linejoin="round" d="M3.75 13.5l10.5-11.25L12 10.5h8.25L9.75 21.75 12 13.5H3.75z" /> </svg>
|
||||||
|
<p>55</p>
|
||||||
|
</span>
|
||||||
|
<span class="space-x-0.5 flex items-center">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 22 22" stroke-width="1" stroke="currentColor" class="w-4 h-4 inline-flex mr-1"> <path stroke-linecap="round" stroke-linejoin="round" d="M19.5 14.25v-2.625a3.375 3.375 0 00-3.375-3.375h-1.5A1.125 1.125 0 0113.5 7.125v-1.5a3.375 3.375 0 00-3.375-3.375H8.25m0 12.75h7.5m-7.5 3H12M10.5 2.25H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 00-9-9z" /> </svg>
|
||||||
|
<p>55</p>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
<!-- prettier-ignore -->
|
||||||
|
<div class="hidden p-4 rounded-lg bg-gray-50 dark:bg-gray-800" id="contributions" role="tabpanel" aria-labelledby="contributions-tab">
|
||||||
|
{% for interpretation in interpretations %}
|
||||||
|
<!-- prettier-ignore -->
|
||||||
|
<dl class="bg-white dark:bg-gray-900 max-w-full p-3 text-gray-900 divide-y divide-gray-200 dark:text-white dark:divide-gray-700 m-3 border-2 border-gray-200 border-solid rounded-lg dark:border-gray-700">
|
||||||
|
<div class="flex flex-row pb-3 p-3 w-2/3 md:w-10/12">
|
||||||
|
<div class="vote-block flex flex-col m-5 justify-center items-center">
|
||||||
|
{% if interpretation.user_id != current_user.id %}
|
||||||
|
<div class="vote-button cursor-pointer" data-vote-for="interpretation" data-entity-id="{{ interpretation.id }}" data-positive="true">
|
||||||
|
<svg class="w-6 h-6 select-none
|
||||||
|
{% if interpretation.current_user_vote %}
|
||||||
|
stroke-green-500
|
||||||
|
{% endif %}
|
||||||
|
" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" > <path stroke-linecap="round" stroke-linejoin="round" d="M4.5 10.5L12 3m0 0l7.5 7.5M12 3v18" /> </svg>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<span
|
||||||
|
class="vote-count text-3xl select-none
|
||||||
|
{% if interpretation.vote_count < 0 %}
|
||||||
|
text-red-500
|
||||||
|
{% elif interpretation.vote_count > 0 %}
|
||||||
|
text-green-500
|
||||||
|
{% endif %}
|
||||||
|
"
|
||||||
|
>
|
||||||
|
{{ interpretation.vote_count }}
|
||||||
|
</span>
|
||||||
|
|
||||||
|
{% if interpretation.user_id != current_user.id %}
|
||||||
|
<div class="vote-button cursor-pointer" data-vote-for="interpretation" data-entity-id="{{ interpretation.id }}" data-positive="false">
|
||||||
|
<svg class="w-6 h-6 select-none
|
||||||
|
{% if interpretation.current_user_vote == False %}
|
||||||
|
stroke-red-500
|
||||||
|
{% endif %}
|
||||||
|
" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M19.5 13.5L12 21m0 0l-7.5-7.5M12 21V3" /> </svg>
|
||||||
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
<!-- prettier-ignore -->
|
||||||
|
<dt class="flex w-full mb-1 text-gray-500 md:text-lg dark:text-gray-400 flex-col">
|
||||||
|
<div class="ql-snow truncate md:max-w-xl">
|
||||||
|
{% set local_breadcrumbs = interpretation.section.breadcrumbs_path %}
|
||||||
|
{% include 'book/local_breadcrumbs_navigation.html'%}
|
||||||
|
<p>{{ interpretation.section.label }}</p>
|
||||||
|
</a>
|
||||||
|
<div class="dark:text-white h-30 ql-editor">
|
||||||
|
<p>{{ interpretation.text|safe }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex mt-auto align-center justify-between md:w-full">
|
||||||
<div>
|
<div>
|
||||||
|
<span class="hidden md:inline-block">Interpretation by</span>
|
||||||
{{form.avatar_img(type='file', class='bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 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', id="avatar_img",
|
{{interpretation.user.username}} on {{interpretation.created_at.strftime('%B %d, %Y')}}
|
||||||
value=current_user.avatar_img if current_user.avatar_img else "")}}</div>
|
|
||||||
</div>
|
</div>
|
||||||
<button type="submit" class="w-full px-5 py-3 text-base font-medium text-center text-white bg-blue-700 rounded-lg hover:bg-blue-800 focus:ring-4 focus:ring-blue-300 sm:w-auto dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800">Save changes</button>
|
<div class="flex ml-auto justify-between w-24">
|
||||||
</form>
|
<span class="space-x-0.5 flex items-center">
|
||||||
<button type="button" data-modal-target="delete_profile_modal" data-modal-toggle="delete_profile_modal" class="text-red-700 hover:text-white border border-red-700 hover:bg-red-800 focus:ring-4 focus:outline-none focus:ring-red-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center mr-2 mb-2 dark:border-red-500 dark:text-red-500 dark:hover:text-white dark:hover:bg-red-600 dark:focus:ring-red-900">Delete you profile</button>
|
<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"> <path stroke-linecap="round" stroke-linejoin="round" d="M9 8.25H7.5a2.25 2.25 0 00-2.25 2.25v9a2.25 2.25 0 002.25 2.25h9a2.25 2.25 0 002.25-2.25v-9a2.25 2.25 0 00-2.25-2.25H15m0-3l-3-3m0 0l-3 3m3-3V15" /> </svg>
|
||||||
|
</span>
|
||||||
|
<div class="space-x-0.5 flex items-center">
|
||||||
|
<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"> <path stroke-linecap="round" stroke-linejoin="round" d="M20.25 8.511c.884.284 1.5 1.128 1.5 2.097v4.286c0 1.136-.847 2.1-1.98 2.193-.34.027-.68.052-1.02.072v3.091l-3-3c-1.354 0-2.694-.055-4.02-.163a2.115 2.115 0 01-.825-.242m9.345-8.334a2.126 2.126 0 00-.476-.095 48.64 48.64 0 00-8.048 0c-1.131.094-1.976 1.057-1.976 2.192v4.286c0 .837.46 1.58 1.155 1.951m9.345-8.334V6.637c0-1.621-1.152-3.026-2.76-3.235A48.455 48.455 0 0011.25 3c-2.115 0-4.198.137-6.24.402-1.608.209-2.76 1.614-2.76 3.235v6.226c0 1.621 1.152 3.026 2.76 3.235.577.075 1.157.14 1.74.194V21l4.155-4.155" /> </svg>
|
||||||
|
<p>{{interpretation.active_comments | length}}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</dt>
|
||||||
{% block right_sidebar %}{% endblock %}
|
</div>
|
||||||
<!-- prettier-ignore -->
|
</dl>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -102,7 +102,7 @@ def verify():
|
||||||
login_user(user=user)
|
login_user(user=user)
|
||||||
log(log.INFO, "Register new user")
|
log(log.INFO, "Register new user")
|
||||||
flash("User created and logged in successful.", "success")
|
flash("User created and logged in successful.", "success")
|
||||||
return redirect(url_for("user.profile"))
|
return redirect(url_for("user.edit_profile"))
|
||||||
login_user(user=user)
|
login_user(user=user)
|
||||||
log(log.INFO, "Verify success.")
|
log(log.INFO, "Verify success.")
|
||||||
flash("Verify success.", "success")
|
flash("Verify success.", "success")
|
||||||
|
|
|
@ -32,9 +32,9 @@ def get_all():
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/profile", methods=["GET", "POST"])
|
@bp.route("/edit_profile", methods=["GET", "POST"])
|
||||||
@login_required
|
@login_required
|
||||||
def profile():
|
def edit_profile():
|
||||||
form = f.EditUserForm()
|
form = f.EditUserForm()
|
||||||
if form.validate_on_submit():
|
if form.validate_on_submit():
|
||||||
user: m.User = current_user
|
user: m.User = current_user
|
||||||
|
@ -55,31 +55,22 @@ def profile():
|
||||||
|
|
||||||
if current_user.is_activated:
|
if current_user.is_activated:
|
||||||
form.name.data = current_user.username
|
form.name.data = current_user.username
|
||||||
return render_template("user/profile.html", form=form)
|
return render_template("user/edit_profile.html", form=form)
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/save", methods=["POST"])
|
@bp.route("/<int:user_id>/profile")
|
||||||
@login_required
|
@login_required
|
||||||
def save():
|
def profile(user_id: int):
|
||||||
form = f.UserForm()
|
user: m.User = m.User.query.get(user_id)
|
||||||
if form.validate_on_submit():
|
interpretations: m.Interpretation = m.Interpretation.query.filter_by(
|
||||||
u: m.User = m.User.query.get(int(form.user_id.data))
|
user_id=user_id
|
||||||
if not u:
|
)
|
||||||
log(log.ERROR, "Not found user by id : [%s]", form.user_id.data)
|
if not user:
|
||||||
flash("Cannot save user data", "danger")
|
log(log.ERROR, "Not found user by id : [%s]", user_id)
|
||||||
u.username = form.username.data
|
flash("Cannot find user data", "danger")
|
||||||
u.activated = form.activated.data
|
return render_template(
|
||||||
if form.password.data.strip("*\n "):
|
"user/profile.html", user=user, interpretations=interpretations
|
||||||
u.password = form.password.data
|
)
|
||||||
u.save()
|
|
||||||
if form.next_url.data:
|
|
||||||
return redirect(form.next_url.data)
|
|
||||||
return redirect(url_for("user.get_all"))
|
|
||||||
|
|
||||||
else:
|
|
||||||
log(log.ERROR, "User save errors: [%s]", form.errors)
|
|
||||||
flash(f"{form.errors}", "danger")
|
|
||||||
return redirect(url_for("user.get_all"))
|
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/create", methods=["POST"])
|
@bp.route("/create", methods=["POST"])
|
||||||
|
|
|
@ -100,23 +100,20 @@ def test_profile(client):
|
||||||
)
|
)
|
||||||
login(client, username=user.username, password="password")
|
login(client, username=user.username, password="password")
|
||||||
|
|
||||||
|
# edit_profile
|
||||||
|
new_name = "Some other name"
|
||||||
res = client.post(
|
res = client.post(
|
||||||
"/user/profile",
|
"/user/edit_profile",
|
||||||
data={
|
data={
|
||||||
"name": "Some other name",
|
"name": new_name,
|
||||||
"avatar_img": avatar_img,
|
"avatar_img": avatar_img,
|
||||||
},
|
},
|
||||||
follow_redirects=True,
|
follow_redirects=True,
|
||||||
)
|
)
|
||||||
assert res.status_code == 200
|
assert res.status_code == 200
|
||||||
assert user.username == "Some other name"
|
assert user.username == new_name
|
||||||
assert user.is_activated
|
assert user.is_activated
|
||||||
assert user.avatar_img
|
assert user.avatar_img
|
||||||
res2 = client.post(
|
|
||||||
"/user/profile",
|
|
||||||
follow_redirects=True,
|
|
||||||
)
|
|
||||||
assert b"This field is required." in res2.data
|
|
||||||
book = m.Book(
|
book = m.Book(
|
||||||
label="Book label",
|
label="Book label",
|
||||||
about="Book about",
|
about="Book about",
|
||||||
|
@ -125,6 +122,16 @@ def test_profile(client):
|
||||||
book.save()
|
book.save()
|
||||||
assert book
|
assert book
|
||||||
|
|
||||||
|
# profile page
|
||||||
|
res = client.get(
|
||||||
|
"/user/2/profile",
|
||||||
|
follow_redirects=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert res
|
||||||
|
assert res.status_code == 200
|
||||||
|
assert str.encode(new_name) in res.data
|
||||||
|
|
||||||
# delete_profile
|
# delete_profile
|
||||||
res = client.post(
|
res = client.post(
|
||||||
"/user/profile_delete",
|
"/user/profile_delete",
|
||||||
|
|
Loading…
Reference in New Issue