refactor: ⚡ Modal layout and turbolinks optimization
Reload with turbolinks, error messages, confirm password validation Login and Signup modals
This commit is contained in:
@@ -58,4 +58,7 @@ group :test do
|
||||
gem 'webdrivers'
|
||||
# SimpleCov is a code coverage analysis tool for Ruby
|
||||
gem 'simplecov'
|
||||
|
||||
# Simple console output formatter for SimpleCov
|
||||
gem 'simplecov-console'
|
||||
end
|
||||
|
||||
@@ -44,6 +44,7 @@ GEM
|
||||
tzinfo (~> 1.1)
|
||||
addressable (2.7.0)
|
||||
public_suffix (>= 2.0.2, < 5.0)
|
||||
ansi (1.5.0)
|
||||
arel (9.0.0)
|
||||
bcrypt (3.1.16)
|
||||
bcrypt (3.1.16-java)
|
||||
@@ -157,6 +158,10 @@ GEM
|
||||
docile (~> 1.1)
|
||||
simplecov-html (~> 0.11)
|
||||
simplecov_json_formatter (~> 0.1)
|
||||
simplecov-console (0.9.1)
|
||||
ansi
|
||||
simplecov
|
||||
terminal-table
|
||||
simplecov-html (0.12.3)
|
||||
simplecov_json_formatter (0.1.3)
|
||||
spring (2.1.1)
|
||||
@@ -170,6 +175,8 @@ GEM
|
||||
actionpack (>= 4.0)
|
||||
activesupport (>= 4.0)
|
||||
sprockets (>= 3.0.0)
|
||||
terminal-table (3.0.1)
|
||||
unicode-display_width (>= 1.1.1, < 3)
|
||||
thor (1.1.0)
|
||||
thread_safe (0.3.6)
|
||||
thread_safe (0.3.6-java)
|
||||
@@ -180,6 +187,7 @@ GEM
|
||||
thread_safe (~> 0.1)
|
||||
uglifier (4.2.0)
|
||||
execjs (>= 0.3.0, < 3)
|
||||
unicode-display_width (2.0.0)
|
||||
web-console (3.7.0)
|
||||
actionview (>= 5.0)
|
||||
activemodel (>= 5.0)
|
||||
@@ -221,6 +229,7 @@ DEPENDENCIES
|
||||
rails (~> 5.2.6)
|
||||
selenium-webdriver
|
||||
simplecov
|
||||
simplecov-console
|
||||
spring
|
||||
spring-watcher-listen (~> 2.0.0)
|
||||
turbolinks (~> 5)
|
||||
|
||||
@@ -3,11 +3,10 @@
|
||||
## How to run
|
||||
|
||||
### Development
|
||||
- Setup
|
||||
- Run migrations
|
||||
```bash
|
||||
docker-compose up -d
|
||||
docker-compose up -d db
|
||||
docker-compose run --rm app bundle exec rails db:migrate
|
||||
docker-compose stop
|
||||
```
|
||||
- Run
|
||||
```bash
|
||||
@@ -15,7 +14,6 @@ docker-compose up
|
||||
```
|
||||
|
||||
### Testing
|
||||
- Run tests
|
||||
```bash
|
||||
docker-compose run --rm app bundle exec rails test
|
||||
```
|
||||
@@ -37,5 +35,6 @@ docker-compose run --rm app rubocop
|
||||
- [x] Add userId key to link model
|
||||
- [x] Login and logout (sessions)
|
||||
- [x] User links view
|
||||
- [ ] Modals layout
|
||||
- [ ] Setup Redis for production cache_store
|
||||
- [x] Modals layout
|
||||
- [ ] Setup Redis for production cache_store
|
||||
- [ ] Deployment CI
|
||||
@@ -7,15 +7,15 @@ class SessionsController < ApplicationController
|
||||
@user = User.find_by(username: session_params[:username])
|
||||
if @user&.authenticate(session_params[:password])
|
||||
session[:user_id] = @user.id
|
||||
redirect_to '/'
|
||||
render json: nil, status: :ok
|
||||
else
|
||||
render json: nil, status: :unauthorized
|
||||
render json: { username: ['Credentials not valid, try again or create an account'] }, status: :unauthorized
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
reset_session
|
||||
redirect_to '/'
|
||||
render json: nil, status: :ok
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
@@ -2,12 +2,16 @@
|
||||
|
||||
class UsersController < ApplicationController
|
||||
def create
|
||||
if user_params[:password] != params[:user][:confirm_password]
|
||||
return render json: { password: ['Password not match with Confirm Password'] }, status: :bad_request
|
||||
end
|
||||
|
||||
@user = User.create(user_params)
|
||||
if @user.errors.any?
|
||||
render json: @user.errors, status: :unprocessable_entity
|
||||
else
|
||||
session[:user_id] = @user.id
|
||||
redirect_to '/'
|
||||
render json: nil, status: :ok
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ export default class extends Controller {
|
||||
}
|
||||
|
||||
openSignupModal() {
|
||||
this.closeLoginModal()
|
||||
this.signupModalTarget.classList.remove("hidden")
|
||||
}
|
||||
|
||||
@@ -21,18 +22,38 @@ export default class extends Controller {
|
||||
|
||||
onSignupSuccess() {
|
||||
this.closeSignupModal();
|
||||
Turbolinks.visit('/')
|
||||
}
|
||||
|
||||
onLoginSuccess() {
|
||||
this.closeLoginModal();
|
||||
Turbolinks.visit('/')
|
||||
}
|
||||
|
||||
onError(event) {
|
||||
const [data, ,] = event.detail
|
||||
|
||||
const usernameError = `Username: ${data.username.join(' ')}`
|
||||
const passwordError = `Password: ${data.username.join(' ')}`
|
||||
const errors = []
|
||||
|
||||
alert(`${usernameError}, ${passwordError}`)
|
||||
if (data.username) {
|
||||
errors.push(`Username: ${data.username.join(' ')}`)
|
||||
}
|
||||
|
||||
if (data.password) {
|
||||
errors.push(`Password: ${data.password.join(' ')}`)
|
||||
}
|
||||
|
||||
alert(errors.join(','))
|
||||
}
|
||||
|
||||
confirmLogout(event) {
|
||||
if (!window.confirm("Do you really want to leave?")) {
|
||||
event.stopPropagation()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
onSuccessLogout() {
|
||||
Turbolinks.visit('/')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
a {
|
||||
a, button, input[type=submit] {
|
||||
cursor: pointer;
|
||||
text-decoration: underline;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<div data-users-target="<%= target %>" class="fixed z-10 inset-0 overflow-y-auto hidden" aria-labelledby="modal-title" role="dialog" aria-modal="true">
|
||||
<div class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
|
||||
<!--
|
||||
Background overlay, show/hide based on modal state.
|
||||
|
||||
Entering: "ease-out duration-300"
|
||||
From: "opacity-0"
|
||||
To: "opacity-100"
|
||||
Leaving: "ease-in duration-200"
|
||||
From: "opacity-100"
|
||||
To: "opacity-0"
|
||||
-->
|
||||
<div class="fixed inset-0 bg-gray-500 bg-opacity-75 transition-opacity" aria-hidden="true"></div>
|
||||
|
||||
<!-- This element is to trick the browser into centering the modal contents. -->
|
||||
<span class="hidden sm:inline-block sm:align-middle sm:h-screen" aria-hidden="true">​</span>
|
||||
|
||||
<!--
|
||||
Modal panel, show/hide based on modal state.
|
||||
|
||||
Entering: "ease-out duration-300"
|
||||
From: "opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
|
||||
To: "opacity-100 translate-y-0 sm:scale-100"
|
||||
Leaving: "ease-in duration-200"
|
||||
From: "opacity-100 translate-y-0 sm:scale-100"
|
||||
To: "opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
|
||||
-->
|
||||
<%= yield %>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,14 +1,14 @@
|
||||
<%= form_with model: Link.new, url: links_path(@link), data: { action: 'ajax:success->links#onCreateLinkSuccess ajax:error->links#onCreateLinkError' } do |f| %>
|
||||
<div class="col-span-3 sm:col-span-2">
|
||||
<label for="company_website" class="block text-sm font-medium text-gray-700">
|
||||
Website
|
||||
<label for="company_website" class="text-lg leading-6 font-medium text-gray-900">
|
||||
Shorten an url
|
||||
</label>
|
||||
<div class="mt-1 flex rounded-md shadow-sm">
|
||||
<%= f.text_field :url, data: { target: "links.url" }, placeholder: true, class: "focus:ring-indigo-500 focus:border-indigo-500 flex-1 block w-full rounded-none rounded-md sm:text-sm border-gray-300"%>
|
||||
<div class="mt-4 flex rounded-md shadow-sm mr-5">
|
||||
<%= f.text_field :url, data: { target: "links.url" }, placeholder: "https://google.com", class: "focus:ring-indigo-500 focus:border-indigo-500 flex-1 block w-full rounded-none rounded-md sm:text-sm border-gray-300" %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="px-4 py-3 bg-gray-50 text-right sm:px-6">
|
||||
<div class="px-4 py-3 text-right sm:px-6">
|
||||
<%= f.submit "Generate", class: "inline-flex justify-center py-2 px-4 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500" %>
|
||||
</div>
|
||||
<% end %>
|
||||
@@ -1,7 +1,6 @@
|
||||
<div data-links-target="userLinks">
|
||||
<% if logged_in? %>
|
||||
<% @current_user.links.each do |link| %>
|
||||
<h2 class="text-2xl leading-7 text-gray-900 sm:text-3xl sm:truncate m-3 mt-6">My links</h2>
|
||||
<% @current_user.links.each do |link| %>
|
||||
<%= render partial: "links/show", locals: { link: link } %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
<% end %>
|
||||
@@ -1,12 +1,4 @@
|
||||
<div class="flex flex-col">
|
||||
<div class="py-2 align-middle inline-block sm:px-6 lg:px-8">
|
||||
<div class="shadow sm:rounded-md sm:overflow-hidden">
|
||||
<div class="px-4 py-5 bg-white space-y-6 sm:p-6">
|
||||
<div class="grid grid-cols-3 gap-6">
|
||||
<%= render partial: "links/form" %>
|
||||
<div data-links-target="output"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bg-white shadow overflow-hidden sm:rounded-lg m-3 p-6">
|
||||
<%= render partial: "links/form" %>
|
||||
<div data-links-target="output"></div>
|
||||
</div>
|
||||
|
||||
@@ -1,13 +1,30 @@
|
||||
<div class="col-span-3 sm:col-span-2">
|
||||
<label for="about" class="block text-sm font-medium text-gray-700">
|
||||
Short url
|
||||
</label>
|
||||
<a href="<%= link.short %>" class="mt-1 text-sm text-gray-600" target="_blank" rel="noreferrer"><%= link.short %></a>
|
||||
</div>
|
||||
|
||||
<div class="col-span-3 sm:col-span-2">
|
||||
<label for="about" class="block text-sm font-medium text-gray-700">
|
||||
Click counter
|
||||
</label>
|
||||
<p class="mt-2 text-sm text-gray-500"><%= link.click_counter %></p>
|
||||
<div class="bg-white shadow overflow-hidden sm:rounded-lg m-3">
|
||||
<div class="border-t border-gray-200">
|
||||
<dl>
|
||||
<div class="bg-gray-50 px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
|
||||
<dt class="text-sm font-medium text-gray-500">
|
||||
Website
|
||||
</dt>
|
||||
<dd class="mt-1 text-sm text-gray-900 sm:mt-0 sm:col-span-2">
|
||||
<a href="<%= link.url %>" class="mt-1 text-sm text-gray-600" target="_blank" rel="noreferrer"><%= link.url %></a>
|
||||
</dd>
|
||||
</div>
|
||||
<div class="bg-white px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
|
||||
<dt class="text-sm font-medium text-gray-500">
|
||||
Shortened url
|
||||
</dt>
|
||||
<dd class="mt-1 text-sm text-gray-900 sm:mt-0 sm:col-span-2">
|
||||
<a href="<%= link.short %>" class="mt-1 text-sm text-gray-600" target="_blank" rel="noreferrer"><%= link.short %></a>
|
||||
</dd>
|
||||
</div>
|
||||
<div class="bg-gray-50 px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
|
||||
<dt class="text-sm font-medium text-gray-500">
|
||||
Click counter
|
||||
</dt>
|
||||
<dd class="mt-1 text-sm text-gray-900 sm:mt-0 sm:col-span-2">
|
||||
<%= link.click_counter %>
|
||||
</dd>
|
||||
</div>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,61 +1,34 @@
|
||||
<div data-users-target="loginModal" class="fixed z-10 inset-0 overflow-y-auto hidden" aria-labelledby="modal-title" role="dialog" aria-modal="true">
|
||||
<div class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
|
||||
<!--
|
||||
Background overlay, show/hide based on modal state.
|
||||
|
||||
Entering: "ease-out duration-300"
|
||||
From: "opacity-0"
|
||||
To: "opacity-100"
|
||||
Leaving: "ease-in duration-200"
|
||||
From: "opacity-100"
|
||||
To: "opacity-0"
|
||||
-->
|
||||
<div class="fixed inset-0 bg-gray-500 bg-opacity-75 transition-opacity" aria-hidden="true"></div>
|
||||
|
||||
<!-- This element is to trick the browser into centering the modal contents. -->
|
||||
<span class="hidden sm:inline-block sm:align-middle sm:h-screen" aria-hidden="true">​</span>
|
||||
|
||||
<!--
|
||||
Modal panel, show/hide based on modal state.
|
||||
|
||||
Entering: "ease-out duration-300"
|
||||
From: "opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
|
||||
To: "opacity-100 translate-y-0 sm:scale-100"
|
||||
Leaving: "ease-in duration-200"
|
||||
From: "opacity-100 translate-y-0 sm:scale-100"
|
||||
To: "opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
|
||||
-->
|
||||
<%= form_with url: '/login', data: { action: 'ajax:success->users#onLoginSuccess ajax:error->users#onError' }, class: "inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full" do |f| %>
|
||||
<div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
|
||||
<div class="sm:flex sm:items-start">
|
||||
<div class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-red-100 sm:mx-0 sm:h-10 sm:w-10">
|
||||
<!-- Heroicon name: outline/exclamation -->
|
||||
<svg class="h-6 w-6 text-red-600" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" />
|
||||
</svg>
|
||||
<%= form_with url: '/login', data: { action: 'ajax:success->users#onLoginSuccess ajax:error->users#onError' }, class: "inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full" do |f| %>
|
||||
<div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
|
||||
<div class="sm:flex sm:items-start">
|
||||
<div class="flex-1 mt-3 text-center sm:mt-0 sm:mx-4 sm:text-left">
|
||||
<h3 class="text-xl leading-6 font-medium text-gray-900" id="modal-title">
|
||||
Login
|
||||
</h3>
|
||||
<div class="flex-col mt-4">
|
||||
<div class="my-2">
|
||||
<label for="username" class="block text-sm font-medium text-gray-700">
|
||||
Username
|
||||
</label>
|
||||
<%= f.text_field :username, class: "focus:ring-indigo-500 focus:border-indigo-500 flex-1 block w-full rounded-none rounded-md sm:text-sm border-gray-300" %>
|
||||
</div>
|
||||
<div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
|
||||
<h3 class="text-lg leading-6 font-medium text-gray-900" id="modal-title">
|
||||
Login
|
||||
</h3>
|
||||
<div class="mt-2">
|
||||
<p class="text-sm text-gray-500">
|
||||
Are you sure you want to deactivate your account? All of your data will be permanently removed. This action cannot be undone.
|
||||
</p>
|
||||
<%= f.label :username%><br>
|
||||
<%= f.text_field :username%><br>
|
||||
<%= f.label :password%><br>
|
||||
<%= f.password_field :password%><br>
|
||||
<div class="my-2">
|
||||
<label for="password" class="block text-sm font-medium text-gray-700">
|
||||
Password
|
||||
</label>
|
||||
<div class="mt-1 flex rounded-md shadow-sm">
|
||||
<%= f.password_field :password, class: "focus:ring-indigo-500 focus:border-indigo-500 flex-1 block w-full rounded-none rounded-md sm:text-sm border-gray-300" %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
|
||||
<%= f.submit "Login", class: "mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-base font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm" %>
|
||||
<button data-action="users#closeLoginModal" type="button" class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 text-base font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:ml-3 sm:w-auto sm:text-sm">
|
||||
Cancel
|
||||
</button>
|
||||
</div>
|
||||
<%end%>
|
||||
</div>
|
||||
<button type="button" data-action="click->users#openSignupModal" class="block text-sm font-medium pl-4 pt-6 underline">Create an account</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
|
||||
<%= f.submit "Login", class: "mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-base font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm" %>
|
||||
<button data-action="click->users#closeLoginModal" type="button" class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 text-base font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:ml-3 sm:w-auto sm:text-sm">
|
||||
Cancel
|
||||
</button>
|
||||
</div>
|
||||
<%end%>
|
||||
@@ -0,0 +1,17 @@
|
||||
<div data-controller="users">
|
||||
<div class="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
|
||||
<% unless logged_in? %>
|
||||
<button data-action="click->users#openLoginModal" class="mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-base font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm">
|
||||
Login
|
||||
</button>
|
||||
<% end %>
|
||||
<%= render partial: "users/show" %>
|
||||
</div>
|
||||
<%= render partial: "users/new", layout: "layouts/modal", locals: { target: 'signupModal' } %>
|
||||
<%= render partial: "sessions/new", layout: "layouts/modal", locals: { target: 'loginModal' } %>
|
||||
</div>
|
||||
|
||||
<div data-controller="links">
|
||||
<%= render partial: "links/new" %>
|
||||
<%= render partial: "links/index" %>
|
||||
</div>
|
||||
@@ -1,13 +0,0 @@
|
||||
<div data-controller="users">
|
||||
<button data-action="users#openLoginModal">Login</button>
|
||||
<button data-action="users#openSignupModal">Sign Up</button>
|
||||
|
||||
<%= render partial: "users/show" %>
|
||||
<%= render partial: "users/new" %>
|
||||
<%= render partial: "sessions/new" %>
|
||||
</div>
|
||||
|
||||
<div data-controller="links">
|
||||
<%= render partial: "links/new" %>
|
||||
<%= render partial: "links/index" %>
|
||||
</div>
|
||||
@@ -1,61 +1,39 @@
|
||||
<div data-users-target="signupModal" class="fixed z-10 inset-0 overflow-y-auto hidden" aria-labelledby="modal-title" role="dialog" aria-modal="true">
|
||||
<div class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
|
||||
<!--
|
||||
Background overlay, show/hide based on modal state.
|
||||
|
||||
Entering: "ease-out duration-300"
|
||||
From: "opacity-0"
|
||||
To: "opacity-100"
|
||||
Leaving: "ease-in duration-200"
|
||||
From: "opacity-100"
|
||||
To: "opacity-0"
|
||||
-->
|
||||
<div class="fixed inset-0 bg-gray-500 bg-opacity-75 transition-opacity" aria-hidden="true"></div>
|
||||
|
||||
<!-- This element is to trick the browser into centering the modal contents. -->
|
||||
<span class="hidden sm:inline-block sm:align-middle sm:h-screen" aria-hidden="true">​</span>
|
||||
|
||||
<!--
|
||||
Modal panel, show/hide based on modal state.
|
||||
|
||||
Entering: "ease-out duration-300"
|
||||
From: "opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
|
||||
To: "opacity-100 translate-y-0 sm:scale-100"
|
||||
Leaving: "ease-in duration-200"
|
||||
From: "opacity-100 translate-y-0 sm:scale-100"
|
||||
To: "opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
|
||||
-->
|
||||
<%= form_with model: User.new, url: users_path(@user), data: { action: 'ajax:success->users#onSignupSuccess ajax:error->users#onError' }, class: "inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full" do |f| %>
|
||||
<div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
|
||||
<div class="sm:flex sm:items-start">
|
||||
<div class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-red-100 sm:mx-0 sm:h-10 sm:w-10">
|
||||
<!-- Heroicon name: outline/exclamation -->
|
||||
<svg class="h-6 w-6 text-red-600" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" />
|
||||
</svg>
|
||||
<%= form_with model: User.new, url: users_path(@user), data: { action: 'ajax:success->users#onSignupSuccess ajax:error->users#onError' }, class: "inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full" do |f| %>
|
||||
<div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
|
||||
<div class="flex-1 mt-3 text-center sm:mt-0 sm:mx-4 sm:text-left">
|
||||
<h3 class="text-xl leading-6 font-medium text-gray-900" id="modal-title">
|
||||
Sign Up
|
||||
</h3>
|
||||
<div class="flex-col mt-4">
|
||||
<div class="my-2">
|
||||
<label for="username" class="block text-sm font-medium text-gray-700">
|
||||
Username
|
||||
</label>
|
||||
<%= f.text_field :username, class: "focus:ring-indigo-500 focus:border-indigo-500 flex-1 block w-full rounded-none rounded-md sm:text-sm border-gray-300" %>
|
||||
</div>
|
||||
<div class="my-2">
|
||||
<label for="password" class="block text-sm font-medium text-gray-700">
|
||||
Password
|
||||
</label>
|
||||
<div class="mt-1 flex rounded-md shadow-sm">
|
||||
<%= f.password_field :password, class: "focus:ring-indigo-500 focus:border-indigo-500 flex-1 block w-full rounded-none rounded-md sm:text-sm border-gray-300" %>
|
||||
</div>
|
||||
<div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
|
||||
<h3 class="text-lg leading-6 font-medium text-gray-900" id="modal-title">
|
||||
Deactivate account
|
||||
</h3>
|
||||
<div class="mt-2">
|
||||
<p class="text-sm text-gray-500">
|
||||
Are you sure you want to deactivate your account? All of your data will be permanently removed. This action cannot be undone.
|
||||
</p>
|
||||
<%= f.label :username%><br>
|
||||
<%= f.text_field :username%><br>
|
||||
<%= f.label :password%><br>
|
||||
<%= f.password_field :password%><br>
|
||||
</div>
|
||||
</div>
|
||||
<div class="my-2">
|
||||
<label for="confirm_password" class="block text-sm font-medium text-gray-700">
|
||||
Confirm password
|
||||
</label>
|
||||
<div class="mt-1 flex rounded-md shadow-sm">
|
||||
<%= f.password_field :confirm_password, class: "focus:ring-indigo-500 focus:border-indigo-500 flex-1 block w-full rounded-none rounded-md sm:text-sm border-gray-300" %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
|
||||
<%= f.submit "Submit", class: "mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-base font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm" %>
|
||||
<button data-action="users#closeSignupModal" type="button" class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 text-base font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:ml-3 sm:w-auto sm:text-sm">
|
||||
Cancel
|
||||
</button>
|
||||
</div>
|
||||
<%end%>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
|
||||
<%= f.submit "Sign Up", class: "mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-base font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm" %>
|
||||
<button data-action="click->users#closeSignupModal" type="button" class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 text-base font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:ml-3 sm:w-auto sm:text-sm">
|
||||
Cancel
|
||||
</button>
|
||||
</div>
|
||||
<%end%>
|
||||
@@ -1,4 +1,4 @@
|
||||
<% if logged_in? %>
|
||||
<h1>You are Logged In, <%= @current_user.username %></h1>
|
||||
<%= button_to "Logout", '/logout', method: :post %>
|
||||
<%= link_to "Logout", '/session/logout', data: { action: 'ajax:before->users#confirmLogout ajax:success->users#onSuccessLogout' }, remote: true, class: "mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-base font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm" %>
|
||||
<h1 class="px-2 py-2 text-sm font-medium">You are Logged In, <%= @current_user.username %></h1>
|
||||
<%end%>
|
||||
+2
-2
@@ -1,12 +1,12 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
Rails.application.routes.draw do
|
||||
root 'sessions#welcome'
|
||||
root 'sessions#index'
|
||||
|
||||
get '/:slug', to: 'links#redirect', as: :short
|
||||
get 'session/logout', to: 'sessions#destroy', as: :logout
|
||||
|
||||
post 'login', to: 'sessions#create', as: :login
|
||||
post 'logout', to: 'sessions#destroy', as: :logout
|
||||
|
||||
resources :links, only: %i[create]
|
||||
resources :users, only: %i[create]
|
||||
|
||||
Reference in New Issue
Block a user