2746 lines
112 KiB
JavaScript
2746 lines
112 KiB
JavaScript
var PROD = 0
|
||
|
||
|
||
if (PROD && location.protocol !== 'https:') {
|
||
location.replace(`https:${location.href.substring(location.protocol.length)}`);
|
||
}
|
||
|
||
|
||
|
||
|
||
// _ _
|
||
// | | | |
|
||
// | |__ ___| |_ __ ___ _ __ ___
|
||
// | '_ \ / _ \ | '_ \ / _ \ '__/ __|
|
||
// | | | | __/ | |_) | __/ | \__ \
|
||
// |_| |_|\___|_| .__/ \___|_| |___/
|
||
// | |
|
||
// |_|
|
||
|
||
|
||
|
||
function init_file_dropzone(parameter_name) {
|
||
Dropzone.options.myGreatDropzone = { // camelized version of the `id`
|
||
paramName: parameter_name, // The name that will be used to transfer the file
|
||
maxFilesize: 6 }; // MB
|
||
}
|
||
// init_file_dropzone("staffpicupload")
|
||
|
||
|
||
function parsesqltime(mysqldate) { // 2021-01-29 09:00:00
|
||
if (! mysqldate) { return 0 }
|
||
var field = mysqldate.match(/^(\d\d\d\d)\-(\d+)\-(\d+)[T|\s](\d+)\:(\d+)\:(\d+)$/)
|
||
var mydate = new Date(field[1], field[2] - 1 , field[3], field[4], field[5], field[6])
|
||
return mydate }
|
||
|
||
function dj(mysqldate) { return dayjs(parsesqltime(mysqldate)) }
|
||
|
||
Object.defineProperty(Vue.prototype, '$dj', { value: dj });
|
||
Object.defineProperty(Vue.prototype, '$parsesqltime', { value: parsesqltime });
|
||
|
||
|
||
|
||
|
||
// ________ __
|
||
// | ____\ \ / /
|
||
// | |__ \ V /
|
||
// | __| > <
|
||
// | | / . \
|
||
// |_| /_/ \_\
|
||
//
|
||
//
|
||
//
|
||
// VISUAL EFFECTS
|
||
//
|
||
|
||
|
||
|
||
function fade_message(theselector='#alert') {
|
||
var a_dom = document.querySelector(theselector);
|
||
TinyAnimate.animateCSS(a_dom, 'opacity', '', 1.0, 0.0, 750, 'easeInOutQuart', function() { }); }
|
||
|
||
function alert_message(msg,color='yellow') {
|
||
var a = $('#alert')
|
||
a.text(msg)
|
||
a.removeClass('hidden');
|
||
a.css('background-color',color)
|
||
var a_dom = document.querySelector('#alert');
|
||
TinyAnimate.animateCSS(a_dom, 'opacity', '', 0.0, 1.0, 500, 'easeInOutQuart', function() {
|
||
setTimeout( fade_message, 2500 ) }); }
|
||
|
||
function fadein_message(theclass='success') {
|
||
//var a = $('#'+theclass)
|
||
//a.css('visibility','visible')
|
||
var a_dom = document.querySelector('.'+theclass);
|
||
TinyAnimate.animateCSS(a_dom, 'opacity', '', 0.0, 1.0, 500, 'easeInOutQuart', function() {
|
||
setTimeout( function() { fade_message('.'+theclass) }, 2500 ) }); }
|
||
|
||
|
||
// _
|
||
// | |
|
||
// ___ ___ _ __ ___ _ __ ___ _ __ ___ _ __ | |_ ___
|
||
// / __/ _ \| '_ ` _ \| '_ \ / _ \| '_ \ / _ \ '_ \| __/ __|
|
||
// | (_| (_) | | | | | | |_) | (_) | | | | __/ | | | |_\__ \
|
||
// \___\___/|_| |_| |_| .__/ \___/|_| |_|\___|_| |_|\__|___/
|
||
// | |
|
||
// |_|
|
||
|
||
//
|
||
// FORM COMPONENTS
|
||
//
|
||
|
||
|
||
// TODO these should know if they're modifying the current user or someone else.
|
||
|
||
// A single text style question
|
||
const TQuestion = Vue.component('field', {
|
||
props: [ 'table', 'qid', 'question', 'answer', 'placeholder', 'targetid', ],
|
||
data: function () {
|
||
return { "a":this.answer } },
|
||
watch: {
|
||
"answer": function(val,Oldval) { this.a = val },
|
||
"a": function (val, oldVal) {
|
||
this.$root.events.trigger('changed',[this.qid,this.table, val, this.targetid]) }, },
|
||
template: `<div class="mb-4">
|
||
<label v-if="question" :for="qid" class="block text-sm font-medium text-gray-700 mb-1">
|
||
{{ question }}
|
||
</label>
|
||
<input
|
||
:id="qid"
|
||
type="text"
|
||
v-model="a"
|
||
:placeholder="placeholder"
|
||
class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring focus:ring-blue-200 focus:ring-opacity-50 p-2 text-sm"
|
||
/>
|
||
</div>`,
|
||
})
|
||
|
||
// A single INLINE text style question
|
||
const TIQuestion = Vue.component('ifield', {
|
||
props: [ 'table', 'qid', 'question', 'answer', 'placeholder', 'myclass', 'targetid', ],
|
||
data: function () {
|
||
return { "a":this.answer } },
|
||
watch: {
|
||
"answer": function(val,Oldval) { this.a = val },
|
||
"a": function (val, oldVal) {
|
||
this.$root.events.trigger('changed',[this.qid,this.table, val, this.targetid]) }, },
|
||
template: `<input :id="this.qid" type="text" v-model="a" :placeholder="placeholder" :class="this.myclass" />`,
|
||
})
|
||
|
||
// A single checkbox
|
||
const Checkbox = Vue.component('checkbox', {
|
||
props: [ 'table', 'qid', 'question', 'answer', 'targetid', ],
|
||
data: function () {
|
||
return { "a":this.answer } },
|
||
watch: {
|
||
"answer": function(val,Oldval) { this.a = val },
|
||
"a": function (val, oldVal) {
|
||
var newVal = 0
|
||
if (val==true) { newVal = 1 }
|
||
this.$root.events.trigger('changed',[this.qid,this.table, newVal, this.targetid]) }, },
|
||
template: `<div class="pure-controls">
|
||
<label :for="this.qid" class="question pure-checkbox">
|
||
<input :id="this.qid" type="checkbox" class="form-control" v-model="a" />
|
||
{{ question }}</label></div>`
|
||
})
|
||
|
||
// A single long format text question
|
||
const TAQuestion = Vue.component('tfield', {
|
||
props: [ 'table', 'qid', 'question', 'answer', 'targetid', 'myclass' ],
|
||
data: function () {
|
||
return { "a": this.answer } },
|
||
watch: {
|
||
"a": function (val, oldVal) {
|
||
this.$root.events.trigger('changed',[this.qid,this.table, val, this.targetid]) },
|
||
"answer": function (val, oldVal) { this.a = val },
|
||
},
|
||
template: `<div class="mb-4">
|
||
<label :for="qid" class="block text-sm font-medium text-gray-700 mb-1">
|
||
{{ question }}
|
||
</label>
|
||
<textarea
|
||
:id="qid"
|
||
v-model="a"
|
||
:class="myclass"
|
||
class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring focus:ring-blue-200 focus:ring-opacity-50 p-2 text-sm"
|
||
></textarea>
|
||
</div>` })
|
||
|
||
|
||
|
||
// long format text WYSIWYG HTML
|
||
const HTAQuestion = Vue.component('htfield', {
|
||
props: [ 'table', 'qid', 'question', 'answer', 'targetid', 'myclass' ],
|
||
data: function () { return { "a": this.answer, "p":0, } }, // the pell editor object
|
||
mounted: function() {
|
||
var self = this
|
||
var element = document.getElementById(self.qid)
|
||
this.p = pell.init( { element: element, onChange: function(h) {
|
||
self.$root.events.trigger('changed',[self.qid, self.table, h, self.targetid]) } } )
|
||
self.p.content.innerHTML = self.answer },
|
||
watch: {
|
||
"answer": function (val, oldVal) { this.p.content.innerHTML = val }, },
|
||
template: `<div><label :for="this.qid" class="question">{{ question }} </label>
|
||
<div :id="this.qid" class="pell"></div></div>` })
|
||
|
||
// long format text WYSIWYG HTML FORM ALIGNED STYLE
|
||
const HTAQuestionFA = Vue.component('htfield_fa', {
|
||
props: [ 'table', 'qid', 'question', 'answer', 'targetid', 'myclass' ],
|
||
data: function () { return { "a": this.answer, "p":0, } }, // the pell editor object
|
||
mounted: function() {
|
||
var self = this
|
||
var element = document.getElementById(self.qid)
|
||
this.p = pell.init( { element: element, onChange: function(h) {
|
||
self.$root.events.trigger('changed',[self.qid, self.table, h, self.targetid]) } } )
|
||
self.p.content.innerHTML = self.answer },
|
||
watch: {
|
||
"answer": function (val, oldVal) { this.p.content.innerHTML = val }, },
|
||
template: `<div class=""><label :for="this.qid" class="question">{{ question }} </label>
|
||
<div :id="this.qid" class="form-control pell"></div></div>` })
|
||
|
||
// A single numeric question
|
||
const NQuestioon = Vue.component('n-question', {
|
||
props: [ 'qq' ],
|
||
data: function () { return { "answer": this.qq.answer } },
|
||
watch: { "answer": function (val, oldVal) {
|
||
this.$root.events.trigger('update_survey', [this.qq.user, this.qq.session, this.qq.qid, val]) }, },
|
||
template: `<div class=""><span class="question">{{ qq.question }}</span><br />
|
||
<div class="makeup_indent "><input class="form-check-input" type="radio" id="one" value="1" v-model="answer">
|
||
<label class="form-check-label" for="one">One</label>
|
||
<input class="form-check-input" type="radio" id="two" value="2" v-model="answer">
|
||
<label class="form-check-label" for="two">Two</label>
|
||
<input class="form-check-input" type="radio" id="three" value="3" v-model="answer">
|
||
<label class="form-check-label" for="three">Three</label>
|
||
<input class="form-check-input" type="radio" id="four" value="4" v-model="answer">
|
||
<label class="form-check-label" for="four">Four</label>
|
||
<input class="form-check-input" type="radio" id="five" value="5" v-model="answer">
|
||
<label class="form-check-label" for="five">Five</label>
|
||
</div></div>`
|
||
})
|
||
|
||
// A single survey text question
|
||
const STQuestion = Vue.component('st-question', {
|
||
props: [ 'qq' ],
|
||
data: function () { return { "answer": this.qq.answer } },
|
||
watch: { "answer": function (val, oldVal) {
|
||
this.$emit('dirty')
|
||
this.$root.events.trigger('update_survey', [this.qq.user, this.qq.session, this.qq.qid, val]); }, },
|
||
template: `<div class="pure-form-aligned"><label class="question">{{ qq.question }}</label>
|
||
<textarea :id="qq.id" class="form-control pure-form-aligned" v-model="answer"></textarea></div>`,
|
||
})
|
||
|
||
|
||
|
||
// The "I Certify" question
|
||
const ICertify = Vue.component('icertify', {
|
||
props: [ 'c' ],
|
||
data: function () { return { "checked": this.c } },
|
||
watch: { checked() {
|
||
this.$emit('dirty')
|
||
this.$parent.docert(this.checked); },
|
||
},
|
||
template: `<div class="makeup_indent"><input class="form-check-input" type="checkbox" id="checkbox" v-model="checked">
|
||
<label class="icert form-check-label" for="checkbox">I certify that I have attended this event.</label><br />
|
||
</div>` });
|
||
|
||
|
||
|
||
// Select menu
|
||
/*
|
||
table: name of database table
|
||
qid: what column of the table to edit
|
||
question: label displayed to user
|
||
answer: data item used for v-model
|
||
menu: key of root vue object with menu items
|
||
labelfield: key of 'menu' object that should be displayed as choices
|
||
targetid: when editing existing row: the id of the row
|
||
*/
|
||
const SelMenu = Vue.component('selectmenu', {
|
||
props: [ 'table', 'qid', 'question', 'answer', 'menu', 'labelfield', 'targetid', ],
|
||
data: function () { return { "a": this.answer } },
|
||
watch: {
|
||
"a": function (val, oldVal) {
|
||
this.$root.events.trigger('changed',[this.qid,this.table, val, this.targetid]) },
|
||
"answer": function (val, oldVal) { this.a = val }, },
|
||
template: `<div class="mb-4">
|
||
<label :for="qid" class="block text-sm font-medium text-gray-700 mb-1">
|
||
{{ question }}
|
||
</label>
|
||
<select
|
||
:id="qid"
|
||
v-model="a"
|
||
class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring focus:ring-blue-200 focus:ring-opacity-50 p-2 text-sm bg-white"
|
||
>
|
||
<option v-for="o in $root[menu]" :value="o.id">
|
||
{{ o[labelfield] }}
|
||
</option>
|
||
</select>
|
||
</div>` })
|
||
|
||
|
||
// Select menu FORM ALIGNED STYLE
|
||
const SelMenuFA = Vue.component('selectmenu_fa', {
|
||
props: [ 'table', 'qid', 'question', 'answer', 'menu', 'labelfield', 'targetid', ],
|
||
data: function () { return { "a": this.answer } },
|
||
watch: {
|
||
"a": function (val, oldVal) {
|
||
this.$root.events.trigger('changed',[this.qid,this.table, val, this.targetid]) },
|
||
"answer": function (val, oldVal) { this.a = val }, },
|
||
template: `<div class="mb-4">
|
||
<label :for="qid" class="block text-sm font-medium text-gray-700 mb-1">
|
||
{{ question }}
|
||
</label>
|
||
<select
|
||
:id="qid"
|
||
v-model="a"
|
||
class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring focus:ring-blue-200 focus:ring-opacity-50 p-2 text-sm bg-white"
|
||
>
|
||
<option v-for="o in $root[menu]" :value="o.id">
|
||
{{ o[labelfield] }}
|
||
</option>
|
||
</select>
|
||
</div>` })
|
||
|
||
|
||
// A date time picker
|
||
const DTPicker = Vue.component('dtpicker', {
|
||
props: [ 'table', 'qid', 'question', 'answer', 'targetid', ],
|
||
methods: { },
|
||
mounted: function() { },
|
||
data: function () { return { "a":this.answer } },
|
||
watch: {
|
||
"answer": function(val,Oldval) { this.a = val },
|
||
"a": function (val, oldVal) {
|
||
this.$root.events.trigger('changed',[this.qid,this.table, val, this.targetid]) }, },
|
||
template: `<div class="mb-4">
|
||
<label v-if="question" :for="qid" class="block text-sm font-medium text-gray-700 mb-1">
|
||
{{ question }}
|
||
</label>
|
||
<input
|
||
type="datetime-local"
|
||
:id="qid"
|
||
v-model="a"
|
||
step="300"
|
||
class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring focus:ring-blue-200 focus:ring-opacity-50 p-2 text-sm"
|
||
/>
|
||
</div>`,
|
||
})
|
||
|
||
|
||
// Accordion style box
|
||
const ExpandyBox = Vue.component('expandybox', {
|
||
props: [ 'header', 'body', ],
|
||
methods: {
|
||
toggle: function() {
|
||
if (this.state=='close') { this.state='open'; this.symbol='-' }
|
||
else { this.state='close'; this.symbol='+' }
|
||
}
|
||
},
|
||
mounted: function() { },
|
||
data: function () { return { "state":'close', "symbol":"+", } },
|
||
watch: {
|
||
"answer": function(val,Oldval) { this.a = val },
|
||
"a": function (val, oldVal) {
|
||
this.$root.events.trigger('changed',[this.qid,this.table, val, this.targetid]) }, },
|
||
template: `<div><div class="pure-g">
|
||
<div class="pure-u-1-1">
|
||
<h4 class="exp_header">
|
||
<a href="#" v-on:click.prevent="toggle()">
|
||
<span class="decorate">{{symbol}}</span>
|
||
{{header}}</a>
|
||
</h4>
|
||
</div>
|
||
</div>
|
||
<div v-if="state=='open'" class="pure-g">
|
||
<div class="pure-u-1-1" v-html="body"><slot></slot></div>
|
||
</div>
|
||
</div>`,
|
||
})
|
||
|
||
// mode pill
|
||
Vue.component('ModePill', {
|
||
props: ['mode'],
|
||
computed: {
|
||
label() {
|
||
switch (this.mode) {
|
||
case 'inperson': return 'In Person';
|
||
case 'online': return 'Online';
|
||
case 'hybrid': return 'Hybrid';
|
||
default: return this.mode;
|
||
}
|
||
},
|
||
bgClass() {
|
||
switch (this.mode) {
|
||
case 'inperson': return 'bg-green-500';
|
||
case 'online': return 'bg-blue-500';
|
||
case 'hybrid': return 'bg-yellow-500 text-black';
|
||
default: return 'bg-gray-400';
|
||
}
|
||
}
|
||
},
|
||
template: `
|
||
<span class="text-xs font-semibold text-white px-2 py-1 rounded"
|
||
:class="bgClass">
|
||
{{ label }}
|
||
</span>
|
||
`
|
||
});
|
||
|
||
|
||
// _ __ __ _____ _____ _____
|
||
// | | / _|/ _| | __ \_ _| __ \
|
||
// ___| |_ __ _| |_| |_ | | | || | | |__) |
|
||
// / __| __/ _` | _| _| | | | || | | _ /
|
||
// \__ \ || (_| | | | | | |__| || |_| | \ \
|
||
// |___/\__\__,_|_| |_| |_____/_____|_| \_\
|
||
//
|
||
//
|
||
|
||
//
|
||
// ONE LINE OF THE STAFF DIR EDITOR listing
|
||
//
|
||
const StaffLine = Vue.component('staff_line', {
|
||
props: [ 's', 'i', 'dup_class', ],
|
||
//data: function() { return { } },
|
||
methods: {
|
||
nope: function() { return 1; },
|
||
odd: function(i) { if (i % 2 ==0) { return "even" } return "odd" },
|
||
bio: function() { return "bio.php?p=" + this.s.id },
|
||
gtitle: function() { if (this.s.gtitle) {return _.findWhere(this.$root.titles_menu, {id:this.s.gtitle}).name}; return "" },
|
||
gdept1: function() { if (this.s.dept1) {return _.findWhere(this.$root.depts_menu, {id:this.s.dept1}).name}; return "" },
|
||
gdept2: function() { if (this.s.dept2) {return _.findWhere(this.$root.depts_menu, {id:this.s.dept2}).name}; return "-" },
|
||
grole: function() { if (this.s.role) {return _.findWhere(this.$root.roles_menu, {id:this.s.role}).descr}; return "" },
|
||
swapedit: function() { this.$emit('swapout', this.s.id) }
|
||
},
|
||
template: `<div>
|
||
<div :class="odd(i) + ' pure-g'">
|
||
<div class="pure-u-1-4"><pre>
|
||
status: {{ s.status }}
|
||
permissions: {{ grole() }}
|
||
pers id: {{ s.id }}
|
||
ext id: {{ s.ext_id }}
|
||
bio page: {{ s.web_on }}
|
||
Photo - use: {{s.use_dir_photo}} release: {{s.general_photo_release}}
|
||
path: {{s.dir_photo_path}}
|
||
# Sections: {{s.num_taught}}
|
||
{{ s.sections }} </pre>
|
||
</div>
|
||
<div class="pure-u-1-4"><pre>
|
||
staff: {{ s.staff_type }}
|
||
conf_id: {{ s.conf_id }}
|
||
G00{{s.conf_goo}}
|
||
espanol: {{s.espanol}}
|
||
</pre>
|
||
</div>
|
||
<div class="pure-u-1-4"><pre>
|
||
{{s.first_name}} {{s.last_name}}
|
||
{{gtitle()}}
|
||
{{gdept1()}}
|
||
{{gdept2()}}
|
||
(old dept: {{s.department}} ) </pre>
|
||
</div>
|
||
<div class="pure-u-1-4"><pre>
|
||
email: {{s.email}}
|
||
room: {{s.room}}
|
||
phone: {{s.phone_number}}
|
||
Zoom: {{s.zoom}}
|
||
Preferred contact: {{s.preferred_contact}}
|
||
</pre><div class="xxpure-u-1-24 clicky" v-on:click="swapedit"><span class="pure-button button-inlist">edit</span></div>
|
||
</div>
|
||
</div>
|
||
</div>`
|
||
});
|
||
|
||
|
||
|
||
//
|
||
//
|
||
// STAFF DIR LISTING
|
||
//
|
||
// ONE LINE - BUT EDITING!
|
||
//
|
||
const StaffLineEdit = Vue.component('staff_line_edit', {
|
||
props: [ 's', 'i' ],
|
||
//data: function() { return { } },
|
||
methods: {
|
||
nope: function() { return 1; },
|
||
odd: function(i) { if (i % 2 ==0) { return "even" } return "odd" },
|
||
bio: function() { return "bio.php?p=" + this.s.id },
|
||
done: function() { this.$emit('done_edit') },
|
||
gtitle: function() { if (this.s.gtitle) {return _.findWhere(this.$root.titles_menu, {id:this.s.gtitle}).name}; return "" },
|
||
gdept1: function() { if (this.s.dept1) {return _.findWhere(this.$root.depts_menu, {id:this.s.dept1}).name}; return "" },
|
||
gdept2: function() { if (this.s.dept2) {return _.findWhere(this.$root.depts_menu, {id:this.s.dept2}).name}; return "-" },
|
||
grole: function() { if (this.s.role) {return _.findWhere(this.$root.roles_menu, {id:this.s.role}).descr}; return "" },
|
||
}, //v-lazy-container="{ selector: 'img' }"
|
||
template: `<form class="pure-form">
|
||
<div :class="odd(i) + ' list-editor pure-g'">
|
||
<div class="pure-u-1-4">
|
||
<checkbox table="personnel" qid="status" question="Published" :answer="s.status" :targetid="s.id"></checkbox>
|
||
permissions: <selectmenu table="personnel_ext" qid="role" :answer="s.role" menu="roles_menu" :targetid="s.ext_id" labelfield="descr"></selectmenu><br />
|
||
pers id: {{ s.id }}<br />
|
||
ext id: {{ s.ext_id }}<br />
|
||
<checkbox table="personnel" qid="web_on" question="Bio Page On" :answer="s.web_on" :targetid="s.id"></checkbox>
|
||
<checkbox table="personnel_ext" qid="use_dir_photo" question="Use Photo" :answer="s.use_dir_photo" :targetid="s.ext_id"></checkbox>
|
||
<checkbox table="personnel_ext" qid="general_photo_release" question="Release Photo" :answer="s.general_photo_release" :targetid="s.ext_id"></checkbox>
|
||
Dir photo <ifield myclass="double" table="personnel_ext" qid="dir_photo_path" :answer="s.dir_photo_path" :targetid="s.ext_id" placeholder="Dir Photo Path"></ifield><br />
|
||
# Sections: {{s.num_taught}}<br />
|
||
{{ s.sections }}
|
||
</div>
|
||
<div class="pure-u-1-4">
|
||
Staff Type <ifield myclass="double" table="personnel" qid="staff_type" :answer="s.staff_type" :targetid="s.id" placeholder="Staff Type"></ifield><br />
|
||
conf_id: {{ s.conf_id }}<br />
|
||
<!-- GOO <ifield myclass="double" table="conf_users" qid="goo" :answer="s.conf_goo" :targetid="s.conf_id" placeholder="GOO"></ifield><br />-->
|
||
GOO {{ s.conf_goo }} <br />
|
||
<checkbox table="personnel_ext" qid="espanol" question="Speak Spanish" :answer="s.espanol" :targetid="s.ext_id"></checkbox>
|
||
</div>
|
||
<div class="pure-u-1-4">
|
||
<ifield myclass="double" table="personnel" qid="first_name" :answer="s.first_name" :targetid="s.id" placeholder="First Name"></ifield><br />
|
||
<ifield myclass="double" table="personnel" qid="last_name" :answer="s.last_name" :targetid="s.id" placeholder="Last Name"></ifield><br />
|
||
<selectmenu table="personnel_ext" qid="gtitle" :answer="s.gtitle" menu="titles_menu" :targetid="s.ext_id" labelfield="name"></selectmenu><br />
|
||
<selectmenu table="personnel_ext" qid="dept1" :answer="s.dept1" menu="depts_menu" :targetid="s.ext_id" labelfield="name"></selectmenu> <br />
|
||
<selectmenu table="personnel_ext" qid="dept2" :answer="s.dept2" menu="depts_menu" :targetid="s.ext_id" labelfield="name"></selectmenu><br />
|
||
(old dept: {{s.department}} )
|
||
</div>
|
||
<div class="pure-u-1-4">
|
||
<ifield table="personnel" qid="email" :answer="s.email" :targetid="s.id" placeholder="Email"></ifield><br />
|
||
<ifield table="personnel" qid="room" :answer="s.room" :targetid="s.id" placeholder="Room"></ifield><br />
|
||
<ifield table="personnel" qid="phone_number" :answer="s.phone_number" :targetid="s.id" placeholder="Phone Number"></ifield><br />
|
||
<ifield table="personnel_ext" qid="zoom" :answer="s.zoom" :targetid="s.ext_id" placeholder="Zoom Room"></ifield><br />
|
||
<ifield table="personnel_ext" qid="preferred_contact" :answer="s.preferred_contact" :targetid="s.ext_id" placeholder="Preferred contact"></ifield>
|
||
<div class="xxpure-u-1-24 clicky" v-on:click="done"><span class="pure-button button-inlist-action">done</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</form>
|
||
`
|
||
});
|
||
|
||
|
||
|
||
|
||
|
||
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // //
|
||
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // //
|
||
//
|
||
// STAFF DIR LISTING MAIN CONTAINER
|
||
//
|
||
const DirList = Vue.component('dirlist', {
|
||
data: function () {
|
||
return { "personnel":[], sortby:'last_name', search:'', reversed: false, id_list:[], id_dups:[],
|
||
components: {n:StaffLine, e: StaffLineEdit }, editing: -1, } },
|
||
mounted: function() {
|
||
var self = this;
|
||
this.$root.fetch_menus();
|
||
|
||
fetch('dir_api.php?a=list/staffsemester', { method: 'GET' }).then(function (response) {
|
||
if (response.ok) {
|
||
response.json().then( function(r2) {
|
||
self.personnel = r2;
|
||
_.each( self.personnel, function(x) {
|
||
if (x.sections==null) { x.num_taught=0 }
|
||
if (x.dir_photo_path==null) { x.dir_photo_path='images_sm/nobody.jpg' }
|
||
if (x.use_dir_photo == "0") { x.use_dir_photo = false } else { x.use_dir_photo = true }
|
||
if (x.espanol == "0" || !x.espanol) { x.espanol = false } else { x.espanol = true }
|
||
if (x.general_photo_release == "0") { x.general_photo_release = false
|
||
} else { x.general_photo_release = true }
|
||
if (self.id_list.includes(x.id)) { self.id_dups.push(x.id) }
|
||
else { self.id_list.push(x.id) }
|
||
x.searchable = ''
|
||
if (x.first_name) { x.searchable += ' ' + x.first_name.toLowerCase() }
|
||
if (x.last_name) { x.searchable += ' ' + x.last_name.toLowerCase() }
|
||
if (x.dept1name) { x.searchable += ' ' + x.dept1name.toLowerCase() }
|
||
if (x.titlename) { x.searchable += ' ' + x.titlename.toLowerCase() }
|
||
if (x.status == "1" || x.status == null) { x.status = "1"
|
||
} else { x.status = false; x.searchable += ' inactive' }
|
||
} ) } ) } else { return Promise.reject(response) }
|
||
}).then(function (data) { }).catch(function (err) { console.warn('Something went wrong.', err); });
|
||
},
|
||
methods: {
|
||
setsort: function(ss) {
|
||
if (this.sortby == ss) { this.reversed = ! this.reversed }
|
||
else {
|
||
this.reversed = false
|
||
this.sortby = ss
|
||
}
|
||
},
|
||
swapme: function(x) {
|
||
this.editing = x
|
||
},
|
||
done_edit: function(id) {
|
||
this.editing = -1
|
||
},
|
||
am_editing: function(id) {
|
||
if (id == this.editing) { return StaffLineEdit }
|
||
return StaffLine
|
||
},
|
||
is_dup_id_class: function(id) { return this.id_dups.includes(id) ? " dup_line" : "" },
|
||
},
|
||
computed: {
|
||
filtered: function() {
|
||
var ff = this.personnel
|
||
var self = this
|
||
if (this.search) {
|
||
var ss = self.search.toLowerCase()
|
||
ff = ff.filter(function(x) { return x.searchable.includes(ss) }) }
|
||
|
||
ff = _.sortBy(ff, function(x) {
|
||
if (x[self.sortby]) {
|
||
var s = x[self.sortby];
|
||
return s.trim().toLowerCase() }
|
||
return 'zzzzzzzzzz' })
|
||
if (this.reversed) {
|
||
ff.reverse()
|
||
}
|
||
return ff
|
||
}
|
||
},
|
||
watch: {
|
||
},
|
||
|
||
template: `<div class="">
|
||
<div class="pure-g pure-form">
|
||
<div class="pure-u-1-24"></div>
|
||
<div class="pure-u-3-4"><b>Filter: </b><input type="text" v-model="search" name="dirfilter" class="double" /></div>
|
||
</div>
|
||
<br />
|
||
<div class="pure-g pure-form">
|
||
<div class="pure-u-1-24"> </div>
|
||
</div>
|
||
<div class="pure-g pure-form">
|
||
<div v-on:click="setsort('num_taught')" class="pure-u-1-24 clicky"><b>C</b></div>
|
||
<div class="pure-u-1-4 clicky">
|
||
<b v-on:click="setsort('last_name')">Name</b><br />
|
||
<b v-on:click="setsort('gtitle')">Title</b>
|
||
</div>
|
||
<div class="pure-u-1-6 clicky">
|
||
<b v-on:click="setsort('department')">Dept</b><br />
|
||
<b v-on:click="setsort('dept1')">Dept1</b>
|
||
</div>
|
||
<div v-on:click="setsort('email')" class="pure-u-1-6 clicky"><b>Email</b></div>
|
||
<div class="pure-u-1-6"><b>Phone</b></div>
|
||
<div v-on:click="setsort('room')" class="pure-u-1-6 clicky"><b>Room</b></div>
|
||
</div>
|
||
<!-- <staff_line_edit :s="this.$root.user" :i="0" :key="'staff_000'"></staff_line_edit> -->
|
||
<component :is="am_editing(p.id)" v-on:swapout="swapme" v-on:done_edit="done_edit" v-for="p,i in filtered" :s="p" :i="i" :dup_class="is_dup_id_class(p.id)" :key="'staff_'+p.id + '_' + i"></component>
|
||
</div>` })
|
||
|
||
|
||
|
||
// https://www.daterangepicker.com/
|
||
// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/datetime-local
|
||
|
||
|
||
|
||
|
||
|
||
// __ _ _ _ _ _ _
|
||
// / _| | | | (_) (_) | (_)
|
||
// | |_| | _____ __ __ _ ___| |_ ___ ___| |_ _ ___ ___
|
||
// | _| |/ _ \ \/ / / _` |/ __| __| \ \ / / | __| |/ _ \/ __|
|
||
// | | | | __/> < | (_| | (__| |_| |\ V /| | |_| | __/\__ \
|
||
// |_| |_|\___/_/\_\ \__,_|\___|\__|_| \_/ |_|\__|_|\___||___/
|
||
//
|
||
//
|
||
|
||
|
||
|
||
|
||
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // //
|
||
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // //
|
||
//
|
||
// EDIT / CREATE activity or event
|
||
//
|
||
const ActivityEditor = Vue.component('activityedit', {
|
||
props: [ 'which', ],
|
||
data: function () {
|
||
return { my_activity:0, creating:0,
|
||
everyname:[], everyone:[], hosts_by_sesid:{}, this_hosts:[], host_search:[], host_search_str:'',
|
||
activities:[], this_activity:{}, editing: -1, active:-1, } },
|
||
mounted: function() {
|
||
this.fetch_mypeople()
|
||
this.$root.fetch_menus()
|
||
if (this.which==0) {
|
||
this.creating = 1
|
||
this.$root.creating = 1
|
||
this.this_activity = {"title":"","desc":"","length":"1","starttime":"",
|
||
"track":"","location":"","gets_survey":"1","category":"1",
|
||
"parent":"","recording":"","instructions":"","image_url":"",
|
||
"is_flex_approved":"1","typeId":"101"}
|
||
} else { this.my_activity = this.which
|
||
this.fetch_myevents() } },
|
||
methods: {
|
||
set_id: function(new_id) { this.this_activity.id = new_id; this.creating=0; this.$root.creating=0 },
|
||
month_year: function(d) { var b = this.$root.$dj(d).format('MMM D YYYY'); return b },
|
||
setsort: function(ss) {
|
||
if (this.sortby == ss) { this.reversed = ! this.reversed }
|
||
else { this.reversed = false; this.sortby = ss } },
|
||
swapme: function(x) { this.editing = x },
|
||
done_edit: function(id) { this.editing = -1 },
|
||
am_editing: function(id) { return 0 },
|
||
remove: function(hostid) {
|
||
var self = this
|
||
basic_get('dir_api.php?a=remove/host/' + this.my_activity + '/' + hostid,
|
||
function(r2) {
|
||
self.this_hosts = _.reject(self.this_hosts, function(x) { return x.hostid == hostid} )
|
||
alert_message('Saved') } )
|
||
},
|
||
add: function(hostid) {
|
||
var self = this
|
||
basic_get('dir_api.php?a=add/host/' + this.my_activity + '/' + hostid,
|
||
function(r2) {
|
||
self.this_hosts.push( _.findWhere(self.everyone, {id:hostid} ) )
|
||
alert_message('Saved') } )
|
||
},
|
||
hostlookup: function() {
|
||
var self = this
|
||
if (this.host_search_str=='') { this.host_search=[] }
|
||
else { this.host_search_str = this.host_search_str.toLowerCase()
|
||
this.host_search = _.first(_.filter(self.everyone, function(x) { return x.name.toLowerCase().search( self.host_search_str) != -1 }),7) } },
|
||
save_new_event: function() {
|
||
this.$root.events.trigger('create_new_session',this.this_activity)
|
||
},
|
||
fetch_mypeople: function() {
|
||
var self = this;
|
||
basic_get('dir_api.php?a=get/names',
|
||
function(r2) {
|
||
self.everyone = r2.users
|
||
_.each( self.everyone, function(x) {
|
||
x.hostid = x.hostid } )
|
||
self.everyname = _.pluck(r2.users,'name') } ) },
|
||
fetch_myevents: function() {
|
||
var self = this;
|
||
basic_get('dir_api.php?a=get/sessions',
|
||
function(r2) {
|
||
self.activities = _.indexBy(r2,function(x) { return x.id } ); self.$forceUpdate()
|
||
self.active += 1;
|
||
_.each( self.activities, function(x) {
|
||
x.searchable = x.title.toLowerCase() + ' ' + x.desc.toLowerCase() } )
|
||
self.this_activity = self.activities[ self.my_activity ]
|
||
self.this_activity.starttime = self.this_activity.starttime.replace(' ','T')} )
|
||
basic_get('dir_api.php?a=get/hosts',
|
||
function(r2) {
|
||
var filtered = r2.filter(x => x.hostid != null)
|
||
self.hosts_by_sesid = _.groupBy(filtered,function(x) { return x.id } )
|
||
self.this_hosts = self.hosts_by_sesid[ self.my_activity ]
|
||
} )
|
||
},
|
||
},
|
||
template: `<div class="">
|
||
<!--<div class="pure-g pure-form pure-form-aligned">
|
||
<div class="pure-u-1-24"></div>
|
||
<div class="pure-u-23-24">
|
||
<div class="pure-control-group">
|
||
<label></label>
|
||
<a class="button-inlist" :href="'?w='+(this.my_activity-1)">Prev</a>
|
||
|
||
<a class="button-inlist" :href="'?w='+(this.my_activity+1)">Next</a>
|
||
</div>
|
||
</div>
|
||
</div>-->
|
||
<div class="pure-g pure-form pure-form-aligned">
|
||
<div class="pure-u-1-24"></div>
|
||
<div class="pure-u-23-24">
|
||
<dtpicker table="conf_sessions" qid="starttime" :answer="this_activity.starttime"
|
||
:targetid="this_activity.id" question="Starts at"></dtpicker>
|
||
<field myclass="double" table="conf_sessions" qid="title" :answer="this_activity.title"
|
||
:targetid="this_activity.id" question="Title" placeholder="Title"></field>
|
||
<htfield_fa table="conf_sessions" qid="desc" question="Description" myclass="pell"
|
||
:answer="this_activity.desc" :targetid="this_activity.id"></htfield_fa>
|
||
<field myclass="double" table="conf_sessions" qid="location" :answer="this_activity.location"
|
||
:targetid="this_activity.id" question="Location / Zoom" placeholder="Location"></field>
|
||
<field myclass="double" table="conf_sessions" qid="location_irl" :answer="this_activity.location_irl"
|
||
:targetid="this_activity.id" question="Location / In Person" placeholder="Location"></field>
|
||
<selectmenu_fa table="conf_sessions"
|
||
qid="mode" :answer="this_activity.mode" menu="modes_menu"
|
||
:targetid="this_activity.id" question="What mode?" labelfield="string"></selectmenu_fa>
|
||
<field myclass="double" table="conf_sessions" qid="length" :answer="this_activity.length"
|
||
:targetid="this_activity.id" question="Length (in hours or minutes)" placeholder="1"></field>
|
||
<selectmenu_fa table="conf_sessions" qid="type" :answer="this_activity.type" menu="sessiontypes_menu"
|
||
:targetid="this_activity.id" question="Type" labelfield="type"></selectmenu_fa>
|
||
<selectmenu_fa v-if="this_activity.type=='101'" table="conf_sessions"
|
||
qid="parent" :answer="this_activity.parent" menu="parents_menu"
|
||
:targetid="this_activity.id" question="What flex day?" labelfield="title"></selectmenu_fa>
|
||
<field myclass="double" table="conf_sessions" qid="recording" :answer="this_activity.recording"
|
||
:targetid="this_activity.id" question="Recording Link" placeholder=""></field>
|
||
<br />
|
||
|
||
|
||
<!-- Existing Hosts List -->
|
||
<div v-if="!creating" class="mb-4">
|
||
<label class="block text-sm font-medium text-gray-700 mb-1">Hosts</label>
|
||
<div class="border rounded-md p-3 bg-gray-50">
|
||
<i v-if="this_hosts.length==0">type below to add a host</i>
|
||
<div v-for="h in this_hosts" class="flex items-center justify-between text-sm mb-1">
|
||
<span>{{ h.name }}</span>
|
||
<button
|
||
type="button"
|
||
@click="remove(h.hostid)"
|
||
class="text-red-500 hover:text-red-700 font-semibold"
|
||
>
|
||
x
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Add Host Section -->
|
||
<div v-if="!creating" class="mb-4">
|
||
<label class="block text-sm font-medium text-gray-700 mb-1">Add a host</label>
|
||
<input
|
||
type="text"
|
||
id="addhost"
|
||
name="addhost"
|
||
v-model="host_search_str"
|
||
@keyup="hostlookup"
|
||
autocomplete="off"
|
||
class="w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring focus:ring-blue-200 focus:ring-opacity-50 p-2 text-sm mb-2"
|
||
/>
|
||
<div class="border rounded-md p-3 bg-gray-50">
|
||
<div v-for="ho in host_search" class="flex items-center justify-between text-sm mb-1">
|
||
<span
|
||
@click="add(ho.id)"
|
||
class="clickme">
|
||
{{ ho.name }}</span>
|
||
<button
|
||
type="button"
|
||
@click="add(ho.id)"
|
||
class="text-blue-500 hover:text-blue-700 font-semibold"
|
||
>
|
||
+
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
</div>
|
||
<!-- add: permissions track, x day if pd day
|
||
x add/remove host x New activity general list & signup
|
||
show signups, surveys instructions survey?
|
||
flex approved? image? what other permissions issues? -->
|
||
</div>` })
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // //
|
||
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // //
|
||
//
|
||
// DISPLAY / EDIT activity or event
|
||
//
|
||
const ActivityInlineEditor = Vue.component('activityinlineedit', {
|
||
props: [ 'which', ],
|
||
data: function () {
|
||
return { my_activity:0, creating:0,
|
||
everyname:[], everyone:[], hosts_by_sesid:{}, this_hosts:[], host_search:[], host_search_str:'',
|
||
activities:[], this_activity:{}, editing: 0, active:-1, } },
|
||
mounted: function() {
|
||
this.fetch_mypeople()
|
||
this.$root.fetch_menus()
|
||
if (this.which==0) {
|
||
this.creating = 1
|
||
this.$root.creating = 1
|
||
this.this_activity = {"title":"","desc":"","length":"1","starttime":"",
|
||
"track":"","location":"","gets_survey":"1","category":"1",
|
||
"parent":"","recording":"","instructions":"","image_url":"",
|
||
"is_flex_approved":"1","typeId":"101"}
|
||
} else { this.my_activity = this.which
|
||
this.fetch_myevents() } },
|
||
methods: {
|
||
set_id: function(new_id) { this.this_activity.id = new_id; this.creating=0; this.$root.creating=0 },
|
||
month_year: function(d) { var b = this.$root.$dj(d).format('MMM D YYYY'); return b },
|
||
setsort: function(ss) {
|
||
if (this.sortby == ss) { this.reversed = ! this.reversed }
|
||
else { this.reversed = false; this.sortby = ss } },
|
||
swapme: function(x) { this.editing = x },
|
||
done_edit: function(id) { this.editing = -1 },
|
||
am_editing: function(id) { return 0 },
|
||
remove: function(hostid) {
|
||
var self = this
|
||
basic_get('dir_api.php?a=remove/host/' + this.my_activity + '/' + hostid,
|
||
function(r2) {
|
||
self.this_hosts = _.reject(self.this_hosts, function(x) { return x.hostid == hostid} )
|
||
alert_message('Saved') } )
|
||
},
|
||
add: function(hostid) {
|
||
var self = this
|
||
basic_get('dir_api.php?a=add/host/' + this.my_activity + '/' + hostid,
|
||
function(r2) {
|
||
self.this_hosts.push( _.findWhere(self.everyone, {id:hostid} ) )
|
||
alert_message('Saved') } )
|
||
},
|
||
hostlookup: function() {
|
||
var self = this
|
||
if (this.host_search_str=='') { this.host_search=[] }
|
||
else { this.host_search_str = this.host_search_str.toLowerCase()
|
||
this.host_search = _.first(_.filter(self.everyone, function(x) { return x.name.toLowerCase().search( self.host_search_str) != -1 }),7) } },
|
||
save_new_event: function() {
|
||
this.$root.events.trigger('create_new_session',this.this_activity)
|
||
},
|
||
fetch_mypeople: function() {
|
||
var self = this;
|
||
basic_get('dir_api.php?a=get/names',
|
||
function(r2) {
|
||
self.everyone = r2.users
|
||
_.each( self.everyone, function(x) {
|
||
x.hostid = x.id } )
|
||
self.everyname = _.pluck(r2.users,'name') } ) },
|
||
fetch_myevents: function() {
|
||
var self = this;
|
||
basic_get('dir_api.php?a=get/sessions',
|
||
function(r2) {
|
||
self.activities = _.indexBy(r2,function(x) { return x.id } ); self.$forceUpdate()
|
||
self.active += 1;
|
||
_.each( self.activities, function(x) {
|
||
x.searchable = x.title + ' ' + x.desc
|
||
x.searchable = x.searchable.toLowerCase()
|
||
} )
|
||
self.this_activity = self.activities[ self.my_activity ]
|
||
self.this_activity.starttime = self.this_activity.starttime.replace(' ','T')} )
|
||
basic_get('dir_api.php?a=get/hosts',
|
||
function(r2) {
|
||
self.hosts_by_sesid = _.groupBy(r2,function(x) { return x.id } )
|
||
var unfiltered = self.hosts_by_sesid[ self.my_activity ]
|
||
self.this_hosts = unfiltered.filter(x => x.hostid != null)
|
||
} )
|
||
},
|
||
},
|
||
template: `<div class="">
|
||
<div v-if="editing" class="bg-white rounded-lg shadow p-4 mb-6">
|
||
<!-- Top action bar -->
|
||
<div class="flex justify-end mb-4">
|
||
<button
|
||
@click.prevent="editing = 0"
|
||
class="text-sm text-blue-600 hover:underline font-medium"
|
||
>
|
||
Done
|
||
</button>
|
||
</div>
|
||
|
||
<!-- Form fields -->
|
||
<div class="space-y-4">
|
||
<field
|
||
myclass="double"
|
||
table="conf_sessions"
|
||
qid="title"
|
||
:answer="this_activity.title"
|
||
:targetid="this_activity.id"
|
||
question="Title"
|
||
placeholder="Title"
|
||
/>
|
||
|
||
<dtpicker
|
||
table="conf_sessions"
|
||
qid="starttime"
|
||
:answer="this_activity.starttime"
|
||
:targetid="this_activity.id"
|
||
question="Starts at"
|
||
/>
|
||
|
||
<field
|
||
myclass="double"
|
||
table="conf_sessions"
|
||
qid="length"
|
||
:answer="this_activity.length"
|
||
:targetid="this_activity.id"
|
||
question="Length (in hours)"
|
||
placeholder="1"
|
||
/>
|
||
|
||
<selectmenu_fa
|
||
table="conf_sessions"
|
||
qid="mode"
|
||
:answer="this_activity.mode"
|
||
menu="modes_menu"
|
||
:targetid="this_activity.id"
|
||
question="What mode?"
|
||
labelfield="string"
|
||
/>
|
||
|
||
<field
|
||
myclass="double"
|
||
table="conf_sessions"
|
||
qid="location"
|
||
:answer="this_activity.location"
|
||
:targetid="this_activity.id"
|
||
question="Location / Zoom"
|
||
placeholder="Location"
|
||
/>
|
||
|
||
<field
|
||
myclass="double"
|
||
table="conf_sessions"
|
||
qid="location_irl"
|
||
:answer="this_activity.location_irl"
|
||
:targetid="this_activity.id"
|
||
question="Location / In Person"
|
||
placeholder="Location"
|
||
/>
|
||
|
||
<!-- Host List -->
|
||
<div v-if="!creating">
|
||
<label class="block text-sm font-medium text-gray-700 mb-1">Hosts</label>
|
||
<div class="border rounded-md p-3 bg-gray-50 space-y-1">
|
||
<div
|
||
v-for="h in this_hosts"
|
||
:key="h.hostid"
|
||
class="flex items-center justify-between text-sm"
|
||
>
|
||
<span>{{ h.name }}</span>
|
||
<button
|
||
type="button"
|
||
@click="remove(h.hostid)"
|
||
class="text-red-500 hover:text-red-700 font-semibold"
|
||
>
|
||
×
|
||
</button>
|
||
</div>
|
||
<div v-if="this_hosts.length === 0" class="text-sm text-gray-500 italic">
|
||
Add a host by typing below
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Host Add Input + Suggestions -->
|
||
<div v-if="!creating">
|
||
<label class="block text-sm font-medium text-gray-700 mb-1">Add a host</label>
|
||
<input
|
||
type="text"
|
||
id="addhost"
|
||
name="addhost"
|
||
v-model="host_search_str"
|
||
@keyup="hostlookup"
|
||
autocomplete="off"
|
||
class="w-full rounded-md border border-gray-500 bg-white text-gray-900 shadow focus:border-blue-600 focus:ring focus:ring-blue-300 focus:ring-opacity-50 px-4 py-2 text-base mb-2"
|
||
/>
|
||
<div class="border rounded-md p-3 bg-gray-50 space-y-1">
|
||
<div
|
||
v-for="ho in host_search"
|
||
:key="ho.id"
|
||
class="flex items-center justify-between text-sm"
|
||
>
|
||
<span @click="add(ho.id)" class="cursor-pointer hover:underline">
|
||
{{ ho.name }}
|
||
</span>
|
||
<button
|
||
type="button"
|
||
@click="add(ho.id)"
|
||
class="text-blue-500 hover:text-blue-700 font-semibold"
|
||
>
|
||
+
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<htfield_fa
|
||
table="conf_sessions"
|
||
qid="desc"
|
||
question="Description"
|
||
myclass="pell"
|
||
:answer="this_activity.desc"
|
||
:targetid="this_activity.id"
|
||
/>
|
||
|
||
<selectmenu_fa
|
||
table="conf_sessions"
|
||
qid="type"
|
||
:answer="this_activity.type"
|
||
menu="sessiontypes_menu"
|
||
:targetid="this_activity.id"
|
||
question="Type"
|
||
labelfield="type"
|
||
/>
|
||
|
||
<selectmenu_fa
|
||
v-if="this_activity.type === '101'"
|
||
table="conf_sessions"
|
||
qid="parent"
|
||
:answer="this_activity.parent"
|
||
menu="parents_menu"
|
||
:targetid="this_activity.id"
|
||
question="What flex day?"
|
||
labelfield="title"
|
||
/>
|
||
|
||
<field
|
||
myclass="double"
|
||
table="conf_sessions"
|
||
qid="recording"
|
||
:answer="this_activity.recording"
|
||
:targetid="this_activity.id"
|
||
question="Recording Link"
|
||
placeholder=""
|
||
/>
|
||
</div>
|
||
</div>
|
||
<div v-else class="flex flex-col md:flex-row gap-4 bg-white rounded-md shadow p-4 mb-4">
|
||
<!-- Left: Edit Button -->
|
||
<div class="md:w-40 shrink-0">
|
||
<a href="#" @click.prevent="editing = 1" class="text-sm text-blue-600 hover:underline font-medium">
|
||
Edit
|
||
</a>
|
||
</div>
|
||
|
||
<!-- Right: Session Info -->
|
||
<div class="flex-grow text-sm text-gray-800">
|
||
<p class="text-base font-semibold text-gray-900 mb-1">{{ this_activity.title }}</p>
|
||
|
||
<p class="text-gray-600 mb-1">
|
||
{{ $root.$dj(this_activity.starttime).format('h:mma') }} /
|
||
<span class="capitalize">{{ this_activity.mode }}</span>
|
||
</p>
|
||
|
||
<p class="text-gray-600 mb-1">
|
||
Presented by:
|
||
<span v-for="(h, i) in this_hosts" :key="h.hostid">
|
||
{{ h.name }}<span v-if="i < this_hosts.length - 1">, </span>
|
||
</span>
|
||
</p>
|
||
|
||
<div class="mt-2 text-gray-700" v-html="this_activity.desc"></div>
|
||
</div>
|
||
</div>
|
||
|
||
</div>` })
|
||
|
||
|
||
|
||
|
||
|
||
//
|
||
//
|
||
//
|
||
//
|
||
//
|
||
//
|
||
// ACTIVITIES LIST MAIN CONTAINER
|
||
// ------------------------------
|
||
//
|
||
//
|
||
//
|
||
const ActivityList = Vue.component('activitylist', {
|
||
props: [ 'itineraryview','static' ],
|
||
data: function () {
|
||
return { activities:[], mysessions:[], search:'', sortby:'starttime', reversed:false, my_ses_ids:[], my_host_ids:[],
|
||
show_filters: 'all', expanded: 1, editing: -1, active:-1, hosts:{},
|
||
hosts_by_sesid: {}, options:{}, conference:{}, ay:{}, conf:-1, survey_on:0, zoom_on:1, } },
|
||
mounted: function() {
|
||
this.fetch_myevents()
|
||
},
|
||
methods: {
|
||
get_day_index: function(dateStr) {
|
||
const date = new Date(dateStr);
|
||
const yyyy = date.getFullYear();
|
||
const mm = String(date.getMonth() + 1).padStart(2, '0');
|
||
const dd = String(date.getDate()).padStart(2, '0');
|
||
return `${yyyy}${mm}${dd}`;
|
||
},
|
||
toggleDay: function(id) {
|
||
const group = document.getElementById(id);
|
||
const btn = document.getElementById(id + '-toggle');
|
||
group.classList.toggle('hidden');
|
||
btn.textContent = group.classList.contains('hidden') ? 'Expand Day' : 'Collapse Day';
|
||
},
|
||
toggleDescription: function(id) {
|
||
const para = document.getElementById(id);
|
||
const btn = document.getElementById(id + '-btn');
|
||
para.classList.toggle('line-clamp-2');
|
||
btn.textContent = para.classList.contains('line-clamp-2') ? 'Show More' : 'Show Less';
|
||
},
|
||
addTime: function(time, x) {
|
||
x = parseInt(x)
|
||
let [y, m, d, h, i, s] = time.split(/[- :]/); // split time into parts
|
||
let dt = new Date(y, m-1, d, h, i, s); // create Date object
|
||
x > 8 ? dt.setMinutes(dt.getMinutes() + x) : dt.setHours(dt.getHours() + x); // add minutes or hours
|
||
var rd = dayjs(dt);
|
||
return rd.format('h:mma');
|
||
//return dt.toISOString().slice(0, 19).replace('T', ' '); // format output
|
||
},
|
||
hoststr: function(id) { var self = this
|
||
return _.reduce( self.hosts_by_sesid[id], function(mem,val) { if (val.name) { return mem + val.name + ", " } return mem }, '') },
|
||
mode_string: function(a) { if (this.$root.active) { return _.findWhere(this.$root.modes_menu, { 'id': a.mode })['string'] } return a.mode },
|
||
get_day_title: function(day) {
|
||
var d = dayjs(day, 'MMM DD YYYY')
|
||
convertedDateString = d.format('YYYY-MM-DD')
|
||
return _.findWhere( this.conference, {date1:convertedDateString} ).title
|
||
},
|
||
month_year: function(d) { var b = this.$root.$dj(d).format('MMM D YYYY'); return b },
|
||
setsort: function(ss) {
|
||
if (this.sortby == ss) { this.reversed = ! this.reversed }
|
||
else { this.reversed = false; this.sortby = ss } },
|
||
swapme: function(x) { this.editing = x },
|
||
done_edit: function(id) { this.editing = -1 },
|
||
am_editing: function(id) { return 0 },
|
||
fetch_myevents: function() {
|
||
var self = this;
|
||
basic_get('dir_api.php?a=get/hosts', function(r2) {
|
||
self.hosts_by_sesid = _.groupBy(r2,function(x) { return x.id } )
|
||
} )
|
||
|
||
basic_get('api2.php?query=app',
|
||
function(r2) {
|
||
self.mysessions = r2.mysessions
|
||
self.my_ses_ids = _.pluck(r2.mysessions, 'id')
|
||
self.activities = r2.sessions
|
||
if (r2.host != null) { self.my_host_ids = r2.host }
|
||
else { self.my_host_ids = [] }
|
||
self.options = r2.options
|
||
self.conference = r2.conference
|
||
self.ay = r2.ay
|
||
self.hosts_by_sesid = _.groupBy(r2.hostbysession,function(x) { return x.id } )
|
||
|
||
self.survey_on = parseInt( _.findWhere(self.options, { label:'survey_on' }).value )
|
||
self.zoom_on = parseInt( _.findWhere(self.options, { label:'zoom_on' }).value )
|
||
self.active = 1
|
||
self.$forceUpdate();
|
||
|
||
} )
|
||
},
|
||
joinme: function(id) {
|
||
var self = this
|
||
basic_get('dir_api.php?a=signup/' + id,
|
||
function(r2) {
|
||
self.mysessions.push(_.findWhere(self.activities, {'id':id}))
|
||
self.my_ses_ids.push(id)
|
||
alert_message("Added activity") })
|
||
},
|
||
dumpme: function(id) {
|
||
var self = this
|
||
basic_get('dir_api.php?a=signdown/' + id,
|
||
function(r2) {
|
||
self.mysessions = _.without( self.mysessions, _.findWhere(self.activities, {'id':id}))
|
||
self.my_ses_ids = _.without( self.my_ses_ids, id)
|
||
self.$forceUpdate()
|
||
alert_message("Removed activity") })
|
||
},
|
||
filtered: function(ff) {
|
||
var self = this
|
||
if (this.search) {
|
||
var ss = self.search.toLowerCase()
|
||
ff = ff.filter(function(x) { return ('searchable' in x ? x.searchable.includes(ss) : 0) })
|
||
}
|
||
|
||
if (this.active>0) {
|
||
var default_conf_id = _.findWhere(self.options, {label:'default_conference'}).value
|
||
self.conf = _.findWhere(self.conference, {id:default_conf_id})
|
||
var start = dayjs( self.conf.date1)
|
||
var end = dayjs(self.conf.date2)
|
||
ff = ff.filter( function(item,index) {
|
||
this_time = dayjs(item.starttime)
|
||
return this_time.isBefore(end) && start.isBefore(this_time) } )
|
||
ff = _.sortBy(ff, function(x) {
|
||
if (x[self.sortby]) { var s = x[self.sortby]; return s.trim().toLowerCase() }
|
||
return '' })
|
||
if (this.reversed) { ff.reverse() }
|
||
return ff
|
||
}
|
||
|
||
return []
|
||
}, },
|
||
computed: {
|
||
current_time: function() { return dayjs().format('MMM D, h:mma') },
|
||
activities_filtered: function() { var a = this.filtered(this.activities); return a; },
|
||
mysessions_filtered: function() { return this.filtered(this.mysessions) },
|
||
|
||
activities_g_filtered: function() { if (this.active<1) { return {} }
|
||
var self=this;
|
||
return _.groupBy(self.activities_filtered, function(x) { return self.month_year(x.starttime) } ); },
|
||
mysessions_g_filtered: function() { if (this.active<1) { return {} }
|
||
var self=this; return _.groupBy(self.mysessions_filtered, function(x) { return self.month_year(x.starttime) } ); }, },
|
||
watch: { },
|
||
template: `<div class="activitylist">
|
||
<div>
|
||
<!-- Current time + Zoom info -->
|
||
<div v-if="itineraryview" class="mb-6">
|
||
<p class="text-sm text-gray-500">
|
||
<!--Current time: {{ current_time }}. -->
|
||
<span v-if="!zoom_on">
|
||
Return here on the day of your sessions for Zoom links.
|
||
</span>
|
||
</p>
|
||
</div>
|
||
|
||
<!-- No sessions signed up -->
|
||
<div v-if="itineraryview && mysessions_filtered.length === 0" class="mb-6">
|
||
<p class="font-semibold text-gray-800">It looks like you haven't signed up for any sessions yet!</p>
|
||
<p class="mt-2 text-sm text-blue-600">
|
||
Go to the <a class="underline hover:text-blue-800" href="act.php">Sessions List</a> to sign up.
|
||
</p>
|
||
</div>
|
||
|
||
<!-- Grouped sessions by date -->
|
||
<div v-if="itineraryview && active > 0" v-for="(items, mmyy) in mysessions_g_filtered" :key="mmyy" class="mb-8">
|
||
<h3 class="text-xl font-bold text-gray-800 mb-2">{{ mmyy }} {{ get_day_title(mmyy) }}</h3>
|
||
|
||
<div v-for="a in items" :key="a.id" class="bg-white rounded-lg shadow p-4 mb-6 border-l-4 border-blue-200">
|
||
<div class="flex flex-col md:flex-row md:justify-between md:items-start gap-4">
|
||
|
||
<!-- Left side controls -->
|
||
<div class="flex flex-wrap gap-2 md:flex-col md:min-w-[100px]">
|
||
<a v-if="my_host_ids.includes(a.id)"
|
||
:href="'ed_act.php?w=' + a.id"
|
||
class="text-sm text-blue-600 hover:underline">Edit</a>
|
||
|
||
<a v-if="my_host_ids.includes(a.id)"
|
||
:href="'report.php?s=' + a.id"
|
||
class="text-sm text-blue-600 hover:underline">Info</a>
|
||
</div>
|
||
|
||
<!-- Session info -->
|
||
<div class="flex-grow relative">
|
||
<h2 class="text-base font-semibold text-gray-800">{{ a.title }}</h2>
|
||
<p class="text-sm text-gray-600">
|
||
{{ $root.$dj(a.starttime).format('h:mma') }} - {{ addTime(a.starttime, a.length) }} <!--· {{ mode_string(a) }} -->
|
||
<span v-if="a.mode === 'hybrid'"> · In person at {{ a.location_irl }} or
|
||
<a v-if="zoom_on && a.location" :href="a.location" class="underline text-blue-600">online</a>
|
||
<span v-else>online (zoom link not found)</span>
|
||
</span>
|
||
<span v-if="a.mode === 'inperson'"> · In person at {{ a.location_irl }}</span>
|
||
<span v-if="zoom_on && a.mode === 'online'"> · <a :href="a.location" class="underline text-blue-600">Online</a></span>
|
||
<span v-if="!zoom_on && a.mode === 'online'"> · Online</span>
|
||
</p>
|
||
|
||
<!-- Bottom action buttons -->
|
||
<div class="mt-4 flex gap-3 flex-wrap">
|
||
<a v-if="zoom_on && a.location"
|
||
:href="a.location"
|
||
class="px-3 py-1 text-sm font-medium text-white bg-blue-600 rounded hover:bg-blue-700">
|
||
Join Zoom
|
||
</a>
|
||
|
||
<a v-if="survey_on"
|
||
:href="'survey.php?s=' + a.id"
|
||
class="px-3 py-1 text-sm font-medium text-white bg-purple-600 rounded hover:bg-purple-700">
|
||
Survey
|
||
</a>
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
|
||
|
||
<div v-if="!itineraryview && active > 0" v-for="(items, mmyy) in activities_g_filtered" :key="mmyy" class="mb-6">
|
||
<div
|
||
class="flex justify-between items-baseline text-xl font-semibold text-gray-800 border-b pb-1 mb-2 clickme"
|
||
@click="toggleDay(get_day_index(mmyy))">
|
||
{{ mmyy }} {{ get_day_title(mmyy) }}
|
||
<button
|
||
:id="get_day_index(mmyy) + '-toggle'"
|
||
@click="toggleDay(get_day_index(mmyy))"
|
||
class="text-sm text-blue-600 hover:underline font-normal"
|
||
>
|
||
Collapse Day
|
||
</button>
|
||
</div>
|
||
|
||
<!-- all sessions in a day -->
|
||
<div :id="get_day_index(mmyy)">
|
||
<div v-for="a in items" :key="a.id" class="relative bg-white rounded-lg shadow p-4 mb-4">
|
||
<div class="flex flex-col md:flex-row md:justify-between md:items-start gap-4">
|
||
<!-- Action buttons (left on desktop) -->
|
||
<div v-if="!static" class="flex-shrink-0 flex gap-2">
|
||
<a v-if="my_ses_ids.includes(a.id) && !my_host_ids.includes(a.id)"
|
||
@click.prevent="dumpme(a.id)"
|
||
href="#"
|
||
class="px-3 py-1 text-sm font-medium rounded text-sm text-white bg-red-600 hover:underline">Cancel</a>
|
||
|
||
<a v-if="!my_ses_ids.includes(a.id) && !my_host_ids.includes(a.id)"
|
||
@click.prevent="joinme(a.id)"
|
||
href="#"
|
||
class="px-3 py-1 text-sm font-medium text-white bg-purple-600 rounded hover:bg-purple-700">Sign Up</a>
|
||
|
||
<a v-if="my_host_ids.includes(a.id)"
|
||
:href="'ed_act.php?w=' + a.id"
|
||
class="px-3 py-1 text-sm font-medium text-white bg-purple-600 rounded hover:bg-purple-700">Edit</a>
|
||
<b v-if="my_host_ids.includes(a.id)">You are Host.</b>
|
||
</div>
|
||
|
||
<!-- Main session info -->
|
||
<div class="flex-grow">
|
||
<h2 class="text-lg font-semibold text-gray-900">{{ a.title }}</h2>
|
||
<ModePill :mode="a.mode" class="absolute top-2 right-2" />
|
||
<p class="text-sm text-gray-700">
|
||
{{ $root.$dj(a.starttime).format('h:mma') }} - {{ addTime(a.starttime, a.length) }} ·
|
||
{{ mode_string(a) }}
|
||
<span v-if="a.mode == 'hybrid' || a.mode == 'inperson'"> · {{ a.location_irl }}</span>
|
||
</p>
|
||
|
||
<p v-if="hoststr(a.id)" class="text-sm text-gray-600">Presented by: {{ hoststr(a.id) }}</p>
|
||
<p v-if="static && a.location_irl" class="text-sm text-gray-600">Location: {{ a.location_irl }}</p>
|
||
<p v-if="static && a.location" class="text-sm text-blue-600">
|
||
Zoom Link:
|
||
<a :href="a.location" class="underline hover:text-blue-800">{{ a.location }}</a>
|
||
</p>
|
||
|
||
<div v-if="expanded" class="mt-2 text-sm text-gray-700" v-html="a.desc"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
</div>` })
|
||
|
||
|
||
|
||
|
||
// A CHART LABEL
|
||
//
|
||
|
||
const ChartLabel = Vue.component('chartlabel', {
|
||
props: [ 'title','start','end' ],
|
||
data: function () {
|
||
return { max_tracks: 6 } },
|
||
template: `<div class="chart_timebox" :style="'grid-column: times; grid-row: time-'+start+' / time-'+end">
|
||
<span class='chart_time'>{{title}}</span>
|
||
</div>` })
|
||
|
||
|
||
//
|
||
//
|
||
// A CHART SESSION
|
||
//
|
||
|
||
const ChartSesh = Vue.component('chartsesh', {
|
||
props: [ 'title','desc','track','start','end','start_h','end_h','mode','presenter','loc' ],
|
||
data: function () {
|
||
return { max_tracks: 6 } },
|
||
methods: {
|
||
t_start: function() {
|
||
if (this.track==0 || this.track==123) { return "track-1-start" }
|
||
return "track-" + this.track + "-start"
|
||
},
|
||
t_end: function() {
|
||
if (this.track==0 || this.track==123) { return "track-" + this.max_tracks + "-end" }
|
||
return "track-" + this.track + "-end"
|
||
},
|
||
},
|
||
|
||
template: `<div :class="'session session-1 track-'+track" :style="'grid-column: '+t_start()+' / '+t_end()+'; grid-row: time-'+start+' / time-'+end">
|
||
<h3 class="session-title">{{title}}</h3>
|
||
<span class="session-time">{{start_h}} - {{end_h}}</span>
|
||
<span class="session-desc">{{desc}}</span>
|
||
<span class="session-presenter">{{presenter}}</span>
|
||
<span class="session-mode">{{mode}}</span>
|
||
<span class="session-loc">{{loc}}</span>
|
||
</div>` })
|
||
|
||
|
||
//
|
||
//
|
||
//
|
||
//
|
||
//
|
||
//
|
||
// ACTIVITIES LIST CHART STYLE VIEW
|
||
// --------------------------------
|
||
//
|
||
//
|
||
//
|
||
const ChartView = Vue.component('chartview', {
|
||
props: [ 'day'],
|
||
data: function () {
|
||
return { activities:[], mysessions:[], search:'', sortby:'starttime', reversed:false, my_ses_ids:[], my_host_ids:[],
|
||
show_filters: 'all', expanded: 1, editing: -1, active:-1, hosts:{},
|
||
filters: {'sp23':['2023-01-01','2023-02-02'],'fa22':['2022-08-17','2022-08-20'], 'sp22':['2022-01-26','2022-01-30'], 'all':['2022-01-01','2023-11-30'] },
|
||
//day_titles: {'Aug 18 2022':" - Optional PD Day", 'Aug 19 2022':' - Convocation Day'},
|
||
day_titles: {'Jan 26 2023':" - Optional Day", 'Jan 27 2023':' - Mandatory Day'},
|
||
time_labels: [['0900','0930','9am'],
|
||
['0930','1000','9:30am'],
|
||
['1000','1030','10am'],
|
||
['1030','1100','10:30am'],
|
||
['1100','1130','11am'],
|
||
['1130','1200','11:30am'],
|
||
['1200','1230','12pm'],
|
||
['1230','1300','12:30pm'],
|
||
['1300','1330','1pm'],
|
||
['1330','1400','1:30pm'],
|
||
['1400','1430','2pm'],
|
||
['1430','1500','2:30pm'],
|
||
['1500','1530','3pm'],
|
||
['1530','1600','3:30pm'],
|
||
['1600','1630','4pm'],
|
||
['1630','1700','4:30pm'],
|
||
['1700','1730','5pm'],
|
||
['1730','1800','5:30pm'],
|
||
],
|
||
hosts_by_sesid: {}, } },
|
||
mounted: function() {
|
||
this.$root.fetch_menus();
|
||
this.fetch_myevents()
|
||
},
|
||
methods: {
|
||
hoststr: function(id) { var self = this
|
||
return _.reduce( self.hosts_by_sesid[id], function(mem,val) { if (val.name) { return mem + val.name + ", " } return mem }, '') },
|
||
mode_string: function(a) { return _.findWhere(this.$root.modes_menu, { 'id': a.mode })['string'] },
|
||
get_day_title: function(day) { if (day in this.day_titles) { return this.day_titles[day] } return '' },
|
||
month_year: function(d) { var b = this.$root.$dj(d).format('MMM D YYYY'); return b },
|
||
setsort: function(ss) {
|
||
if (this.sortby == ss) { this.reversed = ! this.reversed }
|
||
else { this.reversed = false; this.sortby = ss } },
|
||
swapme: function(x) { this.editing = x },
|
||
done_edit: function(id) { this.editing = -1 },
|
||
am_editing: function(id) { return 0 },
|
||
fetch_myevents: function() {
|
||
var self = this;
|
||
basic_get('api2.php?query=ses/'+self.day,
|
||
function(r2) {
|
||
r2 = r2.data
|
||
self.activities = _.sortBy(r2,function(x) { return x.starttime } ); self.$forceUpdate()
|
||
self.active += 1;
|
||
_.each( self.activities, function(x) {
|
||
var field = x.starttime.match(/^(\d\d\d\d)\-(\d+)\-(\d+)\s(\d+)\:(\d+)\:(\d+)$/)
|
||
var mydate = new Date(field[1], field[2] - 1 , field[3], field[4], field[5], field[6])
|
||
x.dj = dayjs(mydate)
|
||
x.searchable = x.title.toLowerCase() + ' ' + x.desc.toLowerCase() } )
|
||
self.$forceUpdate();
|
||
self.active += 1; } )
|
||
basic_get('dir_api.php?a=get/hosts', function(r2) {
|
||
self.hosts_by_sesid = _.groupBy(r2,function(x) { return x.id } )
|
||
} )
|
||
|
||
},
|
||
joinme: function(id) {
|
||
var self = this
|
||
basic_get('dir_api.php?a=signup/' + id,
|
||
function(r2) {
|
||
self.mysessions.push(_.findWhere(self.activities, {'id':id}))
|
||
self.my_ses_ids.push(id)
|
||
alert_message("Added activity") })
|
||
},
|
||
dumpme: function(id) {
|
||
var self = this
|
||
basic_get('dir_api.php?a=signdown/' + id,
|
||
function(r2) {
|
||
self.mysessions = _.without( self.mysessions, _.findWhere(self.activities, {'id':id}))
|
||
self.my_ses_ids = _.without( self.my_ses_ids, id)
|
||
self.$forceUpdate()
|
||
alert_message("Removed activity") })
|
||
},
|
||
filtered: function(ff) { if (this.active<1) { return [] }
|
||
var self = this
|
||
if (this.search) {
|
||
var ss = self.search.toLowerCase()
|
||
ff = ff.filter(function(x) { return ('searchable' in x ? x.searchable.includes(ss) : 0) }) }
|
||
if (this.focus && 'options' in this.$root.$data.user ) {
|
||
var start = dayjs(this.$root.$data.user.options.conf.date1)
|
||
var end = dayjs(this.$root.$data.user.options.conf.date2)
|
||
ff = ff.filter( function(item,index) {
|
||
this_time = dayjs(item.starttime)
|
||
return this_time.isBefore(end) && start.isBefore(this_time) } )
|
||
}
|
||
ff = _.sortBy(ff, function(x) {
|
||
if (x[self.sortby]) { var s = x[self.sortby]; return s.trim().toLowerCase() }
|
||
return '' })
|
||
if (this.reversed) { ff.reverse() }
|
||
return ff }, },
|
||
computed: {
|
||
current_time: function() { return dayjs().format('MMM D, h:ma') },
|
||
activities_filtered: function() { var a = this.filtered(this.activities); return a; },
|
||
mysessions_filtered: function() { return this.filtered(this.mysessions) },
|
||
|
||
activities_g_filtered: function() { if (this.active<1) { return {} }
|
||
var self=this;
|
||
return _.groupBy(self.activities_filtered, function(x) { return self.month_year(x.starttime) } ); },
|
||
mysessions_g_filtered: function() { if (this.active<1) { return {} }
|
||
var self=this; return _.groupBy(self.mysessions_filtered, function(x) { return self.month_year(x.starttime) } ); }, },
|
||
watch: { },
|
||
template: `<div class="activitylist schedule">
|
||
<chartsesh v-for="a in activities_filtered" :title="a.title" :start="$root.$dj(a.starttime).format('HHmm')"
|
||
:end="$root.$dj(a.starttime).add(a.length,a.length>8?'minute':'hour').format('HHmm')"
|
||
:start_h="$root.$dj(a.starttime).format('h:mma')"
|
||
:end_h="$root.$dj(a.starttime).add(a.length,a.length>8?'minute':'hour').format('h:mma')"
|
||
:mode="mode_string(a)" :presenter="hoststr(a.id)"
|
||
:track="a.track"
|
||
:loc="a.location_irl">
|
||
</chartsesh>
|
||
<chartlabel v-for="a in time_labels" :start="a[0]" :end="a[1]" :title="a[2]"></chartlabel>
|
||
</div>` })
|
||
|
||
|
||
|
||
|
||
//
|
||
//
|
||
//
|
||
//
|
||
//
|
||
//
|
||
// Activity EDITOR List
|
||
// ------------------------------
|
||
//
|
||
//
|
||
//
|
||
const ActivityEditorList = Vue.component('activityeditorlist', {
|
||
props: [ ],
|
||
data: function () {
|
||
return { activities:[], mysessions:[], search:'', sortby:'starttime', reversed:false, my_ses_ids:[], my_host_ids:[],
|
||
show_filters: 'all', expanded: 1, editing: -1, active:-1, hosts:{},
|
||
filters: {'fa23':['2023-08-21','2023-08-26'], 'sp23':['2023-01-01','2023-02-02'],'fa22':['2022-08-17','2022-08-20'], 'sp22':['2022-01-26','2022-01-30'], 'all':['2022-01-01','2023-11-30'] },
|
||
//day_titles: {'Aug 18 2022':" - Optional PD Day", 'Aug 19 2022':' - Convocation Day'},
|
||
day_titles: {'Jan 26 2023':" - Optional Day", 'Jan 27 2023':' - Mandatory Day',
|
||
'Aug 24 2023':" - Optional Day", 'Aug 25 2023':' - Mandatory Day'},
|
||
hosts_by_sesid: {}, } },
|
||
mounted: function() {
|
||
this.$root.fetch_menus();
|
||
this.fetch_myevents()
|
||
},
|
||
methods: {
|
||
hoststr: function(id) { var self = this
|
||
return _.reduce( self.hosts_by_sesid[id], function(mem,val) { if (val.name) { return mem + val.name + ", " } return mem }, '') },
|
||
mode_string: function(a) { return _.findWhere(this.$root.modes_menu, { 'id': a.mode })['string'] },
|
||
get_day_title: function(day) { if (day in this.day_titles) { return this.day_titles[day] } return '' },
|
||
month_year: function(d) { var b = this.$root.$dj(d).format('MMM D YYYY'); return b },
|
||
setsort: function(ss) {
|
||
if (this.sortby == ss) { this.reversed = ! this.reversed }
|
||
else { this.reversed = false; this.sortby = ss } },
|
||
fetch_myevents: function() {
|
||
var self = this;
|
||
basic_get('dir_api.php?a=get/mysessions',
|
||
function(r2) {
|
||
self.mysessions = _.sortBy(r2,function(x) { return x.starttime || 0} );
|
||
self.my_ses_ids = _.pluck(r2, 'id')
|
||
self.$forceUpdate();
|
||
self.active += 1;
|
||
} )
|
||
basic_get('dir_api.php?a=get/sessions',
|
||
function(r2) {
|
||
self.activities = _.sortBy(r2,function(x) { return x.starttime } ); self.$forceUpdate()
|
||
self.active += 1;
|
||
_.each( self.activities, function(x) {
|
||
var field = x.starttime.match(/^(\d\d\d\d)\-(\d+)\-(\d+)\s(\d+)\:(\d+)\:(\d+)$/)
|
||
var mydate = new Date(field[1], field[2] - 1 , field[3], field[4], field[5], field[6])
|
||
x.dj = dayjs(mydate)
|
||
x.searchable = x.title + ' ' + x.desc
|
||
x.searchable = x.searchable.toLowerCase()
|
||
} )
|
||
self.$forceUpdate();
|
||
self.active += 1; } )
|
||
basic_get('dir_api.php?a=get/hosts', function(r2) {
|
||
self.hosts_by_sesid = _.groupBy(r2,function(x) { return x.id } )
|
||
} )
|
||
basic_get('dir_api.php?a=get/allhosts',
|
||
function(r2) {
|
||
self.hosts = r2
|
||
setTimeout(function () {
|
||
self.my_host_ids = r2[ self.$root.user.conf_id ]
|
||
if (! self.my_host_ids) { self.my_host_ids = [] }
|
||
}, 750);
|
||
self.active += 1;
|
||
} )
|
||
},
|
||
filtered: function(ff) { if (this.active<1) { return [] }
|
||
var self = this
|
||
var ay = this.$root.settings['default_ay']
|
||
if (this.search) {
|
||
var ss = self.search.toLowerCase()
|
||
ff = ff.filter(function(x) { return ('searchable' in x ? x.searchable.includes(ss) : 0) }) }
|
||
if (this.focus) {
|
||
var start = dayjs(this.$root.ay_menu[ay].begin ) /* UPDATE this.filters.sp23[0]*/
|
||
var end = dayjs(this.$root.ay_menu[ay].end)
|
||
ff = ff.filter( function(item,index) {
|
||
this_time = dayjs(item.starttime)
|
||
return this_time.isBefore(end) && start.isBefore(this_time) } )
|
||
}
|
||
ff = _.sortBy(ff, function(x) {
|
||
if (x[self.sortby]) { var s = x[self.sortby]; return s.trim().toLowerCase() }
|
||
return '' })
|
||
if (this.reversed) { ff.reverse() }
|
||
return ff }, },
|
||
computed: {
|
||
current_time: function() { return dayjs().format('MMM D, h:ma') },
|
||
activities_filtered: function() { var a = this.filtered(this.activities); return a; },
|
||
mysessions_filtered: function() { return this.filtered(this.mysessions) },
|
||
|
||
activities_g_filtered: function() { if (this.active<1) { return {} }
|
||
var self=this;
|
||
return _.groupBy(self.activities_filtered, function(x) { return self.month_year(x.starttime) } ); },
|
||
mysessions_g_filtered: function() { if (this.active<1) { return {} }
|
||
var self=this; return _.groupBy(self.mysessions_filtered, function(x) { return self.month_year(x.starttime) } ); }, },
|
||
watch: { },
|
||
template: `<div class="activitylist">
|
||
<div v-for="items,mmyy in activities_g_filtered">
|
||
<div class="pure-g">
|
||
<div class="day_title pure-u-1-1">{{mmyy}} {{get_day_title(mmyy)}}</div>
|
||
</div>
|
||
<div v-for="a in items" class="activitylist">
|
||
<activityinlineedit :which="a.id"></activityinlineedit>
|
||
</div>
|
||
</div>
|
||
</div>` })
|
||
|
||
|
||
|
||
|
||
//
|
||
//
|
||
//
|
||
//
|
||
//
|
||
//
|
||
// Table of all signups and hosts in a conference
|
||
// ------------------------------
|
||
//
|
||
//
|
||
//
|
||
|
||
const Overview = Vue.component('overview', {
|
||
name: 'Overview',
|
||
data() {
|
||
return {
|
||
sessions: [
|
||
// Define your sessions data here
|
||
// Each session should have an id and title property
|
||
],
|
||
users: [
|
||
// Define your users data here
|
||
// Each user should have an id and name property
|
||
],
|
||
signups: [
|
||
// Define your signups data here
|
||
// Each signup should have a userId and sessionId property
|
||
],
|
||
hosts: [
|
||
// Define your hosts data here
|
||
// Each host should have a userId and sessionId property
|
||
],
|
||
fetched:0,
|
||
};
|
||
},
|
||
computed: {
|
||
sortedSessions() {
|
||
// Sort sessions by startdate (modify the property name as per your data)
|
||
return this.sessions.sort((a, b) => a.starttime.localeCompare(b.starttime));
|
||
},
|
||
sortedUsers() {
|
||
// Sort users by name (modify the property name as per your data)
|
||
return this.users.sort((a, b) => a.name.localeCompare(b.name));
|
||
},
|
||
filteredUsers() {
|
||
// Filter users who have signup or host entries
|
||
var sorted = this.users.sort((a, b) => a.name.localeCompare(b.name))
|
||
return sorted.filter((user) =>
|
||
this.signups.some((signup) => signup.user === user.id) ||
|
||
this.hosts.some((host) => host.user === user.id)
|
||
);
|
||
},
|
||
},
|
||
methods: {
|
||
start: function() {
|
||
var self = this
|
||
basic_get('dir_api.php?a=get/sessions',
|
||
function(r2) { self.sessions = r2; self.fetched += 1; })
|
||
basic_get('dir_api.php?a=get/hosttable',
|
||
function(r2) { self.hosts = r2; self.fetched += 1; })
|
||
basic_get('dir_api.php?a=get/signups',
|
||
function(r2) { self.signups = r2; self.fetched += 1; })
|
||
basic_get('dir_api.php?a=get/users',
|
||
function(r2) { self.users = r2; self.fetched += 1; })
|
||
},
|
||
getSignupHostStatus(userId, sessionId) {
|
||
// Check if the user signed up for the session
|
||
// Check if the user hosted the session
|
||
const host = this.hosts.find((host) => host.host === userId && host.session === sessionId);
|
||
|
||
if (host) {
|
||
return 'H'; // User hosted
|
||
}
|
||
|
||
const signup = this.signups.find((signup) => signup.user === userId && signup.session === sessionId);
|
||
|
||
if (signup) {
|
||
return 'S'; // User signed up
|
||
}
|
||
|
||
return ''; // User didn't sign up or host
|
||
}
|
||
},
|
||
mounted: function() { this.start() },
|
||
template: `<div><table v-if="fetched>3" class="overviewtable">
|
||
<thead>
|
||
<tr>
|
||
<th></th> <!-- Empty header for user names column -->
|
||
<!-- Iterate over sessions and display as columns -->
|
||
<th v-for="session in sortedSessions" :key="session.id" class="rotate"><div>{{ session.title }}</div></th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<!-- Iterate over users and display as rows -->
|
||
<tr v-for="user in filteredUsers" :key="user.id">
|
||
<td>{{ user.name }}</td> <!-- User name column -->
|
||
<!-- Iterate over sessions and display signup/host status -->
|
||
<td v-for="session in sortedSessions" :key="session.id">
|
||
{{ getSignupHostStatus(user.id, session.id) }}
|
||
</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
</div>`
|
||
});
|
||
|
||
|
||
|
||
|
||
|
||
/*
|
||
|
||
- show upcoming, past, dropdown for category
|
||
|
||
- show signup status, signup/cancel button
|
||
|
||
- navigation: check permission, show edit / new button
|
||
|
||
- page: create / edit activity.
|
||
|
||
*/
|
||
|
||
|
||
const AskSurvey = Vue.component('asksurvey', {
|
||
name: 'AskSurvey',
|
||
components: { 'essay-question': STQuestion, 'number-question': NQuestioon },
|
||
props: ['id', ],
|
||
data () { return {
|
||
questions: [] } },
|
||
methods: {
|
||
start: function() {
|
||
var self = this
|
||
basic_get('dir_api.php?a=get/questions/'+self.id,
|
||
function(r2) {
|
||
self.questions = r2 })
|
||
},
|
||
},
|
||
mounted: function() { this.start() },
|
||
template: `<div>
|
||
<h3 v-if="questions.length">{{ questions[0].title }}</h3>
|
||
<div class="session-survey" v-for="q in questions">
|
||
<number-question v-if="q['type']=='2'" :qq="q"></number-question>
|
||
<essay-question v-if="q['type']=='1'" :qq="q"></essay-question>
|
||
</div>
|
||
</div>`
|
||
});
|
||
|
||
|
||
|
||
|
||
const ShowSurveys = Vue.component('show-survey', {
|
||
name: 'ShowSurveys',
|
||
//components: { 'essay-question': EssayQuestion, 'number-question': NumberQuestion },
|
||
props: ['answer', ],
|
||
methods: {
|
||
logger: function() { console.log('logger'); console.log(this); console.log( this.answer ); return ''; },
|
||
ses_name: function() {
|
||
if (this.answer) {
|
||
return this.answer[0][0].s_title }
|
||
return '' }
|
||
},
|
||
template: `<div>
|
||
{{ logger() }}
|
||
<div class="session-survey" v-for="q in answer">
|
||
<b>{{ q[0]['question'] }}</b>
|
||
<number-question v-if="q[0]['type']=='2'" :aa="q"></number-question>
|
||
<essay-question v-if="q[0]['type']=='1'" :aa="q"></essay-question>
|
||
</div>
|
||
</div>`
|
||
});
|
||
|
||
|
||
const Survey = Vue.component('surveydisplay', {
|
||
props: [ 'answers' ],
|
||
data () {
|
||
return {
|
||
qa_all: [ ],
|
||
sesh: {},
|
||
questions: [],
|
||
one: {},
|
||
qdata: [],
|
||
answer: ""
|
||
}
|
||
},
|
||
created: function() {
|
||
var self = this
|
||
self.questions = _.where(this.$root.$data.myquestions,
|
||
{'ses_id':self.$route.params.take_ses_id})
|
||
self.$forceUpdate()
|
||
/*this.$axios.get(this.$server + this.$api + '?a=get/questions', {withCredentials: true}).then( function(resp2) {
|
||
self.qdata = resp2.data
|
||
setTimeout(self.continueExecution, 1000) //wait 1 seconds before continuing
|
||
} )*/
|
||
|
||
this.$axios.get(this.$server + this.$api + '?a=get/answers/all', {withCredentials: true}).then( function(resp2) {
|
||
} ) },
|
||
methods: {
|
||
continueExecution: function() {self.questions = _.where( this.qdata, {'ses_id': this.$route.params.take_ses_id } )},
|
||
one_session: function() {
|
||
if (this.$route.params.take_ses_id) {
|
||
var self = this
|
||
var my_id = self.$route.params.take_ses_id
|
||
var my_ses = _.find(this.$root.$data.activities, function(x) { return x.id==my_id } )
|
||
return my_ses }
|
||
return {'title':''}
|
||
},
|
||
answers: function() {
|
||
var a = this.sesh[parseInt( this.$route.params.ses_id)]
|
||
if (a) { return a }
|
||
return 0
|
||
},
|
||
requested_session: function() {
|
||
var self = this
|
||
return _.find(this.$root.$data.activities, function(x) { return x.id == self.$route.params.ses_id } )
|
||
/*
|
||
a = _.find(this.$root.$data.activities, function(x) { return x.id == self.$route.params.ses_id } )
|
||
return a */
|
||
}
|
||
},
|
||
template: `<div class="session-survey" v-for="q in answer">
|
||
<b>{{ q[0]['question'] }}</b>
|
||
<number-question v-if="q[0]['type']=='2'" :aa="q"></number-question>
|
||
<essay-question v-if="q[0]['type']=='1'" :aa="q"></essay-question>
|
||
</div>
|
||
|
||
|
||
<!-- <div>
|
||
<show-survey v-if="answers()" :answer="answers()"></show-survey>
|
||
<span v-else><ul><li>No responses yet</li></ul>
|
||
</div>
|
||
|
||
Show admin all classes -->
|
||
|
||
<br />
|
||
<br />
|
||
<br />
|
||
</div>
|
||
`
|
||
})
|
||
|
||
|
||
|
||
|
||
|
||
// ACTIVITIY REPORT - SINGLE - SIGNUPS & SURVEYS
|
||
// -----------------------------------
|
||
//
|
||
//
|
||
//
|
||
const ActivityInfoReport = Vue.component('activityinforeport', {
|
||
props: [ 'a', 'host','num','user','emails','survey' ],
|
||
methods: {
|
||
mode_string: function(a) { return _.findWhere(this.$root.modes_menu, { 'id': a.mode })['string'] },
|
||
},
|
||
computed: {
|
||
},
|
||
watch: { },
|
||
template: `<div class="report">
|
||
<div class="pure-g pure-form">
|
||
<div class="pure-u-7-24">
|
||
{{ $root.$dj(a.starttime).format('YYYY MMM DD dd h:mma') }} - {{mode_string(a)}}
|
||
</div>
|
||
<div class="pure-u-17-24">
|
||
<b>{{a.title}}</b>
|
||
<span v-if="a.location"><br />{{ a.location }}</span>
|
||
<div class="rhs_grey">{{a.typeStr}}</div>
|
||
</div>
|
||
</div>
|
||
<div class="pure-g"><div class="pure-u-1-1">
|
||
<a :href="'ed_act.php?w='+a.id" class="button-inlist">Edit</a>
|
||
</div></div>
|
||
<expandybox v-if="a.desc" header="Description" :body="a.desc"></expandybox>
|
||
<expandybox v-if="host" header="Hosts" :body="host"></expandybox>
|
||
<expandybox v-if="user" :header="'Attendees (' + num + ')'" :body="user"></expandybox>
|
||
<expandybox v-if="emails" :header="'Emails'" :body="emails"></expandybox>
|
||
<expandybox v-if="survey" header="Surveys" :body="survey"></expandybox>
|
||
</div>
|
||
</div>` })
|
||
|
||
|
||
|
||
// A single page version, suitable for emailing.
|
||
const ActivityInfoReport2 = Vue.component('activityinforeport2', {
|
||
props: [ 'a', 'host','num','user','emails','survey' ],
|
||
methods: {
|
||
mode_string: function(a) { return _.findWhere(this.$root.modes_menu, { 'id': a.mode })['string'] },
|
||
},
|
||
computed: {
|
||
},
|
||
watch: { },
|
||
template: `<div class="report">
|
||
<div class="pure-g pure-form">
|
||
<div class="pure-u-7-24 marginbottom">
|
||
Title:
|
||
</div>
|
||
<div class="pure-u-17-24 marginbottom">
|
||
<b>{{a.title}}</b>
|
||
</div>
|
||
|
||
<div class="pure-u-7-24 marginbottom">
|
||
Date:
|
||
</div>
|
||
<div class="pure-u-17-24 marginbottom">
|
||
{{ $root.$dj(a.starttime).format('YYYY MMM DD dd h:mma') }}
|
||
</div>
|
||
|
||
<div class="pure-u-7-24 marginbottom">
|
||
Mode / Location:
|
||
</div>
|
||
<div class="pure-u-17-24 marginbottom">
|
||
{{mode_string(a)}} <span v-if="a.location"><br />{{ a.location }}</span> <span v-if="a.location_irl"><br />{{ a.location_irl }}</span>
|
||
</div>
|
||
|
||
<div class="pure-u-7-24 marginbottom">
|
||
Description:
|
||
</div>
|
||
<div class="pure-u-17-24 marginbottom" v-html="a.desc">
|
||
</div>
|
||
|
||
<div class="pure-u-7-24 marginbottom">
|
||
Hosts:
|
||
</div>
|
||
<div class="pure-u-17-24 marginbottom">
|
||
{{host}}
|
||
</div>
|
||
|
||
<div class="pure-u-7-24 marginbottom">
|
||
Attendees:
|
||
</div>
|
||
<div class="pure-u-17-24 marginbottom">
|
||
{{user}}
|
||
</div>
|
||
|
||
<div class="pure-u-7-24 marginbottom4">
|
||
Survey Results:
|
||
</div>
|
||
<div class="pure-u-17-24 marginbottom" v-html="survey">
|
||
</div>
|
||
|
||
</div>
|
||
</div>
|
||
</div>` })
|
||
|
||
|
||
|
||
|
||
|
||
//
|
||
//
|
||
//
|
||
//
|
||
//
|
||
//
|
||
// ACTIVITIES LIST - SIGNUPS & SURVEYS
|
||
// -----------------------------------
|
||
//
|
||
//
|
||
//
|
||
const ActivityReport = Vue.component('activityreport', {
|
||
props: [ 'which' ],
|
||
data: function () {
|
||
return { activities:[],hosts:[], hosts_by_sesid:[], everyone:[], questions:[], answers:{}, answers2:{}, rosters:[] } },
|
||
mounted: function() {
|
||
var self = this
|
||
basic_get('dir_api.php?a=get/sessions', function(r2) {
|
||
self.activities = _.sortBy(r2,function(x) { return x.starttime } ); self.$forceUpdate()
|
||
if (self.which=='sp22') {
|
||
var start = dayjs('2022-01-26')
|
||
var end = dayjs('2022-01-29')
|
||
self.activities = self.activities.filter( function(item,index) {
|
||
this_time = dayjs(item.starttime)
|
||
return this_time.isBefore(end) && start.isBefore(this_time) } )
|
||
}
|
||
if (self.which=='fa22') { /* UPDATE */
|
||
var start = dayjs('2022-08-17')
|
||
var end = dayjs('2022-08-20')
|
||
self.activities = self.activities.filter( function(item,index) {
|
||
this_time = dayjs(item.starttime)
|
||
return this_time.isBefore(end) && start.isBefore(this_time) } )
|
||
}
|
||
|
||
if (self.which.match( /^\d+$/ )) { self.activities = self.activities.filter( function(item,index) {
|
||
return item.id == self.which } )
|
||
}
|
||
|
||
self.active += 1;
|
||
_.each( self.activities, function(x) {
|
||
var field = x.starttime.match(/^(\d\d\d\d)\-(\d+)\-(\d+)\s(\d+)\:(\d+)\:(\d+)$/)
|
||
var mydate = new Date(field[1], field[2] - 1 , field[3], field[4], field[5], field[6])
|
||
x.dj = dayjs(mydate)
|
||
x.searchable = x.title.toLowerCase() + ' ' + x.desc.toLowerCase() } )
|
||
self.$forceUpdate();
|
||
self.active += 1; } )
|
||
basic_get('dir_api.php?a=get/hosts', function(r2) {
|
||
self.hosts_by_sesid = _.groupBy(r2,function(x) { return x.id } )
|
||
} )
|
||
basic_get('dir_api.php?a=get/rosters', function(r2) {
|
||
self.rosters = _.groupBy(r2,function(x) { return x.sesid } )
|
||
} )
|
||
basic_get('dir_api.php?a=get/allhosts', function(r2) {
|
||
self.hosts = r2
|
||
setTimeout(function () { self.hosts = r2; self.$forceUpdate() }, 750);
|
||
self.active += 1;
|
||
} )
|
||
basic_get('dir_api.php?a=get/names', function(r2) {
|
||
self.everyone = []
|
||
_.each( r2.users, function(x) { self.everyone[x.id] = x.name } ) } )
|
||
basic_get('dir_api.php?a=get/questions', function(r2) {
|
||
self.questions = r2 })
|
||
basic_get('dir_api.php?a=get/answers/all', function(r2) {
|
||
var organized = _.groupBy(r2, function(x) { return x.ses_id; } )
|
||
// TODO are answers and answers2 the same?
|
||
_.each( organized, function(val,key,lis) { self.answers[key] = _.groupBy( val, function(y) { return y.q_id; }); } )
|
||
_.each( self.answers, function(val,key,lis) { self.answers2[key] = _.sortBy( val, "q_id" ) } )
|
||
self.$forceUpdate()
|
||
} )
|
||
},
|
||
methods: {
|
||
hoststr: function(id) {
|
||
var self = this
|
||
return _.reduce( self.hosts_by_sesid[id], function(mem,val) { if (val.name) { return mem + val.name + ", " } return mem }, '')
|
||
},
|
||
userstr: function(id) { return _.pluck(this.rosters[id], "name").join(', ') },
|
||
usernum: function(id) { if (id in this.rosters) { return this.rosters[id].length } return 0 },
|
||
useremails: function(id) { return _.pluck(this.rosters[id], "email").join('; ') },
|
||
surveystr: function(id) {
|
||
var self = this
|
||
var result = ""
|
||
if (this.answers2[id]) {
|
||
_.each( this.answers2[id], function (qlist) {
|
||
result += "<b class='survey_q'>" + qlist[0]['question'] + "</b><br />\n<ul>"
|
||
_.each( qlist, function(qanswer) {
|
||
result += "<li>" + qanswer['answer'] + "</li>\n"
|
||
})
|
||
result += "</ul>\n"
|
||
})
|
||
return result
|
||
}
|
||
return "<i>no survey results?</i>"
|
||
var answers = _.find(this.activities, function(x) { return x.id == id } )
|
||
return "Surveys"
|
||
return _.reduce( self.hosts_by_sesid[id], function(mem,val) { if (val.name) { return mem + val.name + ", " } return mem }, '')
|
||
},
|
||
},
|
||
computed: {
|
||
},
|
||
watch: { },
|
||
template: `<div class="activityreport">
|
||
<div v-for="a in activities">
|
||
<activityinforeport2 :a="a" :host="hoststr(a.id)" :num="usernum(a.id)" :user="userstr(a.id)" :emails="useremails(a.id)" :survey="surveystr(a.id)"></activityinforeport2>
|
||
</div>
|
||
</div>` })
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
//
|
||
//
|
||
//
|
||
//
|
||
//
|
||
//
|
||
// TRAINING HISTORY - GOTT COURSES
|
||
// -------------------------------
|
||
//
|
||
//
|
||
//
|
||
const TrainingHistory = Vue.component('traininghistory', {
|
||
props: [ '' ],
|
||
data: function () {
|
||
return { training: {}, mycourses: {}, msg:"Loading..." } },
|
||
mounted: function() {
|
||
var self = this
|
||
basic_get('gott_by_goo.json', function(r2) {
|
||
self.training = r2;
|
||
setTimeout(() => { self.msg = "" }, 1500);
|
||
|
||
} )
|
||
},
|
||
computed: {
|
||
user_courses() {
|
||
if ('user' in this.$root && this.$root.active && this.training) { return this.training[this.$root.user.conf_goo] || null }
|
||
return {}
|
||
}
|
||
},
|
||
methods: {
|
||
formatDate(dateString) {
|
||
const options = { year: 'numeric', month: 'long', day: 'numeric' };
|
||
return new Date(dateString).toLocaleDateString(undefined, options);
|
||
}
|
||
},
|
||
watch: { },
|
||
template: `<div class="space-y-4">
|
||
<div class="bg-blue-50 text-blue-900 p-4 rounded-md shadow-sm">
|
||
<p class="font-medium">These are the GOTT courses you have taken.</p>
|
||
</div>
|
||
|
||
<div v-if="Object.keys(training).length > 0">
|
||
<p class="text-sm text-gray-700 mb-2">{{ msg }}</p>
|
||
|
||
<div class="space-y-3">
|
||
<div
|
||
v-for="(date, course) in user_courses"
|
||
:key="course"
|
||
class="flex flex-col md:flex-row md:items-center md:justify-between bg-white p-4 border rounded shadow-sm"
|
||
>
|
||
<div class="text-gray-800 font-medium">Course: {{ course }}</div>
|
||
<div class="text-gray-600 mt-1 md:mt-0">Completed: {{ formatDate(date) }}</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div v-else>
|
||
<p class="text-gray-500 italic">No training history found.</p>
|
||
</div>
|
||
</div>` })
|
||
|
||
|
||
|
||
|
||
|
||
|
||
//
|
||
//
|
||
// _ _ _
|
||
// | | | | (_)
|
||
// ___ ___| |_| |_ _ _ __ __ _ ___
|
||
// / __|/ _ \ __| __| | '_ \ / _` / __|
|
||
// \__ \ __/ |_| |_| | | | | (_| \__ \
|
||
// |___/\___|\__|\__|_|_| |_|\__, |___/
|
||
// __/ |
|
||
// |___/
|
||
//
|
||
//
|
||
const Settings = Vue.component('settings', {
|
||
props: [ ],
|
||
data: function () {
|
||
return { 'zoom_on':'', 'survey_on':'', 'ay':'', 'default_conference':'' } },
|
||
mounted: function() {
|
||
var self = this
|
||
this.zoom_on = this.$parent.settings.zoom_on
|
||
this.survey_on = this.$parent.settings.survey_on
|
||
this.ay = this.$parent.settings.default_ay
|
||
this.default_conference = this.$parent.settings.default_conference
|
||
},
|
||
methods: {
|
||
},
|
||
computed: {
|
||
},
|
||
watch: { },
|
||
template: `<div class="settingspanel">
|
||
<ul>
|
||
<li>
|
||
<input class="form-check-input" type="checkbox" id="zoom_on" v-model="zoom_on">
|
||
<label class="icert form-check-label" for="zoom_on">Zoom Links Visible</label><br />
|
||
</li>
|
||
<li>
|
||
<input class="form-check-input" type="checkbox" id="survey_on" v-model="survey_on">
|
||
<label class="icert form-check-label" for="survey_on">Surveys Available</label><br />
|
||
</li>
|
||
<li>
|
||
|
||
<selectmenu table="conf_uinforecord" qid="value" :answer="this.ay" menu="ay_menu" :targetid="4" question="Academic Year: " labelfield="label"></selectmenu>
|
||
</li>
|
||
</ul>
|
||
</div>` })
|
||
|
||
|
||
|
||
// _ _
|
||
// | | | |
|
||
// ___ __ _| | ___ _ __ __| | __ _ _ __
|
||
// / __/ _` | |/ _ \ '_ \ / _` |/ _` | '__|
|
||
// | (_| (_| | | __/ | | | (_| | (_| | |
|
||
// \___\__,_|_|\___|_| |_|\__,_|\__,_|_|
|
||
//
|
||
//
|
||
|
||
|
||
// VERY SIMPLE CALENDAR
|
||
//
|
||
const MyCal = Vue.component('mycal', {
|
||
data: function () {
|
||
return { today:new Date(), currentMonth:0, currentYear:0, selectYear:'', selectMonth:'',
|
||
months:["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
|
||
activities:[],
|
||
by_date: {},
|
||
editing: -1, } },
|
||
mounted: function() {
|
||
var self = this
|
||
this.currentYear = this.today.getFullYear()
|
||
this.currentMonth = this.today.getMonth()
|
||
this.selectYear = this.currentYear
|
||
this.selectMonth = this.currentMonth
|
||
basic_get('dir_api.php?a=get/sessions',
|
||
function(r2) { self.activities = _.map(r2, function(x) {
|
||
var dd = new Date(x.starttime);
|
||
var [m,d,y] = [dd.getMonth(), dd.getDate(), dd.getFullYear()] // months start at 0....
|
||
var d_string = d + "-" + m + "-" + y
|
||
if (self.by_date[d_string]) { self.by_date[d_string].push(x) }
|
||
else { self.by_date[d_string] = [x, ] } } )
|
||
self.$forceUpdate() } )
|
||
},
|
||
methods: {
|
||
thisDay: function(i,j) {
|
||
var dayOfMonth = ((7*(i-1))+j)-this.firstDay()
|
||
return dayOfMonth },
|
||
eventsThisDay: function(i,j) {
|
||
var dayOfMonth = ((7*(i-1))+j)-this.firstDay()
|
||
var d_string = dayOfMonth + "-" + this.selectMonth + "-" + this.selectYear
|
||
var day_text = ''
|
||
if (this.by_date[d_string]) {
|
||
evts = _.filter( this.by_date[d_string], function(x) { return x.typeId!="101" } )
|
||
return evts } return [] },
|
||
cleanTime: function(e) {
|
||
var dd = new Date(e.starttime);
|
||
var [h,m] = [dd.getHours(), dd.getMinutes()]
|
||
var ampm = 'am'
|
||
if (h > 12) { h -= 12; ampm = 'pm' }
|
||
if (m == 0) { m = '' }
|
||
else { m = ':' + m }
|
||
return h + m + ampm },
|
||
daysInMonth: function() {
|
||
return 32 - new Date(this.selectYear, this.selectMonth, 32).getDate() },
|
||
firstDay: function() {
|
||
return (new Date(this.selectYear, this.selectMonth)).getDay() },
|
||
next: function() {
|
||
this.selectYear = (this.selectYear === 11) ? this.selectYear + 1 : this.selectYear;
|
||
this.selectMonth = (this.selectMonth + 1) % 12; },
|
||
previous: function() {
|
||
this.selectYear = (this.selectYear === 0) ? this.selectYear - 1 : this.selectYear;
|
||
this.selectMonth = (this.selectMonth === 0) ? 11 : this.selectMonth - 1; },
|
||
},
|
||
computed: {
|
||
},
|
||
watch: {
|
||
},
|
||
template:`<div class="calendar">
|
||
<h3>{{months[selectMonth] + " " + selectYear}}
|
||
<div class="btn_container"><div class="btn_float">
|
||
<button class="pure-button" v-on:click="previous">Previous</button>
|
||
<button class="pure-button" v-on:click="next">Next</button>
|
||
</div></div>
|
||
</h3>
|
||
<table><thead><tr>
|
||
<th>Sun</th><th>Mon</th><th>Tue</th><th>Wed</th><th>Thu</th><th>Fri</th><th>Sat</th>
|
||
</tr></thead>
|
||
<tbody id="calendar-body">
|
||
<tr v-for="i in 6" v-if="(((7*(i-1)))-firstDay() < daysInMonth()+1)">
|
||
<td v-for="j in 7">
|
||
<span v-if="( ((7*(i-1))+j)-firstDay() > 0) && (((7*(i-1))+j)-firstDay() < daysInMonth()+1)">
|
||
<div class="do_month">{{ thisDay(i,j) }}</div>
|
||
<div class="cal_evt" v-for="ev in eventsThisDay(i,j)">{{cleanTime(ev)}} {{ ev.title }}</div>
|
||
</span>
|
||
</td>
|
||
</tr>
|
||
</tbody></table>
|
||
</div>` })
|
||
|
||
|
||
|
||
|
||
|
||
|
||
// _ _ _ _ _
|
||
// | | | | | | | | | |
|
||
// __ _____| | ___ ___ _ __ ___ ___ | | ___| |_| |_ ___ _ __ | |
|
||
// \ \ /\ / / _ \ |/ __/ _ \| '_ ` _ \ / _ \ | |/ _ \ __| __/ _ \ '__| | |
|
||
// \ V V / __/ | (_| (_) | | | | | | __/ | | __/ |_| || __/ | |_|
|
||
// \_/\_/ \___|_|\___\___/|_| |_| |_|\___| |_|\___|\__|\__\___|_| (_)
|
||
//
|
||
//
|
||
|
||
|
||
|
||
|
||
|
||
|
||
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // //
|
||
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // //
|
||
//
|
||
// WELCOME LETTER main component
|
||
//
|
||
const WelcomeLetter = Vue.component('welcomeletter', {
|
||
props: [ 'mysem','mycrn', 'teacher_ext_id', ],
|
||
data: function () {
|
||
return { courses_by_semester:[], wl_sem:'', wl_crn:'', section_wl:{}, sortby:'code', reversed:false, active:-1, } },
|
||
watch: {
|
||
"teacher_ext_id": function (val, oldVal) { this.fetch_sections() },
|
||
},
|
||
mounted: function() {
|
||
var self = this
|
||
if (this.mysem && this.mycrn) { this.fetch_wletters(this.mysem, this.mycrn) }
|
||
else { this.$root.do_after_load( self.fetch_sections) }
|
||
},
|
||
methods: {
|
||
swap_section: function(section_obj) { this.fetch_wletters(section_obj.sem,section_obj.crn) },
|
||
show_list: function() { this.section_wl = {} },
|
||
fetch_wletters: function(ss,cc) {
|
||
var self = this;
|
||
fetch('dir_api.php?a=get/section/' + ss + '/' + cc,
|
||
{ method: 'GET' }).then(function (response) {
|
||
// The API call was successful!
|
||
if (response.ok) {
|
||
response.json().then( function(r2) {
|
||
self.section_wl = r2;
|
||
} )
|
||
} else { return Promise.reject(response) }
|
||
}).then(function (data) {
|
||
}).catch(function (err) { console.warn('Something went wrong.', err); });
|
||
},
|
||
fetch_sections: function() {
|
||
var self = this;
|
||
basic_get('dir_api.php?a=get/sections/' + this.$root.user.ext_id,
|
||
function(r2) { self.courses_by_semester = _.groupBy(r2,function(x) { return x.sem || 0} ); self.$forceUpdate(); self.active += 1; } )
|
||
},
|
||
},
|
||
template: `<div class="">
|
||
<div v-if="section_wl.id" class="pure-g pure-form">
|
||
<div class="pure-u-24-24">
|
||
<div class="clicky" v-on:click="show_list()">back to list of sections</div>
|
||
<div class="">
|
||
Course:
|
||
</div>
|
||
<div class="">
|
||
Description:
|
||
</div>
|
||
<div class="">
|
||
Delivery Format:
|
||
</div>
|
||
<div class="">
|
||
Schedule:
|
||
</div>
|
||
<div class="">
|
||
Length:
|
||
</div>
|
||
<form class="pure-form pure-form-aligned">
|
||
|
||
<tfield table="welcome_letters" qid="introduction" question="Introduction" :answer="this.section_wl.introduction" :targetid="this.section_wl.wl_id"></tfield>
|
||
|
||
<tfield table="welcome_letters" qid="what_expect" question="What to Expect" :answer="this.section_wl.what_expect" :targetid="this.section_wl.wl_id"></tfield>
|
||
|
||
<tfield table="welcome_letters" qid="textbook" question="Textbook Information" :answer="this.section_wl.textbook" :targetid="this.section_wl.wl_id"></tfield>
|
||
|
||
<tfield table="welcome_letters" qid="assessments" question="Tests and Assessments" :answer="this.section_wl.assessments" :targetid="this.section_wl.wl_id"></tfield>
|
||
|
||
<tfield table="welcome_letters" qid="other_info" question="Other Useful Information" :answer="this.section_wl.other_info" :targetid="this.section_wl.wl_id"></tfield>
|
||
|
||
<tfield table="welcome_letters" qid="additional_resources" question="Additional Resources" :answer="this.section_wl.additional_resources" :targetid="this.section_wl.wl_id"></tfield>
|
||
|
||
</form>
|
||
</div>
|
||
</div>
|
||
<div v-else class="pure-g pure-form">
|
||
<div v-for="sect_list,sm in courses_by_semester" class="pure-u-24-24">
|
||
<b> {{sm}}</b><br />
|
||
<div v-for="crs in sect_list" class="clicky" v-on:click="swap_section(crs)">
|
||
{{crs.code}} - {{crs.crn}} - {{crs.name}}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>` })
|
||
|
||
|
||
|
||
|
||
// _ _ _
|
||
// | | | | | |
|
||
// _____ _____ _ __ | |_ ___ | |__ ___| |_ __ ___ _ __
|
||
// / _ \ \ / / _ \ '_ \| __/ __| | '_ \ / _ \ | '_ \ / _ \ '__|
|
||
// | __/\ V / __/ | | | |_\__ \ | | | | __/ | |_) | __/ |
|
||
// \___| \_/ \___|_| |_|\__|___/ |_| |_|\___|_| .__/ \___|_|
|
||
// | |
|
||
// |_| //
|
||
// AJAX POST UPDATES TO API
|
||
//
|
||
|
||
function post_update(table,cols,vals,id=0) {
|
||
action = "nothing"
|
||
//if (table=="update_survey") { action = "update" }
|
||
if (table=="personnel") { action = "update" }
|
||
if (table=="personnel_ext") { action = "update_xt" }
|
||
if (table=="conf_users") { action = "update_cf" }
|
||
if (table=="conf_sessions") { action = "update/activity" }
|
||
if (table=="webpages") { action = "update_web" }
|
||
if (table=="welcome_letters") { action = "update/letter" } // or insert?
|
||
if (table=="uniforecord") { action = "update/settings" }
|
||
var idstr = ""
|
||
if (id) { idstr = "&id=" + id }
|
||
fetch('dir_api.php', {
|
||
method: 'POST',
|
||
headers: new Headers({ 'Content-Type': 'application/x-www-form-urlencoded' }),
|
||
body: "a="+action+"&cols="+cols+"&vals="+vals+idstr,
|
||
}).then(function (response) {
|
||
if (response.ok) {
|
||
response.json().then( function(r2) {
|
||
// display success alert
|
||
alert_message('Saved.')
|
||
} )
|
||
} else { return Promise.reject(response) }
|
||
}).then(function (data) {
|
||
}).catch(function (err) { alert_message("Couldn't save!",pink); console.warn('Something went wrong.', err); });
|
||
}
|
||
|
||
function generic_fail(err,x="Something went wrong with an ajax fetch") {
|
||
console.log(x); console.log(err) }
|
||
|
||
function basic_get( url, after_fxn, fail_fxn=generic_fail ) {
|
||
fetch(url, { method: 'GET' }).then(function (response) {
|
||
if (response.ok) {response.json().then( function(r2) { after_fxn(r2) } )
|
||
} else { return Promise.reject(response) }
|
||
}).then(function (data) { }).catch(function (err) { fail_fxn(err) } ) }
|
||
|
||
var evt = {
|
||
clear_tables: function() {
|
||
var self = this
|
||
_.each( this.tables, function(x) { self[x] = [] } )
|
||
this.data = {}
|
||
this.target_ids = {} },
|
||
send_update: function() {
|
||
var self = this
|
||
_.each( this.tables, function(x) {
|
||
if (self[x].length) {
|
||
var cols = ""
|
||
var vals = ""
|
||
_.each(self[x], function(y) {
|
||
if (cols.length) { cols += "," }
|
||
if (vals.length) { vals += "," }
|
||
cols += y
|
||
if (typeof self.data[y] == "string") {
|
||
re = /,/g
|
||
vals += encodeURIComponent(self.data[y].replace(re,'[CMA]') ) }
|
||
else { vals += self.data[y] }
|
||
})
|
||
var edit_other = 0
|
||
if (self.target_ids[x]) { edit_other = self.target_ids[x] }
|
||
post_update(x, cols, vals, edit_other)
|
||
}
|
||
} ) },
|
||
data: {},
|
||
target_ids: {},
|
||
tables: ['personnel','personnel_ext','webpages','welcome_letters','conf_sessions','conf_hosts',
|
||
'pers_departments','pers_committees','pers_titles'],
|
||
}
|
||
|
||
|
||
|
||
evt.clear_tables()
|
||
MicroEvent.mixin(evt)
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
// _ _____ _____
|
||
// (_) /\ | __ \| __ \
|
||
// _ __ ___ __ _ _ _ __ / \ | |__) | |__) |
|
||
// | '_ ` _ \ / _` | | '_ \ / /\ \ | ___/| ___/
|
||
// | | | | | | (_| | | | | | / ____ \| | | |
|
||
// |_| |_| |_|\__,_|_|_| |_| /_/ \_\_| |_|
|
||
//
|
||
//
|
||
var app = new Vue({
|
||
el: '#dir_editor',
|
||
data: { events: evt,
|
||
msg: 'hello', active: false, creating:0,
|
||
user: {'last_name':'', 'first_name':'', 'department':'', 'extension':'', 'phone_number':'', 'email':'',
|
||
'staff_type':'', 'room':'', 'status':'', 'user_id':'', 'password':'', 'time_created':'', 'time_updated':'',
|
||
'id':'', ext_id:false, 'web_on':'', use_dir_photo:0, general_photo_release:0, espanol:0, zoom:'', preferred_contact:'',
|
||
officehours:'', title:'', picture:'', education:'', bio:'', courses:'', personal_page:'', changed:'' },
|
||
settings:{},
|
||
filter: [],
|
||
roles_menu: [],
|
||
depts_menu: [],
|
||
titles_menu: [],
|
||
sessiontypes_menu: [],
|
||
parents_menu: [],
|
||
ay_menu: [],
|
||
modes_menu: [ {'id': 'Pending', 'string':'Pending'}, {'id':'online','string':'Online'}, {'id':'inperson','string':'In Person'}, {'id':'hybrid','string':'Hybrid'}, {'id':'','string':''}, ],
|
||
waiting_fxns: [],
|
||
data_loaded: 0,
|
||
committees_menu: [],
|
||
menus_fetched: false,
|
||
},
|
||
watch: {
|
||
'data_loaded': function(newVal,oldVal) {
|
||
if (newVal > 0) { _.each( this.waiting_fxns, function(fx) { fx() }) } }, },
|
||
methods: {
|
||
do_after_load: function(do_fxn) { this.waiting_fxns.push(do_fxn) /*....*/ },
|
||
fetch_menus: function() {
|
||
if (! this.menus_fetched) {
|
||
var self = this;
|
||
fetch('dir_api.php?a=menus', { method: 'GET' }).then(function (response) {
|
||
// The API call was successful!
|
||
if (response.ok) {
|
||
response.json().then( function(r2) {
|
||
self.depts_menu = r2.departments;
|
||
self.roles_menu = r2.roles;
|
||
self.titles_menu = r2.titles;
|
||
self.committees_menu = r2.committees;
|
||
self.sessiontypes_menu = r2.sessiontypes;
|
||
self.parents_menu = r2.parents;
|
||
self.menus_fetched = true;
|
||
} )
|
||
} else { return Promise.reject(response) }
|
||
}).then(function (data) {
|
||
}).catch(function (err) {
|
||
// FAILED TO LOAD. MOST LIKELY THE SSO/SESSION TIMED OUT
|
||
// .... reload whole page to get redirect...?
|
||
console.warn('Something went wrong.', err);
|
||
});
|
||
}
|
||
},
|
||
my_subscribe_calendar: function() { return "webcal://hhh.gavilan.edu/phowell/map/calendar" + this.user.conf_id + ".ics" },
|
||
clip_copy: function(x) {
|
||
// see the .htaccess file for the mod_rewrite that makes the ics file work. //
|
||
|
||
var data = [new ClipboardItem({ "text/plain": new Blob([this.my_subscribe_calendar()], { type: "text/plain" }) })];
|
||
navigator.clipboard.write(data).then(function() {
|
||
fadein_message()
|
||
}, function() { console.error("Unable to write to clipboard. :-("); }) }, },
|
||
computed: { },
|
||
mounted: function() {
|
||
var self = this;
|
||
fetch('api2.php?query=start', { method: 'GET' }).then(function (response) {
|
||
// The API call was successful!
|
||
if (response.ok) {
|
||
response.json().then( function(r2) {
|
||
var x = self.user.mysessions
|
||
self.user = r2.user;
|
||
self.depts_menu = r2.departments;
|
||
self.roles_menu = r2.roles;
|
||
self.titles_menu = r2.titles;
|
||
self.committees_menu = r2.committees;
|
||
self.sessiontypes_menu = r2.sessiontypes;
|
||
self.parents_menu = r2.parents;
|
||
self.ay_menu = r2.ay;
|
||
self.settings = r2.settings;
|
||
self.menus_fetched = true;
|
||
self.data_loaded += 1
|
||
// pause half a second for the children to get populated before registering update events...
|
||
setTimeout(function() {
|
||
self.active = true;
|
||
// fancier text editors...
|
||
//pell.init( { element: document.getElementById('bio2'), onChange: function(h) { console.log(h) } } )
|
||
}, 1600);
|
||
} )
|
||
} else { return Promise.reject(response) }
|
||
}).then(function (data) {
|
||
}).catch(function (err) { console.warn('Something went wrong.', err); }) } })
|
||
|
||
|
||
|
||
|
||
// _
|
||
// | |
|
||
// _____ _____ _ __ | |_ ___
|
||
// / _ \ \ / / _ \ '_ \| __/ __|
|
||
// | __/\ V / __/ | | | |_\__ \
|
||
// \___| \_/ \___|_| |_|\__|___/
|
||
//
|
||
//
|
||
|
||
|
||
//
|
||
// SIMPLE EVENTS
|
||
//
|
||
|
||
var update_fxn = _.debounce( function() {
|
||
alert_message('saving...','lightgreen')
|
||
evt.send_update(); evt.clear_tables(); }, 1300 )
|
||
|
||
|
||
var update_survey_fxn = function() {
|
||
|
||
}
|
||
|
||
evt.bind('update_survey',_.debounce( function(dat) {
|
||
if (app.active) {
|
||
fetch('dir_api.php?a=update/answers', {
|
||
method: 'POST',
|
||
headers: new Headers({ 'Content-Type': 'application/x-www-form-urlencoded' }),
|
||
body: "session=" +dat[1] + "&user=" +dat[0] + "&qid=" +dat[2] + "&answer="+dat[3],
|
||
}).then(function (response) {
|
||
if (response.ok) {
|
||
response.json().then( function(r2) {
|
||
// display success alert
|
||
alert_message('Saved.')
|
||
} )
|
||
} else { return Promise.reject(response) }
|
||
}).then(function (data) {
|
||
}).catch(function (err) { alert_message("Couldn't save!",pink); console.warn('Something went wrong.', err); });
|
||
} } , 1300 ) );
|
||
|
||
evt.bind('changed', function(dat) {
|
||
if (app.active) {
|
||
var column = dat[0]
|
||
var table = dat[1]
|
||
var value = dat[2]
|
||
var target = dat[3]
|
||
this.data[column] = value
|
||
if (!this[table].includes(column) ) {this[table].push(column)}
|
||
if (target) { this.target_ids[table] = target } }
|
||
if (app.active && !app.creating) { update_fxn() }
|
||
});
|
||
|
||
evt.bind('create_new_session', function(dat) {
|
||
var default_activity = {"title":"","desc":"","length":"1","starttime":"","track":"","location":"","gets_survey":"1","category":"1",
|
||
"parent":"","recording":"","instructions":"","image_url":"","is_flex_approved":"1","typeId":"101"}
|
||
var new_activity = _.extend(default_activity, evt.data)
|
||
|
||
if ('typeId' in new_activity) { new_activity.type = new_activity.typeId; delete new_activity.typeId; }
|
||
let formData = new FormData();
|
||
_.each( Object.keys(new_activity), function(x) { formData.append(x, new_activity[x]) } )
|
||
|
||
fetch('dir_api.php?a=set/newsession', {
|
||
method: 'POST',
|
||
body: formData, }).then(function (response) {
|
||
if (response.ok) {
|
||
response.json().then( function(r2) {
|
||
alert_message('Saved new activity.')
|
||
app.$children[0].set_id(r2.new_id) } )
|
||
} else { return Promise.reject(response) }
|
||
}).then(function (data) {
|
||
}).catch(function (err) { alert_message("Couldn't create the activity!",pink); console.warn('Something went wrong.', err); }) })
|
||
|
||
|
||
// bold the current page
|
||
|
||
function bold_nav() {
|
||
var currentFileName = window.location.pathname.split('/').pop();
|
||
|
||
// Select the <a> tag with the matching href value and apply the class
|
||
$('#nav a[href="' + currentFileName + '"]').addClass('highlight');
|
||
}
|
||
|
||
|
||
$(document).ready(function() {
|
||
bold_nav()
|
||
})
|
||
|
||
//
|
||
//
|
||
// MISC
|
||
//
|
||
//
|
||
|
||
//
|
||
// <img :src="'//www.gavilan.edu/staff/' + s.dir_photo_path" width="25" height="auto" />
|
||
// v-lazy-container="{ selector: 'img' }"
|
||
//
|