Skip to content

Commit

Permalink
Merge pull request #442 from ChicagoWorldcon/PLAN-587-draft-schedule-tab
Browse files Browse the repository at this point in the history
PLAN-587 PLAN-522 PLAN-515 PLAN-575 PLAN-579 Draft schedules and approval
  • Loading branch information
balen authored Jul 16, 2022
2 parents 6a30e97 + 0fd9390 commit e2f0c23
Show file tree
Hide file tree
Showing 17 changed files with 515 additions and 88 deletions.
8 changes: 6 additions & 2 deletions app/controllers/people_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,18 @@ def snapshot_schedule
# We get the latest snapshot unless a label was pass in
sched = if !label.blank?
PersonScheduleSnapshot
.join(:schedule_snapshot)
.joins(:schedule_snapshot)
.where( person: person.id)
.where('schedule_snapshots.label': label)
.order('updated_at desc').first
else
PersonScheduleSnapshot.where( person: person.id).order('updated_at desc').first
end
render json: sched.snapshot, content_type: 'application/json'
if !sched
render json: {}, content_type: 'application/json'
else
render json: sched.snapshot, content_type: 'application/json'
end
end
end

Expand Down
26 changes: 24 additions & 2 deletions app/controllers/sessions_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,32 @@ def take_snapshot
label = params[:label]
label = 'draft' if label.blank?

SnapshotWorker.perform_async(label, current_person.name)
if ScheduleSnapshot.find_by({label: label})
render status: :unprocessable_entity,
json: { errors: [{title: "Validation failed: you already have a snapshot called #{label}"}]}.to_json,
content_type: 'application/json'
else
SnapshotWorker.perform_async(label, current_person.name)

render status: :ok,
json: { message: 'snapshot scheduled' }.to_json,
content_type: 'application/json'
end
end

def delete_snapshot
authorize current_person, policy_class: policy_class

label = params[:label]
label = 'draft' if label.blank?

snapshot = ScheduleSnapshot.find_by({label: label})
if snapshot
snapshot.delete
end

render status: :ok,
json: { message: 'snapshot scheduled' }.to_json,
json: { message: 'snapshot deleted' }.to_json,
content_type: 'application/json'
end

