879 lines
39 KiB
JavaScript
879 lines
39 KiB
JavaScript
|
|
|
|
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+)\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 });
|
|
|
|
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // //
|
|
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // //
|
|
//
|
|
// 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.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="pure-control-group"><label v-if="this.question" :for="this.qid" class="question">{{ question }}</label>
|
|
<input :id="this.qid" type="text" class="form-control" v-model="a" :placeholder="placeholder" /></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', ],
|
|
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="pure-control-group"><label :for="this.qid" class="question">{{ question }} </label>
|
|
<textarea :id="this.qid" v-model="a"></textarea></div>` })
|
|
|
|
|
|
|
|
// Select menu
|
|
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: `<select :id="this.qid" v-model="a" class="pure-input-1-12">
|
|
<option v-for="o in this.$root[menu]" :value="o.id">{{o[labelfield]}}</option>
|
|
</select>` })
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // //
|
|
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // //
|
|
//
|
|
// 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() { console.log("edit " + this.s.first_name + " " + this.s.last_name)
|
|
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>`
|
|
});
|
|
|
|
/*
|
|
|
|
*
|
|
* status: {{ s.status }} staff: {{ s.staff_type }}
|
|
* permissions: {{ s.role }} {{s.first_name}} {{s.last_name}} {{gdept1()}} # Sections: {{s.num_taught}}
|
|
* ext id: {{ s.ext_id }} {{ s.conf_id }} {{gtitle()}} {{s.room}}
|
|
* bio page: {{ s.web_on }} {{s.espanol}} {{s.goo}} {{s.phone}}
|
|
* Photo - use: {{s.use_dir_photo}} release: {{s.general_photo_release}} {{s.email}} {{s.preferred_contact}}
|
|
* {{s.zoom}} {{s.dir_photo_path}}
|
|
|
|
* [ status stafftype ] fname lname dept1 num_courses --> need_welcome pg
|
|
* [ no pext? perms ] title room dept2 num_flx_activities --> [ ? badges ? tickets ? ]
|
|
* [ no conf? ] goo phone log last updated num_hosted acts
|
|
* [ web on espanol ] email prefcontact dir last updated num_log_entries
|
|
* [ photo on release ] zoom photo path committees?
|
|
*/
|
|
|
|
|
|
|
|
|
|
//
|
|
//
|
|
// STAFF DIR LISTING
|
|
//
|
|
// ONE LINE - BUT EDITING! // todo active / inactive switch
|
|
//
|
|
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>` })
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // //
|
|
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // //
|
|
//
|
|
// ACTIVITIES LIST MAIN CONTAINER
|
|
//
|
|
const ActivityList = Vue.component('activitylist', {
|
|
props: [ 'itineraryview', ],
|
|
data: function () {
|
|
return { activities:[], mysessions:[], search:'', sortby:'starttime', reversed:false,
|
|
expanded: 1,
|
|
editing: -1, active:-1, } },
|
|
mounted: function() {
|
|
this.$root.fetch_menus();
|
|
this.fetch_myevents()
|
|
},
|
|
methods: {
|
|
month_year: function(d) { console.log(d); var b = this.$root.$dj(d).format('MMM D YYYY'); console.log(b); 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/mysessions',
|
|
function(r2) { self.mysessions = _.sortBy(r2,function(x) { return x.starttime || 0} ); self.$forceUpdate(); self.active += 1; console.log(self.active) } )
|
|
basic_get('dir_api.php?a=get/sessions',
|
|
function(r2) {
|
|
self.activities = _.sortBy(r2,function(x) { return x.starttime } ); self.$forceUpdate()
|
|
self.active += 1; console.log(self.active)
|
|
_.each( self.activities, function(x) {
|
|
x.searchable = x.title.toLowerCase() + ' ' + x.desc.toLowerCase() } ) } )
|
|
},
|
|
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 x.searchable.includes(ss) }) }
|
|
ff = _.sortBy(ff, function(x) { console.log(x);
|
|
if (x[self.sortby]) { var s = x[self.sortby]; return s.trim().toLowerCase() }
|
|
return '' })
|
|
if (this.reversed) { ff.reverse() }
|
|
console.log(ff)
|
|
return ff },
|
|
},
|
|
computed: {
|
|
activities_filtered: function() { var a = this.filtered(this.activities); console.log(a); 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="">
|
|
<div class="pure-g pure-form">
|
|
<div class="pure-u-1-24"></div>
|
|
<div class="pure-u-3-4"><b>Search: </b><input type="text" v-model="search" name="actfilter" class="double" /></div>
|
|
</div>
|
|
<div v-if="itineraryview && active>0" v-for="items,mmyy in mysessions_g_filtered">
|
|
<b>{{mmyy}}</b>
|
|
<div v-for="a in items" class="pure-g pure-form">
|
|
<div class="pure-u-1-24"> </div>
|
|
<div class="pure-u-3-24">{{ $root.$dj(a.starttime).format('h:mma') }} </div>
|
|
<div class="pure-u-5-6">{{a.title}} </div>
|
|
</div>
|
|
</div>
|
|
<div v-if="!itineraryview && active>0" v-for="items,mmyy in activities_g_filtered">
|
|
<b>{{mmyy}}</b>
|
|
<div v-for="a in items">
|
|
<div class="pure-g pure-form">
|
|
<div class="pure-u-1-24"> </div>
|
|
<div class="pure-u-3-24">{{ $root.$dj(a.starttime).format('h:mma') }} </div>
|
|
<div class="pure-u-5-6">{{a.type}} - {{a.title}} </div>
|
|
</div>
|
|
<div v-if="expanded" class="pure-g pure-form">
|
|
<div class="pure-u-1-24"> </div>
|
|
<div class="pure-u-3-24"> </div>
|
|
<div class="pure-u-5-6">{{a.desc}} </div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>` })
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // //
|
|
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // //
|
|
//
|
|
// 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) { console.log('tch ext id changed'); 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; console.log(self.active) } )
|
|
},
|
|
},
|
|
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>` })
|
|
|
|
|
|
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // //
|
|
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // //
|
|
//
|
|
// 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>` })
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // //
|
|
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // //
|
|
//
|
|
// AJAX POST UPDATES TO API
|
|
//
|
|
|
|
function post_update(table,cols,vals,id=0) {
|
|
action = "nothing"
|
|
if (table=="personnel") { action = "update" }
|
|
if (table=="personnel_ext") { action = "update_xt" }
|
|
if (table=="conf_users") { action = "update_cf" }
|
|
if (table=="webpages") { action = "update_web" }
|
|
if (table=="welcome_letters") { action = "update/letter" } // or insert?
|
|
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
|
|
//console.log("Sending update... (not really)")
|
|
_.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'],
|
|
}
|
|
|
|
|
|
|
|
|
|
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // //
|
|
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // //
|
|
//
|
|
// INITIALIZE THE APP
|
|
//
|
|
|
|
evt.clear_tables()
|
|
MicroEvent.mixin(evt);
|
|
|
|
|
|
// welcome letter ?
|
|
/*var doing_welcomeletter = 1
|
|
if (typeof editing_crn === 'undefined' || editing_crn === null) {
|
|
// variable is undefined or null
|
|
doing_welcomeletter = 0
|
|
editing_crn = ''
|
|
editing_sem = ''
|
|
} */
|
|
|
|
var app = new Vue({
|
|
el: '#dir_editor',
|
|
data: { events: evt,
|
|
msg: 'hello', active: false,
|
|
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:'' },
|
|
filter: [],
|
|
roles_menu: [],
|
|
depts_menu: [],
|
|
titles_menu: [],
|
|
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.menus_fetched = true;
|
|
} )
|
|
} else { return Promise.reject(response) }
|
|
}).then(function (data) {
|
|
}).catch(function (err) { 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() {
|
|
console.log("Copied to clipboard successfully!");
|
|
fadein_message()
|
|
}, function() {
|
|
console.error("Unable to write to clipboard. :-(");
|
|
});
|
|
},
|
|
},
|
|
computed: { },
|
|
mounted: function() {
|
|
var self = this;
|
|
this.fetch_menus()
|
|
fetch('dir_api.php', { 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;
|
|
self.user.mysessions = x
|
|
if (self.user.use_dir_photo == "0") { self.user.use_dir_photo = false }
|
|
if (self.user.espanol == "0") { self.user.espanol = false }
|
|
if (self.user.general_photo_release == "0") { self.user.general_photo_release = false }
|
|
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); });
|
|
}
|
|
})
|
|
|
|
|
|
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // //
|
|
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // //
|
|
//
|
|
// SIMPLE EVENTS
|
|
//
|
|
|
|
var update_fxn = _.debounce( function() {
|
|
alert_message('saving...','lightgreen')
|
|
evt.send_update(); evt.clear_tables(); }, 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]
|
|
console.log(dat)
|
|
this.data[column] = value
|
|
if (!this[table].includes(column) ) {this[table].push(column)}
|
|
if (target) { this.target_ids[table] = target }
|
|
update_fxn() }
|
|
});
|
|
|
|
|
|
|
|
//
|
|
//
|
|
// MISC
|
|
//
|
|
//
|
|
|
|
//
|
|
// <img :src="'//www.gavilan.edu/staff/' + s.dir_photo_path" width="25" height="auto" />
|
|
// v-lazy-container="{ selector: 'img' }"
|
|
//
|