From 4f22cdeaea871a49ccc8cbb2f625f74594d821be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjam=C3=ADn=20Vicente?= Date: Wed, 23 Dec 2020 22:25:54 -0300 Subject: [PATCH 01/10] fixed description without courses --- app/views/schedule/show.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/schedule/show.html.erb b/app/views/schedule/show.html.erb index 86cbf36..86ea166 100644 --- a/app/views/schedule/show.html.erb +++ b/app/views/schedule/show.html.erb @@ -1,4 +1,4 @@ -<% unless @term.nil? %> +<% unless @term.nil? || @courses.empty? %> <% provide :description, t('schedule_of', subjects_names: @courses.map(&:subject).map(&:name).to_sentence) %> <% end %> From 0b34da18a599175d9e5e30adc4466953d68588f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjam=C3=ADn=20Vicente?= Date: Wed, 23 Dec 2020 22:40:46 -0300 Subject: [PATCH 02/10] removed select background --- app/assets/stylesheets/schedule.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/app/assets/stylesheets/schedule.scss b/app/assets/stylesheets/schedule.scss index fffd629..b5d5584 100644 --- a/app/assets/stylesheets/schedule.scss +++ b/app/assets/stylesheets/schedule.scss @@ -74,6 +74,7 @@ text-align: center; select { border: none; + background: none; font-size: inherit; font-weight: inherit; } From e33bbd988b17d7f846fc532e4b536ddfd0794603 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjam=C3=ADn=20Vicente?= Date: Thu, 24 Dec 2020 11:55:43 -0300 Subject: [PATCH 03/10] fixed holiday exclusion --- .gitignore | 7 + app/models/schedule.rb | 3 +- docs/ajax.md | 305 ----------------------------------------- 3 files changed, 9 insertions(+), 306 deletions(-) delete mode 100644 docs/ajax.md diff --git a/.gitignore b/.gitignore index 158725e..5460504 100644 --- a/.gitignore +++ b/.gitignore @@ -23,3 +23,10 @@ yarn-debug.log* # Test files .rspec + +# Debug +.byebug* + +# Other files +docs/* + diff --git a/app/models/schedule.rb b/app/models/schedule.rb index 8ba9215..175f252 100644 --- a/app/models/schedule.rb +++ b/app/models/schedule.rb @@ -79,7 +79,7 @@ def create_icalendar_events @expandable_events.map do |event| # Info fist_day = course.term.first_day - until_date = course.term.last_day + until_date = course.term.last_day.advance(days: 1) days = event.days.map { |e| ICALENDAR_DAYS[e] }.join(',') event_start = fist_day.to_datetime.change(MODULES_TIME[event.modules.min]) event_start = event_start.change_to_next_wday(event.days.max_by { |d| (fist_day.day - d - 2) % 7 } + 1) @@ -94,6 +94,7 @@ def create_icalendar_events icalendar_event.dtend = event_end + MODULE_LENGH exdates = Holiday.all.filter_map do |holiday| hday = holiday.every_yeat ? holiday.day.change(year: course.term.first_day.year) : holiday.day + hday = hday.to_datetime.change(hour: event_start.hour, min: event_start.min) course.term.first_day < hday && hday < course.term.last_day ? hday : nil end icalendar_event.exdate = exdates diff --git a/docs/ajax.md b/docs/ajax.md deleted file mode 100644 index 4ee7b92..0000000 --- a/docs/ajax.md +++ /dev/null @@ -1,305 +0,0 @@ -# Ayudantía AJAX - -- [¿Qué es AJAX?](#qué-es-ajax) -- [Cómo funciona](#cómo-funciona) -- [Aplicando AJAX en Rail => remote: true](#aplicando-ajax-en-rail--remote-true) -- [Ejercicio ayudantía](#ejercicio-ayudantía) - - [Gemas a utilizar](#gemas-a-utilizar) - - [Agregar JQuery a nuestra app](#agregar-jquery-a-nuestra-app) - - [Archivos necesarios](#archivos-necesarios) - - [Modificando nuestro Controller](#modificando-nuestro-controller) - - [Modificando nuestro Form](#modificando-nuestro-form) - - [Modificando nuestro Index](#modificando-nuestro-index) - - [Crear una partial view para el objeto Task](#crear-una-partial-view-para-el-objeto-task) - - [Agrear AJAX a nuestra acción New](#agrear-ajax-a-nuestra-acción-new) - - [views/tasks/new.js.erb](#viewstasksnewjserb) - - [Agregar AJAX a nuestra acción Create](#agregar-ajax-a-nuestra-acción-create) - - [views/tasks/create.js.erb`](#viewstaskscreatejserb) - - [Agregar AJAX a nuestra acción Edit](#agregar-ajax-a-nuestra-acción-edit) - - [views/tasks/edit.js.erb](#viewstaskseditjserb) - - [Agregar AJAX a nuestra acción Update](#agregar-ajax-a-nuestra-acción-update) - - [views/tasks/update.js.erb](#viewstasksupdatejserb) - - [Agregar AJAX a nuestra acción Destroy](#agregar-ajax-a-nuestra-acción-destroy) - - [views/tasks/destroy.js.erb](#viewstasksdestroyjserb) - - [Consideraciones](#consideraciones) - -## ¿Qué es AJAX? -AJAX, acrónimo de **A**synchronous **J**avaScript **A**nd **X**ML (JavaScript asíncrono y XML), es una técnica de desarrollo web para -crear aplicaciones interactivas o **RIA** (Rich Internet Applications). Estas aplicaciones se ejecutan en el cliente, es -decir, en el navegador de los usuarios mientras se mantiene la comunicación asíncrona con el servidor en segundo plano. -De esta forma es posible realizar cambios sobre las páginas sin necesidad de recargarlas, mejorando la interactividad, -velocidad y usabilidad en las aplicaciones. - -## Cómo funciona - -![alt text](https://www.w3schools.com/whatis/img_ajax.gif "Diagrama AJAX") -1. An event occurs in a web page (the page is loaded, a button is clicked) -2. An XMLHttpRequest object is created by JavaScript -3. The XMLHttpRequest object sends a request to a web server -4. The server processes the request -5. The server sends a response back to the web page -6. The response is read by JavaScript -7. Proper action (like page update) is performed by JavaScript
- -Fuente: https://www.w3schools.com/whatis/whatis_ajax.asp - -## Aplicando AJAX en Rail => remote: true - -Rails proporciona distintas herramientas para facilitar el uso de AJAX. Una de estas es utlizar remote: true. -Al incluirlo en nuestros links o forms estaremos declarando desde un principio que el request lo queremos realizar -mediante JS y no con HTML. Además, evita que se realice la acción predeterminada. - -## Ejercicio ayudantía - -Crear un programa tipo **To-Do app**, donde pueda crear, editar y eliminar instancias de mi modelo, sin tener que -refrescar o trasladarme de página para poder visualizar los cambios. - -Para esto crearemos un modelo llamado Task (lo haré con `scaffold` ya que supongo que muchos han trabajado con esto). - -### Gemas a utilizar - -```Gemfile -gem 'jquery-rails' -``` - -### Agregar JQuery a nuestra app - -En `app/assets/javascripts/application.js`, agregar - -``` js - -//= require jquery3 -//= require jquery_ujs -``` - -Si están corriendo Rails 5.1 o mayor, y tienen incluído `//= require rails-ujs`, no es necesario agregar `//= require jquery_ujs`. - -#### Archivos necesarios - -```tree -+app - +controllers - tasks_controller.rb - +views - +tasks - _form_html.erb - task.html.erb - create.js.erb - destroy.js.erb - edit.js.erb - index.html.erb - new.js.erb - update.js.erb -``` - -### Modificando nuestro Controller - -```ruby -# controllers/tasks_controller.rb -class TasksController < ApplicationController - before_action :set_task, only: [:show, :edit, :update, :destroy] - - def index - @tasks = Task.all - end - - def new - @task = Task.new - end - - def edit - end - - def create - @task = Task.new(task_params) - - respond_to do |format| - if @task.save - format.html { redirect_to @task, notice: 'Task was successfully created.' } - format.js - format.json { render :show, status: :created, location: @task } - else - format.html { render :new } - format.json { render json: @task.errors, status: :unprocessable_entity } - end - end - end - - def update - respond_to do |format| - if @task.update(task_params) - format.html { redirect_to @task, notice: 'Task was successfully updated.' } - format.js - format.json { render :show, status: :ok, location: @task } - else - format.html { render :edit } - format.json { render json: @task.errors, status: :unprocessable_entity } - end - end - end - - def destroy - @task.destroy - respond_to do |format| - format.html { redirect_to tasks_url, notice: 'Task was successfully destroyed.' } - format.js - format.json { head :no_content } - end - end - - private - def set_task - @task = Task.find(params[:id]) - end - - def task_params - params.require(:task).permit(:name) - end -end -``` - -En este caso, agregamos `format.js` a cada acción para que esta pueda responder con JavaScript. - -### Modificando nuestro Form - -```erb - -<%= form_with(model: task, class: 'default-form') do |form| %> - <% if task.errors.any? %> -
-