Expand Down
5 changes: 5 additions & 0 deletions app/javascript/administration/admin_component.vue
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@
ref="mailing-manager"
></mailings-manager>
</admin-accordion>
<admin-accordion id="schedule-settings-accordion" title="Schedule Settings">
<schedule-settings></schedule-settings>
</admin-accordion>
<admin-accordion id="event-settings-accordion" title="Event Settings" @show="showConfigs">
<configurations-manager
model="parameter_name"
Expand All @@ -65,6 +68,7 @@ import MailingsManager from '../mailings/mailings_manager';
import ConfigurationsManager from '../configurations/configurations_manager';
import SheetImporterVue from '../components/sheet_importer_vue.vue';
import AgreementManager from "@/agreements/agreement_manager";
import ScheduleSettings from "@/schedule/schedule_settings.vue";
export default {
components: {
Expand All @@ -75,6 +79,7 @@ export default {
SheetImporterVue,
MailingsManager,
ConfigurationsManager,
ScheduleSettings
},
name: 'AdminComponent',
data: () => ({
Expand Down
8 changes: 8 additions & 0 deletions app/javascript/constants/strings.js
Original file line number Diff line number Diff line change
Expand Up @@ -266,4 +266,12 @@ module.exports = {
geared_families: "Geared towards families",
geared_kids: "Geared towards kids",
},
SCHEDULE_DRAFT_CONFIRM_MESSAGE: "YOU WIN A MODAL! You can't undo this.",
SCHEDULE_FIRM_CONFIRM_MESSAGE: "YOU WIN A SECOND MODAL. You can't undo this one either.",
SCHEDULE_DRAFT_SUCCESS_MESSAGE: "You drafted!!!!!!!!!1!",
SCHEDULE_FIRM_SUCCESS_MESSAGE: "You firmed!",
SCHEDULE_APPROVAL_SAVE_SUCCESS: (approvalType) => `Success - ${approvalType} schedule approval ANNA TEXT.`,
SCHEDULE_APPROVAL_SAVE_ERROR: (approvalType) => errorMessage(`Error - ${approvalType} schedule approval ANNA TEXT`),
SCHEDULE_APPROVAL_COMMENT_SAVE_SUCCESS: (approvalType) => `Success - ${approvalType} schedule approval comment ANNA TEXT.`,
SCHEDULE_APPROVAL_COMMENT_SAVE_ERROR: (approvalType) => errorMessage(`Error - ${approvalType} schedule approval comment ANNA TEXT`),
}
60 changes: 30 additions & 30 deletions app/javascript/people/person_tabs.vue
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,11 @@
:person_id="person.id"
></session-ranker>
</b-tab>
<b-tab title="Live Schedule" lazy v-if="currentUserIsAdmin || currentUserIsStaff" :active="tab === 'schedule'">
<person-schedule></person-schedule>
<b-tab title="Draft Schedule" lazy v-if="displayDraftSchedule" :active="tab === 'draft-schedule'">
<person-draft-schedule></person-draft-schedule>
</b-tab>
<b-tab :title="liveScheduleTitle" lazy v-if="currentUserIsAdmin || currentUserIsStaff || firmSchedule" :active="tab === 'schedule'">
<person-live-schedule></person-live-schedule>
</b-tab>
<b-tab title="Admin" lazy v-if="currentUserIsAdmin || currentUserIsStaff" :active="tab === 'admin'">
<people-admin-tab></people-admin-tab>
Expand All @@ -63,7 +66,8 @@ import AvailabilityAndInterests from '../profile/availability_and_interests.vue'
import PersonDetails from '../profile/person_details.vue'
import PersonSummary from '../profile/person_summary.vue';
import PersonDemographics from '../profile/person_demographics.vue';
import PersonSchedule from '@/profile/person_schedule.vue';
import PersonLiveSchedule from '@/profile/person_live_schedule.vue';
import PersonDraftSchedule from '@/profile/person_draft_schedule.vue';
import PeopleAdminTab from './people_admin_tab.vue';
import ModelLoadingOverlay from '@/components/model_loading_overlay.vue';
Expand All @@ -73,12 +77,25 @@ import { sessionAssignmentModel } from '@/store/session_assignment.store'
import personSessionMixin from '@/auth/person_session.mixin';
import settingsMixin from "@/store/settings.mixin";
import modelUtilsMixin from '@/store/model_utils.mixin';
import { scheduleStatusMixin } from '@/store/schedule_status.mixin';
const { DateTime } = require("luxon");
import VueRouter from 'vue-router';
const { isNavigationFailure, NavigationFailureType } = VueRouter;
// This needs to be kept in sync with the tab order above
const tabsArray = [
'edit',
'other',
'availability',
'session-selection',
'session-ranking',
'draft-schedule',
'schedule',
'admin'
]
export default {
name: "PeopleTabs",
props: ['tab', 'id'],
Expand All @@ -90,13 +107,15 @@ export default {
PersonDetails,
PersonDemographics,
ModelLoadingOverlay,
PersonSchedule,
PersonLiveSchedule,
PersonDraftSchedule,
PeopleAdminTab,
},
mixins: [
personSessionMixin,
settingsMixin,
modelUtilsMixin
modelUtilsMixin,
scheduleStatusMixin,
],
data: () => ({
personModel,
Expand Down Expand Up @@ -136,33 +155,14 @@ export default {
this.$router.push('/people')
},
handleTabActivation(newTab, oldTab, bvEvent) {
let path = '';
const pathStart = this.$route.path.split('/')[1];
switch(newTab) {
case 0:
path = pathStart === 'people' ? 'edit' : '';
break;
case 1:
path = `other`;
break;
case 2:
path = `availability`;
break;
case 3:
path = `session-selection`;
break;
case 4:
path = `session-ranking`;
break;
case 5:
path = `schedule`;
break;
case 6:
path = `admin`;
break;
}
// change the router path to match the current tab
// so that reloads work right
// IF YOU ADD A TAB make sure you update the tabsArray or badness will happen
let path = tabsArray[newTab];
const pathStart = this.$route.path.split('/')[1];
if (newTab === '0' && pathStart !== 'people') {
path = '';
}
if(pathStart === 'people') {
path += `/${this.person.id}`
}
Expand Down
40 changes: 40 additions & 0 deletions app/javascript/profile/person_draft_schedule.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<template>
<person-schedule-display :sessions="sessions" title="Draft Schedule" approvalType="draft"></person-schedule-display>
</template>

<script>
import { mapActions } from 'vuex';
import PersonScheduleDisplay from './person_schedule_display.vue';
import { personModel as model } from '@/store/person.store';
import { modelMixinNoProp } from '@/mixins';
export default {
name: "PersonDraftSchedule",
components: {
PersonScheduleDisplay
},
mixins: [
modelMixinNoProp,
],
data: () => ({
sessions: {},
model,
}),
methods: {
...mapActions({
get: 'jv/get'
}),
},
mounted() {
if(this.selected) {
this.get(`/person/${this.selected.id}/snapshot_schedule`).then(data => {
const {_jv, ...filtered_data} = data;
this.sessions = filtered_data;
})
}
}
}
</script>

<style lang="scss" scoped>
</style>
42 changes: 42 additions & 0 deletions app/javascript/profile/person_live_schedule.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<template>
<person-schedule-display :sessions="sessions" :title="liveScheduleTitle" :approvalType="firmSchedule ? 'firm' : null"></person-schedule-display>
</template>

<script>
import { mapActions } from 'vuex';
import PersonScheduleDisplay from './person_schedule_display.vue';
import { personModel as model } from '@/store/person.store';
import { modelMixinNoProp } from '@/mixins';
import { scheduleStatusMixin } from '@/store/schedule_status.mixin';
export default {
name: "PersonLiveSchedule",
components: {
PersonScheduleDisplay
},
mixins: [
modelMixinNoProp,
scheduleStatusMixin,
],
data: () => ({
sessions: {},
model,
}),
methods: {
...mapActions({
get: 'jv/get'
}),
},
mounted() {
if(this.selected) {
this.get(`/person/${this.selected.id}/live_sessions`).then(data => {
const {_jv, ...filtered_data} = data;
this.sessions = filtered_data;
})
}
}
}
</script>

<style lang="scss" scoped>
</style>
53 changes: 53 additions & 0 deletions app/javascript/profile/person_schedule_approval.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<template>
<div v-if="approvalType">
<b-form-group>
<template #label>Do you approve this <strong>{{approvalType}}</strong> schedule?</template>
<b-form-radio-group stacked :options="approvalOptions" v-model="approved" @change="saveApproval()"></b-form-radio-group>
</b-form-group>
<b-form-group label="If no, what changes would you like to have?">
<b-textarea v-model="approvalComment" :disabled="approved !== false" @blur="saveApprovalComments()"></b-textarea>
</b-form-group>
</div>
</template>

<script>
import { toastMixin } from '@/mixins'
import {
SCHEDULE_APPROVAL_COMMENT_SAVE_ERROR,
SCHEDULE_APPROVAL_COMMENT_SAVE_SUCCESS,
SCHEDULE_APPROVAL_SAVE_ERROR,
SCHEDULE_APPROVAL_SAVE_SUCCESS,
} from '@/constants/strings'
export default {
name: 'PersonScheduleApproval',
props: {
approvalType: {
type: String,
default: null
}
},
mixins: [
toastMixin
],
data: () => ({
approvalOptions: [{text: 'Not Set', value: null}, {text: 'Yes', value: true}, {text: 'No', value: false}],
approved: null,
approvalComment: null,
}),
methods: {
saveApproval() {
//TODO save the value of this.approval
this.toastPromise(Promise.resolve("Replace me"), SCHEDULE_APPROVAL_SAVE_SUCCESS(this.approvalType), SCHEDULE_APPROVAL_SAVE_ERROR(this.approvalType))
},
saveApprovalComments() {
//TODO save the value of this.approvalComment
this.toastPromise(Promise.resolve("Replace me"), SCHEDULE_APPROVAL_COMMENT_SAVE_SUCCESS(this.approvalType), SCHEDULE_APPROVAL_COMMENT_SAVE_ERROR(this.approvalType))
}
}
}
</script>

<style>
</style>
Loading

0 comments on commit e2f0c23

Please sign in to comment.