1
0
mirror of https://github.com/LaCasemate/fab-manager.git synced 2025-03-23 14:19:52 +01:00

Merge branch 'dev' for release X.Y.Z

This commit is contained in:
Nicolas Florentin 2023-09-28 16:03:33 +02:00
commit 6d9a81cf90
15 changed files with 137 additions and 18 deletions

View File

@ -1,5 +1,18 @@
# Changelog Fab-manager
## v6.1.1 2023 September 28
- Fix a bug: unable to sync projects with openprojects
- Fix a bug: public availabilities (no user) was buggy (server error)
- Fix a bug: unable to generate statistic
- Fix a bug: rss/projects was failing with project without image
- improvement : performance of members#show and reservations#index
- [TODO DEPLOY] `rails fablab:openlab:bulk_export`
- [TODO DEPLOY] `rails fablab:openlab:bulk_update`
- [TODO DEPLOY] `rails fablab:es:build_stats`
- [TODO DEPLOY] `rails fablab:maintenance:regenerate_statistics[2023,6]`
## v6.1.0 2023 September 25
- improves api/notification controller to avoid failing when there is a notification with wrong notification_type in db

View File

@ -16,8 +16,10 @@ class API::ReservationsController < API::APIController
where_clause[:reservable_id] = params[:reservable_id] if params[:reservable_id]
@reservations = Reservation.where(where_clause)
.preload(:reservable, :booking_users, :tickets, { statistic_profile: { user: :profile }, slots_reservations: :slot })
elsif params[:reservable_id] && params[:reservable_type] && (current_user.admin? || current_user.manager?)
@reservations = Reservation.where(params.permit(:reservable_id, :reservable_type))
.preload(:reservable, :booking_users, :tickets, { statistic_profile: { user: :profile }, slots_reservations: :slot })
else
@reservations = []
end

View File