<%= pluralize(task.errors.count, "error") %> prohibited this task from being saved:

- -
    - <% task.errors.full_messages.each do |message| %> -
  • <%= message %>
  • - <% end %> -
-
- <% end %> - -
- <%= form.label :name %> - <%= form.text_field :name %> -
- -
- <%= form.submit %> -
-<% end %> -``` -Al form le agregamos la clase `default-form`, la cual cambiaremos cuando tengamos que usarlo para crear y editar una -instancia, y así poder diferenciarlos. - -Notar que estamos usando `form_with`, en el cual se incluye por default `remote: true`, por lo que no es necesario -escribirlo. Si tienen declarado `local: true`, borrenlo, ya que les sobreescribe `remote: true` y hará que su form se -procese con HTML. - -En el caso que estén usando `form_for` o `form_tag`, deben declarar `remote: true`. - -### Modificando nuestro Index - -````erb - -

Tasks

- -
-<% @tasks.each do |task| %> - <%= render task %> -<% end %> -
- -<%= link_to 'New Task', new_task_path, remote: true, class: 'new-task-button' %> -```` - -Si se fijan, le asignaos la clase `my-tasks` al div principal de nuestro index y `new-task-button` al link, -para así acceder a estos más adelante. Además, incluimos `remote: true` en el `link_to`. - -### Crear una partial view para el objeto Task - -```erb - -
-

