Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/main' into undo-loan-return-true
Browse files Browse the repository at this point in the history
  • Loading branch information
rendonluis committed Oct 17, 2023
2 parents f5d3913 + fb17586 commit dc9ad27
Show file tree
Hide file tree
Showing 25 changed files with 575 additions and 56 deletions.
13 changes: 13 additions & 0 deletions .envrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#
# This file tells direnv, if both it and Nix are installed, to automatically
# load the Nix dependencies defined in flake.nix.
#
# For details on the Nix development setup, see NIX.md.
#
if has nix; then
if ! has nix_direnv_version || ! nix_direnv_version 2.3.0; then
source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/2.3.0/direnvrc" "sha256-Dmd+j63L84wuzgyjITIfSxSD57Tx7v51DMxVZOsiUD8="
fi
nix_direnv_watch_file .ruby-version
use flake
fi
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,7 @@ yarn-debug.log*
gallery-dl
/app/assets/builds/*
!/app/assets/builds/.keep


# The nix development setup puts gems here
/vendor/bundle
5 changes: 5 additions & 0 deletions DOCKER.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Development setup using Docker

> [!WARNING]
> This is meant for advanced users already familiar with Docker. If you're
> looking for general development instructions, please see
> [README.md](README.md).
## Initial setup
The following commands should just be run for the initial setup only. Rebuilding
the docker images is only necessary when upgrading, if there are changes to the
Expand Down
89 changes: 89 additions & 0 deletions NIX.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# Development Setup using Nix

> [!WARNING]
> This is meant for advanced users already familiar with Nix. If you're looking
> for general development instructions, please see [README.md](README.md).
## Prerequisites

- [Nix](https://nixos.org/download)
- [Docker w/ Compose](https://github.com/docker/compose#where-to-get-docker-compose) via Docker Desktop or equivalent - this setup runs Rails directly but uses a container for the database.
- [direnv](https://github.com/direnv/direnv) - technically optional but helpful to get the environment to automatically load when entering the project directory

## Initial Dependencies

If you have direnv, the `.envrc` file in the repository will get everything set
up for you automatically, you just need to run `direnv allow`. If you're not
using direnv, you can manually start a development shell with `nix develop`.

## Database

This setup uses the development database configured in `docker-compose.yml`,
which can be started like this:

```shell-session
$ docker compose up -d database
```

The database is working properly if this command produces a list of databases:

```shell-session
$ psql -l "$DATABASE_URL"
```

## Bootstrapping

Use the `setup` script to get started for the first time.

```shell-session
$ bin/setup
```

This script will:

- Fetch Ruby and NPM dependencies
- Bootstrap the development database
- Load some sample data into the development database

The setup script doesn't create the test database, so do that separately:

```shell-session
$ bin/rails db:create:all
```

## Asset Compilation

You can get the assets automatically compiling on file changes by leaving this
command running in a shell:

```shell-session
$ bin/dev -m all=1,web=0
```

Note this skips the Rails server, which we run separately below. This is
because something is preventing Rails from loading properly within the Foreman
environment. If somebody figures this out update this guide!

## Development Server

Run the Rails server in a separate shell:

```shell-session
$ bin/rails server
```

## Running Tests

All tests should be able to run normally:

```shell-session
# Unit tests
$ bin/rails test
# Selenium tests
$ bin/rails test:system
```

The Selenium tests are run by having Nix install Chromium and ChromeDriver and
set a `SELENIUM_CHROME_BINARY` environment variable to point Selenium at
Chromium in `test/application_system_test_case.rb`.
49 changes: 27 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,26 @@

<!-- toc -->

- [Welcome contributors!](#welcome-contributors)
- [About](#about)
* [Project Considerations](#project-considerations)
- [Requirements](#requirements)
- [Integrations](#integrations)
- [Development](#development)
* [Setting up Circulate on your machine](#setting-up-circulate-on-your-machine)
* [Multi-tenancy](#multi-tenancy)
* [Configuring your database](#configuring-your-database)
* [Resetting the application](#resetting-the-application)
* [Running tests](#running-tests)
* [Code formatting and linting](#code-formatting-and-linting)
* [Setup pre-commit checks](#setup-pre-commit-checks)
* [Documentation](#documentation)
* [Who to log in as](#who-to-log-in-as)
- [Deployment](#deployment)
* [Buildpacks](#buildpacks)
* [Release Command](#release-command)
* [Daily Summary Emails](#daily-summary-emails)
- [Alternatives](#alternatives)
- [Circulate](#circulate)
- [About](#about)
- [Project Considerations](#project-considerations)
- [Requirements](#requirements)
- [Integrations](#integrations)
- [Development](#development)
- [Setting up Circulate on your machine](#setting-up-circulate-on-your-machine)
- [Multi-tenancy](#multi-tenancy)
- [Configuring your database](#configuring-your-database)
- [Resetting the application](#resetting-the-application)
- [Running tests](#running-tests)
- [Code formatting and linting](#code-formatting-and-linting)
- [Setup pre-commit checks](#setup-pre-commit-checks)
- [Documentation](#documentation)
- [Who to log in as](#who-to-log-in-as)
- [Deployment](#deployment)
- [Buildpacks](#buildpacks)
- [Release Command](#release-command)
- [Daily Summary Emails](#daily-summary-emails)
- [Alternatives](#alternatives)

<!-- tocstop -->

Expand Down Expand Up @@ -90,8 +90,6 @@ The following third party services are used:

Once you've completed the setup below, you can login to the app using `admin@example.com` and `password` to see the admin interface.

We generally advise folks to avoid Docker for local development unless it is something thet are already very comfortable with. See [DOCKER.md](DOCKER.md) for instructions on setting up your environment using Docker. For non-Docker installations, follow the instructions below.

### Setting up Circulate on your machine

If you're new to Ruby or Rails applications, a recommended way to get set up is to use the [GoRails setup guide](https://gorails.com/setup). On that page you can select your operating system and the versions of Ruby and Rails you want to setup. It's worth going through the entire tutorial if you haven't worked on a Ruby on Rails application on your computer already as it is easier to sort through possible issues before getting into a large project like Circulate. It will take about 30 minutes to complete this tutorial.
Expand Down Expand Up @@ -235,6 +233,13 @@ the second seed library, Denver Tool Library, by appending `.denver` to the user

All of the seed user passwords are the word "password".

### Alternative Development Setups

We generally advise you to _avoid_ these alternative development setups unless you are already very comfortable with them. The above development instructions should be better for most users.

* **Docker:**: See [DOCKER.md](DOCKER.md) for instructions on setting up your environment using Docker.
* **Nix:** See [NIX.md](NIX.md) for details on installing dependencies with Nix.

## Deployment

Circulate is currently running on Heroku in production, but it should run fairly well anywhere Rails applications can be run.
Expand Down
26 changes: 11 additions & 15 deletions app/controllers/account/appointments_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,7 @@ def create
@appointment = @member.appointments.new

if @appointment.update(appointment_params)
message = if merge_simultaneous_appointments
"Your existing appointment scheduled for #{helpers.appointment_date_and_time(@appointment)} has been updated."
else
"Your appointment was scheduled for #{helpers.appointment_date_and_time(@appointment)}."
end
MemberMailer.with(member: @member, appointment: @appointment).appointment_confirmation.deliver_later
redirect_to account_appointments_path, success: message
merge_and_complete_appointment_update
else
load_holds_and_loans
load_appointment_slots
Expand All @@ -47,12 +41,7 @@ def update
@member = current_user.member

if @appointment.update(appointment_params)
message = if merge_simultaneous_appointments
"Your existing appointment scheduled for #{helpers.appointment_date_and_time(@appointment)} has been updated."
else
"Your appointment scheduled for #{helpers.appointment_date_and_time(@appointment)} was updated."
end
redirect_to account_appointments_path, success: message
merge_and_complete_appointment_update
else
load_holds_and_loans
load_appointment_slots
Expand Down Expand Up @@ -84,12 +73,19 @@ def load_holds_and_loans
@loans = @member.loans.includes(:item, member: {appointments: :loans}).checked_out
end

def merge_simultaneous_appointments
# In cases where a member already has an appointment during the selected time slot for the current appointment,
# merge those appointments together to avoid confusion for members or staff.
def merge_and_complete_appointment_update
simultaneous_appointment = @member.appointments.simultaneous(@appointment).first
if simultaneous_appointment
simultaneous_appointment.merge!(@appointment)
true
message = "Your existing appointment scheduled for #{helpers.appointment_date_and_time(simultaneous_appointment)} has been updated."
MemberMailer.with(member: @member, appointment: simultaneous_appointment).appointment_confirmation.deliver_later
else
message = "Your appointment was scheduled for #{helpers.appointment_date_and_time(@appointment)}."
MemberMailer.with(member: @member, appointment: @appointment).appointment_confirmation.deliver_later
end
redirect_to account_appointments_path, success: message
end

def load_appointment_for_editing
Expand Down
4 changes: 3 additions & 1 deletion app/controllers/account/holds_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ def create
end

def destroy
current_member.active_holds.find(params[:id]).destroy!
hold = current_member.active_holds.find(params[:id])
hold.cancel!

redirect_to account_holds_path
end

Expand Down
10 changes: 8 additions & 2 deletions app/helpers/holds_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,15 @@ def render_hold_status(hold)
end

def render_remove_link(hold)
unless hold.appointments.present?
link_to("Remove Hold", account_hold_path(hold), class: "btn", method: :delete, data: {confirm: "Are you sure you want to remove this hold?"})
message = "Are you sure you want to remove this hold?"

if hold.appointment.present?
message <<
" It will also be removed from your appointment."\
" If it's the only item in your appointment, your appointment will be canceled."
end

link_to("Remove Hold", account_hold_path(hold), class: "btn", method: :delete, data: {confirm: message})
end

def place_in_line_for(hold)
Expand Down
10 changes: 9 additions & 1 deletion app/models/appointment.rb
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,18 @@ def merge!(other_appointment)
end
end

def cancel_if_no_items!
destroy! if no_items?
end

private

def no_items?
holds.empty? && loans.empty?
end

def item_present
if holds.empty? && loans.empty?
if no_items?
errors.add(:base, "Please select an item to pick-up or return for your appointment")
end
end
Expand Down
13 changes: 11 additions & 2 deletions app/models/hold.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
class Hold < ApplicationRecord
HOLD_LENGTH = 7.days

has_many :appointment_holds
has_many :appointments, through: :appointment_holds
has_one :appointment_hold, dependent: :destroy
has_one :appointment, through: :appointment_hold

belongs_to :member
belongs_to :item, counter_cache: true
Expand Down Expand Up @@ -57,6 +57,15 @@ def start!(now = Time.current)
)
end

def cancel!
if appointment.present?
appointment_hold.destroy!
appointment.cancel_if_no_items!
end

destroy!
end

# A hold that timed out
def expired?(now = Time.current)
started? && expires_at < now
Expand Down
2 changes: 1 addition & 1 deletion app/views/member_mailer/membership_reminder.text.erb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ We'd love to see you!
<%= HTMLToMarkdown.new.convert(render(partial: "member_mailer/reminder")) %>
---------------------

<%= HTMLToMarkdown.new.convert(render(partial: "signup/confirmations/instructions.html")) %>
<%= HTMLToMarkdown.new.convert(render(partial: "signup/confirmations/instructions", formats: ["html"])) %>

---

Expand Down
7 changes: 0 additions & 7 deletions app/views/member_mailer/welcome_message.text.erb
Original file line number Diff line number Diff line change
@@ -1,10 +1,3 @@
Thank you for signing up as a member of The <%= @library.name %>. We are excited to have you!

<%= HTMLToMarkdown.new.convert(render(partial: "signup/confirmations/instructions", formats: [:html], locals: {library: @library})) %>
If you have any questions, please email us at team@chicagotoollibrary.org.

See you at the library!

---

<%= @library.address %>
4 changes: 3 additions & 1 deletion app/views/renewal/home/index.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
<ul>
<li>Read and agree to our updated terms.</li>
<li>Update your address and contact information if necessary.</li>
<li>Pay your annual membership fee.</li>
<% if @current_library.allow_payments? %>
<li>Pay your annual membership fee.</li>
<% end %>
</ul>
</div>

Expand Down
1 change: 0 additions & 1 deletion app/views/renewal/payments/new.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
<p>
<strong>Last year you paid <%= @amount.format(no_cents: true) %>.</strong>
This year we’re encouraging our library members who can afford to do so to give a little more. As always, though, we don’t turn anyone away for an inability to pay.

</p>
</div>
</div>
Expand Down
7 changes: 6 additions & 1 deletion app/views/signup/confirmations/_instructions.html.erb
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
<%# Library can come from local or instance variable. %>
<% library ||= @library %>
<% if @amount %>
<p><strong>Your payment of <%= @amount.format %> has been processed and applied to your account.</strong></p>
<% end %>
<p>To activate your membership, please bring the following with you to the library the first time you visit:</p>
<ul>
<li><strong>Proof of your address</strong><br>This needs to include your name and current address in <%= @library ? @library.city : library.city %>. Utility bills, leases, and other official mail work well for this.</li>
<li><strong>Proof of your address</strong><br>This needs to include your name and current address in <%= library.city %>. Utility bills, leases, and other official mail work well for this.</li>
<li><strong>A photo ID</strong><br>This needs to show your name and a photo and can be from the state, your job, school, etc.</li>
</ul>
<p>We're located at:<br>
4015 W. Carroll Ave, Suite 101<br>
Chicago, IL 60624</p>

<p>Please consider adding <strong><%= library.email %></strong> to your contacts to ensure our emails make it to your inbox!</p>
Loading

0 comments on commit dc9ad27

Please sign in to comment.