amazon-chime-sdk-rails 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +87 -0
- data/.rspec +2 -0
- data/.travis.yml +47 -0
- data/.yardopts +6 -0
- data/CHANGELOG.md +3 -0
- data/Gemfile +25 -0
- data/LICENSE +21 -0
- data/README.md +1109 -0
- data/Rakefile +20 -0
- data/amazon-chime-sdk-rails.gemspec +29 -0
- data/gemfiles/Gemfile.rails-5.0 +25 -0
- data/gemfiles/Gemfile.rails-5.1 +25 -0
- data/gemfiles/Gemfile.rails-5.2 +25 -0
- data/gemfiles/Gemfile.rails-6.0 +25 -0
- data/lib/amazon-chime-sdk-rails.rb +37 -0
- data/lib/chime_sdk/config.rb +90 -0
- data/lib/chime_sdk/controller/attendees.rb +128 -0
- data/lib/chime_sdk/controller/common.rb +202 -0
- data/lib/chime_sdk/controller/meetings.rb +192 -0
- data/lib/chime_sdk/meeting_coordinator.rb +184 -0
- data/lib/chime_sdk/version.rb +4 -0
- data/lib/generators/chime_sdk/controllers_generator.rb +104 -0
- data/lib/generators/chime_sdk/install_generator.rb +27 -0
- data/lib/generators/chime_sdk/js_generator.rb +67 -0
- data/lib/generators/chime_sdk/views_generator.rb +43 -0
- data/lib/generators/templates/chime_sdk.rb +28 -0
- data/lib/generators/templates/controllers/README +35 -0
- data/lib/generators/templates/controllers/meeting_attendees_controller.rb +106 -0
- data/lib/generators/templates/controllers/meetings_controller.rb +146 -0
- data/lib/generators/templates/views/meetings/index.html.erb +27 -0
- data/lib/generators/templates/views/meetings/show.html.erb +136 -0
- data/spec/factories/rooms.rb +5 -0
- data/spec/factories/users.rb +8 -0
- data/spec/generators/controllers_generator_spec.rb +113 -0
- data/spec/generators/install_generator_spec.rb +24 -0
- data/spec/generators/js_generator_spec.rb +26 -0
- data/spec/generators/views_generator_spec.rb +46 -0
- data/spec/rails_app/Rakefile +15 -0
- data/spec/rails_app/app/assets/config/manifest.js +2 -0
- data/spec/rails_app/app/assets/images/.keep +0 -0
- data/spec/rails_app/app/assets/javascripts/.keep +0 -0
- data/spec/rails_app/app/assets/stylesheets/application.css +15 -0
- data/spec/rails_app/app/assets/stylesheets/scaffolds.scss +65 -0
- data/spec/rails_app/app/controllers/api/meeting_attendees_controller.rb +3 -0
- data/spec/rails_app/app/controllers/api/meetings_controller.rb +3 -0
- data/spec/rails_app/app/controllers/api/rooms_controller.rb +3 -0
- data/spec/rails_app/app/controllers/application_controller.rb +11 -0
- data/spec/rails_app/app/controllers/entries_controller.rb +47 -0
- data/spec/rails_app/app/controllers/meeting_attendees_controller.rb +121 -0
- data/spec/rails_app/app/controllers/meetings_controller.rb +162 -0
- data/spec/rails_app/app/controllers/rooms_controller.rb +76 -0
- data/spec/rails_app/app/controllers/spa_controller.rb +6 -0
- data/spec/rails_app/app/javascript/App.vue +50 -0
- data/spec/rails_app/app/javascript/channels/consumer.js +6 -0
- data/spec/rails_app/app/javascript/channels/index.js +5 -0
- data/spec/rails_app/app/javascript/components/DeviseTokenAuth.vue +84 -0
- data/spec/rails_app/app/javascript/components/meetings/Index.vue +100 -0
- data/spec/rails_app/app/javascript/components/meetings/Meeting.vue +178 -0
- data/spec/rails_app/app/javascript/components/rooms/Index.vue +53 -0
- data/spec/rails_app/app/javascript/components/rooms/Show.vue +91 -0
- data/spec/rails_app/app/javascript/packs/application.js +17 -0
- data/spec/rails_app/app/javascript/packs/spa.js +14 -0
- data/spec/rails_app/app/javascript/router/index.js +74 -0
- data/spec/rails_app/app/javascript/store/index.js +37 -0
- data/spec/rails_app/app/models/application_record.rb +3 -0
- data/spec/rails_app/app/models/entry.rb +5 -0
- data/spec/rails_app/app/models/room.rb +12 -0
- data/spec/rails_app/app/models/user.rb +6 -0
- data/spec/rails_app/app/views/devise/registrations/new.html.erb +34 -0
- data/spec/rails_app/app/views/layouts/_header.html.erb +20 -0
- data/spec/rails_app/app/views/layouts/application.html.erb +18 -0
- data/spec/rails_app/app/views/meetings/index.html.erb +28 -0
- data/spec/rails_app/app/views/meetings/show.html.erb +136 -0
- data/spec/rails_app/app/views/rooms/_form.html.erb +22 -0
- data/spec/rails_app/app/views/rooms/_room.json.jbuilder +7 -0
- data/spec/rails_app/app/views/rooms/edit.html.erb +6 -0
- data/spec/rails_app/app/views/rooms/index.html.erb +27 -0
- data/spec/rails_app/app/views/rooms/index.json.jbuilder +1 -0
- data/spec/rails_app/app/views/rooms/new.html.erb +5 -0
- data/spec/rails_app/app/views/rooms/show.html.erb +42 -0
- data/spec/rails_app/app/views/rooms/show.json.jbuilder +1 -0
- data/spec/rails_app/app/views/spa/index.html.erb +1 -0
- data/spec/rails_app/babel.config.js +72 -0
- data/spec/rails_app/bin/bundle +114 -0
- data/spec/rails_app/bin/rails +9 -0
- data/spec/rails_app/bin/rake +9 -0
- data/spec/rails_app/bin/setup +36 -0
- data/spec/rails_app/bin/spring +17 -0
- data/spec/rails_app/bin/webpack +18 -0
- data/spec/rails_app/bin/webpack-dev-server +18 -0
- data/spec/rails_app/bin/yarn +11 -0
- data/spec/rails_app/config.ru +5 -0
- data/spec/rails_app/config/application.rb +21 -0
- data/spec/rails_app/config/boot.rb +4 -0
- data/spec/rails_app/config/cable.yml +10 -0
- data/spec/rails_app/config/credentials.yml.enc +1 -0
- data/spec/rails_app/config/database.yml +25 -0
- data/spec/rails_app/config/environment.rb +14 -0
- data/spec/rails_app/config/environments/development.rb +62 -0
- data/spec/rails_app/config/environments/production.rb +112 -0
- data/spec/rails_app/config/environments/test.rb +49 -0
- data/spec/rails_app/config/initializers/application_controller_renderer.rb +8 -0
- data/spec/rails_app/config/initializers/assets.rb +15 -0
- data/spec/rails_app/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/rails_app/config/initializers/chime_sdk.rb +28 -0
- data/spec/rails_app/config/initializers/content_security_policy.rb +30 -0
- data/spec/rails_app/config/initializers/cookies_serializer.rb +5 -0
- data/spec/rails_app/config/initializers/devise.rb +311 -0
- data/spec/rails_app/config/initializers/devise_token_auth.rb +60 -0
- data/spec/rails_app/config/initializers/filter_parameter_logging.rb +4 -0
- data/spec/rails_app/config/initializers/inflections.rb +16 -0
- data/spec/rails_app/config/initializers/mime_types.rb +4 -0
- data/spec/rails_app/config/initializers/wrap_parameters.rb +14 -0
- data/spec/rails_app/config/locales/devise.en.yml +65 -0
- data/spec/rails_app/config/locales/en.yml +33 -0
- data/spec/rails_app/config/puma.rb +38 -0
- data/spec/rails_app/config/routes.rb +24 -0
- data/spec/rails_app/config/secrets.yml +8 -0
- data/spec/rails_app/config/spring.rb +6 -0
- data/spec/rails_app/config/storage.yml +34 -0
- data/spec/rails_app/config/webpack/development.js +5 -0
- data/spec/rails_app/config/webpack/environment.js +7 -0
- data/spec/rails_app/config/webpack/loaders/vue.js +6 -0
- data/spec/rails_app/config/webpack/production.js +5 -0
- data/spec/rails_app/config/webpack/test.js +5 -0
- data/spec/rails_app/config/webpacker.yml +97 -0
- data/spec/rails_app/db/migrate/20200912140231_devise_create_users.rb +45 -0
- data/spec/rails_app/db/migrate/20200912140352_add_tokens_to_users.rb +12 -0
- data/spec/rails_app/db/migrate/20200912140657_create_rooms.rb +9 -0
- data/spec/rails_app/db/migrate/20200912140749_create_entries.rb +10 -0
- data/spec/rails_app/db/schema.rb +49 -0
- data/spec/rails_app/db/seeds.rb +41 -0
- data/spec/rails_app/log/.keep +0 -0
- data/spec/rails_app/package.json +23 -0
- data/spec/rails_app/postcss.config.js +12 -0
- data/spec/rails_app/public/404.html +67 -0
- data/spec/rails_app/public/422.html +67 -0
- data/spec/rails_app/public/500.html +66 -0
- data/spec/rails_app/public/favicon.ico +0 -0
- data/spec/rails_app/public/robots.txt +1 -0
- data/spec/rails_app/tmp/.keep +0 -0
- data/spec/requests/atendees_spec.rb +182 -0
- data/spec/requests/meetings_spec.rb +433 -0
- data/spec/spec_helper.rb +35 -0
- metadata +400 -0
@@ -0,0 +1,17 @@
|
|
1
|
+
// This file is automatically compiled by Webpack, along with any other files
|
2
|
+
// present in this directory. You're encouraged to place your actual application logic in
|
3
|
+
// a relevant structure within app/javascript and only use these pack files to reference
|
4
|
+
// that code so it'll be compiled.
|
5
|
+
|
6
|
+
require("@rails/ujs").start()
|
7
|
+
require("turbolinks").start()
|
8
|
+
require("@rails/activestorage").start()
|
9
|
+
require("channels")
|
10
|
+
|
11
|
+
|
12
|
+
// Uncomment to copy all static images under ../images to the output folder and reference
|
13
|
+
// them with the image_pack_tag helper in views (e.g <%= image_pack_tag 'rails.png' %>)
|
14
|
+
// or the `imagePath` JavaScript helper below.
|
15
|
+
//
|
16
|
+
// const images = require.context('../images', true)
|
17
|
+
// const imagePath = (name) => images(name, true)
|
@@ -0,0 +1,14 @@
|
|
1
|
+
import Vue from 'vue'
|
2
|
+
import App from '../App.vue'
|
3
|
+
import router from '../router'
|
4
|
+
import store from '../store'
|
5
|
+
|
6
|
+
Vue.config.productionTip = false
|
7
|
+
|
8
|
+
document.addEventListener('DOMContentLoaded', () => {
|
9
|
+
new Vue({
|
10
|
+
router,
|
11
|
+
store,
|
12
|
+
render: h => h(App)
|
13
|
+
}).$mount('#app')
|
14
|
+
})
|
@@ -0,0 +1,74 @@
|
|
1
|
+
import Vue from 'vue'
|
2
|
+
import VueRouter from 'vue-router'
|
3
|
+
import store from '../store'
|
4
|
+
import DeviseTokenAuth from '../components/DeviseTokenAuth.vue'
|
5
|
+
import Rooms from '../components/rooms/Index.vue'
|
6
|
+
import Room from '../components/rooms/Show.vue'
|
7
|
+
import Meetings from '../components/meetings/Index.vue'
|
8
|
+
import Meeting from '../components/meetings/Meeting.vue'
|
9
|
+
|
10
|
+
Vue.use(VueRouter)
|
11
|
+
|
12
|
+
const routes = [
|
13
|
+
// Routes for common components
|
14
|
+
{
|
15
|
+
path: '/',
|
16
|
+
name: 'Root',
|
17
|
+
component: Rooms
|
18
|
+
},
|
19
|
+
{
|
20
|
+
path: '/users/sign_in',
|
21
|
+
name: 'SignIn',
|
22
|
+
component: DeviseTokenAuth
|
23
|
+
},
|
24
|
+
{
|
25
|
+
path: '/users/sign_out',
|
26
|
+
name: 'SignOut',
|
27
|
+
component: DeviseTokenAuth,
|
28
|
+
props: { isLogout: true }
|
29
|
+
},
|
30
|
+
|
31
|
+
// Routes for Rooms
|
32
|
+
{
|
33
|
+
path: '/rooms',
|
34
|
+
name: 'Rooms',
|
35
|
+
component: Rooms
|
36
|
+
},
|
37
|
+
{
|
38
|
+
path: '/rooms/:room_id',
|
39
|
+
name: 'Room',
|
40
|
+
component: Room,
|
41
|
+
props: true,
|
42
|
+
meta: { requiresAuth: true }
|
43
|
+
},
|
44
|
+
|
45
|
+
// Routes for Meetings
|
46
|
+
{
|
47
|
+
path: '/rooms/:room_id/meetings',
|
48
|
+
name: 'Meetings',
|
49
|
+
component: Meetings,
|
50
|
+
props: true,
|
51
|
+
meta: { requiresAuth: true }
|
52
|
+
},
|
53
|
+
{
|
54
|
+
path: '/rooms/:room_id/meetings/:meeting_id',
|
55
|
+
name: 'Meeting',
|
56
|
+
component: Meeting,
|
57
|
+
props: true,
|
58
|
+
meta: { requiresAuth: true }
|
59
|
+
}
|
60
|
+
]
|
61
|
+
|
62
|
+
const router = new VueRouter({
|
63
|
+
routes
|
64
|
+
})
|
65
|
+
|
66
|
+
router.beforeEach((to, from, next) => {
|
67
|
+
if (to.matched.some(record => record.meta.requiresAuth) && !store.getters.userSignedIn) {
|
68
|
+
next({ name: 'SignIn', query: { redirect: to.fullPath }});
|
69
|
+
} else {
|
70
|
+
next();
|
71
|
+
}
|
72
|
+
})
|
73
|
+
|
74
|
+
export default router
|
@@ -0,0 +1,37 @@
|
|
1
|
+
import Vue from 'vue'
|
2
|
+
import Vuex from 'vuex'
|
3
|
+
import createPersistedState from "vuex-persistedstate"
|
4
|
+
|
5
|
+
Vue.use(Vuex)
|
6
|
+
|
7
|
+
export default new Vuex.Store({
|
8
|
+
state: {
|
9
|
+
signedInStatus: false,
|
10
|
+
currentUser: null,
|
11
|
+
authHeaders: {}
|
12
|
+
},
|
13
|
+
mutations: {
|
14
|
+
signIn(state, { user, authHeaders }) {
|
15
|
+
state.currentUser = user;
|
16
|
+
state.authHeaders = authHeaders;
|
17
|
+
state.signedInStatus = true;
|
18
|
+
},
|
19
|
+
signOut(state) {
|
20
|
+
state.signedInStatus = false;
|
21
|
+
state.currentUser = null;
|
22
|
+
state.authHeaders = {};
|
23
|
+
}
|
24
|
+
},
|
25
|
+
getters: {
|
26
|
+
userSignedIn(state) {
|
27
|
+
return state.signedInStatus;
|
28
|
+
},
|
29
|
+
currentUser(state) {
|
30
|
+
return state.currentUser;
|
31
|
+
},
|
32
|
+
authHeaders(state) {
|
33
|
+
return state.authHeaders;
|
34
|
+
}
|
35
|
+
},
|
36
|
+
plugins: [createPersistedState({storage: window.sessionStorage})]
|
37
|
+
});
|
@@ -0,0 +1,34 @@
|
|
1
|
+
<h2>Sign up</h2>
|
2
|
+
|
3
|
+
<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
|
4
|
+
<%= render "devise/shared/error_messages", resource: resource %>
|
5
|
+
|
6
|
+
<div class="field">
|
7
|
+
<%= f.label :name %><br />
|
8
|
+
<%= f.text_field :name, autocomplete: "name" %>
|
9
|
+
</div>
|
10
|
+
|
11
|
+
<div class="field">
|
12
|
+
<%= f.label :email %><br />
|
13
|
+
<%= f.email_field :email, autofocus: true, autocomplete: "email" %>
|
14
|
+
</div>
|
15
|
+
|
16
|
+
<div class="field">
|
17
|
+
<%= f.label :password %>
|
18
|
+
<% if @minimum_password_length %>
|
19
|
+
<em>(<%= @minimum_password_length %> characters minimum)</em>
|
20
|
+
<% end %><br />
|
21
|
+
<%= f.password_field :password, autocomplete: "new-password" %>
|
22
|
+
</div>
|
23
|
+
|
24
|
+
<div class="field">
|
25
|
+
<%= f.label :password_confirmation %><br />
|
26
|
+
<%= f.password_field :password_confirmation, autocomplete: "new-password" %>
|
27
|
+
</div>
|
28
|
+
|
29
|
+
<div class="actions">
|
30
|
+
<%= f.submit "Sign up" %>
|
31
|
+
</div>
|
32
|
+
<% end %>
|
33
|
+
|
34
|
+
<%= render "devise/shared/links" %>
|
@@ -0,0 +1,20 @@
|
|
1
|
+
<header>
|
2
|
+
<div>
|
3
|
+
<div>
|
4
|
+
<%= link_to 'SPA with Rails API', "/spa/" %>
|
5
|
+
<strong><%= link_to 'Rails App with Action View', root_path %></strong>
|
6
|
+
</div>
|
7
|
+
<div>
|
8
|
+
<strong>Rails Application for Amazon Chime SDK Meeting (Rails App with Action View)</strong>
|
9
|
+
</div>
|
10
|
+
<div>
|
11
|
+
<% if user_signed_in? %>
|
12
|
+
<%= current_user.name %>
|
13
|
+
<%= link_to 'Logout', destroy_user_session_path, method: :delete %>
|
14
|
+
<% else %>
|
15
|
+
<%= link_to "Sign up", new_user_registration_path %>
|
16
|
+
<%= link_to 'Login', new_user_session_path %>
|
17
|
+
<% end %>
|
18
|
+
</div>
|
19
|
+
</div>
|
20
|
+
</header>
|
@@ -0,0 +1,18 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<title>Rails Application for Amazon Chime SDK Meeting</title>
|
5
|
+
<%= csrf_meta_tags %>
|
6
|
+
|
7
|
+
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
|
8
|
+
<%= yield(:javascript_pack_tag) %>
|
9
|
+
<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
|
10
|
+
</head>
|
11
|
+
|
12
|
+
<body>
|
13
|
+
<div id="app">
|
14
|
+
<%= render 'layouts/header' %>
|
15
|
+
<%= yield %>
|
16
|
+
<div>
|
17
|
+
</body>
|
18
|
+
</html>
|
@@ -0,0 +1,28 @@
|
|
1
|
+
<p id="notice"><%= notice %></p>
|
2
|
+
|
3
|
+
<h1>Meetings by Amazon Chime SDK</h1>
|
4
|
+
|
5
|
+
<table>
|
6
|
+
<thead>
|
7
|
+
<tr>
|
8
|
+
<th>Meeting ID</th>
|
9
|
+
<th>External Meeting ID</th>
|
10
|
+
<th>Media Region</th>
|
11
|
+
<th colspan="1"></th>
|
12
|
+
</tr>
|
13
|
+
</thead>
|
14
|
+
|
15
|
+
<tbody>
|
16
|
+
<% @meetings.each do |meeting| %>
|
17
|
+
<tr>
|
18
|
+
<td><%= link_to(meeting[:Meeting][:MeetingId], meeting_resource_path(meeting[:Meeting][:MeetingId])) %></td>
|
19
|
+
<td><%= meeting[:Meeting][:ExternalMeetingId] %></td>
|
20
|
+
<td><%= meeting[:Meeting][:MediaRegion] %></td>
|
21
|
+
<td><%= link_to 'Destroy', meeting_resource_path(meeting[:Meeting][:MeetingId]), method: :delete, data: { confirm: 'Are you sure?' } %></td>
|
22
|
+
</tr>
|
23
|
+
<% end %>
|
24
|
+
</tbody>
|
25
|
+
</table>
|
26
|
+
|
27
|
+
<p><%= link_to 'Create Meeting', meeting_resources_path, method: :post %></p>
|
28
|
+
<p><%= link_to("Back to Room", room_path(@room)) %></p>
|
@@ -0,0 +1,136 @@
|
|
1
|
+
<p id="notice"><%= notice %></p>
|
2
|
+
|
3
|
+
<h1>Meeting by Amazon Chime SDK</h1>
|
4
|
+
|
5
|
+
<p><%= link_to("Show Meetings", meeting_resources_path) %></p>
|
6
|
+
|
7
|
+
<% if @meeting %>
|
8
|
+
<strong>Meeting</strong>
|
9
|
+
<p>
|
10
|
+
Meeting ID : <%= link_to(@meeting[:Meeting][:MeetingId], meeting_resource_path(@meeting[:Meeting][:MeetingId])) %><br>
|
11
|
+
External Meeting ID : <%= @meeting[:Meeting][:ExternalMeetingId] %><br>
|
12
|
+
Media Region : <%= @meeting[:Meeting][:MediaRegion] %>
|
13
|
+
</p>
|
14
|
+
|
15
|
+
<div id="meeting" meeting-data="<%= @meeting.to_json %>"></div>
|
16
|
+
<% end %>
|
17
|
+
|
18
|
+
<% if @attendee %>
|
19
|
+
<strong>Attendee</strong>
|
20
|
+
<p>
|
21
|
+
Attendee ID : <%= link_to(@attendee[:Attendee][:AttendeeId], attendee_resource_path(@meeting[:Meeting][:MeetingId], @attendee[:Attendee][:AttendeeId])) %><br>
|
22
|
+
External User ID : <%= @attendee[:Attendee][:ExternalUserId] %><br>
|
23
|
+
Application Attendee Name : <%= application_attendee_name(@attendee) %>
|
24
|
+
</p>
|
25
|
+
|
26
|
+
<div id="status">
|
27
|
+
<strong>Status</strong>
|
28
|
+
<div id="meeting-status">
|
29
|
+
<p>Meeting : Offline <input type="button" value="Join a meeting" onclick="join()"></p>
|
30
|
+
</div>
|
31
|
+
<div id="attendee-status"></div>
|
32
|
+
</div>
|
33
|
+
|
34
|
+
<audio id="audio"></audio>
|
35
|
+
|
36
|
+
<div id="attendee" attendee-data="<%= @attendee.to_json %>"></div>
|
37
|
+
<div id="attendee-resources-path" attendee-resources-path-data="<%= attendee_resources_path(@meeting[:Meeting][:MeetingId]) %>"></div>
|
38
|
+
<% end %>
|
39
|
+
|
40
|
+
<%= javascript_include_tag "amazon-chime-sdk.min.js" %>
|
41
|
+
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
|
42
|
+
|
43
|
+
<script defer>
|
44
|
+
// This is a very simple script as a template view using Amazon Chime SDK.
|
45
|
+
// This script only provides simple audio meeting function.
|
46
|
+
// See the following guide to develop your own video meeting application.
|
47
|
+
// https://github.com/aws/amazon-chime-sdk-js
|
48
|
+
// https://aws.github.io/amazon-chime-sdk-js/modules/gettingstarted.html
|
49
|
+
|
50
|
+
// Customize this function to extract attendee name to show
|
51
|
+
function showApplicationUserName(attendee) {
|
52
|
+
// return attendee.Attendee.AttendeeId;
|
53
|
+
return `${attendee.Attendee.ApplicationMetadata.User.name} (${attendee.Attendee.AttendeeId})`;
|
54
|
+
}
|
55
|
+
|
56
|
+
const meeting = JSON.parse(document.getElementById('meeting').getAttribute('meeting-data'));
|
57
|
+
const attendee = JSON.parse(document.getElementById('attendee').getAttribute('attendee-data'));
|
58
|
+
const attendeeResourcesPath = document.getElementById('attendee-resources-path').getAttribute('attendee-resources-path-data');
|
59
|
+
const audioOutputElement = document.getElementById('audio');
|
60
|
+
|
61
|
+
const logger = new ChimeSDK.ConsoleLogger('ChimeMeetingLogs', ChimeSDK.LogLevel.INFO);
|
62
|
+
const deviceController = new ChimeSDK.DefaultDeviceController(logger);
|
63
|
+
const configuration = new ChimeSDK.MeetingSessionConfiguration(meeting, attendee);
|
64
|
+
const meetingSession = new ChimeSDK.DefaultMeetingSession(configuration, logger, deviceController);
|
65
|
+
|
66
|
+
const attendeeApi = axios.create({
|
67
|
+
baseURL: `${attendeeResourcesPath}/`
|
68
|
+
});
|
69
|
+
|
70
|
+
async function join() {
|
71
|
+
try {
|
72
|
+
const audioInputDevices = await meetingSession.audioVideo.listAudioInputDevices();
|
73
|
+
const audioOutputDevices = await meetingSession.audioVideo.listAudioOutputDevices();
|
74
|
+
await meetingSession.audioVideo.chooseAudioInputDevice(audioInputDevices[0].deviceId);
|
75
|
+
await meetingSession.audioVideo.chooseAudioOutputDevice(audioOutputDevices[0].deviceId);
|
76
|
+
} catch (error) {
|
77
|
+
// handle error - unable to acquire audio device perhaps due to permissions blocking
|
78
|
+
console.log(error);
|
79
|
+
}
|
80
|
+
meetingSession.audioVideo.bindAudioElement(audioOutputElement);
|
81
|
+
meetingSession.audioVideo.start();
|
82
|
+
document.getElementById("meeting-status").innerHTML = '<p>Meeting : Online <input type="button" value="Leave a meeting" onclick="leave()"></p><div id="audio-status"></div>';
|
83
|
+
document.getElementById("audio-status").innerHTML = '<p>Audio : Active <input type="button" value="Mute" onclick="mute()"></p>';
|
84
|
+
document.getElementById("attendee-status").innerHTML = '<strong>Present Attendees</strong>';
|
85
|
+
parepareAttendeeStatus();
|
86
|
+
}
|
87
|
+
|
88
|
+
function leave() {
|
89
|
+
meetingSession.audioVideo.stop();
|
90
|
+
document.getElementById("meeting-status").innerHTML = '<p>Meeting : Offline <input type="button" value="Join a meeting" onclick="join()">';
|
91
|
+
document.getElementById("attendee-status").innerHTML = '';
|
92
|
+
}
|
93
|
+
|
94
|
+
function mute() {
|
95
|
+
meetingSession.audioVideo.realtimeMuteLocalAudio();
|
96
|
+
document.getElementById("audio-status").innerHTML = '<p>Audio : Muted <input type="button" value="Unmute" onclick="unmute()"></p>';
|
97
|
+
}
|
98
|
+
|
99
|
+
function unmute() {
|
100
|
+
const unmuted = meetingSession.audioVideo.realtimeUnmuteLocalAudio();
|
101
|
+
if (unmuted) {
|
102
|
+
document.getElementById("audio-status").innerHTML = '<p>Audio : Active <input type="button" value="Mute" onclick="mute()"></p>';
|
103
|
+
} else {
|
104
|
+
console.log('You cannot unmute yourself');
|
105
|
+
}
|
106
|
+
}
|
107
|
+
|
108
|
+
function parepareAttendeeStatus() {
|
109
|
+
const presentAttendeeMap = {};
|
110
|
+
const callback = (presentAttendeeId, present) => {
|
111
|
+
if (present) {
|
112
|
+
attendeeApi.get(presentAttendeeId)
|
113
|
+
.then(response => {
|
114
|
+
presentAttendeeMap[presentAttendeeId] = response.data;
|
115
|
+
updateAttendeeStatus(presentAttendeeMap);
|
116
|
+
})
|
117
|
+
.catch(error => {
|
118
|
+
console.log(error);
|
119
|
+
});
|
120
|
+
} else {
|
121
|
+
delete presentAttendeeMap[presentAttendeeId]
|
122
|
+
updateAttendeeStatus(presentAttendeeMap);
|
123
|
+
}
|
124
|
+
};
|
125
|
+
meetingSession.audioVideo.realtimeSubscribeToAttendeeIdPresence(callback);
|
126
|
+
}
|
127
|
+
|
128
|
+
function updateAttendeeStatus(presentAttendeeMap) {
|
129
|
+
presentAttendees = "<strong>Present Attendees</strong><ul>";
|
130
|
+
Object.values(presentAttendeeMap).forEach(attendee => {
|
131
|
+
presentAttendees = presentAttendees + `<li>${showApplicationUserName(attendee)}</li>`
|
132
|
+
});
|
133
|
+
presentAttendees = presentAttendees + '</ul>'
|
134
|
+
document.getElementById("attendee-status").innerHTML = presentAttendees;
|
135
|
+
}
|
136
|
+
</script>
|
@@ -0,0 +1,22 @@
|
|
1
|
+
<%= form_with(model: room, local: true) do |form| %>
|
2
|
+
<% if room.errors.any? %>
|
3
|
+
<div id="error_explanation">
|
4
|
+
<h2><%= pluralize(room.errors.count, "error") %> prohibited this room from being saved:</h2>
|
5
|
+
|
6
|
+
<ul>
|
7
|
+
<% room.errors.full_messages.each do |message| %>
|
8
|
+
<li><%= message %></li>
|
9
|
+
<% end %>
|
10
|
+
</ul>
|
11
|
+
</div>
|
12
|
+
<% end %>
|
13
|
+
|
14
|
+
<div class="field">
|
15
|
+
<%= form.label :name %>
|
16
|
+
<%= form.text_field :name %>
|
17
|
+
</div>
|
18
|
+
|
19
|
+
<div class="actions">
|
20
|
+
<%= form.submit %>
|
21
|
+
</div>
|
22
|
+
<% end %>
|