From a17be289678bb301da44991cfbd89b60351f7932 Mon Sep 17 00:00:00 2001 From: Henry Date: Tue, 28 Jun 2022 10:48:07 -0400 Subject: [PATCH 01/28] ignoring conflicts WIP --- .../conflicts/session_conflicts_controller.rb | 33 ++------- .../conflicts/session_conflicts.vue | 9 +++ app/javascript/store/model.mixin.js | 2 +- .../store/session_conflict.mixin.js | 8 ++- .../store/session_conflict.store.js | 13 +++- app/models/ignored_conflict.rb | 2 + .../conflicts/session_conflict_policy.rb | 4 +- .../conflicts/session_conflict_serializer.rb | 2 +- config/routes.rb | 2 +- ...20220628121934_create_ignored_conflicts.rb | 12 ++++ db/structure.sql | 71 +++++++++++++++++-- lib/tasks/rbac.rake | 6 +- test/factories/ignored_conflicts.rb | 5 ++ test/models/ignored_conflict_test.rb | 7 ++ 14 files changed, 135 insertions(+), 41 deletions(-) create mode 100644 app/models/ignored_conflict.rb create mode 100644 db/migrate/20220628121934_create_ignored_conflicts.rb create mode 100644 test/factories/ignored_conflicts.rb create mode 100644 test/models/ignored_conflict_test.rb diff --git a/app/controllers/conflicts/session_conflicts_controller.rb b/app/controllers/conflicts/session_conflicts_controller.rb index 237c2092a..fb503aafa 100644 --- a/app/controllers/conflicts/session_conflicts_controller.rb +++ b/app/controllers/conflicts/session_conflicts_controller.rb @@ -1,36 +1,17 @@ class Conflicts::SessionConflictsController < ApplicationController respond_to :json - def index + # Add the requested conflict id to the ignored conflicts + def ignore authorize Conflicts::SessionConflict, policy_class: Conflicts::SessionConflictPolicy - per_page = params[:perPage]&.to_i || Conflicts::SessionConflict.default_per_page - current_page = params[:current_page]&.to_i + IgnoredConflict.transaction do + permitted = params.permit(:conflict_id, :conflict_type) - collection = Conflicts::SessionConflict - .includes([:session,:person,:session_assignment,:room]) - .where("session_assignment_name is null or session_assignment_name in ('Moderator', 'Participant', 'Invisible')") - .where("conflict_session_assignment_name is null or conflict_session_assignment_name in ('Moderator', 'Participant', 'Invisible')") - .distinct.page(current_page).per(per_page) - - collection_total = collection.total_count - full_collection_total = Conflicts::SessionConflict.distinct.count + ignored = IgnoredConflict.create(permitted) + end - meta = {} - meta[:total] = collection_total - meta[:full_total] = full_collection_total ? full_collection_total : collection_total - meta[:current_page] = current_page if current_page.present? - meta[:perPage] = per_page if per_page.present? - - options = { - meta: meta, - params: { - domain: "#{request.base_url}", - current_person: current_person - } - } - render json: Conflicts::SessionConflictSerializer.new(collection,options).serializable_hash(), - content_type: 'application/json' + render status: :ok, json: {}.to_json, content_type: 'application/json' end def conflicts_with diff --git a/app/javascript/conflicts/session_conflicts.vue b/app/javascript/conflicts/session_conflicts.vue index 50a64743c..5cb403523 100644 --- a/app/javascript/conflicts/session_conflicts.vue +++ b/app/javascript/conflicts/session_conflicts.vue @@ -11,12 +11,14 @@ v-for="conflict in conflicts" :key="conflict.id" >
+
+
@@ -80,6 +82,13 @@ export default { } }, methods: { + ignore(conflict) { + this.ignore_conflict({conflict_id: conflict.id, conflict_type: conflict.conflict_type}).then( + () => { + console.debug("***** conflict ignored ...") + } + ) + }, getConflicts(sessionId) { this.conflicts = [] this.conflicts_with = [] diff --git a/app/javascript/store/model.mixin.js b/app/javascript/store/model.mixin.js index 971a98618..f48030a85 100644 --- a/app/javascript/store/model.mixin.js +++ b/app/javascript/store/model.mixin.js @@ -11,7 +11,7 @@ export const modelMixinNoProp = { selected() { return this.$store.getters[SELECTED]({model: this.model}) }, - collection() { + collection() { return Object.values(this.$store.getters['jv/get']({_jv: { type: this.model }})) } }, diff --git a/app/javascript/store/session_conflict.mixin.js b/app/javascript/store/session_conflict.mixin.js index 4fda258eb..32767139f 100644 --- a/app/javascript/store/session_conflict.mixin.js +++ b/app/javascript/store/session_conflict.mixin.js @@ -2,6 +2,7 @@ import {mapActions } from 'vuex'; import { sessionConflictModel as model} from '@/store/session_conflict.store'; import {GET_CONFLICTS_FOR_SESSION} from '@/store/session_conflict.store'; import {GET_CONFLICTS_WITH_SESSION} from '@/store/session_conflict.store'; +import {IGNORE_CONFLICT} from '@/store/session_conflict.store'; import modelMixin from "./model.mixin"; @@ -10,13 +11,18 @@ export const sessionConflictMixin = { methods: { ...mapActions({ get_conflicts_for_session: GET_CONFLICTS_FOR_SESSION, - get_conflicts_with_session: GET_CONFLICTS_WITH_SESSION + get_conflicts_with_session: GET_CONFLICTS_WITH_SESSION, + do_ignore_conflict: IGNORE_CONFLICT }), get_conflicts({session_id}) { return this.get_conflicts_for_session({session_id: session_id}); }, get_conflicts_with({session_id}) { return this.get_conflicts_with_session({session_id: session_id}); + }, + ignore_conflict({conflict_id, conflict_type}) { + console.debug("***** IGNORE C") + return this.do_ignore_conflict({conflict_id: conflict_id, conflict_type: conflict_type}); } } } diff --git a/app/javascript/store/session_conflict.store.js b/app/javascript/store/session_conflict.store.js index 3e3818f71..3738e0dcb 100644 --- a/app/javascript/store/session_conflict.store.js +++ b/app/javascript/store/session_conflict.store.js @@ -1,5 +1,6 @@ export const GET_CONFLICTS_FOR_SESSION = 'GET CONFLICTS FOR SESSION'; export const GET_CONFLICTS_WITH_SESSION = 'GET CONFLICTS WITH SESSION'; +export const IGNORE_CONFLICT = 'IGNORE CONFLICT' export const sessionConflictModel = 'session_conflict'; export const sessionConflictEndpoints = { @@ -29,7 +30,17 @@ export const sessionConflictStore = { res({}); } }) - } + }, + [IGNORE_CONFLICT] ({commit, dispatch, state}, {conflict_id, conflict_type}) { + console.debug("***** do ignore", conflict_id, conflict_type) + return new Promise((res, rej) => { + if(conflict_id && conflict_type) { + dispatch('jv/get',`/session_conflict/ignore/${conflict_type}/${conflict_id}`) + } else { + res({}); + } + }) + }, }, selected: { [sessionConflictModel]: undefined diff --git a/app/models/ignored_conflict.rb b/app/models/ignored_conflict.rb new file mode 100644 index 000000000..6d081a0e1 --- /dev/null +++ b/app/models/ignored_conflict.rb @@ -0,0 +1,2 @@ +class IgnoredConflict < ApplicationRecord +end diff --git a/app/policies/conflicts/session_conflict_policy.rb b/app/policies/conflicts/session_conflict_policy.rb index 743849db6..e097d741c 100644 --- a/app/policies/conflicts/session_conflict_policy.rb +++ b/app/policies/conflicts/session_conflict_policy.rb @@ -1,6 +1,6 @@ class Conflicts::SessionConflictPolicy < BasePolicy - def index? - allowed?(action: :index) + def ignore? + allowed?(action: :ignore) end def conflicts_with? diff --git a/app/serializers/conflicts/session_conflict_serializer.rb b/app/serializers/conflicts/session_conflict_serializer.rb index 353e55848..490f82735 100644 --- a/app/serializers/conflicts/session_conflict_serializer.rb +++ b/app/serializers/conflicts/session_conflict_serializer.rb @@ -1,7 +1,7 @@ class Conflicts::SessionConflictSerializer include JSONAPI::Serializer - attribute :person_id, :person_name, :person_published_name, + attribute :id, :person_id, :person_name, :person_published_name, :session_assignment_id, :session_id, :session_title, :session_start_time, :conflict_session_id, :conflict_session_title, diff --git a/config/routes.rb b/config/routes.rb index c923c490c..125acfe35 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -85,7 +85,7 @@ get 'agreement/latest', to: 'agreements#latest' resources :agreements, path: 'agreement' - get 'session_conflict', to: 'conflicts/session_conflicts#index' + get 'session_conflict/ignore/:conflict_type/:conflict_id', to: 'conflicts/session_conflicts#ignore' get 'session_conflict/conflicts_for/:session_id', to: 'conflicts/session_conflicts#conflicts_for' get 'session_conflict/conflicts_with/:session_id', to: 'conflicts/session_conflicts#conflicts_with' diff --git a/db/migrate/20220628121934_create_ignored_conflicts.rb b/db/migrate/20220628121934_create_ignored_conflicts.rb new file mode 100644 index 000000000..c7ddb112d --- /dev/null +++ b/db/migrate/20220628121934_create_ignored_conflicts.rb @@ -0,0 +1,12 @@ +class CreateIgnoredConflicts < ActiveRecord::Migration[6.1] + def change + create_table :ignored_conflicts, id: :uuid do |t| + t.string :conflict_id, limit: 2048 + t.string :conflict_type + + t.timestamps + end + + add_index :ignored_conflicts, [:conflict_id, :conflict_type], unique: true + end +end diff --git a/db/structure.sql b/db/structure.sql index 7879ec8f5..01b68b05a 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -676,6 +676,7 @@ CREATE VIEW public.availability_conflicts AS people.published_name AS person_published_name, sessions.id AS session_id, sessions.title AS session_title, + sessions.start_time AS session_start_time, session_assignments.session_assignment_role_type_id, sart.role_type AS session_assignment_role_type, sart.name AS session_assignment_name @@ -871,6 +872,19 @@ CREATE TABLE public.formats ( ); +-- +-- Name: ignored_conflicts; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.ignored_conflicts ( + id uuid DEFAULT public.gen_random_uuid() NOT NULL, + conflict_id character varying(2048), + conflict_type character varying, + created_at timestamp(6) without time zone NOT NULL, + updated_at timestamp(6) without time zone NOT NULL +); + + -- -- Name: label_dimensions; Type: TABLE; Schema: public; Owner: - -- @@ -1225,6 +1239,7 @@ CREATE VIEW public.person_exclusion_conflicts AS person_schedules.con_state, es.exclusion_id, es.session_id AS excluded_session_id, + s.title AS excluded_session_title, person_schedules.session_id, person_schedules.title, person_schedules.area_list, @@ -1232,6 +1247,7 @@ CREATE VIEW public.person_exclusion_conflicts AS person_schedules.end_time, person_schedules.duration, person_schedules.session_assignment_role_type_id, + person_schedules.session_assignment_id, person_schedules.session_assignment_name, person_schedules.session_assignment_role_type FROM (((public.person_schedules @@ -1418,9 +1434,30 @@ CREATE TABLE public.schema_migrations ( -- CREATE VIEW public.session_conflicts AS + SELECT person_exclusion_conflicts.session_id, + person_exclusion_conflicts.title AS session_title, + person_exclusion_conflicts.start_time AS session_start_time, + NULL::uuid AS room_id, + NULL::text AS room_name, + person_exclusion_conflicts.person_id, + person_exclusion_conflicts.name AS person_name, + person_exclusion_conflicts.published_name AS person_published_name, + person_exclusion_conflicts.session_assignment_id, + person_exclusion_conflicts.session_assignment_role_type_id, + person_exclusion_conflicts.session_assignment_name, + person_exclusion_conflicts.excluded_session_id AS conflict_session_id, + person_exclusion_conflicts.excluded_session_title AS conflict_session_title, + NULL::uuid AS conflict_session_assignment_role_type_id, + NULL::text AS conflict_session_assignment_name, + person_exclusion_conflicts.id AS conflict_id, + 'person_exclusion_conflict'::text AS conflict_type + FROM public.person_exclusion_conflicts +UNION SELECT availability_conflicts.session_id, availability_conflicts.session_title, + availability_conflicts.session_start_time, NULL::uuid AS room_id, + NULL::text AS room_name, availability_conflicts.person_id, availability_conflicts.person_name, availability_conflicts.person_published_name, @@ -1428,16 +1465,18 @@ CREATE VIEW public.session_conflicts AS availability_conflicts.session_assignment_role_type_id, availability_conflicts.session_assignment_name, NULL::uuid AS conflict_session_id, - NULL::text AS conflict_session_title, + NULL::character varying AS conflict_session_title, NULL::uuid AS conflict_session_assignment_role_type_id, NULL::text AS conflict_session_assignment_name, availability_conflicts.id AS conflict_id, - 'availability'::text AS conflict_type + 'availability_conflict'::text AS conflict_type FROM public.availability_conflicts UNION SELECT room_conflicts.session_id, room_conflicts.session_title, + room_conflicts.start_time AS session_start_time, room_conflicts.room_id, + room_conflicts.room_name, NULL::uuid AS person_id, NULL::character varying AS person_name, NULL::character varying AS person_published_name, @@ -1445,7 +1484,7 @@ UNION NULL::uuid AS session_assignment_role_type_id, NULL::character varying AS session_assignment_name, room_conflicts.conflicting_session_id AS conflict_session_id, - NULL::text AS conflict_session_title, + room_conflicts.conflicting_session_title AS conflict_session_title, NULL::uuid AS conflict_session_assignment_role_type_id, NULL::text AS conflict_session_assignment_name, room_conflicts.id AS conflict_id, @@ -1455,7 +1494,9 @@ UNION UNION SELECT person_schedule_conflicts.session_id, person_schedule_conflicts.title AS session_title, + person_schedule_conflicts.start_time AS session_start_time, person_schedule_conflicts.room_id, + person_schedule_conflicts.room_name, person_schedule_conflicts.person_id, person_schedule_conflicts.name AS person_name, person_schedule_conflicts.published_name AS person_published_name, @@ -1467,13 +1508,15 @@ UNION person_schedule_conflicts.conflict_session_assignment_role_type_id, person_schedule_conflicts.conflict_session_assignment_name, person_schedule_conflicts.id AS conflict_id, - 'person_session_conflict'::text AS conflict_type + 'person_schedule_conflict'::text AS conflict_type FROM public.person_schedule_conflicts WHERE (person_schedule_conflicts.back_to_back = false) UNION SELECT person_schedule_conflicts.session_id, person_schedule_conflicts.title AS session_title, + person_schedule_conflicts.start_time AS session_start_time, person_schedule_conflicts.room_id, + person_schedule_conflicts.room_name, person_schedule_conflicts.person_id, person_schedule_conflicts.name AS person_name, person_schedule_conflicts.published_name AS person_published_name, @@ -1485,7 +1528,7 @@ UNION person_schedule_conflicts.conflict_session_assignment_role_type_id, person_schedule_conflicts.conflict_session_assignment_name, person_schedule_conflicts.id AS conflict_id, - 'person_session_conflict'::text AS conflict_type + 'person_back_to_back'::text AS conflict_type FROM public.person_schedule_conflicts WHERE (person_schedule_conflicts.back_to_back = true); @@ -1989,6 +2032,14 @@ ALTER TABLE ONLY public.formats ADD CONSTRAINT formats_pkey PRIMARY KEY (id); +-- +-- Name: ignored_conflicts ignored_conflicts_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.ignored_conflicts + ADD CONSTRAINT ignored_conflicts_pkey PRIMARY KEY (id); + + -- -- Name: label_dimensions label_dimensions_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- @@ -2477,6 +2528,13 @@ CREATE UNIQUE INDEX index_exclusions_sessions_on_exclusion_id_and_session_id ON CREATE INDEX index_exclusions_sessions_on_session_id ON public.exclusions_sessions USING btree (session_id); +-- +-- Name: index_ignored_conflicts_on_conflict_id_and_conflict_type; Type: INDEX; Schema: public; Owner: - +-- + +CREATE UNIQUE INDEX index_ignored_conflicts_on_conflict_id_and_conflict_type ON public.ignored_conflicts USING btree (conflict_id, conflict_type); + + -- -- Name: index_magic_links_on_person_id; Type: INDEX; Schema: public; Owner: - -- @@ -3054,6 +3112,7 @@ INSERT INTO "schema_migrations" (version) VALUES ('20220623144036'), ('20220623145514'), ('20220623172955'), -('20220624121252'); +('20220624121252'), +('20220628121934'); diff --git a/lib/tasks/rbac.rake b/lib/tasks/rbac.rake index 2c43479b0..b74c5d162 100644 --- a/lib/tasks/rbac.rake +++ b/lib/tasks/rbac.rake @@ -497,7 +497,8 @@ namespace :rbac do }, "session_conflict": { "conflicts_with": true, - "conflicts_for": true + "conflicts_for": true, + "ignore": true } }) end @@ -752,7 +753,8 @@ namespace :rbac do }, "session_conflict": { "conflicts_with": true, - "conflicts_for": true + "conflicts_for": true, + "ignore": true } }) end diff --git a/test/factories/ignored_conflicts.rb b/test/factories/ignored_conflicts.rb new file mode 100644 index 000000000..4f79f435e --- /dev/null +++ b/test/factories/ignored_conflicts.rb @@ -0,0 +1,5 @@ +FactoryBot.define do + factory :ignored_conflict do + + end +end diff --git a/test/models/ignored_conflict_test.rb b/test/models/ignored_conflict_test.rb new file mode 100644 index 000000000..0bc33d10c --- /dev/null +++ b/test/models/ignored_conflict_test.rb @@ -0,0 +1,7 @@ +require "test_helper" + +class IgnoredConflictTest < ActiveSupport::TestCase + # test "the truth" do + # assert true + # end +end From 41f16b894788fed3cb2c9d5a5e8d21a53326854e Mon Sep 17 00:00:00 2001 From: Henry Date: Tue, 28 Jun 2022 13:48:23 -0400 Subject: [PATCH 02/28] WIP --- .../conflicts/session_conflicts.vue | 3 ++- app/javascript/constants/strings.js | 3 +++ .../store/session_conflict.mixin.js | 19 ++++++++++++++----- .../store/session_conflict.store.js | 11 ++--------- 4 files changed, 21 insertions(+), 15 deletions(-) diff --git a/app/javascript/conflicts/session_conflicts.vue b/app/javascript/conflicts/session_conflicts.vue index 42317271d..1ad2be85c 100644 --- a/app/javascript/conflicts/session_conflicts.vue +++ b/app/javascript/conflicts/session_conflicts.vue @@ -85,7 +85,8 @@ export default { ignore(conflict) { this.ignore_conflict({conflict_id: conflict.id, conflict_type: conflict.conflict_type}).then( () => { - console.debug("***** conflict ignored ...") + // console.debug("***** conflict ignored ...") + // TODO: refresh } ) }, diff --git a/app/javascript/constants/strings.js b/app/javascript/constants/strings.js index 6654f9a05..7d9762ab5 100644 --- a/app/javascript/constants/strings.js +++ b/app/javascript/constants/strings.js @@ -197,6 +197,9 @@ module.exports = { ERROR_GENERIC_UNRECOVERABLE: (email) => twoLines("The server has encountered an internal error and was unable to complete your request.", `Please contact the server administrator at ${email} and let them know the time and date the error occurred.`), + ADD_CONFLICT_IGNORE_SUCCESS: "Ignore Conflict Added", + ADD_CONFLICT_IGNORE_ERROR: "Ignore Conflict Failed", + // Social Links Errors TWITTER_ID_INVALID_MSG: "Twitter ID is not in a valid format", FACEBOOK_ID_INVALID_MSG: "Facebook ID is not in a valid format", diff --git a/app/javascript/store/session_conflict.mixin.js b/app/javascript/store/session_conflict.mixin.js index 32767139f..7f5db09a1 100644 --- a/app/javascript/store/session_conflict.mixin.js +++ b/app/javascript/store/session_conflict.mixin.js @@ -4,10 +4,15 @@ import {GET_CONFLICTS_FOR_SESSION} from '@/store/session_conflict.store'; import {GET_CONFLICTS_WITH_SESSION} from '@/store/session_conflict.store'; import {IGNORE_CONFLICT} from '@/store/session_conflict.store'; -import modelMixin from "./model.mixin"; +import { toastMixin, modelMixin } from "@/mixins"; + +import { + ADD_CONFLICT_IGNORE_SUCCESS, + ADD_CONFLICT_IGNORE_ERROR +} from '../constants/strings' export const sessionConflictMixin = { - mixins: [modelMixin], + mixins: [modelMixin, toastMixin], methods: { ...mapActions({ get_conflicts_for_session: GET_CONFLICTS_FOR_SESSION, @@ -20,9 +25,13 @@ export const sessionConflictMixin = { get_conflicts_with({session_id}) { return this.get_conflicts_with_session({session_id: session_id}); }, - ignore_conflict({conflict_id, conflict_type}) { - console.debug("***** IGNORE C") - return this.do_ignore_conflict({conflict_id: conflict_id, conflict_type: conflict_type}); + ignore_conflict({conflict_id, conflict_type}, success_text = ADD_CONFLICT_IGNORE_SUCCESS, error_text = ADD_CONFLICT_IGNORE_ERROR) { + return this.toastPromise( + this.do_ignore_conflict({conflict_id: conflict_id, conflict_type: conflict_type}), + success_text, + error_text + ); + } } } diff --git a/app/javascript/store/session_conflict.store.js b/app/javascript/store/session_conflict.store.js index 3738e0dcb..eaddae892 100644 --- a/app/javascript/store/session_conflict.store.js +++ b/app/javascript/store/session_conflict.store.js @@ -32,15 +32,8 @@ export const sessionConflictStore = { }) }, [IGNORE_CONFLICT] ({commit, dispatch, state}, {conflict_id, conflict_type}) { - console.debug("***** do ignore", conflict_id, conflict_type) - return new Promise((res, rej) => { - if(conflict_id && conflict_type) { - dispatch('jv/get',`/session_conflict/ignore/${conflict_type}/${conflict_id}`) - } else { - res({}); - } - }) - }, + return dispatch('jv/get',`/session_conflict/ignore/${conflict_type}/${conflict_id}`); + } }, selected: { [sessionConflictModel]: undefined From 3aa891886b155df42355adae125742cdb2029927 Mon Sep 17 00:00:00 2001 From: Henry Date: Tue, 28 Jun 2022 14:21:32 -0400 Subject: [PATCH 03/28] PLAN-418 and PLAN-385 UI etc to ignore conflicts --- .../conflicts/session_conflicts_controller.rb | 2 ++ app/javascript/conflicts/session_conflicts.vue | 3 +-- app/models/session.rb | 14 ++++++++++++-- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/app/controllers/conflicts/session_conflicts_controller.rb b/app/controllers/conflicts/session_conflicts_controller.rb index fb503aafa..da00e8efb 100644 --- a/app/controllers/conflicts/session_conflicts_controller.rb +++ b/app/controllers/conflicts/session_conflicts_controller.rb @@ -23,6 +23,7 @@ def conflicts_with .where("conflict_session_id = ?", session_id) .where("session_assignment_name is null or session_assignment_name in ('Moderator', 'Participant', 'Invisible')") .where("conflict_session_assignment_name is null or conflict_session_assignment_name in ('Moderator', 'Participant', 'Invisible')") + .where("session_conflicts.conflict_id not in (select conflict_id from ignored_conflicts)") .distinct meta = {} @@ -51,6 +52,7 @@ def conflicts_for .where("session_id = ?", session_id) .where("session_assignment_name is null or session_assignment_name in ('Moderator', 'Participant', 'Invisible')") .where("conflict_session_assignment_name is null or conflict_session_assignment_name in ('Moderator', 'Participant', 'Invisible')") + .where("session_conflicts.conflict_id not in (select conflict_id from ignored_conflicts)") .distinct meta = {} diff --git a/app/javascript/conflicts/session_conflicts.vue b/app/javascript/conflicts/session_conflicts.vue index 1ad2be85c..b47479ea8 100644 --- a/app/javascript/conflicts/session_conflicts.vue +++ b/app/javascript/conflicts/session_conflicts.vue @@ -85,8 +85,7 @@ export default { ignore(conflict) { this.ignore_conflict({conflict_id: conflict.id, conflict_type: conflict.conflict_type}).then( () => { - // console.debug("***** conflict ignored ...") - // TODO: refresh + this.getConflicts(this.sessionId) } ) }, diff --git a/app/models/session.rb b/app/models/session.rb index 48625c530..7d89057ab 100644 --- a/app/models/session.rb +++ b/app/models/session.rb @@ -18,9 +18,14 @@ class Session < ApplicationRecord before_save :keep_who_did_it, :keep_interest_trail, :schedule_consistency - has_many :session_conflicts, class_name: 'Conflicts::SessionConflict' + has_many :session_conflicts, + -> { where("session_conflicts.conflict_id not in (select conflict_id from ignored_conflicts)") }, + class_name: 'Conflicts::SessionConflict' + # Get where this session is on the other side of the conflict relationship - has_many :conflict_sessions, foreign_key: :conflict_session_id, class_name: 'Conflicts::SessionConflict' + has_many :conflict_sessions, + -> { where("session_conflicts.conflict_id not in (select conflict_id from ignored_conflicts)") }, + foreign_key: :conflict_session_id, class_name: 'Conflicts::SessionConflict' has_and_belongs_to_many :room_services @@ -115,6 +120,7 @@ def self.area_list def self.conflict_counts sessions = Session.arel_table conflicts = Conflicts::SessionConflict.arel_table + ignored_conflicts = ::IgnoredConflict.arel_table sessions.project( sessions[:id].as('session_id'), @@ -127,6 +133,10 @@ def self.conflict_counts .and( conflicts[:session_assignment_name].eq(nil).or(conflicts[:session_assignment_name].in(['Moderator', 'Participant', 'Invisible'])).and( conflicts[:conflict_session_assignment_name].eq(nil).or(conflicts[:conflict_session_assignment_name].in(['Moderator', 'Participant', 'Invisible'])) + ).and( + conflicts[:conflict_id].not_in( + ignored_conflicts.project(ignored_conflicts[:conflict_id]) + ) ) ) ) From 7b2f39e99089c6127896000a2b87dde817415ae0 Mon Sep 17 00:00:00 2001 From: Henry Date: Tue, 28 Jun 2022 17:08:39 -0400 Subject: [PATCH 04/28] Fix exclision report PLAN-343 --- .../reports/conflict_reports_controller.rb | 17 ++-- app/lib/migration_helpers/plano_views.rb | 84 +++++++++++++------ 2 files changed, 69 insertions(+), 32 deletions(-) diff --git a/app/controllers/reports/conflict_reports_controller.rb b/app/controllers/reports/conflict_reports_controller.rb index 2a1b444f3..00cba1886 100644 --- a/app/controllers/reports/conflict_reports_controller.rb +++ b/app/controllers/reports/conflict_reports_controller.rb @@ -65,6 +65,7 @@ def person_exclusion_conflicts :person, :session, :exclusion, :excluded_session ) .where("session_assignment_name in ('Moderator', 'Participant', 'Invisible')") + .order('people.published_name asc') workbook = FastExcel.open(constant_memory: true) worksheet = workbook.add_worksheet("Person vs Exclusion") @@ -144,7 +145,7 @@ def back_to_back_to_back 'Conflict 2 Start Time', 'Conflict 2 Session Duration', 'Conflict 2 Room' - + ] ) date_time_style = workbook.number_format("d mmm yyyy h:mm") @@ -179,7 +180,7 @@ def back_to_back_to_back conflict.conflict_duration, conflict.conflict_room_name - + ], styles ) @@ -217,7 +218,7 @@ def back_to_back 'Conflict Start Time', 'Conflict Session Duration', 'Conflict Room' - + ] ) date_time_style = workbook.number_format("d mmm yyyy h:mm") @@ -239,7 +240,7 @@ def back_to_back FastExcel.date_num(conflict.conflict_start_time, conflict.conflict_start_time.in_time_zone.utc_offset), conflict.conflict_duration, conflict.conflict_room_name - + ], styles ) @@ -300,7 +301,7 @@ def people_double_booked 'Conflict Session', 'Conflict Area', 'Conflict Room' - + ] ) date_time_style = workbook.number_format("d mmm yyyy h:mm") @@ -318,7 +319,7 @@ def people_double_booked conflict.conflict_session.title, conflict.conflict_areas_list.join('; '), conflict.conflict_room.name - + ], styles ) @@ -364,7 +365,7 @@ def people_outside_availability 'Session', 'Area', 'Start Time' - + ] ) date_time_style = workbook.number_format("d mmm yyyy h:mm") @@ -378,7 +379,7 @@ def people_outside_availability conflict.session.title, conflict.area_list.join('; '), FastExcel.date_num(conflict.session.start_time, conflict.session.start_time.in_time_zone.utc_offset) - + ], styles ) diff --git a/app/lib/migration_helpers/plano_views.rb b/app/lib/migration_helpers/plano_views.rb index 473d3876c..90e9c4af5 100644 --- a/app/lib/migration_helpers/plano_views.rb +++ b/app/lib/migration_helpers/plano_views.rb @@ -2,6 +2,7 @@ module MigrationHelpers module PlanoViews def self.create_views self.create_person_schedules + self.create_person_and_exclusions self.create_room_allocations self.create_room_conflicts self.create_person_schedule_conflicts @@ -192,33 +193,65 @@ def self.create_person_schedule_conflicts ActiveRecord::Base.connection.execute(query) end + def self.create_person_and_exclusions + query = <<-SQL.squish + CREATE OR REPLACE VIEW person_and_exclusions AS + select + pe.exclusion_id, + pe.person_id, + s.id as session_id, + s.start_time, + (s.start_time + (s.duration || ' minute')::interval) as end_time, + s.title + from + person_exclusions pe + left join exclusions_sessions es on + es.exclusion_id = pe.exclusion_id + left join sessions s on + s.id = es.session_id + where + session_id is not null + order by + pe.person_id, session_id + SQL + ActiveRecord::Base.connection.execute(query) + end + def self.create_person_exclusion_conflicts query = <<-SQL.squish CREATE OR REPLACE VIEW person_exclusion_conflicts AS - SELECT - concat(person_schedules.person_id, ':', es.exclusion_id, ':', person_schedules.session_id) AS id, - person_schedules.person_id, - person_schedules.name, - person_schedules.published_name, - person_schedules.con_state, - es.exclusion_id, - es.session_id AS excluded_session_id, - s.title as excluded_session_title, - person_schedules.session_id, - person_schedules.title, - person_schedules.area_list, - person_schedules.start_time, - person_schedules.end_time, - person_schedules.duration, - person_schedules.session_assignment_role_type_id, - person_schedules.session_assignment_id, - person_schedules.session_assignment_name, - person_schedules.session_assignment_role_type - FROM (((public.person_schedules - LEFT JOIN public.person_exclusions pe ON ((pe.person_id = person_schedules.person_id))) - JOIN public.exclusions_sessions es ON ((es.exclusion_id = pe.exclusion_id))) - LEFT JOIN public.sessions s ON ((s.id = es.session_id))) - WHERE ((person_schedules.session_id <> s.id) AND (person_schedules.start_time >= s.start_time) AND ((person_schedules.start_time <= (s.start_time + ((s.duration || ' minute'::text))::interval)) OR ((person_schedules.end_time >= s.start_time) AND (person_schedules.end_time <= (s.start_time + ((s.duration || ' minute'::text))::interval))))); + select + concat(person_schedules.person_id, ':', pe.exclusion_id, ':', person_schedules.session_id) as id, + person_schedules.person_id, + person_schedules.name, + person_schedules.published_name, + person_schedules.con_state, + pe.exclusion_id, + pe.session_id as excluded_session_id, + pe.title as excluded_session_title, + person_schedules.session_id, + person_schedules.title, + person_schedules.area_list, + person_schedules.start_time, + person_schedules.end_time, + person_schedules.duration, + person_schedules.session_assignment_role_type_id, + person_schedules.session_assignment_id, + person_schedules.session_assignment_name, + person_schedules.session_assignment_role_type + from + person_schedules + join + person_and_exclusions pe on pe.person_id = person_schedules.person_id + and person_schedules.session_id != pe.session_id + and pe.start_time >= person_schedules.start_time + and ( + person_schedules.start_time <= person_schedules.end_time + or + ( + person_schedules.end_time >= person_schedules.start_time and pe.end_time <= person_schedules.end_time + ) + ) SQL ActiveRecord::Base.connection.execute(query) end @@ -470,6 +503,9 @@ def self.drop_views ActiveRecord::Base.connection.execute <<-SQL DROP VIEW IF EXISTS room_allocations; SQL + ActiveRecord::Base.connection.execute <<-SQL + DROP VIEW IF EXISTS person_and_exclusions; + SQL ActiveRecord::Base.connection.execute <<-SQL DROP VIEW IF EXISTS person_schedules; SQL From 75ec4f08c4c8ce3b0b2cdb0de053945c9e2f3912 Mon Sep 17 00:00:00 2001 From: Henry Date: Tue, 28 Jun 2022 18:52:14 -0400 Subject: [PATCH 05/28] fix selection issues with vuex jsonapi store and included models So now we get the other sessions for the conflict and their indicators will update PLAN-410 --- .../conflicts/session_conflicts_controller.rb | 4 +-- app/javascript/components/table_vue.vue | 31 ++++++++++++++++--- app/javascript/sessions/session.js | 3 ++ 3 files changed, 32 insertions(+), 6 deletions(-) diff --git a/app/controllers/conflicts/session_conflicts_controller.rb b/app/controllers/conflicts/session_conflicts_controller.rb index 237c2092a..5eb23da4c 100644 --- a/app/controllers/conflicts/session_conflicts_controller.rb +++ b/app/controllers/conflicts/session_conflicts_controller.rb @@ -50,7 +50,7 @@ def conflicts_with options = { meta: meta, include: [ - # :session + :session ], params: { domain: "#{request.base_url}", @@ -78,7 +78,7 @@ def conflicts_for options = { meta: meta, include: [ - # :conflict_session + :conflict_session ], params: { domain: "#{request.base_url}", diff --git a/app/javascript/components/table_vue.vue b/app/javascript/components/table_vue.vue index 9cd5c72e2..30eaea3bb 100644 --- a/app/javascript/components/table_vue.vue +++ b/app/javascript/components/table_vue.vue @@ -188,7 +188,9 @@ export default { data () { return { selected_items: [], - editable_ids: [] + editable_ids: [], + keep: false, // semaphore to catch "false" unselect + selecedRowNbr: -1 // keep track of selected row to keep display } }, computed: { @@ -266,9 +268,21 @@ export default { onRowSelected(items) { this.selected_items = items if (items[0] && (items.length == 1)) { + // keep the index of the row that was selected + this.selecedRowNbr = this.sortedCollection.indexOf(items[0]) this.select(items[0]); } else { - this.select(null); + if (this.keep) { // semaphore to keep selected from getting unselected ... + // This is ugly but it works !!!! + this.keep = false + if (this.selecedRowNbr > -1) { + this.$refs.table.selectRow(this.selecedRowNbr) + } + } else { + // standard unselect + this.select(null); + this.selecedRowNbr = -1; + } } }, onSortChanged(ctx) { @@ -288,21 +302,30 @@ export default { } }, watch: { + sortedCollection(nv, ov) { + if (ov.length == 0 && nv.length > 0) { + this.keep = false + } else { + // If the length has not changed ... + this.keep = true + } + }, selected(val) { if (!val && this.selected_items.length == 1) { this.$refs.table.clearSelected() } }, - currentPage(ov,nv) { + currentPage(nv,ov) { if (ov != nv) { // page was changed so we clear our selected this.selected_items = [] this.editable_ids = [] + this.keep = false + this.selecedRowNbr = -1 } } }, mounted() { - // ensure that there is no model selected when the table is loaded this.editable_ids = [] this.unselect(); } diff --git a/app/javascript/sessions/session.js b/app/javascript/sessions/session.js index e64b75c2f..33d65e866 100644 --- a/app/javascript/sessions/session.js +++ b/app/javascript/sessions/session.js @@ -1,6 +1,9 @@ import AreaSelectForSearch from './area_select_for_search' export const session_columns = [ + // { + // key: 'id' + // }, { key: 'title', sortKey: 'sessions.title', From 53929bd1e66ab6d0c57ae1bbb1f2beb7bb6d3978 Mon Sep 17 00:00:00 2001 From: Gail Terman Date: Tue, 28 Jun 2022 23:40:07 -0400 Subject: [PATCH 06/28] PLAN-435 Signups required and session environment --- app/controllers/sessions_controller.rb | 1 + app/javascript/constants/strings.js | 6 +++ app/javascript/sessions/session_edit.vue | 60 ++++++++++++++++++--- app/javascript/sessions/session_sidebar.vue | 10 ++-- 4 files changed, 67 insertions(+), 10 deletions(-) diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index 2364eabdf..803ce53b5 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -277,6 +277,7 @@ def allowed_params status environment minors_participation + require_signup ] # Tags # format diff --git a/app/javascript/constants/strings.js b/app/javascript/constants/strings.js index 7d9762ab5..79e56d0fb 100644 --- a/app/javascript/constants/strings.js +++ b/app/javascript/constants/strings.js @@ -244,4 +244,10 @@ module.exports = { SURVEY_REDIRECT: "Unfortunately due to the browser refreshing we have lost any answers you filled in. Please fill the survey out again.", SURVEY_PUBLIC_NO_EDIT: "You cannot edit a published survey. Close the survey to enable editing.", SURVEY_PUBLIC_NO_DELETE: "You cannot delete a published survey. Close the survey to enable deletion.", + SESSION_ENVIRONMENT: { + unknown: "Unknown", + in_person: "In Person", + hybrid: "Hybrid", + virtual: "Virtual" + }, } diff --git a/app/javascript/sessions/session_edit.vue b/app/javascript/sessions/session_edit.vue index b56787cad..8ca9c60aa 100644 --- a/app/javascript/sessions/session_edit.vue +++ b/app/javascript/sessions/session_edit.vue @@ -60,15 +60,43 @@
- +
({ editable: false, - saving: false + saving: false, + SESSION_ENVIRONMENT }), computed: { session() { @@ -172,7 +210,15 @@ export default { }, saveSession() { this.save_model(sessionModel, this.session) - } + }, + saveValidatedSession({dirty, valid=null}) { + if(dirty && valid) { + this.save_model(sessionModel, this.session) + } + }, + getValidationState({ dirty, validated, valid = null }) { + return dirty || validated ? valid : null; + }, } } diff --git a/app/javascript/sessions/session_sidebar.vue b/app/javascript/sessions/session_sidebar.vue index 15d588c7e..040aa5060 100644 --- a/app/javascript/sessions/session_sidebar.vue +++ b/app/javascript/sessions/session_sidebar.vue @@ -55,11 +55,13 @@
None Selected
Format
{{selected.format.name}}
- +
None Set
Interest Instructions
No Entry
@@ -114,6 +116,7 @@ import { areaMixin, scheduledMixin, startTimeMixin } from './session_fields.mixi import { sessionConflictModel } from '@/store/session_conflict.store'; import SessionConflicts from '@/conflicts/session_conflicts.vue'; // import SessionAdminTab from './session_admin_tab'; +import { SESSION_ENVIRONMENT} from '@/constants/strings'; export default { name: 'SessionSidebar', @@ -132,7 +135,8 @@ export default { startTimeMixin ], data: () => ({ - sessionConflictModel + sessionConflictModel, + SESSION_ENVIRONMENT }), computed: { editLink() { From d0035d3bb6181db5372337bb79a849f8a88df71d Mon Sep 17 00:00:00 2001 From: Gail Terman Date: Tue, 28 Jun 2022 23:41:26 -0400 Subject: [PATCH 07/28] PLAN-498 add favico Now we are no longer anonymous! Hope it works all the way up as well as it does on my local! --- app/assets/images/p_for_plano.png | Bin 0 -> 2131 bytes app/views/layouts/application.html.erb | 1 + 2 files changed, 1 insertion(+) create mode 100644 app/assets/images/p_for_plano.png diff --git a/app/assets/images/p_for_plano.png b/app/assets/images/p_for_plano.png new file mode 100644 index 0000000000000000000000000000000000000000..099c95d6d28409dd0a80455f529e7551564b03db GIT binary patch literal 2131 zcmV-Z2(0&sP)$YEt{q7j05$sfH>|C9xt8SQ-sA)+SzJwFXVq zCYq|4dT&5fM2o2uk;`xyaG1+EbFO>uwN@Wap@6_Z`_S)cXYKXv|1bY_h3jqzClEW7u;sb*hgQ+Q5(qH(5#ahn^1u&quK(fS{jGS)OU@N4AgLm1uYRufEMV2Pv(M&1XEk6 z>>2!hdQtR~doI7+oKXpueD|e=`ET~TRrz?3#%D!js}BxbEdfs=QwkSb>{x8Zy8G8$e$&YS)QJNhe70`SoJ(%HHZ#4WyZ-qI zLJDvoJlT9U4%aaFy%};hbR$EB$Z5hkZK%9Qyt~?*>q(M*Rbo@4Wk%Np7j<4&-SqL( z8&1@dC!?~(_%W{~L`@37x~5Oo0pJpc?g`0U-AVQBLCP-VMNY(hEAMZ5$@rUPgq9 zAeSQ$S(4W)_|vn9P=SSDZUNy*YCA^oCa0zQB6;er-@Z3>T!6JtE-IRO@^;YGdUQr` zQ68ZMGNW)7q8($%P~)Wn%!K46Gt=DC2rH|F6Orx+uwyY^Pl!J|N3yqu$t9%f>GtyG z(yH+t0BkK;FVhN<)}SCYy9JTcpaiawK;j6(9Abv|=!4H(d;QwqUG?ZEvp-m2ovlgV z0|6qX@MmPPWrNU)NLERPqigSeb60*`faIWkqY;-Qo%4~QLQM+rr)RO11cX2ciSc3^ z^kyDDlJm9aXXczS5Lsm2M`koKs}Y_+XfVRy8NaRi&cH?E0t~!AwAWzv>U4l=Pl0pz zGjq7ufd$p(6T1egFL(GzPOx}Fk5*wA9jf5Z%7Q1rI%M7hA#inru!7poVs>1B=eFG# z3n_Q2w2z(=VuoW>!NZ@Pp|Q0{>e5zZEJ$|L+>snLDSMaQ)$pCQgmViJJ8ae9O-*A< zF|KZK)?tUu(WazN1<e|4IDyw0 z(st_%#$Gx=Wy>Jpgw`viRV390wJ(dbeE%GDXNu%N4X-OrdO-(`PfJ8QE2zLD7WF7| zUiZh@_2u>gZiAXj3KLSV`wq~$ZgY*@?4iPPiWK#Tt2bRx$<5-Q;uYr-sxX9u6q-no> zCg|o*6Ynb1_xq#(F3kMIOYfy{ddPm=P|B-!|dHOuF30l4{C(KC!w0xao!D3cB6 z^cmB1uH}1Ez&LEfqS{l)tU@FLnbBXIt?03F%2uow_RS0O`3`Fnkb=gx5>bB@0jRu( z*Bz3SBW%@m|1SW?Iq-`Y{!xhjI=C_}R-TfcxXbGdiIWJS1oe+b&=XVmJ!zbCgmc>| ze$h`T+J5x&6&vF8z4Ml>6rypq0LL9lZ@cyN}ob5pp;ff9ggEK&lX~E56xJ^jQfMh(Ka131ctr zqrQ2B^2-C1*AHOI2_lfV*ie3TfMkD_B#B7&RIWc;fUn#OmfpPnq2SBRt&R2?LJQ)3 zHS9>#++K}C$3CtVWS566CL{;y2w&o>3~|2k&O?8`ZsC9J0KnQuu3FM4)SmSFed13l z%?n6MA*~{n%i*S}_pM86;-6p+L`Ywu@d*og{NC&{XY0UM0E7^%ePZzs%`EePo|vko zbFGBwJgU`)Ua{)Ibyv^LEGo <%= stylesheet_pack_tag 'application' %> + <%= favicon_link_tag asset_path('p_for_plano.png') %> Planorama <%= csp_meta_tag %> From 4a2408ce63b193d329f4f554da1e3d166e6c517a Mon Sep 17 00:00:00 2001 From: Gail Terman Date: Tue, 28 Jun 2022 23:52:58 -0400 Subject: [PATCH 08/28] early work on session.statusw --- app/javascript/constants/strings.js | 6 ++++++ app/javascript/sessions/session_edit.vue | 11 ++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/app/javascript/constants/strings.js b/app/javascript/constants/strings.js index 79e56d0fb..06fbf3ee5 100644 --- a/app/javascript/constants/strings.js +++ b/app/javascript/constants/strings.js @@ -250,4 +250,10 @@ module.exports = { hybrid: "Hybrid", virtual: "Virtual" }, + SESSION_STATUS: { + draft: "Draft", + reviewed: "Reviewed", + revised: "Revised", + dropped: "Drpped", + } } diff --git a/app/javascript/sessions/session_edit.vue b/app/javascript/sessions/session_edit.vue index 8ca9c60aa..b2c5cee74 100644 --- a/app/javascript/sessions/session_edit.vue +++ b/app/javascript/sessions/session_edit.vue @@ -129,7 +129,7 @@ import ModelTags from '../components/model_tags'; import PlanoEditor from '@/components/plano_editor'; import { ValidationProvider, extend } from 'vee-validate'; import { min_value } from 'vee-validate/dist/rules' -import { SESSION_ENVIRONMENT } from '@/constants/strings' +import { SESSION_ENVIRONMENT, SESSION_STATUS } from '@/constants/strings' extend('min_value', { ...min_value, @@ -196,7 +196,16 @@ export default { this.session.session_areas_attributes = areasForSaving } + }, + statusOptions() { + return [ + {value: 'draft', text: SESSION_STATUS.draft}, + {value: 'reviewed', text: SESSION_STATUS.reviewed}, + {value: 'revised', text: SESSION_STATUS.revised}, + {value: 'dropped', text: SESSION_STATUS.dropped} + ] } + }, methods: { edit() { From f6b56996d8abbaf3c9b4f84bf7c1635a5476d81b Mon Sep 17 00:00:00 2001 From: Henry Date: Wed, 29 Jun 2022 15:50:35 -0400 Subject: [PATCH 09/28] merge for 1.4.1 --- db/structure.sql | 53 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 35 insertions(+), 18 deletions(-) diff --git a/db/structure.sql b/db/structure.sql index 0ce6ed3af..6907ef51c 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -1024,6 +1024,38 @@ CREATE TABLE public.person_agreements ( ); +-- +-- Name: person_exclusions; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.person_exclusions ( + id uuid DEFAULT public.gen_random_uuid() NOT NULL, + person_id uuid, + exclusion_id uuid, + lock_version integer, + created_at timestamp(6) without time zone NOT NULL, + updated_at timestamp(6) without time zone NOT NULL +); + + +-- +-- Name: person_and_exclusions; Type: VIEW; Schema: public; Owner: - +-- + +CREATE VIEW public.person_and_exclusions AS + SELECT pe.exclusion_id, + pe.person_id, + s.id AS session_id, + s.start_time, + (s.start_time + ((s.duration || ' minute'::text))::interval) AS end_time, + s.title + FROM ((public.person_exclusions pe + LEFT JOIN public.exclusions_sessions es ON ((es.exclusion_id = pe.exclusion_id))) + LEFT JOIN public.sessions s ON ((s.id = es.session_id))) + WHERE (es.session_id IS NOT NULL) + ORDER BY pe.person_id, s.id; + + -- -- Name: person_schedules; Type: VIEW; Schema: public; Owner: - -- @@ -1150,20 +1182,6 @@ CREATE TABLE public.person_constraints ( ); --- --- Name: person_exclusions; Type: TABLE; Schema: public; Owner: - --- - -CREATE TABLE public.person_exclusions ( - id uuid DEFAULT public.gen_random_uuid() NOT NULL, - person_id uuid, - exclusion_id uuid, - lock_version integer, - created_at timestamp(6) without time zone NOT NULL, - updated_at timestamp(6) without time zone NOT NULL -); - - -- -- Name: person_exclusion_conflicts; Type: VIEW; Schema: public; Owner: - -- @@ -1431,7 +1449,6 @@ UNION availability_conflicts.session_title, availability_conflicts.session_start_time, NULL::uuid AS room_id, - NULL::text AS room_name, availability_conflicts.person_id, availability_conflicts.person_name, availability_conflicts.person_published_name, @@ -1450,7 +1467,6 @@ UNION room_conflicts.session_title, room_conflicts.start_time AS session_start_time, room_conflicts.room_id, - room_conflicts.room_name, NULL::uuid AS person_id, NULL::character varying AS person_name, NULL::character varying AS person_published_name, @@ -1470,7 +1486,6 @@ UNION person_schedule_conflicts.title AS session_title, person_schedule_conflicts.start_time AS session_start_time, person_schedule_conflicts.room_id, - person_schedule_conflicts.room_name, person_schedule_conflicts.person_id, person_schedule_conflicts.name AS person_name, person_schedule_conflicts.published_name AS person_published_name, @@ -1490,7 +1505,6 @@ UNION person_schedule_conflicts.title AS session_title, person_schedule_conflicts.start_time AS session_start_time, person_schedule_conflicts.room_id, - person_schedule_conflicts.room_name, person_schedule_conflicts.person_id, person_schedule_conflicts.name AS person_name, person_schedule_conflicts.published_name AS person_published_name, @@ -3101,4 +3115,7 @@ INSERT INTO "schema_migrations" (version) VALUES ('20220623145514'), ('20220623172955'), ('20220624121252'), +('20220628121934'), ('20220629132145'); + + From 23515d90ebf497301082b01327ff803bcfd3a0cc Mon Sep 17 00:00:00 2001 From: Gail Terman Date: Wed, 29 Jun 2022 18:38:46 -0400 Subject: [PATCH 10/28] PLAN-435 session status changer --- app/javascript/constants/strings.js | 5 +++-- app/javascript/sessions/session_edit.vue | 11 +---------- app/javascript/sessions/session_summary.vue | 13 +++++++++++++ 3 files changed, 17 insertions(+), 12 deletions(-) diff --git a/app/javascript/constants/strings.js b/app/javascript/constants/strings.js index 06fbf3ee5..ee4f2d160 100644 --- a/app/javascript/constants/strings.js +++ b/app/javascript/constants/strings.js @@ -254,6 +254,7 @@ module.exports = { draft: "Draft", reviewed: "Reviewed", revised: "Revised", - dropped: "Drpped", - } + dropped: "Dropped", + }, + SESSION_MUST_UNSCHEDULE: "You must unschedule a session before dropping it", } diff --git a/app/javascript/sessions/session_edit.vue b/app/javascript/sessions/session_edit.vue index b2c5cee74..e9176d58b 100644 --- a/app/javascript/sessions/session_edit.vue +++ b/app/javascript/sessions/session_edit.vue @@ -129,7 +129,7 @@ import ModelTags from '../components/model_tags'; import PlanoEditor from '@/components/plano_editor'; import { ValidationProvider, extend } from 'vee-validate'; import { min_value } from 'vee-validate/dist/rules' -import { SESSION_ENVIRONMENT, SESSION_STATUS } from '@/constants/strings' +import { SESSION_ENVIRONMENT } from '@/constants/strings' extend('min_value', { ...min_value, @@ -197,15 +197,6 @@ export default { this.session.session_areas_attributes = areasForSaving } }, - statusOptions() { - return [ - {value: 'draft', text: SESSION_STATUS.draft}, - {value: 'reviewed', text: SESSION_STATUS.reviewed}, - {value: 'revised', text: SESSION_STATUS.revised}, - {value: 'dropped', text: SESSION_STATUS.dropped} - ] - } - }, methods: { edit() { diff --git a/app/javascript/sessions/session_summary.vue b/app/javascript/sessions/session_summary.vue index 54ae497ac..9ef7508c0 100644 --- a/app/javascript/sessions/session_summary.vue +++ b/app/javascript/sessions/session_summary.vue @@ -66,6 +66,14 @@ :checked="scheduled" >Scheduled
+ + + {{SESSION_STATUS.draft}} + {{SESSION_STATUS.reviewed}} + {{SESSION_STATUS.revised}} + {{SESSION_STATUS.dropped}} + +
@@ -75,6 +83,7 @@ import { sessionModel } from '@/store/session.store' import modelUtilsMixin from '@/store/model_utils.mixin'; import { scheduledMixin } from './session_fields.mixin'; +import { SESSION_STATUS, SESSION_MUST_UNSCHEDULE } from '@/constants/strings'; import PlanoEditor from '../components/plano_editor'; @@ -87,6 +96,10 @@ export default { modelUtilsMixin, scheduledMixin ], + data: () => ({ + SESSION_STATUS, + SESSION_MUST_UNSCHEDULE + }), computed: { session() { return this.selected_model(sessionModel); From ba7c769ebb9efcf099aa5755b4206cdf396a8c35 Mon Sep 17 00:00:00 2001 From: Gail Terman Date: Wed, 29 Jun 2022 19:11:05 -0400 Subject: [PATCH 11/28] PLAN-435 display session status in table and flyout - add sorting on status, open for interest, requires signup - add advanced search on status --- app/javascript/constants/strings.js | 1 + app/javascript/sessions/datetime_picker.vue | 12 +++++++++--- app/javascript/sessions/session.js | 14 ++++++++++++-- app/javascript/sessions/session_schedule.vue | 17 ++++++++++++++--- app/javascript/sessions/session_sidebar.vue | 13 +++++++++---- app/javascript/sessions/session_table.vue | 3 --- 6 files changed, 45 insertions(+), 15 deletions(-) diff --git a/app/javascript/constants/strings.js b/app/javascript/constants/strings.js index ee4f2d160..f6a774ea2 100644 --- a/app/javascript/constants/strings.js +++ b/app/javascript/constants/strings.js @@ -257,4 +257,5 @@ module.exports = { dropped: "Dropped", }, SESSION_MUST_UNSCHEDULE: "You must unschedule a session before dropping it", + SESSION_MUST_UNDROP: "You must un-drop the session to be able to schedule it.", } diff --git a/app/javascript/sessions/datetime_picker.vue b/app/javascript/sessions/datetime_picker.vue index 7fa6a219d..91417ef3e 100644 --- a/app/javascript/sessions/datetime_picker.vue +++ b/app/javascript/sessions/datetime_picker.vue @@ -3,8 +3,8 @@
Time
- - + +
@@ -16,7 +16,13 @@ import { settingsMixin } from '@/mixins'; export default { name: "DatetimePicker", - props: ['value'], + props: { + value: null, + disabled: { + type: Boolean, + default: false + } + }, mixins: [settingsMixin], data: () => ({ tempDate: null diff --git a/app/javascript/sessions/session.js b/app/javascript/sessions/session.js index 33d65e866..844da4041 100644 --- a/app/javascript/sessions/session.js +++ b/app/javascript/sessions/session.js @@ -1,3 +1,4 @@ +import { SESSION_STATUS } from '@/constants/strings'; import AreaSelectForSearch from './area_select_for_search' export const session_columns = [ @@ -56,20 +57,29 @@ export const session_columns = [ { key: 'status', label: 'Status', + formatter: (value) => SESSION_STATUS[value] || value, + sortable: true, + sortKey: 'status', + choices: ['draft', 'reviewed', 'revised', 'dropped'].map(value => ({label: SESSION_STATUS[value], value})), + type: "select" }, { key: 'open_for_interest', label: 'Open for Interest', type: "radio", choices: [{label: "Yes", value: "true"}, {label: "No", value: "false"}], - formatter: (value) => value ? "Yes" : "No" + formatter: (value) => value ? "Yes" : "No", + sortable: true, + sortKey: 'open_for_interest' }, { key: 'require_signup', label: 'Requires Signup', type: "radio", choices: [{label: "Yes", value: "true"}, {label: "No", value: "false"}], - formatter: (value) => value ? "Yes" : "No" + formatter: (value) => value ? "Yes" : "No", + sortable: true, + sortKey: 'require_signup' }, { key: 'publish', diff --git a/app/javascript/sessions/session_schedule.vue b/app/javascript/sessions/session_schedule.vue index 67fe2fac0..5981d6797 100644 --- a/app/javascript/sessions/session_schedule.vue +++ b/app/javascript/sessions/session_schedule.vue @@ -2,9 +2,13 @@
+ + + {{SESSION_MUST_UNDROP}} +
Space
- - + +
@@ -20,6 +24,7 @@ import { modelMixinNoProp } from "@/mixins"; import RoomPicker from './room_picker'; import DatetimePicker from './datetime_picker'; +import { SESSION_MUST_UNDROP } from "@/constants/strings"; export default { name: "SessionSchedule", @@ -32,8 +37,14 @@ export default { }, data: () => ({ tempDuration: null, - model: 'session' + model: 'session', + SESSION_MUST_UNDROP }), + computed: { + scheduleDisabled() { + return this.selected.status === 'dropped' + } + } } diff --git a/app/javascript/sessions/session_sidebar.vue b/app/javascript/sessions/session_sidebar.vue index 040aa5060..66fe116a2 100644 --- a/app/javascript/sessions/session_sidebar.vue +++ b/app/javascript/sessions/session_sidebar.vue @@ -3,7 +3,7 @@ @@ -11,10 +11,14 @@
+
Status:
+
+ {{SESSION_STATUS[selected.status]}} +
Description:
-
+
@@ -116,7 +120,7 @@ import { areaMixin, scheduledMixin, startTimeMixin } from './session_fields.mixi import { sessionConflictModel } from '@/store/session_conflict.store'; import SessionConflicts from '@/conflicts/session_conflicts.vue'; // import SessionAdminTab from './session_admin_tab'; -import { SESSION_ENVIRONMENT} from '@/constants/strings'; +import { SESSION_ENVIRONMENT, SESSION_STATUS} from '@/constants/strings'; export default { name: 'SessionSidebar', @@ -136,7 +140,8 @@ export default { ], data: () => ({ sessionConflictModel, - SESSION_ENVIRONMENT + SESSION_ENVIRONMENT, + SESSION_STATUS }), computed: { editLink() { diff --git a/app/javascript/sessions/session_table.vue b/app/javascript/sessions/session_table.vue index b7e222afe..b20a92936 100644 --- a/app/javascript/sessions/session_table.vue +++ b/app/javascript/sessions/session_table.vue @@ -36,9 +36,6 @@ - From 2e1efae70bf0ab5b70cc486b581b10e4720191f8 Mon Sep 17 00:00:00 2001 From: Gail Terman Date: Wed, 29 Jun 2022 22:14:14 -0400 Subject: [PATCH 12/28] PLAN-435 add minors participation field to session --- app/javascript/constants/strings.js | 7 +++++ .../sessions/minors_participation.mixin.js | 30 +++++++++++++++++++ app/javascript/sessions/session_edit.vue | 14 +++++++-- app/javascript/sessions/session_sidebar.vue | 7 ++++- 4 files changed, 55 insertions(+), 3 deletions(-) create mode 100644 app/javascript/sessions/minors_participation.mixin.js diff --git a/app/javascript/constants/strings.js b/app/javascript/constants/strings.js index f6a774ea2..e0d47ce23 100644 --- a/app/javascript/constants/strings.js +++ b/app/javascript/constants/strings.js @@ -258,4 +258,11 @@ module.exports = { }, SESSION_MUST_UNSCHEDULE: "You must unschedule a session before dropping it", SESSION_MUST_UNDROP: "You must un-drop the session to be able to schedule it.", + SESSION_MINORS_PARTICIPATION: { + kids_observe: "Kids welcome to observe", + kids_supervision: "Kids welcome to participate with supervision", + kids_participate: "Kids welcome to participate", + geared_families: "Geared towards families", + geared_kids: "Geared towards kids", + }, } diff --git a/app/javascript/sessions/minors_participation.mixin.js b/app/javascript/sessions/minors_participation.mixin.js new file mode 100644 index 000000000..cdaafa22f --- /dev/null +++ b/app/javascript/sessions/minors_participation.mixin.js @@ -0,0 +1,30 @@ +import { SESSION_MINORS_PARTICIPATION } from "@/constants/strings"; + +export const minorsParticipationMixin = { + data: () => ({ + SESSION_MINORS_PARTICIPATION + }), + computed: { + minorsParticipationOptions() { + return Object.entries(SESSION_MINORS_PARTICIPATION).map(([value, text]) => ({value, text})) + }, + minors_participation: { + get() { + const session = this.session || this.selected; + try { + const existing = JSON.parse(session.minors_participation) + return Array.isArray(existing) ? existing : existing ? [existing] : [] + } catch { + return [] + } + }, + set(val) { + if(this.session) { + this.session.minors_participation = JSON.stringify(val); + } + } + } + } +} + +export default minorsParticipationMixin; diff --git a/app/javascript/sessions/session_edit.vue b/app/javascript/sessions/session_edit.vue index e9176d58b..83fd8f786 100644 --- a/app/javascript/sessions/session_edit.vue +++ b/app/javascript/sessions/session_edit.vue @@ -97,6 +97,14 @@
+
+
+ + + + +
+
({ editable: false, saving: false, - SESSION_ENVIRONMENT + SESSION_ENVIRONMENT, }), computed: { session() { diff --git a/app/javascript/sessions/session_sidebar.vue b/app/javascript/sessions/session_sidebar.vue index 66fe116a2..89e31a567 100644 --- a/app/javascript/sessions/session_sidebar.vue +++ b/app/javascript/sessions/session_sidebar.vue @@ -66,6 +66,9 @@
If "Yes", max openings
{{selected.maximum_people}}
None Set
+
Minors Participation
+
{{ SESSION_MINORS_PARTICIPATION[mp]}}
+
No Selection
Interest Instructions
No Entry
@@ -121,6 +124,7 @@ import { sessionConflictModel } from '@/store/session_conflict.store'; import SessionConflicts from '@/conflicts/session_conflicts.vue'; // import SessionAdminTab from './session_admin_tab'; import { SESSION_ENVIRONMENT, SESSION_STATUS} from '@/constants/strings'; +import { minorsParticipationMixin } from './minors_participation.mixin'; export default { name: 'SessionSidebar', @@ -136,7 +140,8 @@ export default { personSessionMixin, areaMixin, scheduledMixin, - startTimeMixin + startTimeMixin, + minorsParticipationMixin, ], data: () => ({ sessionConflictModel, From 9c99efe27362ff8b9f1d98a1ec962b055abf2b17 Mon Sep 17 00:00:00 2001 From: Gail Terman Date: Wed, 29 Jun 2022 23:36:20 -0400 Subject: [PATCH 13/28] PLAN-435 Add age restriction and required room features to session --- app/controllers/sessions_controller.rb | 2 ++ .../sessions/age_restriction.mixin.js | 19 ++++++++++++++++++ app/javascript/sessions/session_edit.vue | 20 +++++++++++++++++-- app/javascript/sessions/session_sidebar.vue | 8 ++++++++ app/serializers/session_serializer.rb | 4 ++-- ...0220630032544_add_room_notes_to_session.rb | 5 +++++ db/structure.sql | 6 ++++-- 7 files changed, 58 insertions(+), 6 deletions(-) create mode 100644 app/javascript/sessions/age_restriction.mixin.js create mode 100644 db/migrate/20220630032544_add_room_notes_to_session.rb diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index 803ce53b5..5b797e343 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -278,6 +278,8 @@ def allowed_params environment minors_participation require_signup + age_restriction_id + room_notes ] # Tags # format diff --git a/app/javascript/sessions/age_restriction.mixin.js b/app/javascript/sessions/age_restriction.mixin.js new file mode 100644 index 000000000..de84baebb --- /dev/null +++ b/app/javascript/sessions/age_restriction.mixin.js @@ -0,0 +1,19 @@ +import { settingsMixin } from "@/mixins" + +export const ageRestrictionMixin = { + mixins: [ settingsMixin ], + computed: { + ageRestrictionOptions() { + const opts = this.currentSettings.age_restrictions?.map(ar => ({text: ar.name, value: ar.id})) || [] + opts.push({text: 'None', value: null}) + return opts; + } + }, + methods: { + ageRestrictionName(id) { + return this.currentSettings.age_restrictions?.find(ar => ar.id === id)?.name || id; + } + } +} + +export default ageRestrictionMixin diff --git a/app/javascript/sessions/session_edit.vue b/app/javascript/sessions/session_edit.vue index 83fd8f786..d6c79e5ef 100644 --- a/app/javascript/sessions/session_edit.vue +++ b/app/javascript/sessions/session_edit.vue @@ -99,12 +99,26 @@
- + + + +
+
+
+
+
+
+
+ + + +
+
({ editable: false, diff --git a/app/javascript/sessions/session_sidebar.vue b/app/javascript/sessions/session_sidebar.vue index 89e31a567..e81358d71 100644 --- a/app/javascript/sessions/session_sidebar.vue +++ b/app/javascript/sessions/session_sidebar.vue @@ -66,12 +66,18 @@
If "Yes", max openings
{{selected.maximum_people}}
None Set
+
Attendee Age Restrictions
+
{{ ageRestrictionName(selected.age_restriction_id)}}
+
None
Minors Participation
{{ SESSION_MINORS_PARTICIPATION[mp]}}
No Selection
Interest Instructions
No Entry
+
Required Room Features/Services
+
{{selected.room_notes}}
+
No Entry
Scheduled Participant Notes
No Entry
@@ -125,6 +131,7 @@ import SessionConflicts from '@/conflicts/session_conflicts.vue'; // import SessionAdminTab from './session_admin_tab'; import { SESSION_ENVIRONMENT, SESSION_STATUS} from '@/constants/strings'; import { minorsParticipationMixin } from './minors_participation.mixin'; +import { ageRestrictionMixin } from './age_restriction.mixin'; export default { name: 'SessionSidebar', @@ -142,6 +149,7 @@ export default { scheduledMixin, startTimeMixin, minorsParticipationMixin, + ageRestrictionMixin, ], data: () => ({ sessionConflictModel, diff --git a/app/serializers/session_serializer.rb b/app/serializers/session_serializer.rb index 991226397..7fe0f34d0 100644 --- a/app/serializers/session_serializer.rb +++ b/app/serializers/session_serializer.rb @@ -12,8 +12,8 @@ class SessionSerializer :updated_by, :interest_opened_by, :interest_opened_at, :room_id, :proofed, :format_id, :room_set_id, :status, :environment, - :tech_notes, - :minors_participation + :tech_notes, :room_notes, + :minors_participation, :age_restriction_id # tag_list attribute :tag_list do |session| diff --git a/db/migrate/20220630032544_add_room_notes_to_session.rb b/db/migrate/20220630032544_add_room_notes_to_session.rb new file mode 100644 index 000000000..6fff6556c --- /dev/null +++ b/db/migrate/20220630032544_add_room_notes_to_session.rb @@ -0,0 +1,5 @@ +class AddRoomNotesToSession < ActiveRecord::Migration[6.1] + def change + add_column :sessions, :room_notes, :string + end +end diff --git a/db/structure.sql b/db/structure.sql index 01b68b05a..13c7d9da9 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -660,7 +660,8 @@ CREATE TABLE public.sessions ( tech_notes text, age_restriction_id uuid, minors_participation jsonb, - room_set_id uuid + room_set_id uuid, + room_notes character varying ); @@ -3113,6 +3114,7 @@ INSERT INTO "schema_migrations" (version) VALUES ('20220623145514'), ('20220623172955'), ('20220624121252'), -('20220628121934'); +('20220628121934'), +('20220630032544'); From ad3e394a7792ea599ecc7587e6e41d87a2adea3e Mon Sep 17 00:00:00 2001 From: Gail Terman Date: Thu, 30 Jun 2022 00:23:12 -0400 Subject: [PATCH 14/28] PLAN-495 Make the ignore button into an icon - Also has a tooltip --- app/javascript/components/icon_button.vue | 6 ++-- app/javascript/conflicts/ignore_button.vue | 31 +++++++++++++++++++ .../conflicts/session_conflicts.vue | 8 +++-- 3 files changed, 41 insertions(+), 4 deletions(-) create mode 100644 app/javascript/conflicts/ignore_button.vue diff --git a/app/javascript/components/icon_button.vue b/app/javascript/components/icon_button.vue index b7c5897ad..d909f1ea7 100644 --- a/app/javascript/components/icon_button.vue +++ b/app/javascript/components/icon_button.vue @@ -12,7 +12,9 @@ v-b-tooltip.bottom v-bind="$attrs" > - + + + {{disabledTooltip}} @@ -77,7 +79,7 @@ export default { styles.pointerEvents = 'none'; } return styles; - } + }, }, } diff --git a/app/javascript/conflicts/ignore_button.vue b/app/javascript/conflicts/ignore_button.vue new file mode 100644 index 000000000..4442e2ae8 --- /dev/null +++ b/app/javascript/conflicts/ignore_button.vue @@ -0,0 +1,31 @@ + + + + + diff --git a/app/javascript/conflicts/session_conflicts.vue b/app/javascript/conflicts/session_conflicts.vue index b47479ea8..47517506b 100644 --- a/app/javascript/conflicts/session_conflicts.vue +++ b/app/javascript/conflicts/session_conflicts.vue @@ -11,14 +11,14 @@ v-for="conflict in conflicts" :key="conflict.id" >
- +
- +
@@ -34,6 +34,7 @@ import modelMixin from '../store/model.mixin'; import modelUtilsMixin from "@/store/model_utils.mixin" import { sessionModel } from '@/store/session.store' import dateTimeMixin from '../components/date_time.mixin' +import IgnoreButton from './ignore_button.vue'; export default { name: "SessionConflicts", @@ -54,6 +55,9 @@ export default { conflicts: [], conflicts_with: [] }), + components: { + IgnoreButton + }, computed: { selectedSession() { return this.get_model(sessionModel, this.sessionId) From 04b56e2fb97ebf2e397e7449a8fb2fdda99046d8 Mon Sep 17 00:00:00 2001 From: Gail Terman Date: Thu, 30 Jun 2022 00:50:36 -0400 Subject: [PATCH 15/28] PLAN-372 Validate session duration field on frontend --- app/javascript/sessions/session_schedule.vue | 45 ++++++++++++++++++-- 1 file changed, 41 insertions(+), 4 deletions(-) diff --git a/app/javascript/sessions/session_schedule.vue b/app/javascript/sessions/session_schedule.vue index 67fe2fac0..d54a97c99 100644 --- a/app/javascript/sessions/session_schedule.vue +++ b/app/javascript/sessions/session_schedule.vue @@ -6,10 +6,19 @@ -
- + + minutes -
+ {{ validationCtx.errors[0] }} +
@@ -20,6 +29,13 @@ import { modelMixinNoProp } from "@/mixins"; import RoomPicker from './room_picker'; import DatetimePicker from './datetime_picker'; +import { ValidationProvider, extend } from 'vee-validate'; +import { min_value } from 'vee-validate/dist/rules' + +extend('min_value', { + ...min_value, + message: "Sessions can't be less than 10 minutes long" + }) export default { name: "SessionSchedule", @@ -28,12 +44,33 @@ export default { ], components: { RoomPicker, - DatetimePicker + DatetimePicker, + ValidationProvider }, data: () => ({ tempDuration: null, model: 'session' }), + computed: { + duration: { + get() { + return this.tempDuration || this.selected.duration; + }, + set(val) { + this.tempDuration = val; + } + } + }, + methods: { + validatedPatchSelected(data, {dirty, valid=null}) { + if(dirty && valid) { + this.patchSelected(data); + } + }, + getValidationState({ dirty, validated, valid = null }) { + return dirty || validated ? valid : null; + }, + } } From f2686f9127be16f6fdc714f4d54f1ae710a7aaff Mon Sep 17 00:00:00 2001 From: Gail Terman Date: Thu, 30 Jun 2022 01:31:58 -0400 Subject: [PATCH 16/28] PLAN-389 Add skeleton to participant loading - Also set the universal default animation for skeletons to "fade" --- app/javascript/packs/application.js | 4 +- app/javascript/sessions/view_participants.vue | 38 ++++++++++++++----- 2 files changed, 32 insertions(+), 10 deletions(-) diff --git a/app/javascript/packs/application.js b/app/javascript/packs/application.js index 54fa32ad3..5427d3743 100644 --- a/app/javascript/packs/application.js +++ b/app/javascript/packs/application.js @@ -47,7 +47,9 @@ Vue.config.errorHandler = (err, vm, info) => { } } -Vue.use(BootstrapVue); +Vue.use(BootstrapVue, { + BSkeleton: { animation: 'fade' } +}); Vue.use(BootstrapVueIcons); Vue.use(CustomIconsPlugin); Vue.use(AsyncComputed); diff --git a/app/javascript/sessions/view_participants.vue b/app/javascript/sessions/view_participants.vue index 978bbf251..364247ee7 100644 --- a/app/javascript/sessions/view_participants.vue +++ b/app/javascript/sessions/view_participants.vue @@ -1,9 +1,21 @@ @@ -26,21 +38,29 @@ export default { modelMixinNoProp, ], data: () => ({ - model + model, + loading: false }), + methods: { + load() { + this.clear(); + this.loading = true; + this.fetch({session_id: this.session.id}).then(() => { + this.loading = false; + }) + } + }, watch: { session(newSession, oldSession) { if (newSession) { if ((oldSession && oldSession.id !== newSession.id) || !oldSession) { - this.clear(); - this.fetch({session_id: this.session.id}) + this.load(); } } } }, mounted() { - this.clear(); - this.fetch({session_id: this.session.id}) + this.load(); } } From b0a59f48798c732e7fe753b0470c0eaa5b69a805 Mon Sep 17 00:00:00 2001 From: Gail Terman Date: Thu, 30 Jun 2022 01:35:18 -0400 Subject: [PATCH 17/28] PLAN-493 unhide formerly borked reports --- app/javascript/reports/reports_screen.vue | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/javascript/reports/reports_screen.vue b/app/javascript/reports/reports_screen.vue index 38b609997..71c24882c 100644 --- a/app/javascript/reports/reports_screen.vue +++ b/app/javascript/reports/reports_screen.vue @@ -28,9 +28,9 @@
  • Participants over Con Limit
  • - +
  • Non-Accepted Participants on Scheduled Sessions
  • @@ -51,9 +51,9 @@
  • Sessions with no Moderator
  • - +
  • Sessions with Participants not Scheduled
  • From 04c5ac1409fd9a305ba7509008f7d1e38e32366c Mon Sep 17 00:00:00 2001 From: Gail Terman Date: Thu, 30 Jun 2022 01:38:03 -0400 Subject: [PATCH 18/28] Change version number to 1.4.2 --- docs/index.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/index.md b/docs/index.md index 69d87acd8..0be43bbc7 100644 --- a/docs/index.md +++ b/docs/index.md @@ -7,8 +7,8 @@ This software is open source! If you'd like to contribute, please email planoram [Planorama Data Privacy & Protection Policy](/planorama/privacy) -Production version: 1.4.1 +Production version: 1.4.2 -Staging version: 1.4.1 +Staging version: 1.4.2 From 98c70d3bfe4609f606456bb7013290709492cc2d Mon Sep 17 00:00:00 2001 From: Henry Date: Fri, 1 Jul 2022 08:12:35 -0400 Subject: [PATCH 19/28] makes note text so we do not hit the 256 default limit for string --- db/migrate/20220630032544_add_room_notes_to_session.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/db/migrate/20220630032544_add_room_notes_to_session.rb b/db/migrate/20220630032544_add_room_notes_to_session.rb index 6fff6556c..84357057f 100644 --- a/db/migrate/20220630032544_add_room_notes_to_session.rb +++ b/db/migrate/20220630032544_add_room_notes_to_session.rb @@ -1,5 +1,5 @@ class AddRoomNotesToSession < ActiveRecord::Migration[6.1] def change - add_column :sessions, :room_notes, :string + add_column :sessions, :room_notes, :text end end From d0797ad4f1200e41fd10abe0a43919eba2814e3d Mon Sep 17 00:00:00 2001 From: Henry Date: Fri, 1 Jul 2022 08:15:55 -0400 Subject: [PATCH 20/28] PLAN-354 fix scheduled with no people --- app/services/reports_service.rb | 18 +++++++++++++++--- db/structure.sql | 2 +- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/app/services/reports_service.rb b/app/services/reports_service.rb index 6cef1b244..6c01f905a 100644 --- a/app/services/reports_service.rb +++ b/app/services/reports_service.rb @@ -18,16 +18,28 @@ def self.assigned_sessions_not_scheduled def self.scheduled_session_no_people active_roles = SessionAssignmentRoleType.where("role_type = 'participant' and (name != 'Invisible' and name != 'Reserve')") + # Get all sessions that are scheduled with people in role + session_with_people = PersonSchedule.where("session_assignment_role_type_id in (?)", active_roles.collect{|a| a.id}) + # Then get all scheduled sessions not in the above Session.select( ::Session.arel_table[Arel.star], 'areas_list.area_list' ) .joins(self.area_subquery) - .joins(:session_assignments) - .eager_load(:areas, :room) - .where("session_assignments.session_assignment_role_type_id not in (?)", active_roles.collect{|a| a.id}) .where("start_time is not null and room_id is not null") + .where("sessions.id not in (?)", session_with_people.collect{|a| a.session_id}) .order(:start_time) + + + # Session.select( + # ::Session.arel_table[Arel.star], + # 'areas_list.area_list' + # ) + # .joins(:session_assignments) + # .eager_load(:areas, :room) + # .where("session_assignments.session_assignment_role_type_id not in (?)", active_roles.collect{|a| a.id}) + # .where("start_time is not null and room_id is not null") + # .order(:start_time) end diff --git a/db/structure.sql b/db/structure.sql index 715c7c77a..f627f9ab1 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -661,7 +661,7 @@ CREATE TABLE public.sessions ( age_restriction_id uuid, minors_participation jsonb, room_set_id uuid, - room_notes character varying + room_notes text ); From edb17e6f6374acd10e97859caac8d12a67b261be Mon Sep 17 00:00:00 2001 From: Henry Date: Fri, 1 Jul 2022 08:31:58 -0400 Subject: [PATCH 21/28] PLAN-502 tweak conditions for exclusion conflict --- app/lib/migration_helpers/plano_views.rb | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/app/lib/migration_helpers/plano_views.rb b/app/lib/migration_helpers/plano_views.rb index c45bed34b..8974d4c27 100644 --- a/app/lib/migration_helpers/plano_views.rb +++ b/app/lib/migration_helpers/plano_views.rb @@ -213,7 +213,19 @@ def self.create_person_exclusion_conflicts LEFT JOIN public.person_exclusions pe ON ((pe.person_id = person_schedules.person_id))) JOIN public.exclusions_sessions es ON ((es.exclusion_id = pe.exclusion_id))) LEFT JOIN public.sessions s ON ((s.id = es.session_id))) - WHERE ((person_schedules.session_id <> s.id) AND (person_schedules.start_time >= s.start_time) AND ((person_schedules.start_time <= (s.start_time + ((s.duration || ' minute'::text))::interval)) OR ((person_schedules.end_time >= s.start_time) AND (person_schedules.end_time <= (s.start_time + ((s.duration || ' minute'::text))::interval))))); + WHERE ( + person_schedules.session_id <> s.id + AND + person_schedules.start_time >= s.start_time + AND ( + person_schedules.start_time < (s.start_time + (s.duration || ' minute'::text)::interval) + OR ( + person_schedules.end_time > s.start_time + AND person_schedules.end_time <= (s.start_time + (s.duration || ' minute'::text)::interval + ) + ) + ) + ); SQL ActiveRecord::Base.connection.execute(query) end From 32cb93684d1832419a23886be2efa5a715ec4e08 Mon Sep 17 00:00:00 2001 From: Henry Date: Fri, 1 Jul 2022 08:33:19 -0400 Subject: [PATCH 22/28] view for exclusions updated structure --- db/structure.sql | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/db/structure.sql b/db/structure.sql index 715c7c77a..db6e4c73e 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -661,7 +661,7 @@ CREATE TABLE public.sessions ( age_restriction_id uuid, minors_participation jsonb, room_set_id uuid, - room_notes character varying + room_notes text ); @@ -1209,7 +1209,7 @@ CREATE VIEW public.person_exclusion_conflicts AS LEFT JOIN public.person_exclusions pe ON ((pe.person_id = person_schedules.person_id))) JOIN public.exclusions_sessions es ON ((es.exclusion_id = pe.exclusion_id))) LEFT JOIN public.sessions s ON ((s.id = es.session_id))) - WHERE ((person_schedules.session_id <> s.id) AND (person_schedules.start_time >= s.start_time) AND ((person_schedules.start_time <= (s.start_time + ((s.duration || ' minute'::text))::interval)) OR ((person_schedules.end_time >= s.start_time) AND (person_schedules.end_time <= (s.start_time + ((s.duration || ' minute'::text))::interval))))); + WHERE ((person_schedules.session_id <> s.id) AND (person_schedules.start_time >= s.start_time) AND ((person_schedules.start_time < (s.start_time + ((s.duration || ' minute'::text))::interval)) OR ((person_schedules.end_time > s.start_time) AND (person_schedules.end_time <= (s.start_time + ((s.duration || ' minute'::text))::interval))))); -- From 56e3bb3c9f8a15050bedbadc2dbf264f48f92060 Mon Sep 17 00:00:00 2001 From: Henry Date: Fri, 1 Jul 2022 11:53:44 -0400 Subject: [PATCH 23/28] PLAN-501 40 min margin just for B2Bs --- .../reports/conflict_reports_controller.rb | 10 +-- app/lib/migration_helpers/plano_views.rb | 77 +++++++++++----- app/models/conflicts/person_back_to_back.rb | 19 ++++ db/structure.sql | 88 ++++++++++++------- 4 files changed, 135 insertions(+), 59 deletions(-) create mode 100644 app/models/conflicts/person_back_to_back.rb diff --git a/app/controllers/reports/conflict_reports_controller.rb b/app/controllers/reports/conflict_reports_controller.rb index cf810bfce..24165d742 100644 --- a/app/controllers/reports/conflict_reports_controller.rb +++ b/app/controllers/reports/conflict_reports_controller.rb @@ -233,7 +233,7 @@ def back_to_back_to_back def back_to_back authorize SessionAssignment, policy_class: Reports::ConflictReportPolicy - conflicts_table = ::Conflicts::PersonScheduleConflict.arel_table + conflicts_table = ::Conflicts::PersonBackToBack.arel_table subquery = Session.area_list.as('areas_list') conflict_subquery = Session.area_list.as('conflict_areas_list') joins = [ @@ -253,8 +253,8 @@ def back_to_back ) ] - conflicts = Conflicts::PersonScheduleConflict.select( - Conflicts::PersonScheduleConflict.arel_table[Arel.star], + conflicts = Conflicts::PersonBackToBack.select( + Conflicts::PersonBackToBack.arel_table[Arel.star], 'areas_list.area_list as area_list', 'conflict_areas_list.area_list as conflict_area_list' ) @@ -263,7 +263,6 @@ def back_to_back .joins(joins) .where("session_assignment_name is null or session_assignment_name in ('Moderator', 'Participant', 'Invisible')") .where("conflict_session_assignment_name is null or conflict_session_assignment_name in ('Moderator', 'Participant', 'Invisible')") - .where(back_to_back: true) .order('published_name asc, conflict_start_time asc') workbook = FastExcel.open(constant_memory: true) @@ -348,8 +347,7 @@ def people_double_booked .joins(joins) .where("session_assignment_name is null or session_assignment_name in ('Moderator', 'Participant', 'Invisible')") .where("conflict_session_assignment_name is null or conflict_session_assignment_name in ('Moderator', 'Participant', 'Invisible')") - .where(back_to_back: false) - .order('people.published_name asc, conflict_start_time asc') + .order('people.published_name asc, start_time asc') workbook = FastExcel.open(constant_memory: true) worksheet = workbook.add_worksheet("People Double Booked") diff --git a/app/lib/migration_helpers/plano_views.rb b/app/lib/migration_helpers/plano_views.rb index 8974d4c27..92641ab3a 100644 --- a/app/lib/migration_helpers/plano_views.rb +++ b/app/lib/migration_helpers/plano_views.rb @@ -6,6 +6,7 @@ def self.create_views self.create_room_allocations self.create_room_conflicts self.create_person_schedule_conflicts + self.create_person_back_to_back self.create_person_exclusion_conflicts self.create_person_back_to_back_to_back self.create_availability_conflicts @@ -110,6 +111,7 @@ def self.create_room_conflicts end def self.create_person_schedule_conflicts + # change for back to backs query = <<-SQL.squish CREATE OR REPLACE VIEW person_schedule_conflicts AS select @@ -136,15 +138,7 @@ def self.create_person_schedule_conflicts ps2.session_assignment_role_type_id as conflict_session_assignment_role_type_id, ps2.session_assignment_role_type as conflict_session_assignment_role_type, ps2.session_assignment_name as conflict_session_assignment_name, - ps2.room_id as conflict_room_id, - case - when - ((ps2.start_time >= ps1.end_time) and (ps2.start_time <= (ps1.end_time + (40 || ' minute')::interval))) - or - ((ps1.start_time >= ps2.end_time) and (ps1.start_time <= (ps2.end_time + (40 || ' minute')::interval))) - then true - else FALSE - end as back_to_back + ps2.room_id as conflict_room_id from person_schedules ps1 join @@ -152,18 +146,58 @@ def self.create_person_schedule_conflicts and ps2.session_id != ps1.session_id and ps2.start_time >= ps1.start_time and ( - ps2.start_time <= ps1.end_time + (40 || ' minute')::interval + ps2.start_time <= ps1.end_time or ( - ps2.end_time >= ps1.start_time - (40 || ' minute')::interval and ps2.end_time <= ps1.end_time + ps2.end_time >= ps1.start_time and ps2.end_time <= ps1.end_time ) - ) - order by - ps1.person_id + ); SQL ActiveRecord::Base.connection.execute(query) end + def self.create_person_back_to_back + query = <<-SQL.squish + CREATE OR REPLACE VIEW person_back_to_back AS + select + CONCAT(ps1.person_id, ':', ps1.session_id, ':', ps2.session_id) as id, + ps1.person_id, + ps1.name, + ps1.published_name, + ps1.con_state, + ps2.start_time AS conflict_start_time, + ps1.session_id, + ps1.title, + ps1.start_time, + ps1.end_time, + ps1.duration, + ps1.session_assignment_id, + ps1.session_assignment_role_type_id, + ps1.session_assignment_name as session_assignment_name, + ps1.session_assignment_role_type, + ps1.room_id, + ps2.session_id as conflict_session_id, + ps2.title as conflict_session_title, + ps2.end_time as conflict_end_time, + ps2.duration as conflict_duration, + ps2.session_assignment_role_type_id as conflict_session_assignment_role_type_id, + ps2.session_assignment_role_type as conflict_session_assignment_role_type, + ps2.session_assignment_name as conflict_session_assignment_name, + ps2.room_id as conflict_room_id + from + person_schedules ps1 + join + person_schedules ps2 on ps2.person_id = ps1.person_id + and ps2.session_id != ps1.session_id + where + (ps2.start_time >= ps1.end_time) and (ps2.start_time <= (ps1.end_time + (40 || ' minute')::interval)); + SQL + # or + # ((ps1.start_time >= ps2.end_time) and (ps1.start_time <= (ps2.end_time + (40 || ' minute')::interval))) + + ActiveRecord::Base.connection.execute(query) + end + def self.create_person_and_exclusions query = <<-SQL.squish CREATE OR REPLACE VIEW person_and_exclusions AS @@ -231,7 +265,7 @@ def self.create_person_exclusion_conflicts end def self.create_person_back_to_back_to_back - # check + # TODO: change new view query = <<-SQL.squish CREATE OR REPLACE VIEW person_back_to_back_to_back AS select @@ -270,11 +304,9 @@ def self.create_person_back_to_back_to_back psc2.conflict_session_assignment_name, psc2.conflict_room_id from - person_schedule_conflicts psc1 - inner join person_schedule_conflicts psc2 on + person_back_to_back psc1 + inner join person_back_to_back psc2 on psc2.session_id = psc1.conflict_session_id - and psc2.back_to_back = true - where psc1.back_to_back = true SQL ActiveRecord::Base.connection.execute(query) end @@ -419,7 +451,6 @@ def self.create_session_conflicts id as conflict_id, 'person_schedule_conflict' as conflict_type from person_schedule_conflicts - where person_schedule_conflicts.back_to_back = false UNION select session_id, @@ -438,8 +469,7 @@ def self.create_session_conflicts conflict_session_assignment_name, id as conflict_id, 'person_back_to_back' as conflict_type - from person_schedule_conflicts - where person_schedule_conflicts.back_to_back = true + from person_back_to_back SQL ActiveRecord::Base.connection.execute(query) end @@ -460,6 +490,9 @@ def self.drop_views ActiveRecord::Base.connection.execute <<-SQL DROP VIEW IF EXISTS person_schedule_conflicts; SQL + ActiveRecord::Base.connection.execute <<-SQL + DROP VIEW IF EXISTS person_back_to_back; + SQL ActiveRecord::Base.connection.execute <<-SQL DROP VIEW IF EXISTS room_conflicts; SQL diff --git a/app/models/conflicts/person_back_to_back.rb b/app/models/conflicts/person_back_to_back.rb new file mode 100644 index 000000000..a1d97e5cf --- /dev/null +++ b/app/models/conflicts/person_back_to_back.rb @@ -0,0 +1,19 @@ +class Conflicts::PersonBackToBack < ApplicationRecord + self.table_name = :person_back_to_back + self.primary_key = :id + + belongs_to :session_assignment + belongs_to :person + belongs_to :session + belongs_to :session_assignment_role_type + belongs_to :room + + belongs_to :conflict_session_assignment, class_name: 'SessionAssignment' + belongs_to :conflict_session, class_name: 'Session' + belongs_to :conflict_session_assignment_role_type, class_name: 'SessionAssignmentRoleType' + belongs_to :conflict_room, class_name: 'Room' + + def readonly? + true + end +end diff --git a/db/structure.sql b/db/structure.sql index db6e4c73e..7b5a8cdc1 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -1087,16 +1087,16 @@ CREATE VIEW public.person_schedules AS -- --- Name: person_schedule_conflicts; Type: VIEW; Schema: public; Owner: - +-- Name: person_back_to_back; Type: VIEW; Schema: public; Owner: - -- -CREATE VIEW public.person_schedule_conflicts AS +CREATE VIEW public.person_back_to_back AS SELECT concat(ps1.person_id, ':', ps1.session_id, ':', ps2.session_id) AS id, ps1.person_id, ps1.name, ps1.published_name, ps1.con_state, - GREATEST(ps1.start_time, ps2.start_time) AS conflict_start_time, + ps2.start_time AS conflict_start_time, ps1.session_id, ps1.title, ps1.start_time, @@ -1114,14 +1114,10 @@ CREATE VIEW public.person_schedule_conflicts AS ps2.session_assignment_role_type_id AS conflict_session_assignment_role_type_id, ps2.session_assignment_role_type AS conflict_session_assignment_role_type, ps2.session_assignment_name AS conflict_session_assignment_name, - ps2.room_id AS conflict_room_id, - CASE - WHEN (((ps2.start_time >= ps1.end_time) AND (ps2.start_time <= (ps1.end_time + ((40 || ' minute'::text))::interval))) OR ((ps1.start_time >= ps2.end_time) AND (ps1.start_time <= (ps2.end_time + ((40 || ' minute'::text))::interval)))) THEN true - ELSE false - END AS back_to_back + ps2.room_id AS conflict_room_id FROM (public.person_schedules ps1 - JOIN public.person_schedules ps2 ON (((ps2.person_id = ps1.person_id) AND (ps2.session_id <> ps1.session_id) AND (ps2.start_time >= ps1.start_time) AND ((ps2.start_time <= (ps1.end_time + ((40 || ' minute'::text))::interval)) OR ((ps2.end_time >= (ps1.start_time - ((40 || ' minute'::text))::interval)) AND (ps2.end_time <= ps1.end_time)))))) - ORDER BY ps1.person_id; + JOIN public.person_schedules ps2 ON (((ps2.person_id = ps1.person_id) AND (ps2.session_id <> ps1.session_id)))) + WHERE ((ps2.start_time >= ps1.end_time) AND (ps2.start_time <= (ps1.end_time + ((40 || ' minute'::text))::interval))); -- @@ -1163,9 +1159,8 @@ CREATE VIEW public.person_back_to_back_to_back AS psc2.conflict_session_assignment_role_type, psc2.conflict_session_assignment_name, psc2.conflict_room_id - FROM (public.person_schedule_conflicts psc1 - JOIN public.person_schedule_conflicts psc2 ON (((psc2.session_id = psc1.conflict_session_id) AND (psc2.back_to_back = true)))) - WHERE (psc1.back_to_back = true); + FROM (public.person_back_to_back psc1 + JOIN public.person_back_to_back psc2 ON ((psc2.session_id = psc1.conflict_session_id))); -- @@ -1226,6 +1221,39 @@ CREATE TABLE public.person_mailing_assignments ( ); +-- +-- Name: person_schedule_conflicts; Type: VIEW; Schema: public; Owner: - +-- + +CREATE VIEW public.person_schedule_conflicts AS + SELECT concat(ps1.person_id, ':', ps1.session_id, ':', ps2.session_id) AS id, + ps1.person_id, + ps1.name, + ps1.published_name, + ps1.con_state, + GREATEST(ps1.start_time, ps2.start_time) AS conflict_start_time, + ps1.session_id, + ps1.title, + ps1.start_time, + ps1.end_time, + ps1.duration, + ps1.session_assignment_id, + ps1.session_assignment_role_type_id, + ps1.session_assignment_name, + ps1.session_assignment_role_type, + ps1.room_id, + ps2.session_id AS conflict_session_id, + ps2.title AS conflict_session_title, + ps2.end_time AS conflict_end_time, + ps2.duration AS conflict_duration, + ps2.session_assignment_role_type_id AS conflict_session_assignment_role_type_id, + ps2.session_assignment_role_type AS conflict_session_assignment_role_type, + ps2.session_assignment_name AS conflict_session_assignment_name, + ps2.room_id AS conflict_room_id + FROM (public.person_schedules ps1 + JOIN public.person_schedules ps2 ON (((ps2.person_id = ps1.person_id) AND (ps2.session_id <> ps1.session_id) AND (ps2.start_time >= ps1.start_time) AND ((ps2.start_time <= ps1.end_time) OR ((ps2.end_time >= ps1.start_time) AND (ps2.end_time <= ps1.end_time)))))); + + -- -- Name: publication_dates; Type: TABLE; Schema: public; Owner: - -- @@ -1500,26 +1528,24 @@ UNION person_schedule_conflicts.id AS conflict_id, 'person_schedule_conflict'::text AS conflict_type FROM public.person_schedule_conflicts - WHERE (person_schedule_conflicts.back_to_back = false) UNION - SELECT person_schedule_conflicts.session_id, - person_schedule_conflicts.title AS session_title, - person_schedule_conflicts.start_time AS session_start_time, - person_schedule_conflicts.room_id, - person_schedule_conflicts.person_id, - person_schedule_conflicts.name AS person_name, - person_schedule_conflicts.published_name AS person_published_name, - person_schedule_conflicts.session_assignment_id, - person_schedule_conflicts.session_assignment_role_type_id, - person_schedule_conflicts.session_assignment_name, - person_schedule_conflicts.conflict_session_id, - person_schedule_conflicts.conflict_session_title, - person_schedule_conflicts.conflict_session_assignment_role_type_id, - person_schedule_conflicts.conflict_session_assignment_name, - person_schedule_conflicts.id AS conflict_id, + SELECT person_back_to_back.session_id, + person_back_to_back.title AS session_title, + person_back_to_back.start_time AS session_start_time, + person_back_to_back.room_id, + person_back_to_back.person_id, + person_back_to_back.name AS person_name, + person_back_to_back.published_name AS person_published_name, + person_back_to_back.session_assignment_id, + person_back_to_back.session_assignment_role_type_id, + person_back_to_back.session_assignment_name, + person_back_to_back.conflict_session_id, + person_back_to_back.conflict_session_title, + person_back_to_back.conflict_session_assignment_role_type_id, + person_back_to_back.conflict_session_assignment_name, + person_back_to_back.id AS conflict_id, 'person_back_to_back'::text AS conflict_type - FROM public.person_schedule_conflicts - WHERE (person_schedule_conflicts.back_to_back = true); + FROM public.person_back_to_back; -- From 731112480c647bb3c141a4cbd7c6258666c6a780 Mon Sep 17 00:00:00 2001 From: Henry Date: Fri, 1 Jul 2022 13:44:22 -0400 Subject: [PATCH 24/28] PLAN-410 fix incorrect report of conflict --- app/models/session.rb | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/app/models/session.rb b/app/models/session.rb index 7d89057ab..d02bd50f4 100644 --- a/app/models/session.rb +++ b/app/models/session.rb @@ -19,12 +19,20 @@ class Session < ApplicationRecord before_save :keep_who_did_it, :keep_interest_trail, :schedule_consistency has_many :session_conflicts, - -> { where("session_conflicts.conflict_id not in (select conflict_id from ignored_conflicts)") }, + -> { + where("session_conflicts.conflict_id not in (select conflict_id from ignored_conflicts)") + .where("session_assignment_name is null or session_assignment_name in (?)", ['Moderator', 'Participant', 'Invisible']) + .where("conflict_session_assignment_name is null or conflict_session_assignment_name in (?)", ['Moderator', 'Participant', 'Invisible']) + }, class_name: 'Conflicts::SessionConflict' # Get where this session is on the other side of the conflict relationship has_many :conflict_sessions, - -> { where("session_conflicts.conflict_id not in (select conflict_id from ignored_conflicts)") }, + -> { + where("session_conflicts.conflict_id not in (select conflict_id from ignored_conflicts)") + .where("session_assignment_name is null or session_assignment_name in (?)", ['Moderator', 'Participant', 'Invisible']) + .where("conflict_session_assignment_name is null or conflict_session_assignment_name in (?)", ['Moderator', 'Participant', 'Invisible']) + }, foreign_key: :conflict_session_id, class_name: 'Conflicts::SessionConflict' has_and_belongs_to_many :room_services From 1da79f098575e17d05893358b052155e88f2f08a Mon Sep 17 00:00:00 2001 From: Henry Date: Tue, 5 Jul 2022 10:53:17 -0400 Subject: [PATCH 25/28] PLAN-516 do not show dropped sessions in the scheduable list --- app/javascript/schedule/schedule_screen.vue | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/javascript/schedule/schedule_screen.vue b/app/javascript/schedule/schedule_screen.vue index 9feb24e2a..ec4a597ff 100644 --- a/app/javascript/schedule/schedule_screen.vue +++ b/app/javascript/schedule/schedule_screen.vue @@ -142,7 +142,8 @@ export default { ["room_id", "is null"] ] }, - ["duration", ">", "0"] + ["duration", ">", "0"], + ["status", "!=", "dropped"] ] } From bf7f3b3df1f0e93eb44c9afb7036aa99f6a66594 Mon Sep 17 00:00:00 2001 From: Henry Date: Tue, 5 Jul 2022 16:59:21 -0400 Subject: [PATCH 26/28] Fix boundary for exclusion conflict --- app/lib/migration_helpers/plano_views.rb | 76 +++++++++++++----------- 1 file changed, 41 insertions(+), 35 deletions(-) diff --git a/app/lib/migration_helpers/plano_views.rb b/app/lib/migration_helpers/plano_views.rb index 92641ab3a..1e91e226e 100644 --- a/app/lib/migration_helpers/plano_views.rb +++ b/app/lib/migration_helpers/plano_views.rb @@ -225,41 +225,47 @@ def self.create_person_and_exclusions def self.create_person_exclusion_conflicts query = <<-SQL.squish CREATE OR REPLACE VIEW person_exclusion_conflicts AS - SELECT - concat(person_schedules.person_id, ':', es.exclusion_id, ':', person_schedules.session_id) AS id, - person_schedules.person_id, - person_schedules.name, - person_schedules.published_name, - person_schedules.con_state, - es.exclusion_id, - es.session_id AS excluded_session_id, - s.title as excluded_session_title, - person_schedules.session_id, - person_schedules.title, - person_schedules.start_time, - person_schedules.end_time, - person_schedules.duration, - person_schedules.session_assignment_role_type_id, - person_schedules.session_assignment_id, - person_schedules.session_assignment_name, - person_schedules.session_assignment_role_type - FROM (((public.person_schedules - LEFT JOIN public.person_exclusions pe ON ((pe.person_id = person_schedules.person_id))) - JOIN public.exclusions_sessions es ON ((es.exclusion_id = pe.exclusion_id))) - LEFT JOIN public.sessions s ON ((s.id = es.session_id))) - WHERE ( - person_schedules.session_id <> s.id - AND - person_schedules.start_time >= s.start_time - AND ( - person_schedules.start_time < (s.start_time + (s.duration || ' minute'::text)::interval) - OR ( - person_schedules.end_time > s.start_time - AND person_schedules.end_time <= (s.start_time + (s.duration || ' minute'::text)::interval - ) - ) - ) - ); + select + concat(person_schedules.person_id, ':', es.exclusion_id, ':', person_schedules.session_id) as id, + person_schedules.person_id, + person_schedules.name, + person_schedules.published_name, + person_schedules.con_state, + es.exclusion_id, + es.session_id as excluded_session_id, + s.title as excluded_session_title, + person_schedules.session_id, + person_schedules.title, + person_schedules.start_time, + person_schedules.end_time, + person_schedules.duration, + person_schedules.session_assignment_role_type_id, + person_schedules.session_assignment_id, + person_schedules.session_assignment_name, + person_schedules.session_assignment_role_type + from + person_schedules + left join person_exclusions pe on + pe.person_id = person_schedules.person_id + join exclusions_sessions es on + es.exclusion_id = pe.exclusion_id + left join sessions s on + s.id = es.session_id + where + person_schedules.session_id <> s.id + and ( + ( + person_schedules.start_time >= s.start_time + and + person_schedules.start_time < (s.start_time + (s.duration || ' minute'::text)::interval) + ) + or + ( + person_schedules.end_time > s.start_time + and + person_schedules.end_time <= (s.start_time + (s.duration || ' minute'::text)::interval) + ) + ); SQL ActiveRecord::Base.connection.execute(query) end From a60350525c685f3a4778eb8f0279f00d403d4739 Mon Sep 17 00:00:00 2001 From: Henry Date: Tue, 5 Jul 2022 17:46:07 -0400 Subject: [PATCH 27/28] PLAN-520 exclude back to back from room conflict report --- app/controllers/reports/conflict_reports_controller.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/app/controllers/reports/conflict_reports_controller.rb b/app/controllers/reports/conflict_reports_controller.rb index 24165d742..ef7a5246a 100644 --- a/app/controllers/reports/conflict_reports_controller.rb +++ b/app/controllers/reports/conflict_reports_controller.rb @@ -8,6 +8,7 @@ def multiple_sessions_in_room room_conflicts = Conflicts::RoomConflict .includes(:room) .references(:room) + .where("room_conflicts.back_to_back = false") .order('rooms.name, start_time') workbook = FastExcel.open(constant_memory: true) From 1da3156b420d7e5b2bf1b061ceab8ead33fb85b9 Mon Sep 17 00:00:00 2001 From: Henry Date: Wed, 6 Jul 2022 08:57:58 -0400 Subject: [PATCH 28/28] PLAN-522 fix boundary for double booked --- app/lib/migration_helpers/plano_views.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/lib/migration_helpers/plano_views.rb b/app/lib/migration_helpers/plano_views.rb index 1e91e226e..4764ebb9d 100644 --- a/app/lib/migration_helpers/plano_views.rb +++ b/app/lib/migration_helpers/plano_views.rb @@ -146,10 +146,10 @@ def self.create_person_schedule_conflicts and ps2.session_id != ps1.session_id and ps2.start_time >= ps1.start_time and ( - ps2.start_time <= ps1.end_time + ps2.start_time < ps1.end_time or ( - ps2.end_time >= ps1.start_time and ps2.end_time <= ps1.end_time + ps2.end_time > ps1.start_time and ps2.end_time <= ps1.end_time ) ); SQL