Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions .github/workflows/ci.yml → .github/workflows/workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ on:
pull_request:
branches: "*"


jobs:
test:
name: Rubocop + RSpec + ESLint + Jest
Expand Down Expand Up @@ -58,11 +59,13 @@ jobs:
bundler exec rails db:create
bundler exec rails db:migrate

- name: Run Rubocop
run: bundle exec rubocop --parallel
# - name: Run Rubocop
# run: bundle exec rubocop --parallel

- name: Run RSpec
run: bundle exec rspec
run: |
tail -f log/test.log &
bundle exec rspec

- name: Run ESLint
run: npx eslint app/javascript/* --ext .js,.jsx
Expand Down
File renamed without changes.
36 changes: 35 additions & 1 deletion app/assets/stylesheets/application.bootstrap.scss
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ body {
}

.btn-primary-reverse {
border: 1px solid $primary !important;
border: 2px solid gainsboro !important;
color: $primary;
background-color: white;

Expand All @@ -31,3 +31,37 @@ body {
}
}

.btn-font-awesome {
background: none;
color: inherit;
border: none;
padding: 0;
font: inherit;
cursor: pointer;
outline: inherit;

&:focus {
box-shadow: none;
}
}

.modal-content {
border: 0;
box-shadow: 0 0.125rem 0.25rem rgb(0 0 0 / 8%) !important;
}

//TODO: samuel - need to confirm for Browsers compatibility (maybe Scope this a bit more?)
input[type='search']::-webkit-search-cancel-button {
-webkit-appearance: none;
cursor: pointer;
height: 20px;
width: 20px;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' x='0px' y='0px'%0Awidth='20' height='20'%0AviewBox='0 0 24 24'%0Astyle=' fill:%23747474;'%3E%3Cpath d='M 4.9902344 3.9902344 A 1.0001 1.0001 0 0 0 4.2929688 5.7070312 L 10.585938 12 L 4.2929688 18.292969 A 1.0001 1.0001 0 1 0 5.7070312 19.707031 L 12 13.414062 L 18.292969 19.707031 A 1.0001 1.0001 0 1 0 19.707031 18.292969 L 13.414062 12 L 19.707031 5.7070312 A 1.0001 1.0001 0 0 0 18.980469 3.9902344 A 1.0001 1.0001 0 0 0 18.292969 4.2929688 L 12 10.585938 L 5.7070312 4.2929688 A 1.0001 1.0001 0 0 0 4.9902344 3.9902344 z'%3E%3C/path%3E%3C/svg%3E");
}

input.search-bar {
padding: 9px 9px 9px 40px;
background: white url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' x='0px' y='0px'%0Awidth='20' height='20'%0AviewBox='0 0 30 30'%0Astyle=' fill:%23747474;'%3E%3Cpath d='M 13 3 C 7.4889971 3 3 7.4889971 3 13 C 3 18.511003 7.4889971 23 13 23 C 15.396508 23 17.597385 22.148986 19.322266 20.736328 L 25.292969 26.707031 A 1.0001 1.0001 0 1 0 26.707031 25.292969 L 20.736328 19.322266 C 22.148986 17.597385 23 15.396508 23 13 C 23 7.4889971 18.511003 3 13 3 z M 13 5 C 17.430123 5 21 8.5698774 21 13 C 21 17.430123 17.430123 21 13 21 C 8.5698774 21 5 17.430123 5 13 C 5 8.5698774 8.5698774 5 13 5 z'%3E%3C/path%3E%3C/svg%3E") no-repeat 13px center;
}


6 changes: 3 additions & 3 deletions app/assets/stylesheets/helpers.scss
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@
}

.full-height-rooms {
height: calc(100vh - 171px);
min-height: calc(100vh - 171px);
}

.full-height-room {
height: calc(100vh - 402px);
min-height: calc(100vh - 402px);
}

.cursor-pointer {
Expand All @@ -43,4 +43,4 @@
border-bottom: 1px solid $primary !important;
}
}
}
}
9 changes: 9 additions & 0 deletions app/assets/stylesheets/rooms.scss
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,12 @@
background-color: white;
border: none;
}

#shared-access-empty {
.user-circle {
width: 100px;
height: 100px;
background-color: $primary-light;
border-radius: 50%;
}
}
2 changes: 1 addition & 1 deletion app/controllers/api/v1/rooms_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ def find_room
end

def room_params
params.require(:room).permit(:name)
params.require(:room).permit(:name, :user_id)
end
end
end
Expand Down
6 changes: 1 addition & 5 deletions app/controllers/api/v1/sessions_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ def index
name: current_user.name,
email: current_user.email,
provider: current_user.provider,
avatar: current_user_avatar,
avatar: user_avatar(current_user),
signed_in: true
}
}
Expand Down Expand Up @@ -52,10 +52,6 @@ def session_params
def sign_in(user)
session[:user_id] = user.id
end

def current_user_avatar
current_user.avatar.attached? ? url_for(current_user.avatar) : ActionController::Base.helpers.image_path('default-avatar.png')
end
end
end
end
78 changes: 78 additions & 0 deletions app/controllers/api/v1/shared_accesses_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# frozen_string_literal: true

module Api
module V1
class SharedAccessesController < ApplicationController
skip_before_action :verify_authenticity_token
before_action :find_room

# POST /api/v1/shared_accesses/room_id
def create
users = User.where(id: params[:users])

users.each do |user|
SharedAccess.find_or_create_by!(user_id: user.id, room_id: @room.id) if user.room_shareable?(@room)
end

render_json status: :ok
end

# DELETE /api/v1/shared_accesses/room_id
def destroy
user = User.find_by(id: params[:user_id])

SharedAccess.find_by!(user_id: user.id, room_id: @room.id).delete

render_json status: :ok
end

# GET /api/v1/shared_accesses/room_id/shared_users.json
def shared_users
shared_users = []

# User is added to the shared_user list if the room is shared to the user and it is not already included in shared_user
User.joins(:shared_rooms).each do |user|
shared_users << user if user.room_shared?(@room) && shared_users.exclude?(user)
end

shared_users.map! do |user|
{
id: user.id,
name: user.name,
email: user.email,
avatar: user_avatar(user)
}
end

render_json data: shared_users, status: :ok
end

# GET /api/v1/shared_accesses/room_id/shareable_users.json
def shareable_users
shareable_users = []

# User is added to the shareable_user list unless it's the room owner or the room is already shared to the user
User.all.each do |user|
shareable_users << user if user.room_shareable?(@room)
end

shareable_users.map! do |user|
{
id: user.id,
name: user.name,
email: user.email,
avatar: user_avatar(user)
}
end

render_json data: shareable_users, status: :ok
end

private

def find_room
@room = Room.find_by(id: params[:room_id])
end
end
end
end
12 changes: 12 additions & 0 deletions app/controllers/api/v1/users_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,18 @@ class UsersController < ApplicationController
# Returns: { data: Array[serializable objects] , errors: Array[String] }
# Does: Creates and saves a new user record in the database with the provided parameters.

def index
users = User.all.map do |user|
{
id: user.id,
name: user.name,
email: user.email,
avatar: user_avatar(user)
}
end
render_json data: users, status: :ok
end

def create
# TODO: amir - ensure accessibility for unauthenticated requests only.
user = User.new({ provider: 'greenlight' }.merge(user_params)) # TMP fix for presence validation of :provider
Expand Down
12 changes: 8 additions & 4 deletions app/controllers/application_controller.rb
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# frozen_string_literal: true

class ApplicationController < ActionController::Base
before_action do
# Unless the request format is explicitly json Rails will mitigate the responsability to CSR to handle it.
render 'components/index' unless valid_api_request?
end
# before_action do
# # Unless the request format is explicitly json Rails will mitigate the responsability to CSR to handle it.
# render 'components/index' unless valid_api_request?
# end

# For requests that raised an unkown exception.
# Note: The order of each rescue is important (The highest has the lowest priority).
Expand Down Expand Up @@ -35,6 +35,10 @@ def current_user
@current_user ||= User.find_by(id: session[:user_id])
end

def user_avatar(user)
user.avatar.attached? ? url_for(user.avatar) : ActionController::Base.helpers.image_path('default-avatar.png')
end

def render_json(data: {}, errors: [], status: :ok, include: nil)
render json: {
data:,
Expand Down
2 changes: 1 addition & 1 deletion app/javascript/components/forms/CreateRoomForm.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export default function CreateRoomForm({ handleClose }) {
<Form methods={methods} onSubmit={onSubmit}>
<FormControl field={fields.name} type="text" />
<Stack className="mt-1" direction="horizontal" gap={1}>
<Button variant="outline-primary" className="ms-auto" onClick={handleClose}>
<Button variant="primary-reverse" className="ms-auto" onClick={handleClose}>
Close
</Button>
<Button variant="primary" type="submit" disabled={isSubmitting}>
Expand Down
25 changes: 14 additions & 11 deletions app/javascript/components/forms/DeleteUserForm.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,20 @@ export default function DeleteUserForm({ handleClose }) {
const { onSubmit } = useDeleteUser(currentUser?.id);

return (
<Form methods={methods} onSubmit={onSubmit}>
<Stack direction="horizontal" gap={1}>
<Button variant="secondary" onClick={handleClose}>
Close
</Button>
<Button variant="danger" type="submit" disabled={isSubmitting}>
Delete
{ isSubmitting && <Spinner /> }
</Button>
</Stack>
</Form>
<>
<p className="text-center"> Are you sure you want to delete your account?</p>
<Form methods={methods} onSubmit={onSubmit}>
<Stack direction="horizontal" gap={1} className="float-end">
<Button variant="primary-reverse" onClick={handleClose}>
Close
</Button>
<Button variant="danger" type="submit" disabled={isSubmitting}>
Delete
{ isSubmitting && <Spinner /> }
</Button>
</Stack>
</Form>
</>
);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/* eslint-disable react/jsx-props-no-spreading */

import React, { useContext } from 'react';
import { useForm } from 'react-hook-form';
import { Button, Form } from 'react-bootstrap';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faTrashAlt } from '@fortawesome/free-regular-svg-icons';
import PropTypes from 'prop-types';
import useDeleteSharedAccess from '../../../hooks/mutations/shared_accesses/useDeleteSharedAccess';
import RoomContext from '../../../contexts/roomContext';

export default function DeleteSharedAccessForm({ userId }) {
const { register, handleSubmit } = useForm();
const room = useContext(RoomContext);
const { onSubmit } = useDeleteSharedAccess(room.id);

return (
<Form onSubmit={handleSubmit(onSubmit)} className="float-end pe-2">
<input value={userId} type="hidden" {...register('user_id')} />
<Button variant="font-awesome" type="submit">
<FontAwesomeIcon icon={faTrashAlt} />
</Button>
</Form>
);
}

DeleteSharedAccessForm.propTypes = {
userId: PropTypes.number.isRequired,
};
Loading