diff --git a/app/controllers/concerns/resource_methods.rb b/app/controllers/concerns/resource_methods.rb index 4a12b4dc3..3bb5e94e3 100644 --- a/app/controllers/concerns/resource_methods.rb +++ b/app/controllers/concerns/resource_methods.rb @@ -206,6 +206,10 @@ def order_string(order_by: nil) order_str end + def collection_where + nil + end + def collection base = if belong_to_class && belongs_to_param_id parent = belong_to_class.find belongs_to_param_id @@ -226,6 +230,8 @@ def collection .eager_load(eager_load) .joins(join_tables) .where(query(@filters)) + .where(collection_where) + # anpther where? q = q.distinct if join_tables && !join_tables.empty? diff --git a/app/controllers/curated_tags_controller.rb b/app/controllers/curated_tags_controller.rb new file mode 100644 index 000000000..046d439f4 --- /dev/null +++ b/app/controllers/curated_tags_controller.rb @@ -0,0 +1,29 @@ +class CuratedTagsController < ResourceController + MODEL_CLASS = 'CuratedTag'.freeze + SERIALIZER_CLASS = 'CuratedTagSerializer'.freeze + POLICY_CLASS = 'CuratedTagPolicy'.freeze + POLICY_SCOPE_CLASS = 'CuratedTagPolicy::Scope'.freeze + + # Need context from the request + # index has the context + def collection_where + permitted = params.permit(allowed_params) + context = permitted[:context] + table = Arel::Table.new(model_class.table_name) + + table[:context].eq(context) if context + end + + def paginate + false + end + + def allowed_params + %i[ + id + lock_version + name + context + ] + end +end diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index ee3fbd2ed..5ae34f91c 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -176,6 +176,18 @@ def tags content_type: 'application/json' end + def labels + res = Session.tags_on(:labels).order(:name) + + render json: TagSerializer.new(res, + { + # include: serializer_includes, + params: {domain: "#{request.base_url}"} + } + ).serializable_hash(), + content_type: 'application/json' + end + def before_update # if time or room have changed removed ignored conflicts p = _permitted_params(model: object_name, instance: @object) @@ -206,32 +218,37 @@ def serializer_includes def includes [ :format, - :room, - :base_tags + :room ] end def references [ :format, - :room, + :room ] end def eager_load [ {session_areas: :area}, - :areas + :areas, + :published_session, + {taggings: :tag} ] end def array_col?(col_name:) return true if col_name == 'area_list' + return true if col_name == 'tags_array' + return true if col_name == 'labels_array' false end def array_table(col_name:) return 'areas_list' if col_name == 'area_list' + return 'tags_list_table' if col_name == 'tags_array' + return 'labels_list_table' if col_name == 'labels_array' false end @@ -239,6 +256,8 @@ def join_tables sessions = Arel::Table.new(Session.table_name) subquery = Session.area_list.as('areas_list') + tags_subquery = Session.tags_list_table.as('tags_list_table') + labels_subquery = Session.labels_list_table.as('labels_list_table') conflict_counts = Session.conflict_counts.as('conflict_counts') joins = [ sessions.create_join( @@ -248,6 +267,20 @@ def join_tables ), Arel::Nodes::OuterJoin ), + sessions.create_join( + tags_subquery, + sessions.create_on( + tags_subquery[:session_id].eq(sessions[:id]) + ), + Arel::Nodes::OuterJoin + ), + sessions.create_join( + labels_subquery, + sessions.create_on( + labels_subquery[:session_id].eq(sessions[:id]) + ), + Arel::Nodes::OuterJoin + ), sessions.create_join( conflict_counts, sessions.create_on( @@ -286,7 +319,9 @@ def join_tables def select_fields Session.select( ::Session.arel_table[Arel.star], - 'conflict_counts.conflict_count' + 'conflict_counts.conflict_count', + 'tags_list_table.tags_array', + 'labels_list_table.labels_array' ) end @@ -318,6 +353,7 @@ def allowed_params open_for_interest instructions_for_interest tag_list + label_list session_areas_attributes proofed format_id @@ -330,8 +366,5 @@ def allowed_params recorded streamed ] - # Tags - # format - # areas end end diff --git a/app/controllers/settings_controller.rb b/app/controllers/settings_controller.rb index 647cd7893..f3e56f1a8 100644 --- a/app/controllers/settings_controller.rb +++ b/app/controllers/settings_controller.rb @@ -63,14 +63,14 @@ def index attendance_type: [ { value: 'in person', - label: "**In-person only:** I am planning to attend #{convention_name} in-person" + label: "In-person only: I am planning to attend #{convention_name} in-person" }, { value: 'virtual', - label: "**Virtual only:** I am not planning to attend #{convention_name} in-person, and would like to be a virtual participant on virtual-based items only (via Zoom or similar technology)." + label: "Online only: I am not planning to attend #{convention_name} in-person, and would like to be a online participant on online-based items only (via Zoom or similar technology)." }, { value: 'hybrid', - label: "**In-person and virtual:** I am planning to attend #{convention_name} in-person, but would also like to be considered for virtual panels." + label: "In-person and online: I am planning to attend #{convention_name} in-person, but would also like to be considered for online panels." }, ], age_restrictions: ::AgeRestriction.all, diff --git a/app/javascript/components/model_tags.vue b/app/javascript/components/model_tags.vue index 9e70c82bb..556c007c8 100644 --- a/app/javascript/components/model_tags.vue +++ b/app/javascript/components/model_tags.vue @@ -27,6 +27,10 @@ export default { filter: null, taggable: false, fieldOnly: false, + formatter: { + type: Function, + default: (val) => val + }, disabled: { type: Boolean, default: false @@ -65,11 +69,12 @@ export default { ).map( (obj) => { if (this.fieldOnly) { - return obj[this.field] + return this.formatter(obj[this.field]) } else { return { code: obj.id, - label: obj[this.field] + value: obj[this.field], + label: this.formatter(obj[this.field]) } } diff --git a/app/javascript/constants/strings.js b/app/javascript/constants/strings.js index bd45de97d..1bdd33c83 100644 --- a/app/javascript/constants/strings.js +++ b/app/javascript/constants/strings.js @@ -286,8 +286,8 @@ module.exports = { }, PERSON_ATTENDANCE_TYPE: { 'in person': "In Person", - hybrid: "In Person AND Virtually", - virtual: "Virtually", + hybrid: "In Person AND Online", + virtual: "Online", }, PAGE_CONTENT_SAVE_SUCCESS: "Page content saved successfully", @@ -302,7 +302,7 @@ module.exports = { unknown: "Unknown", in_person: "In Person", hybrid: "Hybrid", - virtual: "Virtual" + virtual: "Online" }, SESSION_STATUS: { draft: "Draft", @@ -310,6 +310,7 @@ module.exports = { revised: "Revised", dropped: "Dropped", }, + SESSION_NO_TAGS: (tagName) => `Click the pencil to add ${tagName}`, 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: { @@ -341,7 +342,7 @@ module.exports = { }, EVENT_SETTINGS_MUST_RELOAD: "*** Changes to these settings will only take effect after you reload your browser page. ***", CONFIGURATION_LABEL_OVERRIDES: { - event_virtual: "Does this event include a virtual component?", + event_virtual: "Does this event include an online component?", clyde_base_url: "Base URL for Clyde", profile_show_info_demographic_community: "Show Demographics, Community, and Info in Profile" } diff --git a/app/javascript/dashboard/dashboard.vue b/app/javascript/dashboard/dashboard.vue index 928f88b5d..d3daa601a 100644 --- a/app/javascript/dashboard/dashboard.vue +++ b/app/javascript/dashboard/dashboard.vue @@ -21,7 +21,7 @@ Update your name(s), pronouns, email address, bio, and social media as needed
  • - If you’re not going to be attending the convention in-person, please let us know the timezone that you will be in when you attend virtually. + If you’re not going to be attending the convention in-person, please let us know the timezone that you will be in when you attend online.
  • @@ -61,7 +61,7 @@ Select sessions by using the slider to the right of the description. Your selections will save automatically.
  • - While some items are marked or otherwise described as Virtual, many we’re not sure if they will be taking place in-person or online, so everyone should feel free to sign up for items not marked either way. + While some items are marked or otherwise described as online, many we’re not sure if they will be taking place in-person or online, so everyone should feel free to sign up for items not marked either way.
  • diff --git a/app/javascript/profile/availability_and_interests.vue b/app/javascript/profile/availability_and_interests.vue index c9d27e53e..214f9923a 100644 --- a/app/javascript/profile/availability_and_interests.vue +++ b/app/javascript/profile/availability_and_interests.vue @@ -13,7 +13,7 @@

    Under each day, highlight (click and drag) the times of day that you are available for programming in the calendar view below. You can create multiple blocks of time per day. The in-person convention time is currently displayed. - If you will be attending virtually, and want to enter your availability in that time zone, + If you will be attending online, and want to enter your availability in that time zone, select that option from below the calendar. The time is displayed in the convention time zone, which is currently {{timezone}}. diff --git a/app/javascript/profile/person_details.vue b/app/javascript/profile/person_details.vue index a7b00d409..8ef5e6707 100644 --- a/app/javascript/profile/person_details.vue +++ b/app/javascript/profile/person_details.vue @@ -34,13 +34,13 @@

    -
    Virtual
    +
    Online
    -
    Virtual
    +
    Online
    I plan to attend the convention:
    {{area}}
    - Tag(s): {{tag}} + Tag(s): {{tagFormatter(tag)}}

    Instructions for potential panelists:
    @@ -97,6 +97,7 @@ import personSessionMixin from '../auth/person_session.mixin'; import sessionAssignmentMixin from '../sessions/session_assignment.mixin'; import { sessionAssignmentModel } from '@/store/session_assignment.store' import SessionAssignmentMonitor from './session_assignment_monitor.vue' +import {tagsMixin} from '@/store/tags.mixin'; import { SESSION_RANKING_ERROR } from '../constants/strings'; @@ -109,7 +110,8 @@ export default { personSessionMixin, modelMixin, tableMixin, // covers pagination and sorting - sessionAssignmentMixin + sessionAssignmentMixin, + tagsMixin, ], props: { person_id: { diff --git a/app/javascript/profile/session_search.vue b/app/javascript/profile/session_search.vue index cb7d46c74..094dde773 100644 --- a/app/javascript/profile/session_search.vue +++ b/app/javascript/profile/session_search.vue @@ -17,7 +17,8 @@ v-model="tags" model="tag" field="name" - filter='{"op":"all","queries":[["taggings.taggable_type", "=", "Session"]]}' + filter='{"op":"all","queries":[["taggings.taggable_type", "=", "Session"], ["taggings.context", "=", "tags"]]}' + :formatter="tagFormatter" > @@ -43,6 +44,7 @@ + + diff --git a/app/javascript/sessions/session.js b/app/javascript/sessions/session.js index e00e1d9f6..2ead9d989 100644 --- a/app/javascript/sessions/session.js +++ b/app/javascript/sessions/session.js @@ -3,6 +3,9 @@ import AreaSelectForSearch from './area_select_for_search' import FormatSelectForSearch from './format_select_for_search' import RoomSelectForSearch from './room_select_for_search' +import TagsSelectForSearch from './tags_select_for_search' +import LabelsSelectForSearch from './labels_select_for_search' + export const session_columns = [ // { // key: 'id' @@ -42,6 +45,28 @@ export const session_columns = [ type: 'custom-component', operators: ['is','is not', 'is empty','is not empty'], }, + { + key: 'tag_list', + label: 'Public Tags', + sortable: true, + sortKey: 'tags_list_table.tags_array', + search_key: 'tags_list_table.tags_array', + component: TagsSelectForSearch, + type: 'custom-component', + operators: ['is', 'is not', 'is only', 'is not only', 'is empty', 'is not empty'], + formatter: (value) => value && value.length ? value.join(", ") : value + }, + { + key: 'label_list', + label: 'Admin Labels', + sortable: true, + sortKey: 'labels_list_table.labels_array', + search_key: 'labels_list_table.labels_array', + component: LabelsSelectForSearch, + type: 'custom-component', + operators: ['is', 'is not', 'is only', 'is not only', 'is empty', 'is not empty'], + formatter: (value) => value && value.length ? value.join(", ") : value + }, { key: 'start_time', sortKey: 'sessions.start_time', @@ -144,12 +169,14 @@ export const session_columns = [ { key: 'created_at', label: 'Date Created', - sortable: false + sortKey: 'sessions.created_at', + sortable: true }, { key: 'updated_at', label: 'Date Updated', - sortable: false + sortKey: 'sessions.updated_at', + sortable: true }, { key: 'updated_by', diff --git a/app/javascript/sessions/session_edit.vue b/app/javascript/sessions/session_edit.vue index 498e747aa..35e2415ad 100644 --- a/app/javascript/sessions/session_edit.vue +++ b/app/javascript/sessions/session_edit.vue @@ -30,21 +30,6 @@ @change="saveSession()" > -
    -
    - +
    + No Yes
    +
    + +
    -
    +
    +
    + +
    @@ -171,6 +174,8 @@ import { min_value } from 'vee-validate/dist/rules' import { SESSION_ENVIRONMENT } from '@/constants/strings' import {minorsParticipationMixin} from './minors_participation.mixin'; import { ageRestrictionMixin } from './age_restriction.mixin'; +import TagDisplay from './tag_display.vue'; +import { tagsMixin } from '@/store/tags.mixin'; extend('min_value', { ...min_value, @@ -183,12 +188,14 @@ export default { ModelSelect, ModelTags, PlanoEditor, - ValidationProvider + ValidationProvider, + TagDisplay }, mixins: [ modelUtilsMixin, minorsParticipationMixin, - ageRestrictionMixin + ageRestrictionMixin, + tagsMixin, ], data: () => ({ editable: false, @@ -199,14 +206,6 @@ export default { session() { return this.selected_model(sessionModel) }, - session_tags: { - get() { - return this.session.tag_list - }, - set(val) { - this.session.tag_list = val - } - }, session_areas: { get() { let res = Object.values(this.session.session_areas).filter( diff --git a/app/javascript/sessions/session_sidebar.vue b/app/javascript/sessions/session_sidebar.vue index 3b89720ff..cccf700d6 100644 --- a/app/javascript/sessions/session_sidebar.vue +++ b/app/javascript/sessions/session_sidebar.vue @@ -95,6 +95,10 @@
    None Selected
    Session Environment
    {{SESSION_ENVIRONMENT[selected.environment]}}
    +
    Public Tags
    +
    {{ formatTags(selected.tag_list) }}
    +
    Admin Labels
    +
    {{ formatTags(selected.label_list) }}
    Room Setup
    {{selected.room_set.name}}
    None Selected
    @@ -169,6 +173,7 @@ import SessionConflicts from '@/conflicts/session_conflicts.vue'; import { SESSION_ENVIRONMENT, SESSION_STATUS} from '@/constants/strings'; import { minorsParticipationMixin } from './minors_participation.mixin'; import { ageRestrictionMixin } from './age_restriction.mixin'; +import { tagsMixin } from '@/store/tags.mixin' export default { name: 'SessionSidebar', @@ -187,11 +192,12 @@ export default { startTimeMixin, minorsParticipationMixin, ageRestrictionMixin, + tagsMixin, ], data: () => ({ sessionConflictModel, SESSION_ENVIRONMENT, - SESSION_STATUS + SESSION_STATUS, }), computed: { editLink() { diff --git a/app/javascript/sessions/session_table.vue b/app/javascript/sessions/session_table.vue index 158dff34b..cbd1da8d7 100644 --- a/app/javascript/sessions/session_table.vue +++ b/app/javascript/sessions/session_table.vue @@ -54,6 +54,16 @@ {{formatAreas(item.area_list)}} + +