Altering Feedback.js to send info & picture to an email address - javascript

I recently stumbled upon some really cool js which renders a screenshot with a highlighted area for feedback on your website. The website for this program can be found here: http://experiments.hertzen.com/jsfeedback/
However, I'd really like to get it to send an email (to an address of my choosing) once the data is collected instead of whatever it is doing now. I've been looking through it and I'm assuming it would be done in the feedback.js file under
send: function( adapter ) {
However, I'm not entirely sure how to change what is there to keep the screenshot and data.

When you initialize Feedback(), you can set some options.
In your case the url option is important. This url should point to a php script which uses the $_POST[] data send by feedback.js.
After you got all the data you can send it in an email with php.
Here is an example how to set some options:
Feedback({
label: 'What is your problem',
header: 'Report an issue',
nextLabel: 'Next',
reviewLabel: 'Review screenshot',
sendLabel: 'Send email',
closeLabel: 'Cancel',
messageSuccess: 'Done!',
messageError: 'Oops..',
url: 'path/to/email/sendFeedback.php' // This is what you need
});
In the sendFeedback.php file you should do something like te following
if($_POST) {
$image = $_POST['data'];
$otherField = $_POST['your-other-field'];
// Send email here
}
$_POST['data'] will hold the image as a DOMString.
Other input field values are in other parameters depending on which other fields you define.
In php there are many ways to send emails.
mail() is just one of them. Info can be found at php.net..

Related

When I add "METHOD: REQUEST" to iCalendar, Gmail stops recognizing as event

I'm using iCalendar to schedule events for Gmail users. However, I want to be able to send updates, if/when the event changes. I read that I must use METHOD:REQUEST in order to allow updates.
However, when I add the METHOD:REQUEST to my ics file, Gmail stops recognizing it as a calendar invite.
Here is the working example WITHOUT "METHOD:REQUEST"
BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Cratic//Cratic Huddle//EN
NAME:Cratic Huddle
X-WR-CALNAME:Cratic Huddle
TIMEZONE-ID:Europe/Berlin
X-WR-TIMEZONE:Europe/Berlin
BEGIN:VEVENT
UID:60212c8395841f2cd057864f#cratic.ai
SEQUENCE:0
DTSTAMP:20210208T130601Z
DTSTART:20210219T133059Z
DTEND:20210219T140059Z
SUMMARY:Cratic Huddle
DESCRIPTION:This is the information
ORGANIZER;CN="Izzi":mailto:firstname.lastname#gmail.com
ATTENDEE;ROLE=REQ-PARTICIPANT:MAILTO:firstname.lastname#gmail.com
BEGIN:VALARM
ACTION:DISPLAY
TRIGGER:-PT15M
DESCRIPTION:Cratic Huddle
END:VALARM
BEGIN:VALARM
ACTION:AUDIO
TRIGGER:-PT15M
ATTACH;VALUE=URI:Basso
END:VALARM
URL;VALUE=URI:cratic.ai
END:VEVENT
END:VCALENDAR
The above works perfectly; Gmail pops up with a button asking if I want to accept.
Here is the NOT working example WITH "METHOD:REQUEST"
BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Cratic//Cratic Huddle//EN
METHOD:REQUEST
NAME:Cratic Huddle
X-WR-CALNAME:Cratic Huddle
TIMEZONE-ID:Europe/Berlin
X-WR-TIMEZONE:Europe/Berlin
BEGIN:VEVENT
UID:60212c8395841f2cd057864f#cratic.ai
SEQUENCE:0
DTSTAMP:20210208T125937Z
DTSTART:20210219T133059Z
DTEND:20210219T140059Z
SUMMARY:Cratic Huddle
DESCRIPTION:This is the information
ORGANIZER;CN="Izzi":mailto:firstname.lastname#gmail.com
ATTENDEE;ROLE=REQ-PARTICIPANT:MAILTO:firstname.lastname#gmail.com
BEGIN:VALARM
ACTION:DISPLAY
TRIGGER:-PT15M
DESCRIPTION:Cratic Huddle
END:VALARM
BEGIN:VALARM
ACTION:AUDIO
TRIGGER:-PT15M
ATTACH;VALUE=URI:Basso
END:VALARM
URL;VALUE=URI:cratic.ai
END:VEVENT
END:VCALENDAR
This generates a blank email in google, with the .ics file attached. It does not appear in the calendar or anywhere else.
These two iCalendar files are identical in every other way. But for some reason adding the METHOD:REQUEST is killing the ics file / google's ability to read it.
Why??
Ok - After many hours of reading RFC5546, Stackoverflow, and many other blogs, I finally have the answers.
Scope:
Sending calendar invites to Gmail / Outlook / Privateemail (namecheap's email client)
Email clients automatically recognizing .ics files and generating "accept" templates
Events automatically appearing in client calendars as "tentative"
Sending event revisions that automatically move client calendar events
There are two fundamental principles that are critical to making this work:
The contents of the .ics file must very closely match the .ics file of the Gmail / Outlook community, this includes the parameters and the order of the parameters.
The way the .ics file is attached to the email transmission is odd but critical: (a) the .ics file must be turned into 'base64', and (b) the headers of the file need to give a type: 'text/calendar;method=REQUEST;name="file.ics"'
Below I will give examples of each, which I hope save others time on this process.
.ics Content Example:
let iCal =
`BEGIN:VCALENDAR
PRODID:-//Cratic//_Scheduler//EN
VERSION:2.0
CALSCALE:GREGORIAN
METHOD:REQUEST
BEGIN:VEVENT
DTSTART:${DTStart}
DTEND:${DTEnd}
DTSTAMP:${DTStamp}
ORGANIZER;CN=name:mailto:name#gmail.com
UID:${event._id}#url.com
ATTENDEE;CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN=name#outlook.com;X-NUM-GUESTS=0:mailto:name#outlook.com
CREATED:${DTStamp}
DESCRIPTION:${event.body}
LAST-MODIFIED:${DTStamp}
LOCATION:${location}
SEQUENCE:${sequence}
STATUS:CONFIRMED
SUMMARY:${event.title}
TRANSP:OPAQUE
END:VEVENT
END:VCALENDAR`
Please note: the above ordering is very important! And you must have no dead spaces around the text, even one extra space before or after will disrupt the email client. Also, this is a reusable dynamic iCal event template, as long as I keep a record of the event._id, I can use that _id to send revisions to all my clients.
Attaching .ics to Email Client:
// convert the invite to be base64 for attachment
const buf = Buffer.from(iCal.toString(), 'utf-8');
const base64Cal = buf.toString('base64');
// build the email
const sendEmail = async () => {
const res = await client.transmissions.send({
recipients: [{ address: 'name#outlook.com' }],
content: {
from: 'name#sparkmail.com',
subject: req.body.a.title,
text: req.body.a.body,
attachments: [
{
name: 'invite.ics',
type: 'text/calendar;method=REQUEST;name=\"invite.ics\"',
data: base64Cal,
},
],
},
options: { sandbox: false },
});
}
// send the email
sendEmail();
Please note: The attachment type is critical for Outlook to recognize the event.
Although I'm sure there are other / better ways to integrate with these services, I found the above steps allowed me to accomplish my scope.

Update a OnDemandGrid based on dstore/Rest result in POST and not PUT

I am puzzled.
I have an OnDemandGrid editable, and under it i have a dstore/Rest collection pointing to my backend (in PHP).
The OnDemandGrid is mixed with the Editor... I can edit my data, but i cannot save it. What i receive on the server side is a "POST" request to insert a full row in the collection... And i never recieve the update.
Should'nt i receive a PUT request instead? I am using id's in the data...
This is the client-side part:
function (...)
{
var EditGrid = declare([ OnDemandGrid, Keyboard, Editor ]);
var coll = new Rest({
target: 'my.php/x/',
idProperty: 'id',
rangeStartParam: 'range',
rangeCountParam: 'limit',
sortParam: 'sort'
});
var grid = new EditGrid({ columns: {
user_name:{
label: 'User name',
editor: 'text',
editOn: 'click, dbclick',
autoSave: true,
}},
collection: coll }, 'grid' );
grid.startup();
}
I correctly receive the GET query to populate the table... Then, after editing a row and hitting "return", i get a POST!
The server side is a bit more complex to show here... Basically, on GET i do an SQL query and json-ize the results, while on POST i just return this:
http_response_code(201);
header("location: ".$_SERVER['PATH_INFO'].$id);
Where $id is the same ID i received from the request...
After the POST, i don't receive anything else. And in the POST data, i only ever receive a copy of the old, not modified, row... I never receive the "new" edited data.
It seems to me i should receive a PUT request at some point... I tried the browser debugger, server logs, nothing anywhere.
Can anybody help me out here?
I finally fixed it.
It's very convoluted and very little documented all this mess. I had to dig into the browser debugger and dgrid/Rest source code a bit.
So the problem was all in my REST backend. It turns out dgrid does a GET before the PUT/POST requesting the item to be modified, and it does a GET with only one record by asking for the specific "id". It make sense.
Well, my backend would return an ARRAY with one element in it, in JSON format. This was the error! This is not properly parsed by dgrid and it led to the POST instead of PUT.
Once i fixed the GET backend to return a single JSON item instead of an array with one JSON item inside, dgrid started sending the correct PUTs.

How to create append an array to a json value using (js/node/express)

I'm trying to re-create a CRUD app in NodeJs that I did using php/mysql etc, that takes a users form information and stores it in a file called "sample-data.json".
Essentially, with NodeJs a user fills in a form, front-end JS takes that info, passes it along to an api route I set up, and then using FS, writes that info to the sample-data.json file etc.
With the code below, once a users hits submit on the form, the code takes that info, and passes it to the "sampledataapi" route.
$("#createTodoForm").submit(function(evt){
evt.preventDefault();
$.post("/sampledataapi",{
todoCompany : $("#todoTitle").val(),
thisTodoIsFor : $("#todoIsFor").val(),
todoPostedBy : $("#todoPostedBy").val(),
todoCompleted : $("#todoCompleted").val(),
todoPriority : $("#todoPriority").val(),
todoMessages : $("#todoFirstMessage").val()
}, showDataGotten );
});
Once it saves the data, my sample-data.json file which initially has an empty array inside of it, then gets populated with info.
So sample-data.json goes from this: []
To this(once data has been entered):
[
{
"todoCompany":"sample company",
"thisTodoIsFor":"todo is for me",
"todoPostedBy":"admin",
"todoCompleted":"no",
"todoPriority":"green",
"todoMessages" : "sample message"
}
]
Now when I do this, all works fine but I run into problems when I want to have "todoMessages" be an array from the get go. Reason is that once the user posts their data, they will have the ability to erase/add messages from that block.
So I need that when the user submits the data, instead of that "todoMessages" being a regular string, I want it to be like this:
"todoMessages" : [ "sample message" ]
This way, I can push info into it OR delete from it etc.
How can I make it so that when the user creates his data, and the data passes the info to the route/json file, that it automatically creates todoMessages as an array?
I have tried (on front end)
todoMessages : [$("#todoFirstMessage").val()]
but then the front end reads "undefined"
and the backend json has this:
"todoMessages[]":"sample message"

Possible ways to send huge amount of data to PHP server

I have a step form in a project that handles a lot of data. To prevent errors during creation, all information is stored client-side, and in the end, is sent to the server.
the information sent to the server looks like this:
{
name: "project1",
decription: "lot of text",
schedule:[{weekDay:1, startHour:"09:00", endHour:"15:00"}, ...]
tasks:["task1", "task2"... until 20/30],
files:[{file1}, {file2}, ...],
services:[{
name: "service1",
decription: "lot of text",
schedule:[{weekDay:1, startHour:"09:00", endHour:"15:00"}, ...]
tasks:["task1", "task2"... until 20/30],
files:[{file1}, {file2}, ...],
jobs:[{
name: "job1",
decription: "lot of text",
schedule:[{weekDay:1, startHour:"09:00", endHour:"15:00"}, ...]
tasks:["task1", "task2"... until 20/30],
files:[{file1}, {file2}, ...]
},{
name: "job2",
}
]
...
},{
name:"service2",
...
}
}
And so on..
This is a really reduced example, in a real enviroment there will be 1 project with about 10-15 services, each one with 4-5 jobs.
I have been able to process everything with about 15 items in the last level, and now I´m trying to preprocess data to delete objects not neeeded in the server before send, and with that I expect to be able to send over 50 items in the last level without triggering "max_input_variables exceeded xxx" server side. But still, will be very close to the limit in some cases.
I´m thinking about changing the way I send/receive data, but I´m not sure if my guesses are even correct.
Before some suggest a json request to prevent the input variables error, the request has to bee multipart/form-data to send files.
Said that, my guesses were the following:
Mount all the data as json in a single variable and keep the files in separated variables ( formData would look like {project:{hugeJSON}, files:[file1, file2], services:[{files:[...]}, {files:[...]}] } )
Send partial data during the form fill to the server and store it somewhere, (a tmp file would be my best bet) and in the last step, send only the main form information.
Probably a stupid guess, but is there something like sending chunked data? Ideally, I would like to show to the user a loading bar saying "Creating project--> Saving Service nº1 --> Generating Docs for Service 1..." I think that I could achieve this making my server-side script generate a chunked reponse, but not sure about that.
Well, any help that could show me the correct way would be really appreciated.
Tank you in advance.
Once you are finished filling your object, you should stringify it and send it to the server as a post parameter.
Once you receive it serverside, you can parse JSON and continue working.

Posting data via js/jQuery

I am really new to Javascript and its many brilliant libraries, I find even the most simple scripts hard to perform.
I do want to learn this language, because it would be powerful for creating client websites, however at the moment I am trying to do something relatively simple, this is to flag a personal message on my site. There are many messages in a big list, and what I am looking at doing is when the user clicks the "Flag PM" image, it will run flag.php in the background which will change the flag field in MySQL from 0 to 1.
This script is all dependant on one field, that is id so I can run this through the database. Anyway, here is my code;
flag.php
require('_inc/_core/core.php'); // inc core_funcs for sql & clean
$pm_id = clean($_POST['p_id']); // create new variable, clean the post
echo "The ID for the PM is " . $pm_id;
mysql_query("UPDATE `messages` SET `flag_status` = 1 WHERE `id` = {$pm_id}"); // update the db
JS/jQuery
// Flag a Personal Message
$("#flagPM").submit(function(event) {
event.preventDefault();
$.post("flag.php", { p_id: pm_id } );
alert(event);
});
HTML handling the form
<form action="#" id="flagPM"><input type="hidden" id="pm_id" value="$id" />
<input type="submit" class="submit" value="FLAG" /></form>
So there is a hidden input field named pm_id that contains what I want posted.
Would really appreciate some help, the Javascript is being run from an independent file that is two directory's up from flag.php
Thank you
the Javascript is being run from an independent file that is two
directory's up from flag.php
In that case simply doing:
$.post("flag.php", { id: id } );
wont reach the flag.php file, you need to specify correct path including folder names that you mentioned:
$.post("folder1/folder2/flag.php", { id: id } );
By the way, you should use a callback for the $.post function to know what message is returned by flag.php:
$.post("flag.php", { id: id }, function(data){
alert(data);
} );
From your flag.php, make sure to echo something so that you get that response in your ajax handler:
// your other code here, such as query, etc
echo 'whatever...';

Categories

Resources