set up access requests further
This commit is contained in:
parent
8d6ae2321c
commit
88e550c13a
12 changed files with 221 additions and 101 deletions
BIN
app/assets/images/view-only.png
Normal file
BIN
app/assets/images/view-only.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 421 B |
|
@ -1,3 +1,58 @@
|
|||
.viewOnly {
|
||||
float: left;
|
||||
margin-left: 16px;
|
||||
display: none;
|
||||
height: 32px;
|
||||
border: 1px solid #BDBDBD;
|
||||
border-radius: 2px;
|
||||
background-color: #424242;
|
||||
color: #FFF;
|
||||
font-size: 14px;
|
||||
line-height: 32px;
|
||||
|
||||
&.isViewOnly {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.eyeball {
|
||||
background: url('<%= asset_path('view-only.png') %>') no-repeat 4px 0;
|
||||
padding-left: 40px;
|
||||
border-right: #747474;
|
||||
padding-right: 10px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.requestNotice {
|
||||
display: none;
|
||||
padding: 0 8px;
|
||||
}
|
||||
|
||||
.requestAccess {
|
||||
background-color: #a354cd;
|
||||
&:hover {
|
||||
background-color: #9150bc;
|
||||
}
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.requestPending {
|
||||
background-color: #4fc059;
|
||||
}
|
||||
|
||||
.requestNotAccepted {
|
||||
background-color: #c04f4f;
|
||||
}
|
||||
|
||||
&.sendRequest .requestAccess {
|
||||
display: inline-block;
|
||||
}
|
||||
&.sentRequest .requestPending {
|
||||
display: inline-block;
|
||||
}
|
||||
&.requestDenied .requestNotAccepted {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
||||
.request_access {
|
||||
position: absolute;
|
||||
|
|
98
app/controllers/access_controller.rb
Normal file
98
app/controllers/access_controller.rb
Normal file
|
@ -0,0 +1,98 @@
|
|||
# frozen_string_literal: true
|
||||
class AccessController < ApplicationController
|
||||
before_action :require_user, only: [:access, :access_request, :approve_access, :approve_access_post,
|
||||
:deny_access, :deny_access_post, :request_access]
|
||||
before_action :set_map, only: [:access, :access_request, :approve_access, :approve_access_post,
|
||||
:deny_access, :deny_access_post, :request_access]
|
||||
after_action :verify_authorized
|
||||
|
||||
|
||||
# GET maps/:id/request_access
|
||||
def request_access
|
||||
@map = nil
|
||||
respond_to do |format|
|
||||
format.html do
|
||||
render 'maps/request_access'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# POST maps/:id/access_request
|
||||
def access_request
|
||||
request = AccessRequest.create(user: current_user, map: @map)
|
||||
# what about push notification to map owner?
|
||||
MapMailer.access_request_email(request, @map).deliver_later
|
||||
|
||||
respond_to do |format|
|
||||
format.json do
|
||||
head :ok
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# POST maps/:id/access
|
||||
def access
|
||||
user_ids = params[:access] || []
|
||||
|
||||
@map.add_new_collaborators(user_ids).each do |user_id|
|
||||
# add_new_collaborators returns array of added users,
|
||||
# who we then send an email to
|
||||
MapMailer.invite_to_edit_email(@map, current_user, User.find(user_id)).deliver_later
|
||||
end
|
||||
@map.remove_old_collaborators(user_ids)
|
||||
|
||||
respond_to do |format|
|
||||
format.json do
|
||||
head :ok
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# GET maps/:id/approve_access/:request_id
|
||||
def approve_access
|
||||
request = AccessRequest.find(params[:request_id])
|
||||
request.approve()
|
||||
respond_to do |format|
|
||||
format.html { redirect_to map_path(@map), notice: 'Request was approved' }
|
||||
end
|
||||
end
|
||||
|
||||
# GET maps/:id/deny_access/:request_id
|
||||
def deny_access
|
||||
request = AccessRequest.find(params[:request_id])
|
||||
request.deny()
|
||||
respond_to do |format|
|
||||
format.html { redirect_to map_path(@map), notice: 'Request was turned down' }
|
||||
end
|
||||
end
|
||||
|
||||
# POST maps/:id/approve_access/:request_id
|
||||
def approve_access_post
|
||||
request = AccessRequest.find(params[:request_id])
|
||||
request.approve()
|
||||
respond_to do |format|
|
||||
format.json do
|
||||
head :ok
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# POST maps/:id/deny_access/:request_id
|
||||
def deny_access_post
|
||||
request = AccessRequest.find(params[:request_id])
|
||||
request.deny()
|
||||
respond_to do |format|
|
||||
format.json do
|
||||
head :ok
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_map
|
||||
@map = Map.find(params[:id])
|
||||
authorize @map
|
||||
end
|
||||
|
||||
end
|
|
@ -1,9 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
class MapsController < ApplicationController
|
||||
before_action :require_user, only: [:create, :update, :destroy, :access, :events]
|
||||
before_action :set_map, only: [:show, :request_access, :update, :destroy, :access, :contains,
|
||||
:events, :export, :access_request, :approve_access, :deny_access, :approve_access_post,
|
||||
:deny_access_post]
|
||||
before_action :require_user, only: [:create, :update, :destroy, :events]
|
||||
before_action :set_map, only: [:show, :update, :destroy, :contains, :events, :export]
|
||||
after_action :verify_authorized
|
||||
|
||||
# GET maps/:id
|
||||
|
@ -17,17 +15,13 @@ class MapsController < ApplicationController
|
|||
@allmappings = policy_scope(@map.mappings)
|
||||
@allmessages = @map.messages.sort_by(&:created_at)
|
||||
@allstars = @map.stars
|
||||
@allrequests = @map.access_requests
|
||||
end
|
||||
format.json { render json: @map }
|
||||
format.csv { redirect_to action: :export, format: :csv }
|
||||
end
|
||||
end
|
||||
|
||||
# GET maps/:id/request_access
|
||||
def request_access
|
||||
@map = nil
|
||||
end
|
||||
|
||||
# GET maps/new
|
||||
def new
|
||||
@map = Map.new(name: 'Untitled Map', permission: 'public', arranged: true)
|
||||
|
@ -86,37 +80,6 @@ class MapsController < ApplicationController
|
|||
end
|
||||
end
|
||||
|
||||
# POST maps/:id/access_request
|
||||
def access_request
|
||||
request = AccessRequest.create(user: current_user, map: @map)
|
||||
# what about push notification to map owner?
|
||||
MapMailer.access_request_email(request, @map).deliver_later
|
||||
|
||||
respond_to do |format|
|
||||
format.json do
|
||||
head :ok
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# POST maps/:id/access
|
||||
def access
|
||||
user_ids = params[:access] || []
|
||||
|
||||
@map.add_new_collaborators(user_ids).each do |user_id|
|
||||
# add_new_collaborators returns array of added users,
|
||||
# who we then send an email to
|
||||
MapMailer.invite_to_edit_email(@map, current_user, User.find(user_id)).deliver_later
|
||||
end
|
||||
@map.remove_old_collaborators(user_ids)
|
||||
|
||||
respond_to do |format|
|
||||
format.json do
|
||||
head :ok
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# GET maps/:id/contains
|
||||
def contains
|
||||
respond_to do |format|
|
||||
|
@ -152,48 +115,6 @@ class MapsController < ApplicationController
|
|||
end
|
||||
end
|
||||
|
||||
# GET maps/:id/approve_access/:request_id
|
||||
def approve_access
|
||||
request = AccessRequest.find_by_id(params[:request_id])
|
||||
request.approve() if request
|
||||
respond_to do |format|
|
||||
format.html { redirect_to map_path(@map), notice: request ? 'Request was approved' : 'No request there to approve' }
|
||||
end
|
||||
end
|
||||
|
||||
# GET maps/:id/deny_access/:request_id
|
||||
def deny_access
|
||||
request = AccessRequest.find_by_id(params[:request_id])
|
||||
request.deny() if request
|
||||
respond_to do |format|
|
||||
format.html { redirect_to map_path(@map), notice: request ? 'Request was turned down' : 'No request there to deny' }
|
||||
end
|
||||
end
|
||||
|
||||
# POST maps/:id/approve_access/:request_id
|
||||
def approve_access_post
|
||||
request = AccessRequest.find_by_id(params[:request_id])
|
||||
request.approve() if request
|
||||
respond_to do |format|
|
||||
format.json do
|
||||
head :bad_request unless request
|
||||
head :ok
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# POST maps/:id/deny_access/:request_id
|
||||
def deny_access_post
|
||||
request = AccessRequest.find_by_id(params[:request_id])
|
||||
request.deny() if request
|
||||
respond_to do |format|
|
||||
format.json do
|
||||
head :bad_request unless request
|
||||
head :ok
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_map
|
||||
|
|
|
@ -7,13 +7,12 @@ class AccessRequest < ApplicationRecord
|
|||
self.answered = true
|
||||
self.save
|
||||
UserMap.create(user: self.user, map: self.map)
|
||||
# send an email and push notification here?
|
||||
MapMailer.invite_to_edit_email(self.map, self.map.user, self.user).deliver_later
|
||||
end
|
||||
|
||||
def deny
|
||||
self.approved = false
|
||||
self.answered = true
|
||||
self.save
|
||||
# send an email and push notification here?
|
||||
end
|
||||
end
|
||||
|
|
|
@ -103,7 +103,8 @@ class Map < ApplicationRecord
|
|||
mappers: contributors,
|
||||
collaborators: editors,
|
||||
messages: messages.sort_by(&:created_at),
|
||||
stars: stars
|
||||
stars: stars,
|
||||
requests: access_requests
|
||||
}
|
||||
end
|
||||
|
||||
|
@ -123,6 +124,7 @@ class Map < ApplicationRecord
|
|||
removed = current_collaborators.map(&:id).map do |old_user_id|
|
||||
next nil if user_ids.include?(old_user_id)
|
||||
user_maps.where(user_id: old_user_id).find_each(&:destroy)
|
||||
access_requests.where(user_id: old_user_id).find_each(&:destroy)
|
||||
old_user_id
|
||||
end
|
||||
removed.compact
|
||||
|
|
|
@ -14,6 +14,23 @@
|
|||
<div class="sidebarSearchIcon"></div>
|
||||
<div class="clearfloat"></div>
|
||||
</div> <!-- end sidebarSearch -->
|
||||
|
||||
<% request = current_user && @map && @allrequests.find{|a| a.user == current_user}
|
||||
className = (@map and not policy(@map).update?) ? 'isViewOnly ' : ''
|
||||
if @map
|
||||
className += 'sendRequest' if not request
|
||||
className += 'sentRequest' if request and not request.answered
|
||||
className += 'requestDenied' if request and request.answered and not request.approved
|
||||
end %>
|
||||
|
||||
<div class="viewOnly <%= className %>">
|
||||
<div class="eyeball">View Only</div>
|
||||
<% if current_user %>
|
||||
<div class="requestAccess requestNotice">Request Access</div>
|
||||
<div class="requestPending requestNotice">Request Pending</div>
|
||||
<div class="requestNotAccepted requestNotice">Request Not Accepted</div>
|
||||
<% end %>
|
||||
</div>
|
||||
<div class="clearfloat"></div>
|
||||
</div><!-- end upperLeftUI -->
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
<div style="padding: 16px; background: white; text-align: left;">
|
||||
<% button_style = "background-color:#4fc059;border-radius:2px;color:white;display:inline-block;font-family:Roboto,Arial,Helvetica,sans-serif;font-size:12px;font-weight:bold;min-height:29px;line-height:29px;min-width:54px;outline:0px;padding:0 8px;text-align:center;text-decoration:none" %>
|
||||
|
||||
<p><span style="font-weight: bold;"><%= @inviter.name %></span> has invited you to <span style="font-weight: bold">collaboratively edit</span> the following metamap:</p>
|
||||
<p><span style="font-weight: bold;"><%= @inviter.name %></span> has invited you to <span style="font-weight: bold">collaboratively edit</span> the following map:</p>
|
||||
<p><%= link_to @map.name, map_url(@map), target: "_blank", style: "font-size: 18px; text-decoration: none; color: #4fc059;" %></p>
|
||||
<% if @map.desc %>
|
||||
<p style="font-size: 12px;"><%= @map.desc %></p>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<%= @inviter.name %> has invited you to collaboratively edit the following metamap:
|
||||
<%= @inviter.name %> has invited you to collaboratively edit the following map:
|
||||
|
||||
<%= @map.name %> [<%= map_url(@map) %>]
|
||||
|
||||
|
|
|
@ -7,12 +7,14 @@
|
|||
<% content_for :title, 'Request Access | Metamaps' %>
|
||||
<% content_for :mobile_title, 'Request Access' %>
|
||||
|
||||
<div class='request_access'>
|
||||
<div class='monkey'></div>
|
||||
<div class='explainer_text'>
|
||||
Oops! This map is private, but you can request<br> to edit it from the map creator.
|
||||
<div id="yield">
|
||||
<div class='request_access'>
|
||||
<div class='monkey'></div>
|
||||
<div class='explainer_text'>
|
||||
Hmmm. This map is private, but you can request to edit it from the map creator.
|
||||
</div>
|
||||
<div class='make_request'>REQUEST ACCESS</div>
|
||||
</div>
|
||||
<div class='make_request'>REQUEST ACCESS</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
|
@ -26,8 +28,8 @@ $(document).ready(function() {
|
|||
type: 'POST',
|
||||
contentType: 'application/json',
|
||||
statusCode: {
|
||||
200: function () { that.text('Request Sent!'); setTimeout(function () {window.location.href = '/'}, 2000) },
|
||||
500: function () { that.text('An error occurred') }
|
||||
200: function () { that.text('Request Sent'); setTimeout(function () {window.location.href = '/'}, 2000) },
|
||||
400: function () { that.text('An error occurred') }
|
||||
}
|
||||
})
|
||||
})
|
||||
|
|
|
@ -16,16 +16,18 @@ Metamaps::Application.routes.draw do
|
|||
|
||||
resources :maps, except: [:index, :edit] do
|
||||
member do
|
||||
get :request_access
|
||||
get 'approve_access/:request_id', action: :approve_access, as: :approve_access
|
||||
get 'deny_access/:request_id', action: :deny_access, as: :deny_access
|
||||
get :export
|
||||
post 'events/:event', action: :events
|
||||
get :contains
|
||||
post :access_request, default: { format: :json }
|
||||
post 'approve_access/:request_id', action: :approve_access_post, default: { format: :json }
|
||||
post 'deny_access/:request_id', action: :deny_access_post, default: { format: :json }
|
||||
post :access, default: { format: :json }
|
||||
|
||||
get :request_access, to: 'access#request_access'
|
||||
get 'approve_access/:request_id', to: 'access#approve_access', as: :approve_access
|
||||
get 'deny_access/:request_id', to: 'access#deny_access', as: :deny_access
|
||||
post :access_request, to: 'access#access_request', default: { format: :json }
|
||||
post 'approve_access/:request_id', to: 'access#approve_access_post', default: { format: :json }
|
||||
post 'deny_access/:request_id', to: 'access#deny_access_post', default: { format: :json }
|
||||
post :access, to: 'access#access', default: { format: :json }
|
||||
|
||||
post :star, to: 'stars#create', default: { format: :json }
|
||||
post :unstar, to: 'stars#destroy', default: { format: :json }
|
||||
end
|
||||
|
|
|
@ -60,8 +60,28 @@ const Map = {
|
|||
InfoBox.init()
|
||||
CheatSheet.init()
|
||||
|
||||
$('.viewOnly .requestAccess').click(self.requestAccess)
|
||||
|
||||
$(document).on(Map.events.editedByActiveMapper, self.editedByActiveMapper)
|
||||
},
|
||||
requestAccess: function () {
|
||||
$('.viewOnly').removeClass('sendRequest').addClass('sentRequest')
|
||||
const mapId = Active.Map.id
|
||||
$.post({
|
||||
url: `/maps/${mapId}/access_request`
|
||||
})
|
||||
GlobalUI.notifyUser('Map creator will be notified of your request')
|
||||
},
|
||||
setAccessRequest: function (requests, activeMapper) {
|
||||
let className = 'isViewOnly '
|
||||
if (activeMapper) {
|
||||
const request = _.find(requests, r => r.user_id === activeMapper.id)
|
||||
if (!request) className += 'sendRequest'
|
||||
else if (request && !request.answered) className += 'sentRequest'
|
||||
else if (request && request.answered && !request.approved) className += 'requestDenied'
|
||||
}
|
||||
$('.viewOnly').removeClass('sendRequest sentRequest requestDenied').addClass(className)
|
||||
},
|
||||
launch: function (id) {
|
||||
var bb = Metamaps.Backbone
|
||||
var start = function (data) {
|
||||
|
@ -84,6 +104,9 @@ const Map = {
|
|||
if (map.authorizeToEdit(mapper)) {
|
||||
$('.wrapper').addClass('canEditMap')
|
||||
}
|
||||
else {
|
||||
Map.setAccessRequest(data.requests, mapper)
|
||||
}
|
||||
|
||||
// add class to .wrapper for specifying if the map can
|
||||
// be collaborated on
|
||||
|
@ -139,6 +162,7 @@ const Map = {
|
|||
Filter.close()
|
||||
InfoBox.close()
|
||||
Realtime.endActiveMap()
|
||||
$('.viewOnly').removeClass('isViewOnly')
|
||||
}
|
||||
},
|
||||
updateStar: function () {
|
||||
|
|
Loading…
Add table
Reference in a new issue