restructure app

This commit is contained in:
Josh 2018-05-29 15:28:29 -04:00
parent 5042e2572c
commit 32ec2bacce
31 changed files with 303 additions and 472 deletions

View File

@ -1,8 +1,6 @@
GEM
remote: https://rubygems.org/
specs:
action_interceptor (1.1.0)
rails (>= 3.1)
actioncable (5.0.7)
actionpack (= 5.0.7)
nio4r (>= 1.2, < 3.0)
@ -79,12 +77,6 @@ GEM
faraday (0.12.2)
multipart-post (>= 1.2, < 3)
ffi (1.9.23)
fine_print (3.1.0)
action_interceptor (>= 1.0)
jquery-rails
rails (>= 3.1)
responders
squeel
font-awesome-sass (5.0.13)
sassc (>= 1.11)
globalid (0.4.1)
@ -141,8 +133,6 @@ GEM
omniauth-twitter (1.4.0)
omniauth-oauth (~> 1.1)
rack
polyamorous (1.1.0)
activerecord (>= 3.0)
popper_js (1.12.9)
puma (3.11.4)
rack (2.0.5)
@ -179,9 +169,6 @@ GEM
rb-fsevent (0.10.3)
rb-inotify (0.9.10)
ffi (>= 0.5.0, < 2)
responders (2.4.0)
actionpack (>= 4.2.0, < 5.3)
railties (>= 4.2.0, < 5.3)
rspec-core (3.7.1)
rspec-support (~> 3.7.0)
rspec-expectations (3.7.0)
@ -227,10 +214,6 @@ GEM
activesupport (>= 4.0)
sprockets (>= 3.0.0)
sqlite3 (1.3.13)
squeel (1.2.3)
activerecord (>= 3.0)
activesupport (>= 3.0)
polyamorous (~> 1.1.0)
tabler-rubygem (0.1.2)
autoprefixer-rails (>= 6.0.3)
thor (0.20.0)
@ -265,7 +248,6 @@ DEPENDENCIES
dotenv-rails
factory_bot_rails
faker
fine_print
font-awesome-sass (~> 5.0.13)
jbuilder (~> 2.5)
jquery-rails

View File

