Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • c3lingo/rescheduled
1 result
Show changes
Showing
with 269 additions and 62 deletions
<div>
<h1 class="text-xl my-4 dark:text-red-500">Conferences</h1>
<ul>
<% @conferences.each do |conference| %>
<li><%= link_to conference.name, conference_path(conference.slug), class: "inline-block px-4 py-2 text-slate-500 hover:text-slate-900 dark:hover:text-slate-200 hover:bg-slate-100 dark:hover:bg-gray-600 rounded-md" %></li>
<% end %>
</ul>
<div class="container mx-auto px-4 py-8">
<div class="flex justify-between items-center mb-6">
<h1 class="text-2xl font-bold dark:text-gray-200">Conferences</h1>
<% if user_signed_in? && current_user.has_role?("events_admin") %>
<%= link_to new_conference_path, class: "inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-md shadow-sm text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 dark:bg-blue-700 dark:hover:bg-blue-800" do %>
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 mr-2" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd" d="M10 3a1 1 0 011 1v5h5a1 1 0 110 2h-5v5a1 1 0 11-2 0v-5H4a1 1 0 110-2h5V4a1 1 0 011-1z" clip-rule="evenodd" />
</svg>
New Conference
<% end %>
<% end %>
</div>
<div class="bg-white dark:bg-gray-800 shadow overflow-hidden sm:rounded-md">
<ul class="divide-y divide-gray-200 dark:divide-gray-700">
<% if @conferences.empty? %>
<li class="px-6 py-4 text-center text-gray-500 dark:text-gray-400">No conferences available.</li>
<% else %>
<% @conferences.each do |conference| %>
<li>
<div class="px-4 py-4 flex items-center justify-between">
<div class="min-w-0 flex-1">
<div class="flex items-center">
<p class="text-lg font-medium text-blue-600 dark:text-blue-400">
<%= link_to conference.name, conference_path(slug: conference.slug) %>
</p>
</div>
<div class="mt-2 flex items-center text-sm text-gray-500 dark:text-gray-400">
<% if conference.starts_at && conference.ends_at %>
<span>
<%= conference.starts_at.strftime("%b %d, %Y") %> - <%= conference.ends_at.strftime("%b %d, %Y") %>
</span>
<% end %>
</div>
</div>
<% if user_signed_in? && current_user.has_role?("events_admin") %>
<div class="flex-shrink-0 flex">
<%= link_to edit_conference_path(slug: conference.slug), class: "ml-2 text-gray-400 hover:text-gray-500 dark:hover:text-gray-300" do %>
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
<path d="M13.586 3.586a2 2 0 112.828 2.828l-.793.793-2.828-2.828.793-.793zM11.379 5.793L3 14.172V17h2.828l8.38-8.379-2.83-2.828z" />
</svg>
<% end %>
</div>
<% end %>
</div>
</li>
<% end %>
<% end %>
</ul>
</div>
</div>
<div class="container mx-auto px-4 py-8">
<h1 class="text-2xl font-bold mb-6 dark:text-gray-200">New Conference</h1>
<%= form_with(model: @conference, url: conferences_path, class: "space-y-6") do |form| %>
<% if @conference.errors.any? %>
<div class="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded mb-4">
<h2 class="font-bold"><%= pluralize(@conference.errors.count, "error") %> prohibited this conference from being saved:</h2>
<ul class="list-disc list-inside mt-2">
<% @conference.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="space-y-4">
<div>
<%= form.label :name, class: "block text-sm font-medium text-gray-700 dark:text-gray-300" %>
<%= form.text_field :name, class: "mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white" %>
</div>
<div>
<%= form.label :slug, class: "block text-sm font-medium text-gray-700 dark:text-gray-300" %>
<%= form.text_field :slug, class: "mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white" %>
<p class="mt-1 text-xs text-gray-500 dark:text-gray-400">Used in URLs. Should contain only lowercase letters, numbers, and hyphens.</p>
</div>
<div>
<%= form.label :url, class: "block text-sm font-medium text-gray-700 dark:text-gray-300" %>
<%= form.url_field :url, class: "mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white" %>
</div>
<div>
<%= form.label :time_zone, class: "block text-sm font-medium text-gray-700 dark:text-gray-300" %>
<%= form.time_zone_select :time_zone, nil, { include_blank: "Select Time Zone" }, { class: "mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white" } %>
</div>
<div class="grid grid-cols-1 gap-4 md:grid-cols-2">
<div>
<%= form.label :starts_at, class: "block text-sm font-medium text-gray-700 dark:text-gray-300" %>
<%= form.datetime_local_field :starts_at, class: "mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white" %>
</div>
<div>
<%= form.label :ends_at, class: "block text-sm font-medium text-gray-700 dark:text-gray-300" %>
<%= form.datetime_local_field :ends_at, class: "mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white" %>
</div>
</div>
<div data-controller="dynamic-fields">
<div>
<%= form.label :import_job_class, class: "block text-sm font-medium text-gray-700 dark:text-gray-300" %>
<%= form.select :import_job_class,
[["Select Import Job Class", ""]] +
ConferencesController.available_import_job_classes.map { |class_name, display_name| [display_name, class_name] },
{},
{ class: "mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white",
data: { dynamic_fields_target: "importJobClass", action: "change->dynamic-fields#updateRequiredFields" } } %>
<p class="mt-1 text-xs text-gray-500 dark:text-gray-400">Select the import job class to see required data fields</p>
</div>
<fieldset class="mt-6 border border-gray-300 rounded-md p-4 dark:border-gray-600">
<legend class="px-2 text-sm font-medium text-gray-700 dark:text-gray-300">Required Data Fields</legend>
<div class="space-y-4" data-dynamic-fields-target="requiredFields">
<!-- Required fields will be dynamically added here -->
<p class="text-sm text-gray-500 dark:text-gray-400">Select an import job class to see required fields</p>
</div>
</fieldset>
<fieldset class="mt-6 border border-gray-300 rounded-md p-4 dark:border-gray-600" data-controller="dynamic-fields">
<legend class="px-2 text-sm font-medium text-gray-700 dark:text-gray-300">Custom Data Fields</legend>
<div class="space-y-4" data-dynamic-fields-target="container">
<!-- Dynamic fields will be added here -->
</div>
<template data-dynamic-fields-target="template">
<div class="flex items-center space-x-2 nested-field">
<div class="flex-1">
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300">Key</label>
<input type="text" name="data[custom_key_NEW_RECORD]" placeholder="Enter key" class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white" data-field-key>
</div>
<div class="flex-1">
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300">Value</label>
<input type="text" name="data[custom_value_NEW_RECORD]" placeholder="Enter value" class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white">
</div>
<div class="flex items-end">
<button type="button" data-action="click->dynamic-fields#removeField" class="mt-1 p-2 text-red-600 hover:text-red-800 dark:text-red-400 dark:hover:text-red-300">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd" d="M9 2a1 1 0 00-.894.553L7.382 4H4a1 1 0 000 2v10a2 2 0 002 2h8a2 2 0 002-2V6a1 1 0 100-2h-3.382l-.724-1.447A1 1 0 0011 2H9zM7 8a1 1 0 012 0v6a1 1 0 11-2 0V8zm5-1a1 1 0 00-1 1v6a1 1 0 102 0V8a1 1 0 00-1-1z" clip-rule="evenodd" />
</svg>
</button>
</div>
</div>
</template>
<div class="mt-4">
<button type="button" data-action="click->dynamic-fields#addField" class="inline-flex items-center px-3 py-2 border border-transparent text-sm leading-4 font-medium rounded-md text-indigo-700 bg-indigo-100 hover:bg-indigo-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 dark:bg-indigo-900 dark:text-indigo-200 dark:hover:bg-indigo-800">
<svg xmlns="http://www.w3.org/2000/svg" class="-ml-0.5 mr-2 h-4 w-4" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd" d="M10 3a1 1 0 011 1v5h5a1 1 0 110 2h-5v5a1 1 0 11-2 0v-5H4a1 1 0 110-2h5V4a1 1 0 011-1z" clip-rule="evenodd" />
</svg>
Add Custom Field
</button>
</div>
</fieldset>
</div>
<div class="flex justify-between pt-6">
<%= link_to "Cancel", conferences_path, class: "px-4 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-md shadow-sm hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 dark:bg-gray-700 dark:text-gray-200 dark:border-gray-600 dark:hover:bg-gray-600" %>
<%= form.submit "Create Conference", class: "inline-flex justify-center px-4 py-2 text-sm font-medium text-white bg-blue-600 border border-transparent rounded-md shadow-sm hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 dark:bg-blue-700 dark:hover:bg-blue-800" %>
</div>
<% end %>
</div>
......@@ -13,8 +13,8 @@ current_time = Time.zone.now.in_time_zone(@conference.time_zone)
<%= render partial: 'assignments/filteredlist_option', locals: { user: } %>
<% end %>
</template>
<div>
<div>
<div class="container mx-auto px-4 py-8">
<div class="mb-4">
<a href="#now" onclick="document.querySelector('#now')?.scrollIntoView({ behavior: 'smooth', block: 'center', inline: 'nearest' }); return false" class="underline text-blue-500">Jump to current time</a>
</div>
<h1 class="text-2xl font-bold my-2 dark:text-red-500"><%= @conference.name %></h1>
......
......@@ -14,7 +14,7 @@ module ReScheduled
# Please, add to the `ignore` list any other `lib` subdirectories that do
# not contain `.rb` files, or that should not be reloaded or eager loaded.
# Common ones are `templates`, `generators`, or `middleware`, for example.
config.autoload_lib(ignore: %w(assets tasks))
config.autoload_lib(ignore: %w[assets tasks])
# Configuration for the application, engines, and railties goes here.
#
......
......@@ -14,6 +14,6 @@
# Crono.perform(TestJob).every 2.days, at: '15:30'
#
Crono.perform(FetchConferenceDataJob, '38c3').every 5.minutes
Crono.perform(FetchConferenceDataJob, '38c3-more').every 5.minutes
#Crono.perform(TelegramNotifyUpcomingJob, { offset: 15.minutes.to_i, interval: 1.minute.to_i }).every 1.minute
Crono.perform(FetchConferenceDataJob, "38c3").every 5.minutes
Crono.perform(FetchConferenceDataJob, "38c3-more").every 5.minutes
# Crono.perform(TelegramNotifyUpcomingJob, { offset: 15.minutes.to_i, interval: 1.minute.to_i }).every 1.minute
......@@ -77,5 +77,5 @@ Rails.application.configure do
config.telegram_default_target = ENV["TELEGRAM_DEFAULT_TARGET"] || "2192297"
end
Rails.application.routes.default_url_options[:host] = '127.0.0.1'
Rails.application.routes.default_url_options[:protocol] = 'http'
Rails.application.routes.default_url_options[:host] = "127.0.0.1"
Rails.application.routes.default_url_options[:protocol] = "http"
......@@ -25,8 +25,8 @@ Rails.application.configure do
# Set cache headers for static files
config.public_file_server.headers = {
'Cache-Control' => 'public, max-age=31536000',
'Expires' => 1.year.from_now.to_formatted_s(:rfc822)
"Cache-Control" => "public, max-age=31536000",
"Expires" => 1.year.from_now.to_formatted_s(:rfc822)
}
# Compress CSS using a preprocessor.
......@@ -105,5 +105,5 @@ Rails.application.configure do
end
# Rails.application.routes.default_url_options.merge({ host: 'rescheduled.c3lingo.org', protocol: 'https' })
Rails.application.routes.default_url_options[:host] = 'rescheduled.c3lingo.org'
Rails.application.routes.default_url_options[:protocol] = 'https'
Rails.application.routes.default_url_options[:host] = "rescheduled.c3lingo.org"
Rails.application.routes.default_url_options[:protocol] = "https"
......@@ -24,7 +24,7 @@ Devise.setup do |config|
# Configure the e-mail address which will be shown in Devise::Mailer,
# note that it will be overwritten if you use your own mailer class
# with default "from" parameter.
config.mailer_sender = 'please-change-me-at-config-initializers-devise@example.com'
config.mailer_sender = "please-change-me-at-config-initializers-devise@example.com"
# Configure the class responsible to send e-mails.
# config.mailer = 'Devise::Mailer'
......@@ -36,7 +36,7 @@ Devise.setup do |config|
# Load and configure the ORM. Supports :active_record (default) and
# :mongoid (bson_ext recommended) by default. Other ORMs may be
# available as additional gems.
require 'devise/orm/active_record'
require "devise/orm/active_record"
# ==> Configuration for any authentication mechanism
# Configure which keys are used when authenticating a user. The default is
......@@ -46,7 +46,7 @@ Devise.setup do |config|
# session. If you need permissions, you should implement that in a before filter.
# You can also supply a hash where the value is a boolean determining whether
# or not authentication should be aborted when the value is not present.
config.authentication_keys = [:name]
config.authentication_keys = [ :name ]
# Configure parameters from the request object used for authentication. Each entry
# given should be a request method and it will automatically be passed to the
......@@ -58,12 +58,12 @@ Devise.setup do |config|
# Configure which authentication keys should be case-insensitive.
# These keys will be downcased upon creating or modifying a user and when used
# to authenticate or find a user. Default is :email.
config.case_insensitive_keys = [:email]
config.case_insensitive_keys = [ :email ]
# Configure which authentication keys should have whitespace stripped.
# These keys will have whitespace before and after removed upon creating or
# modifying a user and when used to authenticate or find a user. Default is :email.
config.strip_whitespace_keys = [:email, :name]
config.strip_whitespace_keys = [ :email, :name ]
# Tell if authentication through request.params is enabled. True by default.
# It can be set to an array that will enable params authentication only for the
......@@ -97,7 +97,7 @@ Devise.setup do |config|
# Notice that if you are skipping storage for all authentication paths, you
# may want to disable generating routes to Devise's sessions controller by
# passing skip: :sessions to `devise_for` in your config/routes.rb
config.skip_session_storage = [:http_auth]
config.skip_session_storage = [ :http_auth ]
# By default, Devise cleans up the CSRF token on authentication to
# avoid CSRF token fixation attacks. This means that, when using AJAX
......
......@@ -3,6 +3,6 @@
# Configure parameters to be partially matched (e.g. passw matches password) and filtered from the log file.
# Use this to limit dissemination of sensitive information.
# See the ActiveSupport::ParameterFilter documentation for supported notations and behaviors.
Rails.application.config.filter_parameters += [
:passw, :secret, :token, :_key, :crypt, :salt, :certificate, :otp, :ssn
Rails.application.config.filter_parameters += %i[
passw secret token _key crypt salt certificate otp ssn
]
# default: &default
# dispatchers:
# - polling_interval: 1
# batch_size: 500
# workers:
# - queues: "*"
# threads: 3
# processes: <%= ENV.fetch("JOB_CONCURRENCY", 1) %>
# polling_interval: 0.1
#
# development:
# <<: *default
#
# test:
# <<: *default
#
# production:
# <<: *default
default: &default
dispatchers:
- polling_interval: 1
batch_size: 500
workers:
- queues: "*"
threads: 3
processes: <%= ENV.fetch("JOB_CONCURRENCY", 1) %>
polling_interval: 0.1
development:
<<: *default
test:
<<: *default
production:
<<: *default
Rails.application.routes.draw do
namespace :admin do
resources :roles, only: [ :index, :edit, :update ]
resources :conferences, param: :slug
end
devise_for :users
mount Crono::Engine, at: '/crono'
mount ActionCable.server => '/cable'
mount Crono::Engine, at: "/crono"
mount ActionCable.server => "/cable"
get 'speakers/show'
get 'users/leaderboard'
get "speakers/show"
get "users/leaderboard"
# Reveal health status on /up that returns 200 if the app boots with no exceptions, otherwise 500.
# Can be used by load balancers and uptime monitors to verify that the app is live.
......@@ -15,27 +19,30 @@ Rails.application.routes.draw do
root "conferences#index"
resources :conferences, param: :slug do
get 'stats', on: :member
get ':date', action: :show, on: :member, as: :date, date: /\d{4}-\d{2}-\d{2}/
collection do
get "required_fields", to: "conferences#required_fields"
end
get "stats", on: :member
get ":date", action: :show, on: :member, as: :date, date: /\d{4}-\d{2}-\d{2}/
resources :sessions, param: :ref_id do
member do
patch :update_notes
end
resources :assignments, only: [:create, :destroy]
resources :candidates, only: [:create, :destroy]
delete 'candidates', to: 'candidates#destroy_self'
resources :assignments, only: %i[create destroy]
resources :candidates, only: %i[create destroy]
delete "candidates", to: "candidates#destroy_self"
end
resources :speakers, param: :ref_id
end
resources :assignments, only: [:index] do
get 'for/:user_id', action: 'by_user', on: :collection, as: :user
resources :assignments, only: [ :index ] do
get "for/:user_id", action: "by_user", on: :collection, as: :user
end
resources :sessions, param: :ref_id
resources :filedrop_files, only: [] do
member do
get 'download', to: 'filedrop_files#download'
get "download", to: "filedrop_files#download"
end
end
......
class AddRefIdToSpeakers < ActiveRecord::Migration[7.1]
def change
add_column :speakers, :ref_id, :string
add_index :speakers, [:ref_id, :conference_id], unique: true
add_index :speakers, [ :ref_id, :conference_id ], unique: true
end
end
class AddRefIdToSessions < ActiveRecord::Migration[7.1]
def change
add_column :sessions, :ref_id, :string
add_index :sessions, [:ref_id, :conference_id], unique: true
add_index :sessions, [ :ref_id, :conference_id ], unique: true
end
end
class AddRefIdToStages < ActiveRecord::Migration[7.1]
def change
add_column :stages, :ref_id, :string
add_index :stages, [:ref_id, :conference_id], unique: true
add_index :stages, [ :ref_id, :conference_id ], unique: true
end
end
......@@ -7,6 +7,6 @@ class CreateCronoJobs < ActiveRecord::Migration[6.1]
t.boolean :healthy
t.timestamps null: false
end
add_index :crono_jobs, [:job_id], unique: true
add_index :crono_jobs, [ :job_id ], unique: true
end
end
......@@ -7,6 +7,6 @@ class CreateRelevantStages < ActiveRecord::Migration[7.1]
t.timestamps
end
add_index :relevant_stages, [:conference_id, :stage_id], unique: true
add_index :relevant_stages, [ :conference_id, :stage_id ], unique: true
end
end
class CreateRoles < ActiveRecord::Migration[8.0]
def change
create_table :roles do |t|
t.string :name
t.text :description
t.timestamps
end
end
end
class CreateUserRoles < ActiveRecord::Migration[8.0]
def change
create_table :user_roles do |t|
t.references :user, null: false, foreign_key: true
t.references :role, null: false, foreign_key: true
t.timestamps
end
end
end
class CreatePermissions < ActiveRecord::Migration[8.0]
def change
create_table :permissions do |t|
t.string :name
t.text :description
t.timestamps
end
end
end
class CreateRolePermissions < ActiveRecord::Migration[8.0]
def change
create_table :role_permissions do |t|
t.references :role, null: false, foreign_key: true
t.references :permission, null: false, foreign_key: true
t.timestamps
end
end
end