Almost half of the `delete_button` instances use `request.path` for `url` or `redirect`. By adding default values to them, we can remove bunch of lines.
193 lines
8.2 KiB
Plaintext
193 lines
8.2 KiB
Plaintext
<% @page_title = "#{@project_data[:name]} - Users" %>
|
|
|
|
<div class="space-y-1">
|
|
<%== render(
|
|
"components/breadcrumb",
|
|
locals: {
|
|
back: "/project",
|
|
parts: [%w[Projects /project], [@project_data[:name], @project_data[:path]], %w[Users #]]
|
|
}
|
|
) %>
|
|
<%== render("components/page_header", locals: { title: "User Management" }) %>
|
|
</div>
|
|
|
|
<div class="grid gap-6">
|
|
<!-- Invite user -->
|
|
<div>
|
|
<div class="md:flex md:items-center md:justify-between pb-1 lg:pb-2">
|
|
<div class="min-w-0 flex-1">
|
|
<h3 class="text-2xl font-bold leading-7 text-gray-900 sm:truncate sm:text-2xl sm:tracking-tight">
|
|
Invite a new user
|
|
</h3>
|
|
</div>
|
|
</div>
|
|
<div class="overflow-hidden rounded-lg shadow ring-1 ring-black ring-opacity-5 bg-white divide-y divide-gray-200">
|
|
<div class="px-4 py-5 sm:p-6">
|
|
<form action="<%= "#{@project_data[:path]}/user" %>" role="form" method="POST">
|
|
<%== csrf_tag("#{@project_data[:path]}/user") %>
|
|
<div class="space-y-4">
|
|
<div>
|
|
<p class="mt-1 text-sm text-gray-500">
|
|
You can invite a new user to your project using one of the preconfigured access policies below. If
|
|
you'd like to further customize permissions, you can use the
|
|
<a href="#policy-editor" class="font-semibold leading-6 text-orange-500 hover:text-orange-700">
|
|
advanced policy editor</a>
|
|
below.
|
|
</p>
|
|
</div>
|
|
<div class="grid grid-cols-12 gap-3">
|
|
<div class="col-span-12 sm:col-span-5">
|
|
<%== render(
|
|
"components/form/text",
|
|
locals: {
|
|
name: "email",
|
|
type: "email",
|
|
attributes: {
|
|
required: true,
|
|
placeholder: "Email"
|
|
}
|
|
}
|
|
) %>
|
|
</div>
|
|
<div class="col-span-12 sm:col-span-3">
|
|
<%== render("components/form/policy_select", locals: { name: "policy", selected: "member" }) %>
|
|
</div>
|
|
<div class="col-span-3 sm:col-span-2">
|
|
<%== render("components/form/submit_button", locals: { text: "Invite" }) %>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- User List -->
|
|
<div>
|
|
<form id="managed-policy" action="<%= "#{@project_data[:path]}/user/policy/managed" %>" role="form" method="POST">
|
|
<%== csrf_tag("#{@project_data[:path]}/user/policy/managed") %>
|
|
<div class="md:flex md:items-center md:justify-between pb-1 lg:pb-2">
|
|
<div class="min-w-0 flex-1">
|
|
<h3 class="text-2xl font-bold leading-7 text-gray-900 sm:truncate sm:text-2xl sm:tracking-tight">
|
|
Users
|
|
</h3>
|
|
</div>
|
|
</div>
|
|
<div class="overflow-hidden rounded-lg shadow ring-1 ring-black ring-opacity-5 bg-white divide-y divide-gray-200">
|
|
<table class="min-w-full divide-y divide-gray-300">
|
|
<thead class="bg-gray-50">
|
|
<tr>
|
|
<th scope="col" class="py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-6">Email</th>
|
|
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900">Default Policy</th>
|
|
<th scope="col" class="py-3.5 pl-3 pr-4 sm:pr-6 text-left text-sm font-semibold text-gray-900"></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody class="divide-y divide-gray-200 bg-white">
|
|
<% @users.each do |user| %>
|
|
<tr id="user-<%= user[:ubid]%>">
|
|
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm font-medium text-gray-900 sm:pl-6" scope="row">
|
|
<%= user[:email] %>
|
|
</td>
|
|
<td class="whitespace-nowrap px-3 py-4 text-sm text-gray-500">
|
|
<%== render(
|
|
"components/form/policy_select",
|
|
locals: {
|
|
name: "user_policies[#{user[:ubid]}]",
|
|
selected: @user_policies[user[:ubid]]
|
|
}
|
|
) %>
|
|
</td>
|
|
<td class="py-4 pl-3 pr-4 text-right sm:pr-6">
|
|
<%== render(
|
|
"components/delete_button",
|
|
locals: {
|
|
text: "Remove",
|
|
url: "#{@project_data[:path]}/user/#{user[:ubid]}",
|
|
confirmation: user[:email]
|
|
}
|
|
) %>
|
|
</td>
|
|
|
|
</tr>
|
|
<% end %>
|
|
<% @invitations.each do |invitation| %>
|
|
<tr id="invitation-<%= invitation[:email].gsub(/\W+/, "") %>">
|
|
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm font-medium text-gray-900 sm:pl-6" scope="row">
|
|
<%= invitation[:email] %>
|
|
<span
|
|
class="inline-flex items-baseline rounded-full ml-1 px-2 text-xs font-semibold leading-5 bg-yellow-100 text-yellow-800"
|
|
>
|
|
Invitation expires on
|
|
<%= invitation[:expires_at] %>
|
|
</span>
|
|
</td>
|
|
<td class="whitespace-nowrap px-3 py-4 text-sm text-gray-500">
|
|
<%== render(
|
|
"components/form/policy_select",
|
|
locals: {
|
|
name: "invitation_policies[#{invitation[:email]}]",
|
|
selected: invitation[:policy]
|
|
}
|
|
) %>
|
|
</td>
|
|
<td class="py-4 pl-3 pr-4 text-right sm:pr-6">
|
|
<%== render(
|
|
"components/delete_button",
|
|
locals: {
|
|
text: "Remove",
|
|
url: "#{@project_data[:path]}/user/invitation/#{invitation[:email]}",
|
|
confirmation: invitation[:email]
|
|
}
|
|
) %>
|
|
</td>
|
|
</tr>
|
|
<% end %>
|
|
</tbody>
|
|
</table>
|
|
<div class="px-4 py-5 sm:p-6">
|
|
<%== render("components/form/submit_button", locals: { text: "Update" }) %>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
<!-- Advanced Policy Editor -->
|
|
<div id="policy-editor">
|
|
<div class="md:flex md:items-center md:justify-between pb-1 lg:pb-2">
|
|
<div class="min-w-0 flex-1">
|
|
<h3 class="text-2xl font-bold leading-7 text-gray-900 sm:truncate sm:text-2xl sm:tracking-tight">
|
|
Advanced Policy Editor
|
|
</h3>
|
|
</div>
|
|
</div>
|
|
<div class="overflow-hidden rounded-lg shadow ring-1 ring-black ring-opacity-5 bg-white divide-y divide-gray-200">
|
|
<div class="px-4 py-5 sm:p-6">
|
|
<form id="advanced-policy" action="<%= "#{@project_data[:path]}/user/policy/advanced" %>" role="form" method="POST">
|
|
<%== csrf_tag("#{@project_data[:path]}/user/policy/advanced") %>
|
|
<div class="space-y-4">
|
|
<div>
|
|
<p class="mt-1 text-sm text-gray-500">
|
|
If our predefined policies do not meet your needs, you can give more granular permissions by editing
|
|
the policy below. Any permissions given through the access policy ediyor will be combined with the
|
|
user's default access policy. You can learn more about our access policy language in
|
|
<a href="" class="font-semibold leading-6 text-orange-500 hover:text-orange-700">our documentation</a>.
|
|
</p>
|
|
</div>
|
|
<div class="grid grid-cols-12 gap-6">
|
|
<div class="col-span-full">
|
|
<div class="policy-editor text-sm">
|
|
<pre class="bg-gray-50 rounded-lg p-3 h-[50vh] overflow-scroll" contenteditable="true">
|
|
<%= flash.dig("old", "body") || @policy[:body] %>
|
|
</pre>
|
|
<textarea name="body" class="hidden" required></textarea>
|
|
</div>
|
|
</div>
|
|
<div class="col-span-3 sm:col-span-6">
|
|
<%== render("components/form/submit_button", locals: { text: "Update" }) %>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|