<%= task.name %>

- -
    -
  • <%= link_to 'Edit Task', edit_task_path(task), remote: true %>
  • -
  • <%= link_to 'Delete Task', task, remote: true, method: :delete %>
  • -
-
-``` -En el div del principio le aisgnamos como id el id del task que está mostrando. -Estos nos servirá más adelante para poder acceder facilmente a este. - -### Agrear AJAX a nuestra acción New - -```js -// views/tasks/new.js.erb -$(".new-task-button").after(" <%= j render partial: 'form', locals: {task: @task} %> "); -$(".default-form").addClass("create-form").removeClass("default-form"); -$(".new-task-button").hide(); -``` - -Este código correrá cuando llamemos al método new de TasksController. - -Para que entiendan un poco mejor el código, la primera linea va a encontrar el link que tiene la clase `new-task-button` -y abajo renderizará la view parcial tasks/_form.html.erb. La `j` es un abreviado de `escape-javascript`. - -La segunda linea le egrega la clase `create-form` y le remueve `default-form` a el form que acabamos de renderizar. -Finalmente, la tercera línea esconde nuestro `new-task-button`. - - -### Agregar AJAX a nuestra acción Create - -```js -// views/tasks/create.js.erb -$(".create-form").hide(); -$(".my-tasks").append("<%= j render partial: 'task', locals: {task: @task} %>"); -$(".new-task-button").show(); -``` - -Esto hará que, al hacer submit en nuestro `create-form`, se esconda, se agregue nuestra nueva task al listado en nuestro -index y que vuelva a mostrarse nuestro new-task-button. - -### Agregar AJAX a nuestra acción Edit - -```js -// views/tasks/edit.js.erb -$("div#<%= @task.id %>").html(" <%= j render partial: 'form', locals: {task: @task} %> "); -$(".default-form").addClass('update-form').removeClass('default-form').attr("id", "<%= @task.id %>"); -``` - -Esta línea hace que el contenido dentro del `div` con el id igual al id del task que queremos editar, se reemplace por -nuestro form. Luego, al form que acabamos de renderizar, le agregaremos la clase `update-form` y el id de nuestro -`task`. Así podremos diferenciar este form de uno del método `create`, y, además, podremos diferenciar cada form para -`update` uno del otro. - -### Agregar AJAX a nuestra acción Update - -```js -// views/tasks/update.js.erb -$("div#<%= @task.id %>").html("<%= j render partial: 'task', locals: {task: @task} %>"); -``` - -Al hacer submit, el form se reemplazará por el contenido del task -que acabamos de editar. - -### Agregar AJAX a nuestra acción Destroy - -```js -// views/tasks/destroy.js.erb -$("div#<%= @task.id %>").fadeOut(); -``` - -Esta línea permitirá que el task que estamos eliminando deje de visualizarse en la pantalla. - -## Consideraciones -* Recuerden que deben crear los archivos *.js.erb, y ahí escribir su código. No se confundan con los *html.erb. -* Recuerden que los archivos *.js.erb solo modifican su view. Todo procesamiento lo sigue realizando, en segundo plano, -el controlador. -* El código implementado en cada *js.erb es solo una alternativa de como actualizar la view. Pueden conseguir el mismo -efecto de muchas maneras (revisar la [documentación de jquery](https://api.jquery.com/)). -* Pueden crear sus propios métodos personalizados y lograr distintos efectos. Investiguen en cómo hacerlo. -* Si actualizan algún task y luego refrescan la página, estos cambiaran su orden. Esto se debe a que se -están ordenando según la última fecha de edición. Pueden configurar el método index del controlador para que se ordenen -según su fecha de creación, para que así mantengan su orden. - \ No newline at end of file From ecd0435e147d4710a6b1ad239a8c1349a5c16713 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjam=C3=ADn=20Vicente?= Date: Thu, 24 Dec 2020 13:59:38 -0300 Subject: [PATCH 04/10] added calendar metadata --- app/controllers/schedule_controller.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/controllers/schedule_controller.rb b/app/controllers/schedule_controller.rb index 40709e8..1ee5ced 100644 --- a/app/controllers/schedule_controller.rb +++ b/app/controllers/schedule_controller.rb @@ -86,6 +86,9 @@ def ics_format calendar.add_event(event) end end + calendar.prodid = 'benjavicente/ucalendar' + calendar.append_custom_property('X-WR-CALNAME', I18n.t('schedule')) + calendar.append_custom_property('X-WR-TIMEZONE', 'America/Santiago') calendar.to_ical end From 6cc826da804f70447ce962312143cc948288127a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjam=C3=ADn=20Vicente?= Date: Thu, 24 Dec 2020 14:29:35 -0300 Subject: [PATCH 05/10] added locales and fixed typos --- .gitignore | 1 - app/admin/holidays.rb | 2 +- app/lib/date_time.rb | 2 +- app/models/application_record.rb | 2 +- app/models/schedule.rb | 6 +- config/locales/es.yml | 77 +++++++++++++++++++----- db/migrate/20201216004221_init_app_db.rb | 4 +- 7 files changed, 71 insertions(+), 23 deletions(-) diff --git a/.gitignore b/.gitignore index 5460504..6fdfd90 100644 --- a/.gitignore +++ b/.gitignore @@ -29,4 +29,3 @@ yarn-debug.log* # Other files docs/* - diff --git a/app/admin/holidays.rb b/app/admin/holidays.rb index d7a21f7..613bd52 100644 --- a/app/admin/holidays.rb +++ b/app/admin/holidays.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true ActiveAdmin.register Holiday do - permit_params :day, :name, :every_yeat + permit_params :day, :name, :every_year end diff --git a/app/lib/date_time.rb b/app/lib/date_time.rb index ed4e803..e37c06b 100644 --- a/app/lib/date_time.rb +++ b/app/lib/date_time.rb @@ -4,7 +4,7 @@ class DateTime # Cambia el día de semana a la entregada, # solo considerando el dia actual y posteriores - def change_to_next_wday(week_day) + def change_wday(week_day) self + (week_day - wday) % 7 end end diff --git a/app/models/application_record.rb b/app/models/application_record.rb index e98ae1e..87f61f3 100644 --- a/app/models/application_record.rb +++ b/app/models/application_record.rb @@ -13,7 +13,7 @@ def self.sample(amount = nil) # https://stackoverflow.com/a/36335591 def self.human_enum_name(enum_name, enum_value) - I18n.t("activerecord.attributes.#{model_name.i18n_key}.#{enum_name.to_s.pluralize}.#{enum_value}") + I18n.t("activerecord.attributes.#{model_name.i18n_key}.#{enum_name.to_s.pluralize}.long_name.#{enum_value}") end def self.short_enum_name(enum_name, enum_value) diff --git a/app/models/schedule.rb b/app/models/schedule.rb index 175f252..ccc5582 100644 --- a/app/models/schedule.rb +++ b/app/models/schedule.rb @@ -82,9 +82,9 @@ def create_icalendar_events until_date = course.term.last_day.advance(days: 1) days = event.days.map { |e| ICALENDAR_DAYS[e] }.join(',') event_start = fist_day.to_datetime.change(MODULES_TIME[event.modules.min]) - event_start = event_start.change_to_next_wday(event.days.max_by { |d| (fist_day.day - d - 2) % 7 } + 1) + event_start = event_start.change_wday(event.days.max_by { |d| (fist_day.day - d - 2) % 7 } + 1) event_end = fist_day.to_datetime.change(MODULES_TIME[event.modules.max]) - event_end = event_end.change_to_next_wday(event.days.max_by { |d| (fist_day.day - d - 2) % 7 } + 1) + event_end = event_end.change_wday(event.days.max_by { |d| (fist_day.day - d - 2) % 7 } + 1) # Calendar icalendar_event = Icalendar::Event.new icalendar_event.summary = ErbTemplate.new('event/summary').render(binding) @@ -93,7 +93,7 @@ def create_icalendar_events icalendar_event.dtstart = event_start icalendar_event.dtend = event_end + MODULE_LENGH exdates = Holiday.all.filter_map do |holiday| - hday = holiday.every_yeat ? holiday.day.change(year: course.term.first_day.year) : holiday.day + hday = holiday.every_year ? holiday.day.change(year: course.term.first_day.year) : holiday.day hday = hday.to_datetime.change(hour: event_start.hour, min: event_start.min) course.term.first_day < hday && hday < course.term.last_day ? hday : nil end diff --git a/config/locales/es.yml b/config/locales/es.yml index 79bc1a8..4668e5c 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -1,12 +1,12 @@ es: - page_description: Obtiene el horario de los cursos y guardalos en tu calendario. - with: con - schedule_of: "Horario de %{subjects_names}" + course_form_instrucions: Busca cursos por Código-Sección o por NRC + courses: Cursos download_schedule: Descargar horario - schedule: "Horario" + page_description: Obtiene el horario de los cursos y guardalos en tu calendario. period_not_found: "Periodo no encontrado %{year}-%{period}" - courses: Cursos - course_form_instrucions: Busca cursos por Código-Sección o por NRC + schedule_of: "Horario de %{subjects_names}" + schedule: Horario + with: con date: day_names: ["Domingo", "Lunes", "Martes", "Miércoles", "Jueves", "Viernes", "Sábado"] support: @@ -14,18 +14,67 @@ es: words_connector: ", " two_words_connector: " y " last_word_connector: " y " + # Rails Active Record + # https://guides.rubyonrails.org/i18n.html#translations-for-active-record-models + attributes: + year: Año + period: Periodo + fist_day: Primer día + last_day: Último día + academic_unit: Unidad académica + campus: Campus + course: Curso + category: Categoria + created_at: Creado en + name: Nombre + day: Día + schedule: Horario + every_year: Cada año + subject: Ramo + teacher: Profesor + term: Semestre académico + updated_at: Actualizado en + classroom: Sala + module: Módulo activerecord: + models: + academic_unit: Unidad académica + campus: Campus + course: Curso + exam: Prueba + holiday: Feriado + schedule_event: + one: Módulo de un curso + other: Módulos de cursos + schedule: Horario + subject: Ramo + teacher: Profesor + term: Semestre académico + user: Usuario attributes: + course: + section: Sección + format: Formato + total_vacancy: Cupos + "withdrawal?": Permite retiro + "english?": Se dicta en ingles + "require_special_approval?": Requiere aprob. especial + subject: + code: Código + credits: Creditos + fr_area: Área FG + category: Categoria schedule_event: categories: - class: "Clase" - assis: "Ayudantía" - lab: "Laboratorio" - workshop: "Taller" - field: "Terreno" - practice: "Práctica" - tesis: "Tesis" - other: "Otro" + long_name: + class: "Clase" + assis: "Ayudantía" + lab: "Laboratorio" + workshop: "Taller" + field: "Terreno" + practice: "Práctica" + tesis: "Tesis" + other: "Otro" short_name: class: "Clas" assis: "Ayd" diff --git a/db/migrate/20201216004221_init_app_db.rb b/db/migrate/20201216004221_init_app_db.rb index a3644d7..dc8f103 100644 --- a/db/migrate/20201216004221_init_app_db.rb +++ b/db/migrate/20201216004221_init_app_db.rb @@ -6,7 +6,7 @@ def change t.timestamps t.date :day, null: false t.string :name, null: false - t.boolean :every_yeat, default: false, null: false + t.boolean :every_year, default: false, null: false end create_table :teachers do |t| @@ -37,7 +37,7 @@ def change t.string :code, null: false t.string :name, null: false t.integer :credits - t.string :fr_area + t.string :fg_area t.string :category end add_index :subjects, :code, unique: true From 8447185db78140054016576ca56dec10127d31d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjam=C3=ADn=20Vicente?= Date: Thu, 24 Dec 2020 14:33:56 -0300 Subject: [PATCH 06/10] added models dependencies --- app/models/academic_unit.rb | 2 +- app/models/campus.rb | 2 +- app/models/term.rb | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/models/academic_unit.rb b/app/models/academic_unit.rb index a5a96c4..b347e64 100644 --- a/app/models/academic_unit.rb +++ b/app/models/academic_unit.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true class AcademicUnit < ApplicationRecord - has_many :courses + has_many :courses, dependent: :destroy end diff --git a/app/models/campus.rb b/app/models/campus.rb index e33d54e..63a6954 100644 --- a/app/models/campus.rb +++ b/app/models/campus.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true class Campus < ApplicationRecord - has_many :courses + has_many :courses, dependent: :destroy end diff --git a/app/models/term.rb b/app/models/term.rb index 19fa5d5..420bea8 100644 --- a/app/models/term.rb +++ b/app/models/term.rb @@ -2,7 +2,7 @@ # Periodo de clases class Term < ApplicationRecord - enum period: %i[tav 1 2] # TODO: tav debería ser 3 en el enum + enum period: %i[1 2 tav] default_scope { order(year: :desc, period: :asc) } has_many :courses, dependent: :destroy From da4cd7f3b146b73439e7bb2fc24ca5fba9a511bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjam=C3=ADn=20Vicente?= Date: Thu, 24 Dec 2020 15:42:27 -0300 Subject: [PATCH 07/10] include better database seeds --- db/seeds.rb | 103 ++++++++++++++++++++++++++++++++++---- db/seeds/2021_holidays.rb | 33 ++++++++++++ 2 files changed, 125 insertions(+), 11 deletions(-) create mode 100644 db/seeds/2021_holidays.rb diff --git a/db/seeds.rb b/db/seeds.rb index 63c9de2..f7a0123 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -1,15 +1,96 @@ # frozen_string_literal: true -# This file should contain all the record creation needed to seed the database with its default values. -# The data can then be loaded with the bin/rails db:seed command (or created alongside the database with db:setup). -# -# Examples: -# -# movies = Movie.create([{ name: 'Star Wars' }, { name: 'Lord of the Rings' }]) -# Character.create(name: 'Luke', movie: movies.first) - User.create!(email: 'admin@example.com', password: '123456') if Rails.env.development? -Term.create!(year: 2020, period: 2, first_day: Date.new(2020, 8, 10), last_day: Date.new(2020, 12, 12)) -Term.create!(year: 2021, period: :tav, first_day: Date.new(2021, 1, 6), last_day: Date.new(2021, 1, 31)) -Term.create!(year: 2021, period: 1, first_day: Date.new(2021, 3, 9), last_day: Date.new(2021, 7, 21)) +Term.create! do |t| + t.year = 2020 + t.period = :tav + t.first_day = '2021-01-04' + t.last_day = '2021-01-31' +end + +Term.create! do |t| + t.year = 2021 + t.period = 1 + t.first_day = '2021-03-15' + t.last_day = '2021-07-09' +end + +Term.create! do |t| + t.year = 2021 + t.period = 2 + t.first_day = '2021-08-09' + t.last_day = '2021-12-03' +end + +Holiday.create! do |h| + h.name = 'Día del trabajo' + h.day = '2020-05-01' + h.every_year = true +end + +Holiday.create! do |h| + h.name = 'Días de las Glorias Navales' + h.day = '2020-05-21' + h.every_year = true +end + +Holiday.create! do |h| + h.name = 'Asunción de la Virgen' + h.day = '2020-08-15' + h.every_year = true +end + +Holiday.create! do |h| + h.name = 'Primera Junta Nacional de Gobierno' + h.day = '2020-09-18' + h.every_year = true +end + +Holiday.create! do |h| + h.name = 'Glorias del Ejército' + h.day = '2020-09-19' + h.every_year = true +end + +Holiday.create! do |h| + h.name = 'Glorias de la Armada' + h.day = '2020-09-21' + h.every_year = true +end + +Holiday.create! do |h| + h.name = 'Celebración del Día del Encuentro de Dos Mundos' + h.day = '2020-10-11' + h.every_year = true +end + +Holiday.create! do |h| + h.name = 'Día de las Iglesias Evangélicas y Protestantes' + h.day = '2020-10-31' + h.every_year = true +end + +Holiday.create! do |h| + h.name = 'Día de Todos los Santos' + h.day = '2020-11-01' + h.every_year = true +end + +Holiday.create! do |h| + h.name = 'Inmaculada Concepción de la Virgen' + h.day = '2020-12-08' + h.every_year = true +end + +Holiday.create! do |h| + h.name = 'Navidad' + h.day = '2020-12-25' + h.every_year = true +end + +# Carga seeds adicionales + +Dir[File.join(Rails.root, 'db', 'seeds/*', '*.rb')].sort.each do |seed| + load seed +end diff --git a/db/seeds/2021_holidays.rb b/db/seeds/2021_holidays.rb new file mode 100644 index 0000000..a39012f --- /dev/null +++ b/db/seeds/2021_holidays.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true + +Holiday.create! do |h| + h.name = 'Viernes Santo' + h.day = '2021-04-02' +end + +Holiday.create! do |h| + h.name = 'Sábado Santo' + h.day = '2021-04-03' +end + +Holiday.create! do |h| + h.name = 'Suspensión de las actividades académicas y administrativas' + h.day = '2021-04-30' +end + +(10..15).each do |day| + Holiday.create! do |h| + h.name = 'Semana de receso' + h.day = "2021-05-#{day}" + end +end + +Holiday.create! do |h| + h.name = 'San Pedro y San Pablo' + h.day = '2021-06-28' +end + +Holiday.create! do |h| + h.name = 'Suspensión de las actividades académicas y administrativas' + h.day = '2020-09-17' +end From d863fc776e7022b265a6a6023ab05e2fc3fb5916 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjam=C3=ADn=20Vicente?= Date: Thu, 24 Dec 2020 16:21:39 -0300 Subject: [PATCH 08/10] updated docs and fixed typos --- README.md | 134 +++++++++++++++++++++++++++++++++++++++-------- config/routes.rb | 2 +- db/schema.rb | 4 +- 3 files changed, 114 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index 7c89a5c..007db53 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,33 @@ # UCalendar -Implementación en Rails de [uc-nrc-icalendar](https://github.com/benjavicente/uc-nrc-icalendar). +Implementación en Rails de [uc-nrc-icalendar][uc-nrc-icalendar]. -## SetUp +Aplicación web que obtiene los cursos de [Busca Cursos][buscacursosuc] +y crea un calendario en formato [iCalendar][iCal] que luego puede ser +importado a Google Calendar. + +[Deploy en Heroku][deploy-page] + + +## Uso + +1. Seleccionar el semestre académico. +2. Ingresar los códigos del curso junto a su sección (`EJM1230-1`) o + el NRC de cada uno. +3. Descargar el calendario `ics` o copiar el `url` de descarga. +4. Agregar el calendario a la aplicación de calenadrio con el + acrhivo `ics` (en [google][gc-by-ics]) + o con el `url` (en [google][gc-by-url]). + + +## Set-Up + +Antes de crear la base de datos, crear un archivo`.env` con la clave +de postgres: + +```env +POSTGRES_PASSWORD= +``` Para crear el entorno de desarrollo: @@ -12,40 +37,103 @@ yarn install rails db:setup ``` -Crear un archivo `.env` con: +Para iniciar el servidor -```env -POSTGRES_PASSWORD= +```bash +sudo service postgresql start +rails s ``` -## Administración -Para que se pueda obtener los cursos, primero se tiene que crear un -periodo en la base de datos. Para hacer esto se puede usar la página -de administración (`/admin`), y crear uno en la sección _Terms_. +### Administración -## Creación de calendarios +Para que se pueda obtener los cursos, tiene que existir un periodo +académico (_term_) en la base de datos. Tambíen, para que no se creen +eventos en feriados deben crearse estos feriados (_holidays_). + +Estos se pueden crear con las _seeds_ o en el interfaz de +administración (`/admin`). -TODO ## Obtener los calendarios externamente ```js -`HOST/term/${year}/${period}/schedule.ics?cs[]=${course_section}&nrc[]=${nrc}` +HOST = 'https://ucalendar.herokuapp.com' ``` -Donde `year` es el año, `period` el periodo (`1`, `2` o `tav`), -`course_section` es el curso con su sección (ej `MAT1610-1`) y -`nrc` el `nrc` del curso (ej `14778`). +### Directo + +```js +`${HOST}/term/${year}/${period}/schedule.ics?cs[]=${cs}&nrc[]=${nrc}` +``` + +- `year`: año buscado, requerido +- `period`: periodo buscado, requerido +- `cs[]`: curso con su sección (ej `MAT1610-1`), opcional, acepta multiples valores +- `nrc[]`: ncr del curso, opcional, acepta multiples valores + +Ejemplo: + +```url +https://ucalendar.herokuapp.com/term/2021/1/schedule.ics?cs[]=MAT1640-1&cs[]=MAT1630-1 +``` + +### Versíon corta + +```js +`${HOST}?s.ics?year=${year}&period=${period}&cs=${course_section}&nrc=${nrc}` +``` + +Acepta los mismos parámetros de el `GET`, pero `year` y `period` son +opcionales, si no están presentes obtienen los datos de la el periodo +académico. + +Además, acepta: + +- `cs`: cursos coon su sección separados por comas +- `nrc`: nrc de los cursos separados por comas + +Ejemplos (formato HTML): + +```url +https://ucalendar.herokuapp.com/s.ics?cs=MAT1640-1,MAT1630-1 +``` + +### Ver periodos + +```js +`${HOST}/terms.json` +``` + +Obtiene una lista de los periodos académicos en formato `JSON`. + + +## GH Pages (Página estática) + +Ya que se utiliza una vista con AJAX, esta puede ser compilada a +una [página estática]. Para esto se usa la rama `gh-pages`, que es +creada con la página con el comando `rake gh_pages:compile`. + +Página en [github.io][gh-page]. + + +## Links adicionales -## Links de interés +- Página con documentación de icalendar: [icalendar.org] +- Diagrama de la base de datos en: [dbdiagram.io] -- [Busca Cursos](http://buscacursos.uc.cl/) -- [dbdiagram.io database](https://dbdiagram.io/d/5fd964db9a6c525a03bb3aee) -- [Percent-encoding](https://en.wikipedia.org/wiki/Percent-encoding) -### Icalendar + -- [Icalendar.org](https://icalendar.org/) -- [icalendar recurrence](https://icalendar.org/iCalendar-RFC-5545/3-3-10-recurrence-rule.html) -- [icalendar ex-dates](https://icalendar.org/iCalendar-RFC-5545/3-8-5-1-exception-date-times.html) +[buscacursosuc]: http://buscacursos.uc.cl/ +[uc-nrc-icalendar]: https://github.com/benjavicente/uc-nrc-icalendar +[ical]: https://es.wikipedia.org/wiki/ICalendar +[icalendar.org]: https://icalendar.org/ +[dbdiagram.io]: https://dbdiagram.io/d/5fd964db9a6c525a03bb3aee +[página estática]: https://es.wikipedia.org/wiki/P%C3%A1gina_web_est%C3%A1tica +[gc-by-ics]: https://calendar.google.com/calendar/u/0/r/settings/export + "Importar en Google Calendar con archivo ICS" +[gc-by-url]: https://calendar.google.com/calendar/u/0/r/settings/addbyurl + "Importar en Google Calendar con URL del calendario" +[gh-page]: https://benjavicente.github.io/ucalendar/ +[deploy-page]: https://ucalendar.herokuapp.com/ diff --git a/config/routes.rb b/config/routes.rb index 5110463..032dd3d 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -4,7 +4,7 @@ devise_for :users, ActiveAdmin::Devise.config ActiveAdmin.routes(self) root 'schedule#show_short' - get 't/s', to: 'schedule#show_short', as: 'schedule_short' + get 's', to: 'schedule#show_short', as: 'schedule_short' get 'term/:year/:period/schedule', to: 'schedule#show', as: 'schedule' get 'terms', to: 'terms#show', as: 'terms' end diff --git a/db/schema.rb b/db/schema.rb index 9aab8f3..e8865a3 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -79,7 +79,7 @@ t.datetime "updated_at", precision: 6, null: false t.date "day", null: false t.string "name", null: false - t.boolean "every_yeat", default: false, null: false + t.boolean "every_year", default: false, null: false end create_table "schedule_events", force: :cascade do |t| @@ -104,7 +104,7 @@ t.string "code", null: false t.string "name", null: false t.integer "credits" - t.string "fr_area" + t.string "fg_area" t.string "category" t.index ["code"], name: "index_subjects_on_code", unique: true end From 0a1948623b39f73ff2d36ee748ab72d7a8ae1ae4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjam=C3=ADn=20Vicente?= Date: Thu, 24 Dec 2020 16:26:22 -0300 Subject: [PATCH 09/10] fixed terms seeds --- db/seeds.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/db/seeds.rb b/db/seeds.rb index f7a0123..79c44a0 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -4,21 +4,21 @@ Term.create! do |t| t.year = 2020 - t.period = :tav + t.period = 'tav' t.first_day = '2021-01-04' t.last_day = '2021-01-31' end Term.create! do |t| t.year = 2021 - t.period = 1 + t.period = '1' t.first_day = '2021-03-15' t.last_day = '2021-07-09' end Term.create! do |t| t.year = 2021 - t.period = 2 + t.period = '2' t.first_day = '2021-08-09' t.last_day = '2021-12-03' end From b7ed4d514e22921a65d8eae5040b39cddb83cb15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjam=C3=ADn=20Vicente?= Date: Thu, 24 Dec 2020 16:28:46 -0300 Subject: [PATCH 10/10] fixed term order --- app/models/term.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/term.rb b/app/models/term.rb index 420bea8..b875b4a 100644 --- a/app/models/term.rb +++ b/app/models/term.rb @@ -3,7 +3,7 @@ # Periodo de clases class Term < ApplicationRecord enum period: %i[1 2 tav] - default_scope { order(year: :desc, period: :asc) } + default_scope { order(year: :desc, period: :desc) } has_many :courses, dependent: :destroy