@ -39,6 +39,10 @@
grid-template-columns: repeat(auto-fill, minmax(290px, 1fr));
gap: 3.2rem;
& > span { grid-column: 1/-1;}
& > a {
grid-column: 1/-1;
justify-self: center;
}
}
@media (min-width: 1200px) {

View File

@ -126,8 +126,7 @@
<p class="name">{{project.name}}</p>
<span class="openlab" ng-if="openlab.searchOverWholeNetwork"><i class="fa fa-tag"></i> {{ project.app_name }}</span>
</div>
</div>
<a class="btn btn-warning" ng-click="loadMore()" ng-if="projectsPagination.hasNextPage()" translate>{{ 'app.public.projects_list.load_next_projects' }}</a>
<a class="fab-button is-secondary" ng-click="loadMore()" ng-if="projectsPagination.hasNextPage()" translate>{{ 'app.public.projects_list.load_next_projects' }}</a>
</div>
</section>

View File

@ -40,7 +40,6 @@ class Availabilities::AvailabilitiesService
if @level == 'slot'
slots = availabilities.map(&:slots).flatten
blocked_slots = Slots::InterblockingService.new.blocked_slots_for_machines(machines, slots)
flag_or_remove_blocked_slots(slots, blocked_slots, @current_user)
else
@ -141,7 +140,7 @@ class Availabilities::AvailabilitiesService
end
def flag_or_remove_blocked_slots(slots, blocked_slots, user)
if user.admin? || user.manager?
if user && (user.admin? || user.manager?)
blocked_slots.each do |slot|
slot.is_blocked = true
end

View File

@ -3,8 +3,6 @@
# Provides methods to sync projects on OpenLab
class OpenLabService
class << self
include ActionView::Helpers::SanitizeHelper
def to_hash(project)
{
id: project.id,
@ -20,9 +18,9 @@ class OpenLabService
steps_body: steps_body(project),
image_path: project.project_image&.attachment&.medium&.url,
project_path: "/#!/projects/#{project.slug}",
updated_at: project.updated_at.to_s(:iso8601),
created_at: project.created_at.to_s(:iso8601),
published_at: project.published_at.to_s(:iso8601)
updated_at: project.updated_at.to_fs(:iso8601),
created_at: project.created_at.to_fs(:iso8601),
published_at: project.published_at.to_fs(:iso8601)
}
end
@ -32,7 +30,7 @@ class OpenLabService
.gsub("\r\n", ' ').gsub("\n\r", ' ')
.gsub("\n", ' ').gsub("\r", ' ').gsub("\t", ' ')
strip_tags(concatenated_steps).strip
ActionController::Base.helpers.strip_tags(concatenated_steps).strip
end
end
end

View File

@ -17,7 +17,7 @@ class Statistics::BuilderService
private
def default_options
yesterday = Time.current
yesterday = 1.day.ago
{
start_date: yesterday.beginning_of_day,
end_date: yesterday.end_of_day

View File

@ -10,7 +10,8 @@ json.trainings @member.trainings do |t|
json.id t.id
json.name t.name
end
json.training_reservations @member.reservations.where(reservable_type: 'Training').map(&:slots_reservations).flatten do |sr|
reservations = @member.reservations.where(reservable_type: 'Training').preload(slots_reservations: [:slot, reservation: :reservable])
json.training_reservations reservations.select { |r| r.reservable_type == "Training" }.map(&:slots_reservations).flatten do |sr|
json.id sr.id
json.start_at sr.slot.start_at
json.end_at sr.slot.end_at
@ -19,7 +20,7 @@ json.training_reservations @member.reservations.where(reservable_type: 'Training
json.is_valid @member.statistic_profile.training_ids.include?(sr.reservation.reservable_id)
json.canceled_at sr.canceled_at
end
json.machine_reservations @member.reservations.where(reservable_type: 'Machine').map(&:slots_reservations).flatten do |sr|
json.machine_reservations reservations.select { |r| r.reservable_type == "Machine" }.map(&:slots_reservations).flatten do |sr|
json.id sr.id
json.start_at sr.slot.start_at
json.end_at sr.slot.end_at
@ -27,7 +28,7 @@ json.machine_reservations @member.reservations.where(reservable_type: 'Machine')
json.reservable_type 'Machine'
json.canceled_at sr.canceled_at
end
json.space_reservations @member.reservations.where(reservable_type: 'Space').map(&:slots_reservations).flatten do |sr|
json.space_reservations reservations.select { |r| r.reservable_type == "Space" }.map(&:slots_reservations).flatten do |sr|
json.id sr.id
json.start_at sr.slot.start_at
json.end_at sr.slot.end_at

View File

@ -22,7 +22,9 @@ xml.rss version: '2.0', 'xmlns:xCal' => 'urn:ietf:params:xml:ns:xcal' do
xml.xCal :dtend do
xml.text! event.availability.end_at.strftime('%FT%T%:z')
end
xml.enclosure url: root_url + event.event_image.attachment.large.url, length: event.event_image.attachment.large.size, type: event.event_image.attachment.content_type if event.event_image
if event.event_image&.attachment?
xml.enclosure url: root_url + event.event_image.attachment.large.url, length: event.event_image.attachment.large.size, type: event.event_image.attachment.content_type
end
xml.category event.category.name
end
end

View File

@ -17,7 +17,9 @@ xml.rss version: '2.0' do
xml.link root_url + '#!/projects/' + project.slug
xml.author project.author&.user&.profile&.full_name
xml.description project.description
xml.enclosure url: root_url + project.project_image.attachment.large.url, length: project.project_image.attachment.large.size, type: project.project_image.attachment.content_type if project.project_image
if project.project_image&.attachment?
xml.enclosure url: root_url + project.project_image.attachment.large.url, length: project.project_image.attachment.large.size, type: project.project_image.attachment.content_type
end
end
end
end

View File

@ -1,6 +1,6 @@
{
"name": "fab-manager",
"version": "6.1.0",
"version": "6.1.1",
"description": "Fab-manager is the FabLab management solution. It provides a comprehensive, web-based, open-source tool to simplify your administrative tasks and your marker's projects.",
"keywords": [
"fablab",

View File

@ -3,7 +3,7 @@
require 'test_helper'
class Availabilities::AsPublicTest < ActionDispatch::IntegrationTest
test 'get public machines availabilities if machines module is active' do
test "[level == 'availability'] get public machines availabilities if machines module is active" do
start_date = Time.current.to_date
end_date = 7.days.from_now.to_date
@ -24,6 +24,24 @@ class Availabilities::AsPublicTest < ActionDispatch::IntegrationTest
end
end
test "[level == 'slot'] get public machines availabilities if machines module is active" do
start_date = Time.current.to_date
end_date = start_date + 1.day
get "/api/availabilities/public?start=#{start_date}&end=#{end_date}&timezone=Europe%2FParis&#{all_machines}"
# Check response format & status
assert_equal 200, response.status
assert_match Mime[:json].to_s, response.content_type
# Check the correct availabilities was returned
availabilities = json_response(response.body)
assert_not_empty availabilities, 'no availabilities were found'
availabilities.each do |a|
assert_not_empty a[:machine_ids]
end
end
test 'get anymore machines availabilities if machines module is inactive' do
Setting.set('machines_module', false)
start_date = Time.current.to_date
@ -61,6 +79,45 @@ class Availabilities::AsPublicTest < ActionDispatch::IntegrationTest
end
end
test "[level == 'availability'] get public spaces availabilities" do
start_date = Time.current.to_date
end_date = 7.days.from_now.to_date
get "/api/availabilities/public?start=#{start_date}&end=#{end_date}&timezone=Europe%2FParis&#{all_spaces}"
# Check response format & status
assert_equal 200, response.status
assert_match Mime[:json].to_s, response.content_type
# Check the correct availabilities was returned
availabilities = json_response(response.body)
assert_not_empty availabilities, 'no availabilities were found'
availabilities.each_with_index do |a, index|
assert_not_nil a, "availability #{index} was unexpectedly nil"
assert_equal 'space', a[:available_type], "availability #{index} is not a space availability"
assert Time.zone.parse(a[:start]) > start_date, "availability #{index} starts before the requested period"
assert Time.zone.parse(a[:end]) < end_date, "availability #{index} ends after the requested period"
end
end
test "[level == 'slot'] get public spaces availabilities" do
start_date = Time.current.to_date
end_date = start_date + 1.day
get "/api/availabilities/public?start=#{start_date}&end=#{end_date}&timezone=Europe%2FParis&#{all_spaces}"
# Check response format & status
assert_equal 200, response.status
assert_match Mime[:json].to_s, response.content_type
# Check the correct availabilities was returned
availabilities = json_response(response.body)
assert_not_empty availabilities, 'no availabilities were found'
availabilities.each do |a|
assert_not_nil a[:space_id]
end
end
test 'get public spaces availabilities' do
start_date = Time.current.to_date
end_date = 7.days.from_now.to_date

View File

@ -0,0 +1,13 @@
# frozen_string_literal: true
require 'test_helper'
module Rss; end
class Rss::EventsTestTest < ActionDispatch::IntegrationTest
test '#index' do
get rss_events_path
assert_response :success
assert Nokogiri::XML(response.body).errors.empty?
end
end

View File

@ -0,0 +1,13 @@
# frozen_string_literal: true
require 'test_helper'
module Rss; end
class Rss::ProjectsTestTest < ActionDispatch::IntegrationTest
test '#index' do
get rss_projects_path
assert_response :success
assert Nokogiri::XML(response.body).errors.empty?
end
end

View File

@ -0,0 +1,16 @@
# frozen_string_literal: true
require 'test_helper'
# In the following tests, amounts are expressed in centimes, ie. 1000 = 1000 cts = 10,00 EUR
class OpenLabServiceTest < ActiveSupport::TestCase
test "do not raise any error" do
h = nil
assert_nothing_raised do
h = OpenLabService.to_hash(projects(:project_1))
end
assert_instance_of Hash, h
end
end