Updated to nearly fully functional. Pre-release 1. Still needs some UI changes in the slideshow and admin pages (move the save button & fix the save detection for the internship list). Customer had one more page change request which I need to re-define and handle.
This commit is contained in:
@@ -1,7 +0,0 @@
|
||||
<template name="AppreciationEditor">
|
||||
<div id="appreciationEditor">
|
||||
<h1>Appreciation Editor</h1>
|
||||
<div class="editor"></div>
|
||||
<button id="save">Save</button>
|
||||
</div>
|
||||
</template>
|
||||
@@ -1,6 +0,0 @@
|
||||
#appreciationEditor
|
||||
display: block
|
||||
.ck.ck-editor__editable_inline
|
||||
border-color: rgba(0,0,0,.2)
|
||||
.ck.ck-editor__editable_inline.ck-focused
|
||||
border-color: rgba(0,0,0,1)
|
||||
@@ -1,87 +0,0 @@
|
||||
import './AppreciationEditor.html';
|
||||
import swal from "sweetalert2";
|
||||
|
||||
let originalData = "";
|
||||
|
||||
Tracker.autorun(function() {
|
||||
Meteor.subscribe("pages");
|
||||
});
|
||||
|
||||
Template.AppreciationEditor.onRendered(function() {
|
||||
let _this = this;
|
||||
|
||||
//#appreciationEditor'
|
||||
// CKEditor.create(document.querySelector('#editor'), {}).then(editor => {
|
||||
// _this.ckEditor = editor;
|
||||
//
|
||||
// Tracker.autorun(function() {
|
||||
// let doc = Meteor.collections.Pages.findOne({name: 'Appreciation'});
|
||||
//
|
||||
// originalData = (doc === undefined ? "" : doc.html);
|
||||
// editor.setData(originalData);
|
||||
// });
|
||||
// }).catch(err => {
|
||||
// console.error(err);
|
||||
// });
|
||||
$('.editor').tinymce({
|
||||
inline: true
|
||||
});
|
||||
Tracker.autorun(function() {
|
||||
let doc = Meteor.collections.Pages.findOne({name: 'Appreciation'});
|
||||
|
||||
originalData = (doc === undefined ? "" : doc.html);
|
||||
$('.editor').html(originalData);
|
||||
});
|
||||
});
|
||||
|
||||
Template.AppreciationEditor.onDestroyed(function() {
|
||||
// let data = this.ckEditor.getData();
|
||||
let data = $('.editor').html();
|
||||
|
||||
if(data != originalData) {
|
||||
swal({
|
||||
title: "Save Changes",
|
||||
text: "Would you like to save any changes you have made to this sheet?",
|
||||
type: "question",
|
||||
showCancelButton: true,
|
||||
confirmButtonColor: "#7cdd7f",
|
||||
confirmButtonText: "Yes",
|
||||
cancelButtonText: "No"
|
||||
}).then(
|
||||
function(isConfirm) {
|
||||
if(isConfirm) {
|
||||
Meteor.call('updatePage', 'Appreciation', data, function (error, result) {
|
||||
if (error) sAlert.error(error);
|
||||
else sAlert.success("Content Saved Successfully");
|
||||
});
|
||||
}
|
||||
},
|
||||
function(dismiss) {}
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
Template.AppreciationEditor.helpers({
|
||||
// html: function() {
|
||||
// let doc = Meteor.collections.Pages.findOne({name: 'Appreciation'});
|
||||
//
|
||||
// return doc == undefined ? "" : doc.html;
|
||||
// }
|
||||
});
|
||||
|
||||
Template.AppreciationEditor.events({
|
||||
'click #save': function(event, template) {
|
||||
// let data = template.ckEditor.getData();
|
||||
let data = $('.editor').html();
|
||||
|
||||
if(data != originalData) {
|
||||
Meteor.call('updatePage', 'Appreciation', data, function (error, result) {
|
||||
if (error) sAlert.error(error);
|
||||
else sAlert.success("Content Saved Successfully");
|
||||
});
|
||||
}
|
||||
else {
|
||||
sAlert.success("Data has not changed!");
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -1,7 +0,0 @@
|
||||
<template name="BoardEditor">
|
||||
<div id="boardEditor">
|
||||
<h1>Current Board Editor</h1>
|
||||
<div id="editor"></div>
|
||||
<button id="save">Save</button>
|
||||
</div>
|
||||
</template>
|
||||
@@ -1,68 +0,0 @@
|
||||
|
||||
import './BoardEditor.html';
|
||||
import swal from "sweetalert2";
|
||||
|
||||
let originalData = "";
|
||||
|
||||
Tracker.autorun(function() {
|
||||
Meteor.subscribe("pages");
|
||||
});
|
||||
|
||||
Template.BoardEditor.onRendered(function() {
|
||||
let _this = this;
|
||||
|
||||
CKEditor.create(document.querySelector('#editor'), {}).then(editor => {
|
||||
_this.ckEditor = editor;
|
||||
|
||||
Tracker.autorun(function() {
|
||||
let doc = Meteor.collections.Pages.findOne({name: 'Board'});
|
||||
|
||||
originalData = (doc === undefined ? "" : doc.html);
|
||||
editor.setData(originalData);
|
||||
});
|
||||
}).catch(err => {
|
||||
console.error(err);
|
||||
});
|
||||
});
|
||||
|
||||
Template.BoardEditor.onDestroyed(function() {
|
||||
let data = this.ckEditor.getData();
|
||||
|
||||
if(data != originalData) {
|
||||
swal({
|
||||
title: "Save Changes",
|
||||
text: "Would you like to save any changes you have made to this sheet?",
|
||||
type: "question",
|
||||
showCancelButton: true,
|
||||
confirmButtonColor: "#7cdd7f",
|
||||
confirmButtonText: "Yes",
|
||||
cancelButtonText: "No"
|
||||
}).then(
|
||||
function(isConfirm) {
|
||||
if(isConfirm) {
|
||||
Meteor.call('updatePage', 'Board', data, function (error, result) {
|
||||
if (error) sAlert.error(error);
|
||||
else sAlert.success("Content Saved Successfully");
|
||||
});
|
||||
}
|
||||
},
|
||||
function(dismiss) {}
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
Template.BoardEditor.events({
|
||||
'click #save': function(event, template) {
|
||||
let data = template.ckEditor.getData();
|
||||
|
||||
if(data != originalData) {
|
||||
Meteor.call('updatePage', 'Board', data, function (error, result) {
|
||||
if (error) sAlert.error(error);
|
||||
else sAlert.success("Content Saved Successfully");
|
||||
});
|
||||
}
|
||||
else {
|
||||
sAlert.success("Data has not changed!");
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -1,7 +0,0 @@
|
||||
<template name="DatesEditor">
|
||||
<div id="datesEditor">
|
||||
<h1>Important Dates Editor</h1>
|
||||
<div id="editor"></div>
|
||||
<button id="save">Save</button>
|
||||
</div>
|
||||
</template>
|
||||
6
imports/ui/Admin/DatesEditor.import.styl
vendored
6
imports/ui/Admin/DatesEditor.import.styl
vendored
@@ -1,6 +0,0 @@
|
||||
#datesEditor
|
||||
display: block
|
||||
.ck.ck-editor__editable_inline
|
||||
border-color: rgba(0,0,0,.2)
|
||||
.ck.ck-editor__editable_inline.ck-focused
|
||||
border-color: rgba(0,0,0,1)
|
||||
@@ -1,69 +0,0 @@
|
||||
|
||||
import './DatesEditor.html';
|
||||
import swal from "sweetalert2";
|
||||
|
||||
let originalData = "";
|
||||
|
||||
Tracker.autorun(function() {
|
||||
Meteor.subscribe("pages");
|
||||
});
|
||||
|
||||
Template.DatesEditor.onRendered(function() {
|
||||
let _this = this;
|
||||
|
||||
CKEditor.create(document.querySelector('#editor'), {}).then(editor => {
|
||||
_this.ckEditor = editor;
|
||||
|
||||
Tracker.autorun(function() {
|
||||
let doc = Meteor.collections.Pages.findOne({name: 'Dates'});
|
||||
|
||||
originalData = (doc === undefined ? "" : doc.html);
|
||||
editor.setData(originalData);
|
||||
});
|
||||
}).catch(err => {
|
||||
console.error(err);
|
||||
});
|
||||
});
|
||||
|
||||
Template.DatesEditor.onDestroyed(function() {
|
||||
let data = this.ckEditor.getData();
|
||||
|
||||
if(data != originalData) {
|
||||
swal({
|
||||
title: "Save Changes",
|
||||
text: "Would you like to save any changes you have made to this sheet?",
|
||||
type: "question",
|
||||
showCancelButton: true,
|
||||
confirmButtonColor: "#7cdd7f",
|
||||
confirmButtonText: "Yes",
|
||||
cancelButtonText: "No"
|
||||
}).then(
|
||||
function(isConfirm) {
|
||||
if(isConfirm) {
|
||||
Meteor.call('updatePage', 'Dates', data, function (error, result) {
|
||||
if (error) sAlert.error(error);
|
||||
else sAlert.success("Content Saved Successfully");
|
||||
});
|
||||
}
|
||||
},
|
||||
function(dismiss) {}
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
Template.DatesEditor.events({
|
||||
'click #save': function(event, template) {
|
||||
let data = template.ckEditor.getData();
|
||||
|
||||
if(data != originalData) {
|
||||
Meteor.call('updatePage', 'Dates', data, function (error, result) {
|
||||
if (error) sAlert.error(error);
|
||||
else sAlert.success("Content Saved Successfully");
|
||||
});
|
||||
}
|
||||
else {
|
||||
sAlert.success("Data has not changed!");
|
||||
}
|
||||
}
|
||||
});
|
||||
s
|
||||
33
imports/ui/Admin/InternshipEditor.html
Normal file
33
imports/ui/Admin/InternshipEditor.html
Normal file
@@ -0,0 +1,33 @@
|
||||
<template name="InternshipEditor">
|
||||
<div id="internshipEditor">
|
||||
<div class="internshipNavigation">
|
||||
<div class="addInternship"><input type="text" name="newInternshipName" class="newInternshipName form-control"/><i class="fa fa-plus-circle createInternship noselect clickable" aria-hidden="true"></i></div><span class="editPageText noselect clickable"><i class="fa fa-pencil" aria-hidden="true"></i><br/>Header</span>
|
||||
|
||||
<ul class="internshipList">
|
||||
{{#each internships}}
|
||||
<li class="internshipListItem noselect clickable" data-id="{{_id}}"><span class="name">{{name}}</span><i class="fa fa-times-circle deleteInternship" aria-hidden="true"></i></li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
</div>
|
||||
<div class="internshipHtml">
|
||||
{{> InternshipHtmlEditor internship=selectedInternship}}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template name="InternshipHtmlEditor">
|
||||
{{#if showInstructions}}
|
||||
<h2>Instructions</h2>
|
||||
<p>Add internships using the +. Type in the internship's name as it will appear in the list to the user, then click the + a second time to add it.
|
||||
Edit the internships by selecting them in the list. The contents will replace these instructions, and you can edit the internship HTML directly.</p>
|
||||
{{/if}}
|
||||
{{#if showSelectImageDialog}}
|
||||
<div class="modalBackground">
|
||||
{{> SelectImageDialog (selectImageDialogArgs)}}
|
||||
</div>
|
||||
{{/if}}
|
||||
<div class="editorContainer {{#if showInstructions}}hidden{{/if}}">
|
||||
<div class="editor textView"></div>
|
||||
<button id="save">Save</button>
|
||||
</div>
|
||||
</template>
|
||||
118
imports/ui/Admin/InternshipEditor.import.styl
vendored
Normal file
118
imports/ui/Admin/InternshipEditor.import.styl
vendored
Normal file
@@ -0,0 +1,118 @@
|
||||
#internshipEditor
|
||||
display: block
|
||||
.internshipNavigation
|
||||
float: left
|
||||
clear: none
|
||||
display: inline-block
|
||||
min-width: 200px
|
||||
width: 20%
|
||||
padding-right: 20px
|
||||
position: relative
|
||||
padding-top: 50px
|
||||
|
||||
.addInternship
|
||||
margin-bottom: 10px
|
||||
position: absolute
|
||||
left: 0
|
||||
top: 0
|
||||
right: 60px
|
||||
height: 40px
|
||||
input[name="newInternshipName"]
|
||||
display: inline-block
|
||||
width: 0
|
||||
transition: all .75s ease
|
||||
border: 0
|
||||
opacity: 0
|
||||
font-size: 1.2em
|
||||
input[name="newInternshipName"].show
|
||||
opacity: 1
|
||||
border: 1px solid #ccc
|
||||
border-radius: 4px
|
||||
width: 70%
|
||||
transform: translateX(4px)
|
||||
.createInternship
|
||||
display: inline-block
|
||||
position: relative
|
||||
top: 2px
|
||||
padding: 2px 6px
|
||||
margin: 0 4px
|
||||
//width: 33px
|
||||
text-align: center
|
||||
font-size: 1.5em
|
||||
line-height: 1.5em
|
||||
border-radius: 8px
|
||||
//border: 1px solid rgba(0, 0, 0, 0)
|
||||
box-sizing: border-box
|
||||
.createInternship:hover
|
||||
//border: 1px inset #b100d1
|
||||
//-webkit-box-shadow: inset 0px 0px 20px 0px #de7cff
|
||||
//-moz-box-shadow: inset 0px 0px 20px 0px #de7cff
|
||||
//box-shadow: inset 0px 0px 20px 0px #de7cff
|
||||
color: #5c8744
|
||||
.createInternship
|
||||
transform: translateX(-25px) rotate(0deg)
|
||||
transition: all .75s ease
|
||||
.createInternship.move
|
||||
transform: translateX(6px) rotate(720deg)
|
||||
.editPageText
|
||||
position: absolute
|
||||
right: 0
|
||||
top: 0
|
||||
width: 60px
|
||||
font-size: 14px
|
||||
text-align: center
|
||||
line-height: 14px
|
||||
font-weight: 800
|
||||
border: 1.5px solid gray
|
||||
border-radius: 6px
|
||||
padding: 6px
|
||||
margin-right: 5px
|
||||
.editPageText:hover
|
||||
background-color: #c6c6c6
|
||||
.editPageText:active
|
||||
border-color: black
|
||||
|
||||
.internshipListItem
|
||||
display: block
|
||||
background: white
|
||||
padding: 2px 0
|
||||
white-space: nowrap
|
||||
position: relative
|
||||
height: 24px
|
||||
.name
|
||||
position: absolute
|
||||
left: 0
|
||||
top: 0
|
||||
bottom: 0
|
||||
right: 24px
|
||||
overflow: hidden
|
||||
.deleteInternship
|
||||
position: absolute
|
||||
right: 0
|
||||
top: 0
|
||||
bottom: 0
|
||||
width: 24px
|
||||
padding-top: 0px
|
||||
padding-left: 2px
|
||||
color: #7c0000
|
||||
line-height: 24px
|
||||
font-size: 18px
|
||||
.deleteInternship:hover
|
||||
font-size: 22px
|
||||
top: 0
|
||||
right: 2px
|
||||
color: #ab0000
|
||||
.deleteInternship:active
|
||||
color: #613434
|
||||
.internshipListItem:hover
|
||||
background: #e2ddc0
|
||||
.internshipListItem:active
|
||||
background: rgba(254, 255, 0, 0.56)
|
||||
.internshipListItem.selected
|
||||
background: rgba(254, 255, 0, 0.56)
|
||||
|
||||
.internshipHtml
|
||||
display: inline-block
|
||||
max-width: 80%
|
||||
min-width: 200px
|
||||
width: 100%
|
||||
228
imports/ui/Admin/InternshipEditor.js
Normal file
228
imports/ui/Admin/InternshipEditor.js
Normal file
@@ -0,0 +1,228 @@
|
||||
|
||||
import './InternshipEditor.html';
|
||||
import '/imports/ui/dialogs/SelectImageDialog.js';
|
||||
import swal from "sweetalert2";
|
||||
|
||||
const PREFIX = "InternshipEditor_";
|
||||
|
||||
Tracker.autorun(function() {
|
||||
Meteor.subscribe("Internship");
|
||||
});
|
||||
|
||||
Template.InternshipEditor.onCreated(function() {
|
||||
this.internships = Meteor.collections.Internship.find({}, {sort: {name: 1}});
|
||||
Session.set(PREFIX + 'selectedInternship', null);
|
||||
});
|
||||
Template.InternshipEditor.helpers({
|
||||
internships: function() {
|
||||
return Template.instance().internships;
|
||||
},
|
||||
selectedInternship: function() {
|
||||
return Session.get(PREFIX + "selectedInternship");
|
||||
}
|
||||
});
|
||||
Template.InternshipEditor.events({
|
||||
'click .deleteInternship': function(event, template) {
|
||||
let $li = template.$(event.target).parent();
|
||||
|
||||
Meteor.call('removeInternship', $li.data('id'), function(error, id) {
|
||||
if(error) sAlert.error("Failed to create the internship!\n" + error);
|
||||
});
|
||||
},
|
||||
'click .internshipListItem': function(event, template) {
|
||||
let $li = template.$(event.currentTarget);
|
||||
|
||||
$li.addClass('selected');
|
||||
$li.siblings().removeClass('selected');
|
||||
Session.set(PREFIX + "selectedInternship", Meteor.collections.Internship.findOne($li.data('id')));
|
||||
},
|
||||
'click .editPageText': function(event,template) {
|
||||
|
||||
},
|
||||
"keyup input[name='newInternshipName']" : function(event, template) {
|
||||
if(event.keyCode === 13) {
|
||||
event.preventDefault();
|
||||
$('.createInternship').trigger('click');
|
||||
}
|
||||
},
|
||||
"click .createInternship": function(event, template) {
|
||||
let $input = template.$('input[name="newInternshipName"]');
|
||||
|
||||
if($input.hasClass('show')) {
|
||||
let name = $input.val();
|
||||
|
||||
name = name ? name.trim() : undefined;
|
||||
name = name && name.length > 0 ? name : undefined;
|
||||
|
||||
if(name) {
|
||||
let content = "<p><strong>Job Title: </strong></p>\n<p><strong>Supervisor / Sponsor: </strong></p>\n<p><strong>Location of Internship: </strong></p>\n<p><strong>Dates & hours: </strong></p>\n<p><strong>Duties & Activities: </strong></p>\n<p><strong>Desirable Qualities / Skills: </strong></p>";
|
||||
//Meteor.collections.Internship.insert({name, content});
|
||||
Meteor.call('addInternship', name, content, function(error, id) {
|
||||
if(error) sAlert.error("Failed to create the internship!\n" + error);
|
||||
else {
|
||||
//Clear the text editor.
|
||||
$input.val("");
|
||||
|
||||
//Quick hack to attempt to allow the internship we created to be added to the list before we try to select it and edit it.
|
||||
let count = 0;
|
||||
let interval = setInterval(function() {
|
||||
let selected = Meteor.collections.Internship.findOne(id);
|
||||
|
||||
if(selected) {
|
||||
//Select the sheet in the drop down.
|
||||
let $li = template.$('ul.internshipList li[data-id="' + id + '"]');
|
||||
|
||||
$li.addClass("selected");
|
||||
$li.siblings().removeClass("selected");
|
||||
Session.set(PREFIX + "selectedInternship", selected);
|
||||
clearInterval(interval);
|
||||
}
|
||||
else count++;
|
||||
|
||||
//Avoid infinite loop that should never happen.
|
||||
if(count > 100) clearInterval(interval);
|
||||
}, 100);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$input.removeClass('show');
|
||||
$(event.target).toggleClass('move');
|
||||
}
|
||||
else {
|
||||
$input.addClass('show');
|
||||
$(event.target).toggleClass('move');
|
||||
$input.focus();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Template.InternshipHtmlEditor.onCreated(function() {
|
||||
let template = this;
|
||||
|
||||
this.showSelectImageDialog = new ReactiveVar(false);
|
||||
|
||||
this.saveChanges = function(ask) {
|
||||
let data = this.$('.editor').val();
|
||||
let template = this;
|
||||
|
||||
//Only ask the user if they want to update their changes if they actually have changes that have not yet been saved.
|
||||
if(data !== template.currentHtml) {
|
||||
const changedData = data;
|
||||
|
||||
//Ensure this does not get run twice.
|
||||
template.currentHtml = changedData;
|
||||
|
||||
if(ask) {
|
||||
//Ask the user if they want to update the repository with their changes.
|
||||
swal({
|
||||
title: "Save Changes",
|
||||
text: "Would you like to save any changes you have made to this page?",
|
||||
type: "question",
|
||||
showCancelButton: true,
|
||||
confirmButtonColor: "#7cdd7f",
|
||||
confirmButtonText: "Yes",
|
||||
cancelButtonText: "No"
|
||||
}).then(
|
||||
function(isConfirm) {
|
||||
if(isConfirm) {
|
||||
Meteor.call('updateInternship', template.data.internship._id, changedData, function (error, result) {
|
||||
if (error) sAlert.error(error);
|
||||
else sAlert.success("Content Saved Successfully");
|
||||
});
|
||||
}
|
||||
},
|
||||
function(dismiss) {}
|
||||
);
|
||||
}
|
||||
else {
|
||||
Meteor.call('updateInternship', template.data.internship._id, changedData, function (error, result) {
|
||||
if (error) sAlert.error(error);
|
||||
else sAlert.success("Content Saved Successfully");
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
Template.InternshipHtmlEditor.onRendered(function() {
|
||||
let template = this;
|
||||
|
||||
$('.editor').tinymce({
|
||||
inline: true,
|
||||
menubar: false,
|
||||
theme: 'inlite',
|
||||
plugins: [
|
||||
'autolink',
|
||||
'contextmenu',
|
||||
'link',
|
||||
'lists',
|
||||
'table',
|
||||
'textcolor'
|
||||
],
|
||||
toolbar: [
|
||||
'undo redo | bold italic underline | fontselect fontsizeselect',
|
||||
'forecolor backcolor | alignleft aligncenter alignright alignfull | link unlink | numlist bullist outdent indent'
|
||||
],
|
||||
table_default_attributes: {
|
||||
border: 0,
|
||||
cellpadding: 4
|
||||
},
|
||||
table_default_styles: {
|
||||
borderCollapse: "collapse"
|
||||
},
|
||||
insert_toolbar: 'quicktable', //image
|
||||
selection_toolbar: 'bold italic | h1 h2 h3 | bullist numlist outdent indent | blockquote quicklink',
|
||||
contextmenu: 'InsertImage | inserttable | cell row column deletetable', //image
|
||||
contextmenu_never_use_native: false,
|
||||
|
||||
|
||||
setup: function(editor) {
|
||||
editor.addMenuItem('InsertImage', {
|
||||
text: "Insert Image",
|
||||
context: 'tools',
|
||||
onclick: function() {
|
||||
template.showSelectImageDialog.set(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
Tracker.autorun(function() {
|
||||
//let data = Template.currentData().data; //Note: Calling Template.currentData() is a reactive way to get the template parameters.
|
||||
let data = Blaze.getData(template.view).internship;
|
||||
|
||||
if(data) {
|
||||
template.currentHtml = data.content;
|
||||
$('.editor').html(data.content && data.content.length > 0 ? data.content : "Change Me!");
|
||||
}
|
||||
});
|
||||
});
|
||||
Template.InternshipHtmlEditor.onDestroyed(function() {
|
||||
this.saveChanges(true);
|
||||
});
|
||||
Template.InternshipHtmlEditor.events({
|
||||
'click #save': function(event, template) {
|
||||
template.saveChanges(false);
|
||||
}
|
||||
});
|
||||
Template.InternshipHtmlEditor.helpers({
|
||||
showSelectImageDialog() {
|
||||
return Template.instance().showSelectImageDialog.get();
|
||||
},
|
||||
selectImageDialogArgs() {
|
||||
let template = Template.instance();
|
||||
return {
|
||||
onApply(value) {
|
||||
tinymce.activeEditor.insertContent('<img src="' + value + '"/>');
|
||||
template.showSelectImageDialog.set(false);
|
||||
},
|
||||
onClose() {
|
||||
template.showSelectImageDialog.set(false);
|
||||
}
|
||||
};
|
||||
},
|
||||
showInstructions() {
|
||||
return !Template.currentData().internship;
|
||||
}
|
||||
});
|
||||
@@ -1,4 +0,0 @@
|
||||
<template name="InternshipsEditor">
|
||||
<div id="internshipsEditor">
|
||||
</div>
|
||||
</template>
|
||||
@@ -1,2 +0,0 @@
|
||||
#internshipsEditor
|
||||
display: block
|
||||
@@ -1,2 +0,0 @@
|
||||
|
||||
import './InternshipsEditor.html';
|
||||
@@ -1,7 +0,0 @@
|
||||
<template name="NewsEditor">
|
||||
<div id="newsEditor">
|
||||
<h1>News Editor</h1>
|
||||
<div class="editor"></div>
|
||||
<button id="save">Save</button>
|
||||
</div>
|
||||
</template>
|
||||
6
imports/ui/Admin/NewsEditor.import.styl
vendored
6
imports/ui/Admin/NewsEditor.import.styl
vendored
@@ -1,6 +0,0 @@
|
||||
#newsEditor
|
||||
display: block
|
||||
.ck.ck-editor__editable_inline
|
||||
border-color: rgba(0,0,0,.2)
|
||||
.ck.ck-editor__editable_inline.ck-focused
|
||||
border-color: rgba(0,0,0,1)
|
||||
@@ -1,86 +0,0 @@
|
||||
|
||||
import './NewsEditor.html';
|
||||
import swal from "sweetalert2";
|
||||
|
||||
let originalData = "";
|
||||
|
||||
Tracker.autorun(function() {
|
||||
Meteor.subscribe("pages");
|
||||
});
|
||||
|
||||
Template.NewsEditor.onRendered(function() {
|
||||
let _this = this;
|
||||
|
||||
//#appreciationEditor'
|
||||
// CKEditor.create(document.querySelector('#editor'), {}).then(editor => {
|
||||
// _this.ckEditor = editor;
|
||||
//
|
||||
// Tracker.autorun(function() {
|
||||
// let doc = Meteor.collections.Pages.findOne({name: 'Appreciation'});
|
||||
//
|
||||
// originalData = (doc === undefined ? "" : doc.html);
|
||||
// editor.setData(originalData);
|
||||
// });
|
||||
// }).catch(err => {
|
||||
// console.error(err);
|
||||
// });
|
||||
$('.editor').tinymce({
|
||||
inline: true
|
||||
});
|
||||
Tracker.autorun(function() {
|
||||
let doc = Meteor.collections.Pages.findOne({name: 'News'});
|
||||
|
||||
originalData = (doc === undefined ? "" : doc.html);
|
||||
$('.editor').html(originalData);
|
||||
});
|
||||
});
|
||||
|
||||
Template.NewsEditor.onDestroyed(function() {
|
||||
let data = this.ckEditor.getData();
|
||||
|
||||
if(data != originalData) {
|
||||
swal({
|
||||
title: "Save Changes",
|
||||
text: "Would you like to save any changes you have made to this sheet?",
|
||||
type: "question",
|
||||
showCancelButton: true,
|
||||
confirmButtonColor: "#7cdd7f",
|
||||
confirmButtonText: "Yes",
|
||||
cancelButtonText: "No"
|
||||
}).then(
|
||||
function(isConfirm) {
|
||||
if(isConfirm) {
|
||||
Meteor.call('updatePage', 'News', data, function (error, result) {
|
||||
if (error) sAlert.error(error);
|
||||
else sAlert.success("Content Saved Successfully");
|
||||
});
|
||||
}
|
||||
},
|
||||
function(dismiss) {}
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
Template.NewsEditor.helpers({
|
||||
// html: function() {
|
||||
// let doc = Meteor.collections.Pages.findOne({name: 'News'});
|
||||
//
|
||||
// return doc == undefined ? "" : doc.html;
|
||||
// }
|
||||
});
|
||||
|
||||
Template.NewsEditor.events({
|
||||
'click #save': function(event, template) {
|
||||
let data = template.ckEditor.getData();
|
||||
|
||||
if(data != originalData) {
|
||||
Meteor.call('updatePage', 'News', data, function (error, result) {
|
||||
if (error) sAlert.error(error);
|
||||
else sAlert.success("Content Saved Successfully");
|
||||
});
|
||||
}
|
||||
else {
|
||||
sAlert.success("Data has not changed!");
|
||||
}
|
||||
}
|
||||
});
|
||||
13
imports/ui/Admin/PageEditor.html
Normal file
13
imports/ui/Admin/PageEditor.html
Normal file
@@ -0,0 +1,13 @@
|
||||
<template name="PageEditor">
|
||||
<div id="pageEditor">
|
||||
{{#if showSelectImageDialog}}
|
||||
<div class="modalBackground">
|
||||
{{> SelectImageDialog (selectImageDialogArgs)}}
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
<h1>{{editorName}} Editor</h1>
|
||||
<div class="editor"></div>
|
||||
<button id="save">Save</button>
|
||||
</div>
|
||||
</template>
|
||||
226
imports/ui/Admin/PageEditor.js
Normal file
226
imports/ui/Admin/PageEditor.js
Normal file
@@ -0,0 +1,226 @@
|
||||
import './PageEditor.html';
|
||||
import '/imports/ui/dialogs/SelectImageDialog.js';
|
||||
import swal from "sweetalert2";
|
||||
|
||||
let currentHtml = "";
|
||||
let currentPath = "";
|
||||
|
||||
let routeData = {
|
||||
AppreciationEditor: {title: "Appreciation", name: "Appreciation"},
|
||||
NewsEditor: {title: "News", name: "News"},
|
||||
DatesEditor: {title: "Dates", name: "Dates"},
|
||||
BoardEditor: {title: "Current Board", name: "Board"},
|
||||
SlideshowPageEditor: {title: "Slideshow Page", name: "Slideshow"}
|
||||
};
|
||||
|
||||
Tracker.autorun(function() {
|
||||
//let name = routeData[FlowRouter.getRouteName()] ? routeData[FlowRouter.getRouteName()].name : "";
|
||||
|
||||
//if(name) {
|
||||
//TODO: Filter the page by the page name.
|
||||
Meteor.subscribe("pages");
|
||||
//}
|
||||
});
|
||||
|
||||
Template.PageEditor.onCreated(function() {
|
||||
let template = this;
|
||||
|
||||
this.showSelectImageDialog = new ReactiveVar(false);
|
||||
this.pageName = new ReactiveVar();
|
||||
|
||||
this.saveChanges = function() {
|
||||
if(currentPath && currentPath !== FlowRouter.getRouteName()) {
|
||||
let data = this.$('.editor').val();
|
||||
let template = this;
|
||||
|
||||
currentPath = FlowRouter.getRouteName();
|
||||
|
||||
//Only ask the user if they want to update their changes if they actually have changes that have not yet been saved.
|
||||
if(data !== currentHtml) {
|
||||
const changedData = data;
|
||||
|
||||
//Ensure this does not get run twice.
|
||||
currentHtml = data;
|
||||
|
||||
//Ask the user if they want to update the repository with their changes.
|
||||
swal({
|
||||
title: "Save Changes",
|
||||
text: "Would you like to save any changes you have made to this page?",
|
||||
type: "question",
|
||||
showCancelButton: true,
|
||||
confirmButtonColor: "#7cdd7f",
|
||||
confirmButtonText: "Yes",
|
||||
cancelButtonText: "No"
|
||||
}).then(
|
||||
function(isConfirm) {
|
||||
if(isConfirm) {
|
||||
Meteor.call('updatePage', template.pageName.get(), changedData, function (error, result) {
|
||||
if (error) sAlert.error(error);
|
||||
else sAlert.success("Content Saved Successfully");
|
||||
});
|
||||
}
|
||||
},
|
||||
function(dismiss) {}
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Tracker.autorun(function() {
|
||||
if(routeData[FlowRouter.getRouteName()]) {
|
||||
template.saveChanges();
|
||||
|
||||
//Save the page's name (indexes the page HTML in the collection) to the reactive variable so that all the content changes automatically.
|
||||
template.pageName.set(routeData[FlowRouter.getRouteName()].name);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
Template.PageEditor.onRendered(function() {
|
||||
let template = this;
|
||||
|
||||
$('.editor').tinymce({
|
||||
// inline: true,
|
||||
// menubar: false,
|
||||
// theme: 'inlite', //inlite
|
||||
// //skin: 'light',
|
||||
// plugins: [
|
||||
// 'autolink',
|
||||
// 'contextmenu',
|
||||
// 'link',
|
||||
//// 'linkchecker', Broken
|
||||
// 'lists',
|
||||
//// 'powerpaste', Broken
|
||||
// 'table',
|
||||
// //'image',
|
||||
// 'textcolor'
|
||||
// ],
|
||||
// toolbar: [
|
||||
// 'undo redo | bold italic underline | fontselect fontsizeselect',
|
||||
// 'forecolor backcolor | alignleft aligncenter alignright alignfull | link unlink | numlist bullist outdent indent | InsertImage | inserttable | cell row column deletetable'
|
||||
// ],
|
||||
// table_default_attributes: {
|
||||
// border: 0,
|
||||
// cellpadding: 4
|
||||
// },
|
||||
// table_default_styles: {
|
||||
// borderCollapse: "collapse"
|
||||
// },
|
||||
// insert_toolbar: 'quicktable', //image
|
||||
// selection_toolbar: 'bold italic | h1 h2 h3 | blockquote quicklink',
|
||||
// contextmenu: 'InsertImage | inserttable | cell row column deletetable', //image
|
||||
// contextmenu_never_use_native: false,
|
||||
|
||||
|
||||
|
||||
//image_advtab: true,
|
||||
//image_description: true,
|
||||
//image_dimensions: true,
|
||||
//image_title: true,
|
||||
//image_list: function(success) {
|
||||
// //Expects an array of objects containing title:String and value:String properties where the value is a path to the image.
|
||||
// Meteor.call('getGeneralImages', function(data, err) {
|
||||
// if(err) {
|
||||
// sAlert.error(err);
|
||||
// }
|
||||
// else {
|
||||
// success(data);
|
||||
// }
|
||||
// });
|
||||
//}
|
||||
//powerpaste_word_import: 'clean',
|
||||
//powerpaste_html_import: 'clean'
|
||||
|
||||
|
||||
inline: true,
|
||||
menubar: false,
|
||||
theme: 'inlite',
|
||||
plugins: [
|
||||
'autolink',
|
||||
'contextmenu',
|
||||
'link',
|
||||
'lists',
|
||||
'table',
|
||||
'textcolor'
|
||||
],
|
||||
toolbar: [
|
||||
'undo redo | bold italic underline | fontselect fontsizeselect',
|
||||
'forecolor backcolor | alignleft aligncenter alignright alignfull | link unlink | numlist bullist outdent indent'
|
||||
],
|
||||
table_default_attributes: {
|
||||
border: 0,
|
||||
cellpadding: 4
|
||||
},
|
||||
table_default_styles: {
|
||||
borderCollapse: "collapse"
|
||||
},
|
||||
insert_toolbar: 'quicktable', //image
|
||||
selection_toolbar: 'bold italic | h1 h2 h3 | blockquote quicklink',
|
||||
contextmenu: 'InsertImage | inserttable | cell row column deletetable', //image
|
||||
contextmenu_never_use_native: false,
|
||||
|
||||
|
||||
setup: function(editor) {
|
||||
editor.addMenuItem('InsertImage', {
|
||||
text: "Insert Image",
|
||||
context: 'tools',
|
||||
onclick: function() {
|
||||
template.showSelectImageDialog.set(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
Tracker.autorun(function() {
|
||||
let doc = Meteor.collections.Pages.findOne({name: template.pageName.get()});
|
||||
|
||||
currentHtml = (doc === undefined ? "" : doc.html);
|
||||
$('.editor').html(currentHtml);
|
||||
});
|
||||
});
|
||||
|
||||
Template.PageEditor.onDestroyed(function() {
|
||||
this.saveChanges();
|
||||
});
|
||||
|
||||
Template.PageEditor.events({
|
||||
'click #save': function(event, template) {
|
||||
let data = template.$('.editor').val();
|
||||
|
||||
if(data !== currentHtml) {
|
||||
Meteor.call('updatePage', template.pageName.get(), data, function (error, result) {
|
||||
if (error) sAlert.error(error);
|
||||
else {
|
||||
sAlert.success("Content Saved Successfully");
|
||||
//Ensure we recognize things were saved later.
|
||||
currentHtml = data;
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
sAlert.success("Data has not changed!");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Template.PageEditor.helpers({
|
||||
editorName() {
|
||||
return routeData[FlowRouter.getRouteName()].title; //FlowRouter.getRouteName() is reactive allowing this to trigger when the content changes.
|
||||
},
|
||||
showSelectImageDialog() {
|
||||
return Template.instance().showSelectImageDialog.get();
|
||||
},
|
||||
selectImageDialogArgs() {
|
||||
let template = Template.instance();
|
||||
return {
|
||||
onApply(value) {
|
||||
tinymce.activeEditor.insertContent('<img src="' + value + '"/>');
|
||||
template.showSelectImageDialog.set(false);
|
||||
},
|
||||
onClose() {
|
||||
template.showSelectImageDialog.set(false);
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
41
imports/ui/Admin/SlideshowEditor.html
Normal file
41
imports/ui/Admin/SlideshowEditor.html
Normal file
@@ -0,0 +1,41 @@
|
||||
<template name="SlideshowEditor">
|
||||
<div id="slideshowEditor">
|
||||
<h1>Slideshow Editor</h1>
|
||||
<div class="slideshowsGroup" style="vertical-align: bottom">
|
||||
<label class='controlLabel'>Selected Slideshow: </label>
|
||||
<select name="slideshows">
|
||||
{{#each slideshows}}
|
||||
<option value="{{_id}}">{{name}}</option>
|
||||
{{/each}}
|
||||
</select>
|
||||
<input type="text" name="newSlideshowName" class="newSlideshowName form-control"/><i class="fa fa-plus-circle createSlideshow noselect clickable" aria-hidden="true"></i>{{#if selectedSlideshow}}<i class="fa fa-trash deleteSlideshow noselect clickable" aria-hidden="true"></i>{{/if}}
|
||||
</div>
|
||||
{{#if selectedSlideshow}}
|
||||
{{> SlideshowContentEditor selectedSlideshow._id}}
|
||||
{{/if}}
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template name="SlideshowContentEditor">
|
||||
<div id="slideshowContentEditor">
|
||||
{{#if showSelectImageDialog}}
|
||||
<div class="modalBackground">
|
||||
{{> SelectImageDialog (selectImageDialogArgs)}}
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
{{#each slides}}
|
||||
<div class="slideThumbnail" style="background-image: url('/slideshow-image/{{this}}')" data-image-id="{{this}}">
|
||||
<div class="controls">
|
||||
<i class="fa fa-angle-double-left moveLeft noselect clickable" aria-hidden="true">
|
||||
</i><i class="fa fa-times removeThumbnail noselect clickable" aria-hidden="true">
|
||||
</i><i class="fa fa-angle-double-right moveRight noselect clickable" aria-hidden="true"></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--<p>{{this}}</p>-->
|
||||
{{/each}}
|
||||
<div class="addSlide noselect clickable" style='background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMzAwcHgiIHdpZHRoPSIzMDBweCIgZmlsbD0iIzAwMDAwMCIgdmVyc2lvbj0iMS4xIiB4PSIwcHgiIHk9IjBweCIgdmlld0JveD0iMCAwIDEzOSAxMzkiIGVuYWJsZS1iYWNrZ3JvdW5kPSJuZXcgMCAwIDEzOSAxMzkiIHhtbDpzcGFjZT0icHJlc2VydmUiIGlkPSJzdmcxMCI+IDxkZWZzIGlkPSJkZWZzMTQiIC8+PHBhdGggZD0iTTY5LjQ5OSw4LjYxOWMtMzMuNTQzLDAtNjAuODMzLDI3LjI5LTYwLjgzMyw2MC44MzRjMCwzMy41NDUsMjcuMjksNjAuODM1LDYwLjgzMyw2MC44MzUgIGMzMy41NDUsMCw2MC44MzYtMjcuMjksNjAuODM2LTYwLjgzNUMxMzAuMzM1LDM1LjkwOSwxMDMuMDQ0LDguNjE5LDY5LjQ5OSw4LjYxOXogTTY5LjQ5OSwxMjQuMjg4ICBjLTMwLjIzNSwwLTU0LjgzMy0yNC41OTktNTQuODMzLTU0LjgzNWMwLTMwLjIzNSwyNC41OTgtNTQuODM0LDU0LjgzMy01NC44MzRjMzAuMjM2LDAsNTQuODM2LDI0LjU5OSw1NC44MzYsNTQuODM0ICBDMTI0LjMzNSw5OS42ODksOTkuNzM1LDEyNC4yODgsNjkuNDk5LDEyNC4yODh6IiBpZD0icGF0aDIiIC8+PHBhdGggZD0iTSA4NS42NCw5NS42OCA4NC4xMTk3MTgsOTIuNTM1ODQ4IDQyLjYzNiw5Mi42Mzk5NjYgNDIuNjM2LDQ2LjI1NiBIIDk2LjMwMyBWIDcyLjMyIGggMi4zNyA0LjE2MiBWIDQyLjYgYyAwLC0xLjUzNCAtMS4yNDMsLTIuNzc3IC0yLjc3OCwtMi43NzcgSCAzOC45NDUgYyAtMS41MzUsMCAtMi43NzgsMS4yNDMgLTIuNzc4LDIuNzc3IHYgNTMuNzA1IGMgMCwxLjUzNCAxLjI0MywyLjc3NyAyLjc3OCwyLjc3NyBIIDk0LjY3MyBWIDk1LjY4IEggODkuNjQgWiIgaWQ9InBhdGg0Ii8+PHBvbHlnb24gcG9pbnRzPSIxMDQuOTk5LDc2LjMyIDEwMi44MzUsNzYuMzIgOTguNjczLDc2LjMyIDk4LjY3Myw4NS4zNTMgODkuNjQsODUuMzUzIDg5LjY0LDkxLjY4IDk4LjY3Myw5MS42OCA5OC42NzMsOTkuMDgzIDk4LjY3MywxMDAuNzEyIDEwNC45OTksMTAwLjcxMiAxMDQuOTk5LDkxLjY4IDExNC4wMzEsOTEuNjggMTE0LjAzMSw4NS4zNTMgMTA0Ljk5OSw4NS4zNTMgIiBpZD0icG9seWdvbjYiIHRyYW5zZm9ybT0ibWF0cml4KDEuMDM0MTQ4NiwwLDAsMS4wMzQxNDg2LC01LjcwMDk4OCwtMS45NzI4ODk2KSIgLz48Y2lyY2xlIGN4PSI2Mi42MTM1NzkiIGN5PSI2NC42NDAyMjgiIHI9IjUuNzQ4MDAwMSIgaWQ9ImNpcmNsZTgiIHN0eWxlPSJmaWxsOiNmZWM5NDE7ZmlsbC1vcGFjaXR5OjEiIC8+PHBhdGggc3R5bGU9ImZpbGw6IzU0NDgwMDtmaWxsLW9wYWNpdHk6MTtmaWxsLXJ1bGU6ZXZlbm9kZDtzdHJva2U6bm9uZTtzdHJva2Utd2lkdGg6MC40NjMzMzMzNHB4O3N0cm9rZS1saW5lY2FwOmJ1dHQ7c3Ryb2tlLWxpbmVqb2luOm1pdGVyO3N0cm9rZS1vcGFjaXR5OjEiIGQ9Im0gNDcuMDYxNTQ5LDg3LjE0ODk5OSBjIDAsMCA1LjU2NTY4OSwtMjQuMzkzMzg5IDcuODA4ODg2LC0yNC41NzE5NjQgMi4yNDMxOTcsLTAuMTc4NTc1IDcuMzkyNDE0LDkuODkxMjU5IDcuMzkyNDE0LDkuODkxMjU5IDAsMCAyLjI5MTI1MiwtMy44OTYwMTYgMy41NDAwMjksLTMuNTQwMDI5IDEuMjQ4Nzc3LDAuMzU1OTg3IDYuOTcwMTMzLDcuOTQ5ODkgOC4xMjEyNDEsOC42NDE4MzQgMS4xNTExMDgsMC42OTE5NDQgMy41NzYxMjksLTIuNzc5NjQ0IDUuNzI2NTE0LC0zLjEyMzU1NiAyLjE1MDM4NSwtMC4zNDM5MTIgNy40OTY1MzMsOC4wMTcxMjUgNy40OTY1MzMsOC4wMTcxMjUgaCAtMS44NzcyIGwgLTEuNzY2OTQ5LDQuNzg5NDQ2IHoiIGlkPSJwYXRoODIzIi8+PC9zdmc+");'></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
108
imports/ui/Admin/SlideshowEditor.import.styl
vendored
Normal file
108
imports/ui/Admin/SlideshowEditor.import.styl
vendored
Normal file
@@ -0,0 +1,108 @@
|
||||
#slideshowEditor
|
||||
display: block
|
||||
|
||||
select[name='slideshows']
|
||||
font-size: 1.5em
|
||||
min-width: 100px
|
||||
input[name="newSlideshowName"]
|
||||
display: inline-block
|
||||
transition: all .75s ease
|
||||
width: 0
|
||||
border: 0
|
||||
opacity: 0
|
||||
font-size: 1.2em
|
||||
input[name="newSlideshowName"].show
|
||||
opacity: 1
|
||||
border: 1px solid #ccc
|
||||
border-radius: 4px
|
||||
width: 200px
|
||||
transform: translateX(4px)
|
||||
.createSlideshow
|
||||
display: inline-block
|
||||
padding: 2px 6px
|
||||
margin: 0 4px
|
||||
//width: 33px
|
||||
text-align: center
|
||||
font-size: 1.5em
|
||||
line-height: 1.5em
|
||||
border-radius: 8px
|
||||
//border: 1px solid rgba(0, 0, 0, 0)
|
||||
box-sizing: border-box
|
||||
.createSlideshow:hover
|
||||
//border: 1px inset #b100d1
|
||||
//-webkit-box-shadow: inset 0px 0px 20px 0px #de7cff
|
||||
//-moz-box-shadow: inset 0px 0px 20px 0px #de7cff
|
||||
//box-shadow: inset 0px 0px 20px 0px #de7cff
|
||||
color: #5c8744
|
||||
.createSlideshow
|
||||
transform: translateX(-25px) rotate(0deg)
|
||||
transition: all .75s ease
|
||||
.createSlideshow.move
|
||||
transform: translateX(6px) rotate(720deg)
|
||||
.deleteSlideshow
|
||||
display: inline-block
|
||||
padding: 2px 3px
|
||||
margin: 0 4px
|
||||
width: 1.5em
|
||||
line-height: 1.5em
|
||||
//width: 33px
|
||||
text-align: center
|
||||
font-size: 1.5em
|
||||
border-radius: 50%
|
||||
//border: 1px solid #8c0000
|
||||
box-sizing: border-box
|
||||
color: black
|
||||
.deleteSlideshow:hover
|
||||
color: #8c2353
|
||||
.addSlide
|
||||
display:inline-block
|
||||
width: 200px
|
||||
height: 200px
|
||||
background-size: contain
|
||||
background-repeat: no-repeat
|
||||
border-radius: 6px
|
||||
border 3px dashed black
|
||||
.addSlide:hover
|
||||
border-color: #5c8744
|
||||
.slideThumbnail
|
||||
position: relative
|
||||
width: 200px
|
||||
height: 200px
|
||||
background-position: 50% 50%
|
||||
background-repeat:no-repeat
|
||||
background-size: contain
|
||||
display: inline-block
|
||||
.controls
|
||||
position: absolute
|
||||
bottom: 50%
|
||||
left: 50%
|
||||
right: 50%
|
||||
top: 50%
|
||||
height: 22px
|
||||
width: 90px
|
||||
margin-left: -45px
|
||||
margin-top: -10px
|
||||
background-color: rgba(0, 0, 0, .8)
|
||||
display: none
|
||||
text-align: center
|
||||
font-size: 20px
|
||||
line-height: 20px
|
||||
border-radius: 8px
|
||||
border: 1px solid black
|
||||
.slideThumbnail:hover > .controls, .controls:hover
|
||||
display: block
|
||||
.moveLeft, .moveRight, .removeThumbnail
|
||||
color: white
|
||||
padding: 0 4px
|
||||
.moveLeft
|
||||
padding-right: 14px
|
||||
.moveRight
|
||||
padding-left: 14px
|
||||
.moveLeft:hover, .moveRight:hover
|
||||
color: #00ff55
|
||||
.moveLeft:active, .moveRight:active
|
||||
color: #006e27
|
||||
.removeThumbnail:hover
|
||||
color: #ff0019
|
||||
.removeThumbnail:active
|
||||
color: #57000c
|
||||
213
imports/ui/Admin/SlideshowEditor.js
Normal file
213
imports/ui/Admin/SlideshowEditor.js
Normal file
@@ -0,0 +1,213 @@
|
||||
|
||||
import './SlideshowEditor.html';
|
||||
import '/imports/ui/dialogs/SelectImageDialog.js';
|
||||
import swal from "sweetalert2";
|
||||
|
||||
const PREFIX = "SlideshowEditor_";
|
||||
|
||||
Tracker.autorun(function() {
|
||||
Meteor.subscribe("slideshow");
|
||||
});
|
||||
|
||||
Template.SlideshowEditor.onCreated(function() {
|
||||
this.slideshows = Meteor.collections.Slideshow.find({}, {sort: {name: 1}});
|
||||
Session.set(PREFIX + 'selectedSlideshow', null);
|
||||
});
|
||||
|
||||
Template.SlideshowEditor.onRendered(function() {
|
||||
let _this = this;
|
||||
|
||||
Tracker.autorun(function() {
|
||||
//This is a reactive call, allowing this function to be re-run when the cursor changes.
|
||||
let slideshows = _this.slideshows.fetch();
|
||||
|
||||
if(slideshows.length > 0 && !Session.get(PREFIX + "selectedSlideshow")) {
|
||||
//Mark the first slideshow as selected because it will be selected in the UI by default.
|
||||
Session.set(PREFIX + "selectedSlideshow", slideshows[0]);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
Template.SlideshowEditor.onDestroyed(function() {
|
||||
|
||||
});
|
||||
|
||||
Template.SlideshowEditor.helpers({
|
||||
slideshows: function() {
|
||||
return Template.instance().slideshows;
|
||||
},
|
||||
selectedSlideshow: function(){
|
||||
return Session.get(PREFIX + "selectedSlideshow");
|
||||
},
|
||||
isSlideshowSelected: function() {
|
||||
let selectedSlideshow = Session.get(PREFIX + "selectedSlideshow");
|
||||
|
||||
return selectedSlideshow == this ? "selected" : "";
|
||||
},
|
||||
hasSelectedSlideshow: function() {
|
||||
return Session.get(PREFIX + "selectedSlideshow");
|
||||
}
|
||||
});
|
||||
|
||||
Template.SlideshowEditor.events({
|
||||
'change select[name="slideshows"]': function(event, template) {
|
||||
let slideshowId = $(event.target).val();
|
||||
let slideshow = Meteor.collections.Slideshow.findOne(slideshowId);
|
||||
|
||||
Session.set(PREFIX + 'selectedSlideshow', slideshow);
|
||||
},
|
||||
"keyup input[name='newSlideshowName']" : function(event, template) {
|
||||
if(event.keyCode === 13) {
|
||||
event.preventDefault();
|
||||
$('.createSlideshow').trigger('click');
|
||||
}
|
||||
},
|
||||
"click .createSlideshow": function(event, template) {
|
||||
let $input = template.$('input[name="newSlideshowName"]');
|
||||
|
||||
if($input.hasClass('show')) {
|
||||
let name = $input.val();
|
||||
|
||||
name = name ? name.trim() : undefined;
|
||||
name = name && name.length > 0 ? name : undefined;
|
||||
|
||||
if(name) {
|
||||
Meteor.call('addSlideshow', name, function(error, id) {
|
||||
if(error) sAlert.error("Failed to create the slideshow!\n" + error);
|
||||
else {
|
||||
//Clear the text editor.
|
||||
$input.val("");
|
||||
|
||||
//Quick hack to attempt to allow the slideshow we created to be added to the select box before we try to select it and edit it.
|
||||
let count = 0;
|
||||
let interval = setInterval(function() {
|
||||
let selected = Meteor.collections.Slideshow.findOne(id);
|
||||
|
||||
if(selected) {
|
||||
//Select the sheet in the drop down.
|
||||
template.$('select[name="slideshows"]').val(id);
|
||||
Session.set(PREFIX + "selectedSlideshow", selected);
|
||||
clearInterval(interval);
|
||||
}
|
||||
else count++;
|
||||
|
||||
//Avoid infinite loop that should never happen.
|
||||
if(count > 100) clearInterval(interval);
|
||||
}, 100);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$input.removeClass('show');
|
||||
$(event.target).toggleClass('move');
|
||||
template.$('.deleteSlideshow').show();
|
||||
}
|
||||
else {
|
||||
$input.addClass('show');
|
||||
$(event.target).toggleClass('move');
|
||||
$input.focus();
|
||||
template.$('.deleteSlideshow').hide();
|
||||
}
|
||||
},
|
||||
"click .deleteSlideshow": function(event, template) {
|
||||
let $combo = template.$('select[name="slideshows"]');
|
||||
let slideshow = Session.get(PREFIX + 'selectedSlideshow');
|
||||
|
||||
if(slideshow) {
|
||||
swal({
|
||||
title: 'Are you sure?',
|
||||
text: "You won't be able to revert this!",
|
||||
type: 'warning',
|
||||
showCancelButton: true,
|
||||
confirmButtonColor: '#3085d6',
|
||||
cancelButtonColor: '#d33',
|
||||
confirmButtonText: 'Yes, delete it!'
|
||||
}).then((result) => {
|
||||
Meteor.call('removeSlideshow', slideshow._id, function(error, id) {
|
||||
if(error) sAlert.error("Failed to remove the slideshow!\n" + error);
|
||||
else {
|
||||
sAlert.success("Slideshow removed.");
|
||||
//Fire the event so that our selection changes once the slideshow is removed from the combo.
|
||||
$combo.trigger('change');
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Template.SlideshowContentEditor.onCreated(function() {
|
||||
this.showSelectImageDialog = new ReactiveVar(false);
|
||||
});
|
||||
Template.SlideshowContentEditor.helpers({
|
||||
showSelectImageDialog: function() {
|
||||
return Template.instance().showSelectImageDialog.get();
|
||||
},
|
||||
slides: function() {
|
||||
return Meteor.collections.Slideshow.findOne(Template.instance().data).images;
|
||||
},
|
||||
selectImageDialogArgs() {
|
||||
let template = Template.instance();
|
||||
|
||||
return {
|
||||
onApply(data) {
|
||||
//tinymce.activeEditor.insertContent('<img src="' + value + '"/>');
|
||||
template.showSelectImageDialog.set(false);
|
||||
//Send the slide image as a base64 string.
|
||||
Meteor.call('addSlideshowImage', template.data, data, function(error, id) {
|
||||
if(error) sAlert.error("Failed to add the slide.\n" + error);
|
||||
else {
|
||||
//TODO: ?
|
||||
}
|
||||
});
|
||||
},
|
||||
onClose() {
|
||||
template.showSelectImageDialog.set(false);
|
||||
}
|
||||
};
|
||||
}
|
||||
//getImage(id) {
|
||||
// Meteor.call('getSlideshowImage', id, function(error, base64)) {
|
||||
// if(error) sAlert.error("Failed to get the slide image.\n" + error);
|
||||
// else {
|
||||
//
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
});
|
||||
Template.SlideshowContentEditor.events({
|
||||
"click .addSlide": function(event, template) {
|
||||
template.showSelectImageDialog.set(true);
|
||||
},
|
||||
'click .moveLeft': function(event, template) {
|
||||
let $slideThumbnail = $(event.target).parent().parent();
|
||||
let index = $slideThumbnail.index();
|
||||
|
||||
//If we can move it to the right then do so.
|
||||
if(index - 1 >= 0) {
|
||||
Meteor.call('swapSlideshowImages', template.data, index, index - 1, function(error) {
|
||||
if(error) sAlert.error("Failed to move the slide.\n" + error);
|
||||
});
|
||||
}
|
||||
},
|
||||
'click .moveRight': function(event, template) {
|
||||
let $slideThumbnail = $(event.target).parent().parent();
|
||||
let index = $slideThumbnail.index();
|
||||
let thumbnailCount = $slideThumbnail.siblings().length; //Should give us the number of siblings including the add image button (we don't want to count it), and excluding this slide thumbnail (we do want to count it).
|
||||
|
||||
//If we can move it to the right then do so.
|
||||
if(index + 1 < thumbnailCount) {
|
||||
Meteor.call('swapSlideshowImages', template.data, index, index + 1, function(error) {
|
||||
if(error) sAlert.error("Failed to move the slide.\n" + error);
|
||||
});
|
||||
}
|
||||
},
|
||||
'click .removeThumbnail': function(event, template) {
|
||||
let $slideThumbnail = $(event.target).parent().parent();
|
||||
let imageId = $slideThumbnail.data("image-id");
|
||||
|
||||
Meteor.call('removeSlideshowImage', template.data, imageId, function(error) {
|
||||
if(error) sAlert.error("Failed to remove the slide.\n" + error);
|
||||
});
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user