@ -48,6 +48,10 @@ $rule-color: lightblue;
padding-bottom: 56.25%;
}
a {
text-decoration: none !important;
}
.start-block {
background-color: white;
border: 3px solid lightblue;
@ -66,6 +70,10 @@ iframe{
height: 100%;
}
.subtitle {
font-size: 25px;
}
html, body {
width: 100%;
height: 100%;

View File

@ -1,3 +0,0 @@
// Place all the styles related to the Meetings controller here.
// They will automatically be included in application.css.
// You can use Sass (SCSS) here: http://sass-lang.com/

View File

@ -47,9 +47,9 @@ class ApplicationController < ActionController::Base
def default_meeting_options
{
user_is_moderator: false,
meeting_logout_url: request.base_url + logout_room_path(@room.uid),
meeting_logout_url: request.base_url + logout_room_path(@room),
meeting_recorded: true,
moderator_message: "To invite someone to the meeting, send them this link:\n\n#{request.base_url + room_path(@room.uid)}"
moderator_message: "To invite someone to the meeting, send them this link:\n\n#{request.base_url + room_path(@room)}"
}
end
end

View File

@ -4,7 +4,6 @@ class MainController < ApplicationController
# GET /
def index
@meeting = Meeting.new
end
private

View File

@ -1,46 +0,0 @@
class MeetingsController < ApplicationController
# GET /m/:meeting_uid
def show
@meeting = Meeting.find_by(uid: params[:meeting_uid])
if @meeting
else
# Handle meeting doesn't exist.
end
end
# POST /m/:meeting_uid
def join
meeting = Meeting.find_by(uid: params[:meeting_uid])
if meeting
# If the user is logged in, join using their authenticated name.
if current_user
redirect_to meeting.join_path(current_user.name)
# Otherwise, use their inputed join name.
elsif params[:join_name]
redirect_to meeting.join_path(params[:join_name])
end
else
# Handle meeting doesn't exist.
end
end
# POST /m
def create
meeting = Meeting.new(meeting_params)
if meeting.save
redirect_to meeting_path(meeting_uid: meeting.uid)
else
redirect_to root_path
end
end
private
def meeting_params
params.require(:meeting).permit(:name)
end
end

View File

@ -1,27 +1,46 @@
class RoomsController < ApplicationController
before_action :find_room, :verify_room_ownership
skip_before_action :verify_room_ownership, only: [:show, :join, :wait]
before_action :find_room, except: :create
# GET /r/:room_uid
#before_action :verify_room_ownership
#skip_before_action :verify_room_ownership, only: [:create, :show, :join, :wait]
# POST /r
def create
room = Room.new(name: room_params[:name])
room.user = current_user
if room.save
redirect_to room
else
end
end
# GET/POST /r/:room_uid
def show
opts = default_meeting_options
if @meeting.is_running?
if @room.is_running?
if current_user
# If you don't own the room but the meeting is running, join up.
if !@room.owned_by?(current_user)
opts[:user_is_moderator] = false
redirect_to @meeting.join_path(current_user.name, opts)
redirect_to @room.join_path(current_user, opts)
end
else
# If you're unauthenticated, you must enter a name to join the meeting.
redirect_to join_room_path(@room.uid)
if params[:join_name]
redirect_to @room.join_path(params[:join_name], opts)
else
# Render the join page so they can supply their name.
render :join
end
end
else
# If the meeting isn't running and you don't own the room, go to the waiting page.
if !@room.owned_by?(current_user)
redirect_to wait_room_path(@room.uid)
redirect_to wait_room_path(@room)
end
end
end
@ -31,47 +50,19 @@ class RoomsController < ApplicationController
# Join the user in and start the meeting.
opts = default_meeting_options
opts[:user_is_moderator] = true
redirect_to @meeting.join_path(current_user.name, opts)
end
# GET /r/:room_uid/join
def join
if @meeting.is_running?
opts = default_meeting_options
if current_user
# If the user exists, join them in.
opts[:user_is_moderator] = @room.owned_by?(current_user)
redirect_to @meeting.join_path(current_user.name, opts)
else
# If they are unauthenticated, prompt for join name.
if params[:join_name]
redirect_to @meeting.join_path(params[:join_name], opts)
else
# Render the join page so they can supply their name.
render :join
end
end
else
if @room.owned_by?(current_user)
# Redirect owner to room.
redirect_to room_path(@room.uid)
else
# Otherwise, they have to wait for the meeting to start.
redirect_to wait_room_path(@room.uid)
end
end
redirect_to @room.join_path(current_user, opts)
end
# GET/POST /r/:room_uid/wait
def wait
if @meeting.is_running?
if @room.is_running?
if current_user
# If they are logged in and waiting, use their account name.
redirect_to @meeting.join_path(current_user.name, default_meeting_options)
redirect_to @room.join_path(current_user, default_meeting_options)
elsif !params[:unauthenticated_join_name].blank?
# Otherwise, use the name they submitted on the wating page.
redirect_to @meeting.join_path(params[:unauthenticated_join_name], default_meeting_options)
redirect_to @room.join_path(params[:unauthenticated_join_name], default_meeting_options)
end
end
end
@ -79,7 +70,7 @@ class RoomsController < ApplicationController
# GET /r/:room_uid/logout
def logout
# Redirect the owner to their room.
redirect_to room_path(@room.uid)
redirect_to root_path
end
# GET /r/:room_uid/sessions
@ -89,6 +80,10 @@ class RoomsController < ApplicationController
private
def room_params
params.require(:room).permit(:name, :auto_join)
end
# Find the room from the uid.
def find_room
@room = Room.find_by(uid: params[:room_uid])
@ -97,8 +92,6 @@ class RoomsController < ApplicationController
# Handle room doesn't exist.
end
@meeting = @room.meeting
end
# Ensure the user is logged into the room they are accessing.

View File

@ -1,156 +0,0 @@
class Meeting < ApplicationRecord
before_create :generate_meeting_id
validates :name, presence: true
belongs_to :room, optional: true
RETURNCODE_SUCCESS = "SUCCESS"
# Creates a meeting on the BigBlueButton server.
def start_meeting(options = {})
create_options = {
record: options[:meeting_recorded].to_s,
logoutURL: options[:meeting_logout_url] || '',
moderatorPW: random_password(12),
attendeePW: random_password(12),
moderatorOnlyMessage: options[:moderator_message]
}
#meeting_options.merge!(
#{ "meta_room-id": options[:room_owner],
# "meta_meeting-name": options[:meeting_name]}
#) if options[:room_owner]
# Send the create request.
begin
bbb.create_meeting(name, uid, create_options)
rescue BigBlueButton::BigBlueButtonException => exc
puts "BigBlueButton failed on create: #{exc.key}: #{exc.message}"
end
end
# Returns a URL to join a user into a meeting.
def join_path(username, options = {})
# Create the meeting if it isn't running.
start_meeting(options) unless is_running?
# Set meeting options.
options[:meeting_logout_url] ||= nil
options[:moderator_message] ||= ''
options[:user_is_moderator] ||= false
options[:meeting_recorded] ||= false
#options[:wait_for_moderator] ||= false
#options[:meeting_name] ||= name
#options[:room_owner] ||= nil
return call_invalid_res if !bbb
# Get the meeting info.
meeting_info = bbb.get_meeting_info(uid, nil)
# Determine the password to use when joining.
password = if options[:user_is_moderator]
meeting_info[:moderatorPW]
else
meeting_info[:attendeePW]
end
# Generate the join URL.
bbb.join_meeting_url(uid, username, password)
end
# Fetches all recordings for a meeting.
def recordings
res = bbb.get_recordings(meetingID: uid)
res[:recordings]
end
# Checks if a meeting is running on the BigBlueButton server.
def is_running?
begin
bbb.get_meeting_info(uid, nil)
return true
rescue BigBlueButton::BigBlueButtonException => exc
return false
end
end
private
def bbb_endpoint
Rails.configuration.bigbluebutton_endpoint
end
def bbb_secret
Rails.configuration.bigbluebutton_secret
end
# Sets a BigBlueButtonApi object for interacting with the API.
def bbb
@bbb ||= if Rails.configuration.loadbalanced_configuration
lb_user = retrieve_loadbalanced_credentials(self.room.user.provider)
BigBlueButton::BigBlueButtonApi.new(remove_slash(lb_user["apiURL"]), lb_user["secret"], "0.8")
else
BigBlueButton::BigBlueButtonApi.new(remove_slash(bbb_endpoint), bbb_secret, "0.8")
end
end
# Rereives the loadbalanced BigBlueButton credentials for a user.
def retrieve_loadbalanced_credentials(provider)
# Include Omniauth accounts under the Greenlight provider.
provider = "greenlight" if Rails.configuration.providers.include?(provider.to_sym)
# Build the URI.
uri = encode_bbb_url(
Rails.configuration.loadbalancer_endpoint,
Rails.configuration.loadbalancer_secret,
{name: provider}
)
# Make the request.
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = (uri.scheme == 'https')
response = http.get(uri.request_uri)
unless response.kind_of?(Net::HTTPSuccess)
raise "Error retrieving provider credentials: #{response.code} #{response.message}"
end
# Parse XML.
doc = XmlSimple.xml_in(response.body, 'ForceArray' => false)
# Return the user credentials if the request succeeded on the loadbalancer.
return doc['user'] if doc['returncode'] == RETURNCODE_SUCCESS
raise "User with provider #{provider} does not exist." if doc['messageKey'] == "noSuchUser"
raise "API call #{url} failed with #{doc['messageKey']}."
end
# Builds a request to retrieve credentials from the load balancer.
def encode_bbb_url(base_url, secret, params)
encoded_params = OAuth::Helper.normalize(params)
string = "getUser" + encoded_params + secret
checksum = OpenSSL::Digest.digest('sha1', string).unpack("H*").first
URI.parse("#{base_url}?#{encoded_params}&checksum=#{checksum}")
end
# Removes trailing forward slash from a URL.
def remove_slash(s)
s.nil? ? nil : s.chomp("/")
end
# Generates a BigBlueButton meeting id from a meeting token.
def generate_meeting_id
self.uid = Digest::SHA1.hexdigest(Rails.application.secrets[:secret_key_base] + name + Time.now.to_i.to_s).to_s
end
# Generates a random password for a meeting.
def random_password(length)
o = ([('a'..'z'), ('A'..'Z')].map do |i| i.to_a end).flatten
((0...length).map do o[rand(o.length)] end).join
end
end

View File

@ -1,23 +1,174 @@
class Room < ApplicationRecord
before_create :set_uid
before_create :generate_uids
belongs_to :user
has_one :meeting
RETURNCODE_SUCCESS = "SUCCESS"
def to_param
uid
end
# Determines if a user owns a room.
def owned_by?(user)
return false if user.nil?
user.room == self
user.rooms.include?(self)
end
# Checks if a room is running on the BigBlueButton server.
def is_running?
begin
bbb.get_meeting_info(bbb_id, nil)
return true
rescue BigBlueButton::BigBlueButtonException => exc
return false
end
end
# Determines the invite URL for the room.
def invite_path
"/r/#{uid}"
end
# Creates a meeting on the BigBlueButton server.
def start_session(options = {})
create_options = {
record: options[:meeting_recorded].to_s,
logoutURL: options[:meeting_logout_url] || '',
moderatorPW: random_password(12),
attendeePW: random_password(12),
moderatorOnlyMessage: options[:moderator_message]
}
#meeting_options.merge!(
#{ "meta_room-id": options[:room_owner],
# "meta_meeting-name": options[:meeting_name]}
#) if options[:room_owner]
# Send the create request.
begin
bbb.create_meeting(name, bbb_id, create_options)
rescue BigBlueButton::BigBlueButtonException => exc
puts "BigBlueButton failed on create: #{exc.key}: #{exc.message}"
end
end
# Returns a URL to join a user into a meeting.
def join_path(user, options = {})
user = user.name if user.is_a?(User)
# Create the meeting if it isn't running.
start_session(options) unless is_running?
# Set meeting options.
options[:meeting_logout_url] ||= nil
options[:moderator_message] ||= ''
options[:user_is_moderator] ||= false
options[:meeting_recorded] ||= false
#options[:wait_for_moderator] ||= false
#options[:meeting_name] ||= name
#options[:room_owner] ||= nil
return call_invalid_res if !bbb
# Get the meeting info.
meeting_info = bbb.get_meeting_info(bbb_id, nil)
# Determine the password to use when joining.
password = if options[:user_is_moderator]
meeting_info[:moderatorPW]
else
meeting_info[:attendeePW]
end
# Generate the join URL.
bbb.join_meeting_url(bbb_id, user, password)
end
# Fetches all recordings for a meeting.
def recordings
res = bbb.get_recordings(meetingID: bbb_id)
res[:recordings]
end
private
# Generates a uid for the room.
def set_uid
digest = user.id.to_s + user.provider + user.username
digest += user.uid unless user.uid.nil?
self.uid = [user.name.split(' ').first.downcase, Digest::SHA1.hexdigest(digest)[0..7]].join('-')
def bbb_endpoint
Rails.configuration.bigbluebutton_endpoint
end
end
def bbb_secret
Rails.configuration.bigbluebutton_secret
end
# Sets a BigBlueButtonApi object for interacting with the API.
def bbb
@bbb = BigBlueButton::BigBlueButtonApi.new(remove_slash(bbb_endpoint), bbb_secret, "0.8")
#@bbb ||= if Rails.configuration.loadbalanced_configuration
# lb_user = retrieve_loadbalanced_credentials(self.room.user.provider)
# BigBlueButton::BigBlueButtonApi.new(remove_slash(lb_user["apiURL"]), lb_user["secret"], "0.8")
#else
# BigBlueButton::BigBlueButtonApi.new(remove_slash(bbb_endpoint), bbb_secret, "0.8")
#end
end
# Generates a uid for the room and BigBlueButton.
def generate_uids
self.uid = [user.firstname, (0...8).map { (65 + rand(26)).chr }.join].join('-')
self.bbb_id = Digest::SHA1.hexdigest(Rails.application.secrets[:secret_key_base] + Time.now.to_i.to_s).to_s
end
# Rereives the loadbalanced BigBlueButton credentials for a user.
def retrieve_loadbalanced_credentials(provider)
# Include Omniauth accounts under the Greenlight provider.
provider = "greenlight" if Rails.configuration.providers.include?(provider.to_sym)
# Build the URI.
uri = encode_bbb_url(
Rails.configuration.loadbalancer_endpoint,
Rails.configuration.loadbalancer_secret,
{name: provider}
)
# Make the request.
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = (uri.scheme == 'https')
response = http.get(uri.request_uri)
unless response.kind_of?(Net::HTTPSuccess)
raise "Error retrieving provider credentials: #{response.code} #{response.message}"
end
# Parse XML.
doc = XmlSimple.xml_in(response.body, 'ForceArray' => false)
# Return the user credentials if the request succeeded on the loadbalancer.
return doc['user'] if doc['returncode'] == RETURNCODE_SUCCESS
raise "User with provider #{provider} does not exist." if doc['messageKey'] == "noSuchUser"
raise "API call #{url} failed with #{doc['messageKey']}."
end
# Builds a request to retrieve credentials from the load balancer.
def encode_bbb_url(base_url, secret, params)
encoded_params = OAuth::Helper.normalize(params)
string = "getUser" + encoded_params + secret
checksum = OpenSSL::Digest.digest('sha1', string).unpack("H*").first
URI.parse("#{base_url}?#{encoded_params}&checksum=#{checksum}")
end
# Removes trailing forward slash from a URL.
def remove_slash(s)
s.nil? ? nil : s.chomp("/")
end
# Generates a random password for a meeting.
def random_password(length)
o = ([('a'..'z'), ('A'..'Z')].map do |i| i.to_a end).flatten
((0...length).map do o[rand(o.length)] end).join
end
end

View File

@ -3,7 +3,7 @@ class User < ApplicationRecord
after_create :initialize_room
before_save { email.downcase! unless email.nil? }
has_one :room
has_many :rooms
validates :name, length: { maximum: 24 }, presence: true
validates :username, presence: true
@ -89,7 +89,6 @@ class User < ApplicationRecord
# Initializes a room for the user.
def initialize_room
room = Room.create(user_id: self.id)
Meeting.create(room_id: room.id, name: "Example")
Room.create(user_id: self.id, name: firstname + "'s Room")
end
end

View File

@ -33,6 +33,11 @@
<%= yield %>
<%= render "shared/footer" %>
<!-- Modal Load -->
<% if current_user %>
<%= render "shared/modals/create_room_modal" %>
<% end %>
</div>
</body>

View File

@ -1,15 +0,0 @@
<div class="row invite-join-wrapper hidden">
<div class="col-xs-6">
<%= render 'shared/title', title: t('invite') do %>
<span><%= t('invite_description') %></span>
<% end %>
<%= render 'shared/meeting_url', hidden: false %>
</div>
<div class="verticle-line"></div>
<div class="col-xs-6">
<%= render 'shared/title', title: t('join'), title_class: 'join-meeting-title' %>
<button type="button" class="btn btn-primary center-block meeting-start has-tooltip" data-placement="top" title="<%= t('start_meeting') %>">
<%= t('start_join') %>
</button>
</div>
</div>

View File

@ -2,7 +2,6 @@
<% if current_user %>
<h1 id="user-text" class="display-3 text-center text-primary mt-9"><%= "Welcome, #{current_user.firstname}." %></h1>
<%= render "shared/modals/create_room_modal" %>
<% else %>
<h1 id="main-text" class="display-3 text-center text-primary mt-9">Teach Students Online.</h1>
<%= render "shared/modals/video_modal" %>
@ -10,47 +9,19 @@
<hr class="small-rule">
<% if current_user %>
<div class="row">
<% 3.times do %>
<div class="col-4">
<div class="card">
<div class="card-body p-1">
<table class="table table-hover table-outline table-vcenter text-nowrap card-table">
<tbody>
<td>
<span class="colorinput-color bg-azure"></span>
</td>
<td>
<div>Example Room</div>
<div class="small text-muted">
<i>Created on June 17th, 2017</i>
</div>
</td>
<td class="text-right">
<div class="item-action dropdown">
<a href="javascript:void(0)" data-toggle="dropdown" class="icon"><i class="fe fe-more-vertical"></i></a>
<div class="dropdown-menu dropdown-menu-right">
<a href="javascript:void(0)" class="dropdown-item"><i class="dropdown-icon fe fe-tag"></i> Action </a>
<a href="javascript:void(0)" class="dropdown-item"><i class="dropdown-icon fe fe-edit-2"></i> Another action </a>
<a href="javascript:void(0)" class="dropdown-item"><i class="dropdown-icon fe fe-message-square"></i> Something else here</a>
<div class="dropdown-divider"></div>
<a href="javascript:void(0)" class="dropdown-item"><i class="dropdown-icon fe fe-link"></i> Separated link</a>
</div>
</div>
</td>
</tbody>
</table>
<div class="row">
<% current_user.rooms.each do |room| %>
<div class="col-4">
<%= link_to room do %>
<%= render "shared/components/room_block", room: room %>
<% end %>
</div>
</div>
<% end %>
</div>
<% end %>
</div>
<!-- <%= render "shared/start_meeting" %> -->
<br>
<br>
<% else %>
<%= render "shared/features" %>
<%= render "shared/features" %>
<% end %>
</div>

View File

@ -1,11 +0,0 @@
<h4>This is an unauthenticated meeting page.</h4>
<% if current_user %>
<%= link_to "Join", join_meeting_path(uid: @meeting.uid), {method: :post} %>
<% else %>
<p>Enter a name to join the session.</p>
<%= form_tag join_meeting_path do %>
<%= text_field_tag "join_name" %>
<%= submit_tag "Join" %>
<% end %>
<% end %>

View File

@ -1,7 +1,7 @@
<p>The join the meeting, enter a name.</p>
<p>Enter a name to start a session.</p>
<%= form_tag join_room_path(room_uid: @room.uid) do %>
<%= form_tag room_path(@room) do %>
<%= text_field_tag "join_name" %>
<%= submit_tag "Join" %>
<% end %>
<% end %>

View File

@ -1,17 +1,6 @@
<div class="container">
<div class="row">
<div class="col-10 offset-1">
<p style="font-size: 25px;">Sessions</p>
<!-- <div class="input-icon float-right">
<input type="text" class="form-control" placeholder="Search for...">
<span class="input-icon-addon">
<i class="fe fe-search"></i>
</span>
</div> -->
<hr>
</div>
</div>
<%= render "shared/components/subtitle", subtitle: "Sessions" %>
<div class="col-10 offset-1">
<div class="card">
@ -82,9 +71,9 @@
Sessions
<br><br>
<%= @meeting.recordings %>
<%= @room.recordings %>
<% @meeting.recordings.each do |rec| %>
<% @room.recordings.each do |rec| %>
<p><%= rec[:metadata][:meetingName] %></p>
<% Array.wrap(rec[:playback][:format]).each do |form| %>
<%= link_to form[:type], form[:url] %>

View File

@ -1,20 +1,15 @@
<p>This is a room.</p>
<p><%= @room.user.name %><p>
<p><%= @room.meeting.uid %><p>
<p><%= @room.uid %><p>
<%= link_to 'Sessions', sessions_path %>
<%= link_to 'Settings', root_path %>
<p>Click below to join the meeting.</p>
<% if @room.meeting.is_running? %>
<% if @room.is_running? %>
<p>meeting is already running</p>
<% else %>
<%= link_to "Start Meeting", start_room_path(@room.uid) %>
<%= link_to "Start Room", start_room_path(@room) %>
<% end %>
<br><br>
<%= link_to 'Logout', logout_path %>
<%= link_to "Sessions", sessions_path(@room) %>

View File

@ -1,21 +0,0 @@
<div class="center-panel">
<div class="row">
<div class="center-block center-panel-size col-xs-12">
<div class="panel panel-default">
<div class="panel-body">
<% if bigbluebutton_endpoint_default? %>
<div class="panel-alert alert alert-danger"><%= t('warning_bigbluebutton_endpoint_default') %></div>
<% end %>
<h3 class="title-wrapper text-center">
<%= yield :title %>
</h3>
<%= yield %>
</div>
<%= yield :footer %>
<div class="help-link">
<%= link_to t('help'), 'http://bigbluebutton.org/videos/', target: '_blank' %>
</div>
</div>
</div>
</div>
</div>

View File

@ -1,9 +1,9 @@
<div class="header py-4 mb-6">
<div class="container">
<div class="d-flex">
<a class="header-brand" href="{{ site.base }}/index.html">
<%= link_to root_path, class: "header-brand" do %>
<%= image_tag("bbb_logo.png", class: "header-brand-img") %>
</a>
<% end %>
<div class="d-flex order-lg-2 ml-auto">
<% if current_user %>
@ -24,10 +24,22 @@
<small class="text-muted d-block mt-1"><%= current_user.subtitle %></small>
</span>
</a>
<div class="dropdown-menu dropdown-menu-right dropdown-menu-arrow" x-placement="bottom-end" style="position: absolute; transform: translate3d(-56px, 32px, 0px); top: 0px; left: 0px; will-change: transform;">
<a class="dropdown-item" href="#">
<i class="dropdown-icon fe fe-user"></i> Sessions
</a>
<%= link_to settings_path, class: "dropdown-item" do %>
<i class="dropdown-icon fe fe-settings"></i> Settings
<% end %>
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="#">
<i class="dropdown-icon fe fe-help-circle"></i> Need help?
</a>
<%= link_to logout_path, class: "dropdown-item" do %>
<i class="dropdown-icon fe fe-log-out"></i> Sign out
<% end %>
</div>
</div>
<%= link_to logout_path do %>
<i class="fas fa-sign-out-alt fa-2x px-5"></i>
<% end %>
<% else %>
<button type="submit" class="btn btn-pill btn-outline-primary ml-auto" data-toggle="modal" data-target="#loginModal">Login</button>
<%= render "shared/modals/login_modal" %>

View File

@ -1,3 +0,0 @@
<div class="meeting-name-form-wrapper">
<input type="text" class="form-control meeting-name" placeholder="Enter meeting name." maxlength="<%= meeting_name_limit %>">
</div>

View File

@ -1,17 +0,0 @@
<span class="signup">
<% if current_user %>
<div class="text-center">
<% if @main_room %>
<span><%= t('logged_in_description_html', link: link_to(current_user.name, room_path(current_user))) %></span>
<% else %>
<%= link_to(t('return_to_room'), room_path(current_user)) %>
<% end %>
<div><%= link_to t('logout'), logout_url %></div>
</div>
<% else %>
<div class="text-center">
<span><%= t('login_description') %></span>
<div><%= link_to t('login'), login_url %></div>
</div>
<% end %>
</span>

View File

@ -1,7 +0,0 @@
<% title_class ||= '' %>
<div class="title-wrapper text-center">
<div class="title">
<h2 class="<%= title_class if title_class %>"><%= title %></h2>
<%= yield %>
</div>
</div>

View File

@ -0,0 +1,27 @@
<div class="card">
<div class="card-body p-1">
<table class="table table-hover table-outline table-vcenter text-nowrap card-table">
<tbody>
<td>
<span class="colorinput-color bg-azure"></span>
</td>
<td>
<div><%= room.name %></div>
<div class="small text-muted">
<i>Created on <%= room.created_at.strftime("%B #{room.created_at.day.ordinalize}, %Y") %></i>
</div>
</td>
<td class="text-right">
<div class="item-action dropdown">
<a href="javascript:void(0)" data-toggle="dropdown" class="icon"><i class="fe fe-more-vertical"></i></a>
<div class="dropdown-menu dropdown-menu-right">
<a href="javascript:void(0)" class="dropdown-item"><i class="dropdown-icon fe fe-tag"></i> Action </a>
<a href="javascript:void(0)" class="dropdown-item"><i class="dropdown-icon fe fe-edit-2"></i> Another action </a>
<a href="javascript:void(0)" class="dropdown-item"><i class="dropdown-icon fe fe-trash"></i> Delete</a>
</div>
</div>
</td>
</tbody>
</table>
</div>
</div>

View File

@ -0,0 +1,6 @@
<div class="row">
<div class="col-10 offset-1">
<p class="subtitle"><%= subtitle %></p>
<hr>
</div>
</div>

View File

@ -8,28 +8,27 @@
</div>
<hr class="small-rule">
<div class="form-group">
<%= form_for(:room, url: create_room_path) do |f| %>
<div class="input-icon">
<span class="input-icon-addon">
<i class="fas fa-chalkboard-teacher"></i>
</span>
<input type="email" class="form-control" placeholder="Enter a room name...">
<%= f.text_field :name, class: "form-control", placeholder: "Enter a room name...", autocomplete: :off %>
</div>
<label class="custom-switch mt-5 mb-5 float-left">
<input type="checkbox" name="custom-switch-checkbox" class="custom-switch-input">
<%= f.check_box :auto_join, class: "custom-switch-input", checked: true %>
<span class="custom-switch-indicator"></span>
<span class="custom-switch-description">Automatically join me into the room when created.</span>
</label>
</div>
<div class="form-footer">
<button type="submit" class="btn btn-outline-primary btn-block btn-pill">Create Room</button>
<%= f.submit "Create Room", class: "btn btn-outline-primary btn-block btn-pill" %>
</div>
<% end %>
</div>
<div class="card-footer">
<p>You will be free to delete this room at any time.</p>
</div>
</div>
</div>
</div>
</div>

View File

@ -1,11 +1,6 @@
<div class="container">
<div class="row">
<div class="col-10 offset-1">
<p style="font-size: 25px;">Settings</p>
<hr>
</div>
</div>
<%= render "shared/components/subtitle", subtitle: "Settings" %>
<div class="row">
<div class="col-2 offset-1">
@ -108,7 +103,7 @@
settingsButtons = $('.setting-btn');
settingsViews = $('.setting-view');
$(window).on('load', function(){
$(document).ready(function(){
settingsButtons.each(function(i, btn) {
if(i != 0){ $(settingsViews[i]).hide(); }
$(btn).click(function(){
@ -122,4 +117,4 @@ $(window).on('load', function(){
});
});
});
</script>
</script>

View File

@ -1,20 +1,15 @@
Rails.application.routes.draw do
# Room routes.
scope '/r/:room_uid' do
get '/', to: 'rooms#show', as: :room
get '/start', to: 'rooms#start', as: :start_room
get '/join', to: 'rooms#join', as: :join_room
match '/wait', to: 'rooms#wait', as: :wait_room, via: [:get, :post]
get '/logout', to: 'rooms#logout', as: :logout_room
get '/sessions', to: 'rooms#sessions', as: :sessions
end
# Meeting routes.
scope '/m' do
post '/', to: 'meetings#create', as: :create_meeting
get '/:meeting_uid', to: 'meetings#show', as: :meeting
post '/:meeting_uid', to: 'meetings#join', as: :join_meeting
scope '/r' do
post '/', to: 'rooms#create', as: :create_room
scope '/:room_uid' do
match '/', to: 'rooms#show', as: :room, via: [:get, :post]
get '/start', to: 'rooms#start', as: :start_room
match '/wait', to: 'rooms#wait', as: :wait_room, via: [:get, :post]
get '/logout', to: 'rooms#logout', as: :logout_room
get '/sessions', to: 'rooms#sessions', as: :sessions
end
end
# Signup routes.

View File

@ -2,7 +2,9 @@ class CreateRooms < ActiveRecord::Migration[5.0]
def change
create_table :rooms do |t|
t.belongs_to :user, index: true
t.string :name, index: true
t.string :uid, index: true
t.string :bbb_id, index: true
t.timestamps
end

View File

@ -1,11 +0,0 @@
class CreateMeetings < ActiveRecord::Migration[5.0]
def change
create_table :meetings do |t|
t.belongs_to :room, index: true
t.string :name, index: true
t.string :uid, index: true
t.timestamps
end
end
end

View File

@ -10,24 +10,17 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20180504131713) do
create_table "meetings", force: :cascade do |t|
t.integer "room_id"
t.string "name"
t.string "uid"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["name"], name: "index_meetings_on_name"
t.index ["room_id"], name: "index_meetings_on_room_id"
t.index ["uid"], name: "index_meetings_on_uid"
end
ActiveRecord::Schema.define(version: 20180504131705) do
create_table "rooms", force: :cascade do |t|
t.integer "user_id"
t.string "name"
t.string "uid"
t.string "bbb_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["bbb_id"], name: "index_rooms_on_bbb_id"
t.index ["name"], name: "index_rooms_on_name"
t.index ["uid"], name: "index_rooms_on_uid"
t.index ["user_id"], name: "index_rooms_on_user_id"
end