NodeJS ReactJS, NOT using Isomorphic-fetch, using jQuery JSONP GET -> Oracle Service Cloud Article Feedback ci/ajaxCustom Endpoint
app.js
'use strict'; const compression = require('compression'); const express = require('express'); const next = require('next'); const path = require('path'); const fetch = require('isomorphic-fetch'); const dev = process.env.NODE_ENV !== 'production'; const app = next({ dev }); const handle = app.getRequestHandler(); const auth = '...'; const site = 'help-*-*'; const server = express(); class GetHelp { constructor() { this.initApp(); } /* Start express application and express healthcheck. */ initApp() { app.prepare().then(() => { /* * API Server */ server.get('/api/search/:searchTerm', (req, res, next) => { const searchTerm = req.params.searchTerm; var endpoint = `services/rest/connect/v1.3/analyticsReportResults`; fetch( `https://${auth}@${site}.....com/${endpoint}`, { method: 'POST', mode: 'no-cors', body: JSON.stringify({ "id": 178394, "filters": [{ "name": "os_search", "values": [ searchTerm ] }] }) }) .then(function(res) { return res.json(); }) .then(function(data) { res.setHeader('Content-Type', 'application/json'); res.send(JSON.stringify({ article: data })); }); }); server.get('/api/article/:articleId', (req, res, next) => { const articleId = req.params.articleId; var endpoint = ""; if (parseInt(articleId)) { endpoint = `/services/rest/connect/v1.3/answers/${articleId}/?fields=solution,summary`; } else { endpoint = `/services/rest/connect/v1.3/queryResults/?query=select summary,solution from answers where customFields.c.slug='${articleId}'and customFields.c.lang_id=2035 and language=1 and AccessLevels.NamedIDList.ID=11`; } fetch( `https://${auth}@${site}.....com/${endpoint}`, { method: 'GET', mode: 'no-cors', }) .then(function(res) { return res.json(); }) .then(function(data) { res.setHeader('Content-Type', 'application/json'); res.send(JSON.stringify({ article: data })); }); }); var endpoint = "services/rest/connect/v1.3/queryResults/?query=select lookupName,value from messageBases "; endpoint += "where lookupName in (" + msgToGet + ")"; fetch( `https://${auth}@${site}.....com/${endpoint}`, { method: 'GET', mode: 'no-cors', }) .then(function(res) { return res.json(); }) .then(function(data) { res.setHeader('Content-Type', 'application/json'); res.send(JSON.stringify({ messageBase: data })); }); }); /* * APP Routes */ server.get('/search/:searchTerm/page/:page', (req, res) => { const params = { searchTerm: req.params.searchTerm, page: req.params.page } return app.render(req, res, '/search', params); }); server.get('/article/:articleId', (req, res) => { const params = { articleId: req.params.articleId } return app.render(req, res, '/article', params); }); server.get('*', (req, res) => { return handle(req, res); }); server.listen(8080, 'local-www....dev.com', () => { this.initHealthcheck(); }); }); } } module.exports = new GetHelp();
…
/components/StarRating.js
</pre></pre> import React from 'react'; import Link from '../components/Link'; import Router from 'next/router' import 'isomorphic-fetch'; import Modal from 'react-modal'; const site = 'help-en-us'; const customStyles = { content : { top: '50%', left: '50%', right: 'auto', bottom: 'auto', marginRight: '-50%', transform: 'translate(-50%, -50%)' } }; export default class extends React.Component { constructor(props) { super(props); this.state = { starRating: 0, articleId: this.props.articleId, thankYou: false, showStars: true }; this.handleStar = this.handleStar.bind(this); this.submitRating = this.submitRating.bind(this); this.getToken = this.getToken.bind(this); this.onKeyPress = this.onKeyPress.bind(this); this.openModal = this.openModal.bind(this); this.afterOpenModal = this.afterOpenModal.bind(this); this.closeModal = this.closeModal.bind(this); this.cancelModal = this.cancelModal.bind(this); this.submitAnswerFeedback = this.submitAnswerFeedback.bind(this); this.getToken = this.getToken.bind(this); } async submitRating(rating) { let result = await $.ajax({ url: `http://${site}.....com/ci/ajaxCustom/submitAnswerRating`, data: `a_id=${this.props.articleId}&amp;rate=${rating}&amp;options_count=5`, dataType: 'jsonp', jsonpCallback: 'submitAnswerRating', success: function(response){ console.log(response.submitted); } }); let flag = await result; return flag }; async getToken(rating){ let result = await $.ajax({ url: `http://${site}.....com/ci/ajaxCustom/getNewFormToken`, data: `formToken=${Math.random().toString(36).substr(2)}`, dataType: 'jsonp', jsonpCallback: 'getNewFormToken', success: function(response){ //console.log(typeof(response.newToken)); return response; } }); let token = await result; return token }; async submitAnswerFeedback(){ let a_id = this.props.articleId; let rating = this.state.starRating; let feedbackMessageValue = this.state.feedbackMessageValue; let token = this.state.token; console.log('sAF: ' + token); let result = await $.ajax({ url: `http://${site}.....com/ci/ajaxCustom/submitAnswerFeedback`, data: `a_id=${a_id}&amp;rate=${rating}&amp;message=${feedbackMessageValue}&amp;f_tok=${token}`, dataType: 'jsonp', jsonpCallback: 'submitAnswerFeedback', success: function(response){ console.log(response); } }); let message = await result; this.closeModal(); return message }; async handleStar(rating){ // submit the star rating clicked let ratingSubmitted = await this.submitRating(rating); if(rating >= 3){ // submitted, and done this.setState({ thankYou: true, starRating: rating, ratingSubmitted: ratingSubmitted, showStars: false }) } else { // less than 3, so get a token, and open popup let token = await this.getToken(rating); console.log('obj: ' + token.newToken); console.log(typeof(token.newToken)); this.openModal(); this.setState({ thankYou: true, starRating: rating, ratingSubmitted: ratingSubmitted, token: token.newToken, showStars: false }) } } onKeyPress(e) { let feedbackMessageValue = e.target.value; } onChange(e) { let feedbackMessageValue = e.target.value; this.setState({ feedbackMessageValue: feedbackMessageValue }); } openModal() { this.setState({ modalIsOpen: true }); } afterOpenModal() { // references are now sync'd and can be accessed. this.subtitle.style.color = '#f00'; } closeModal() { this.setState({ modalIsOpen: false }); } cancelModal() { this.setState({ modalIsOpen: false, showStars: true, thankYou: false }) } render () { const stars = [1,2,3,4,5]; const starRating = this.state.starRating; const thankYou = this.state.thankYou; const showStars = this.state.showStars; return ( <div className="box"> <div className="answerFeedback"> {!thankYou ? <div className="title">Please rate this article:</div> : ""} {showStars ? ( <div className="starsBox"> { stars.map((star) => { return( <span key={star} className={`g72-star ${star<=starRating?'selectedStar':''}`} onClick={(e) => this.handleStar(star)}> </span> ) }) } </div>) : (<span></span>) } {thankYou ? <div className="thankYou">Thank you for your feedback!</div> : ""} <div> { //<button onClick={this.openModal}>Open Modal</button> } <Modal isOpen={this.state.modalIsOpen} onAfterOpen={this.afterOpenModal} onRequestClose={this.closeModal} style={customStyles} contentLabel="Example Modal"> <h2 ref = { subtitle => this.subtitle = subtitle }>Provide Additional Information</h2> <div className = "submittedMessage">Your rating has been submitted, please tell us how we can make this answer more useful.</div> <div className = "faqQuestion">FAQ Feedback – How can we improve this answer? *</div> <textarea className = "feedbackMessage" id = "feedbackMessage" name = "feedbackMessage" rows = "4" cols = "50" value = { this.state.feedbackMessageValue } onKeyPress = { (e) => this.onKeyPress(e) } onChange={(e) => this.onChange(e)}></textarea> <div className="formButtons"> <button onClick = { this.submitAnswerFeedback } className="submitButton">Submit</button> <button onClick = { this.cancelModal } className="cancelButton">Cancel</button> </div> </Modal> </div> </div> <style jsx>{` .answerFeedback .title { font-weigth: bold; } .answerFeedback .g72-star { font-size: 1.5em; margin: 5px; cursor: pointer; color: #6d6b6b; } .answerFeedback .g72-star:hover, .selectedStar{ color: rgb(251, 224, 0) !important; } .starsBox { background: #a09e9e; border-radius: 10px; padding: 0 10px; width: 170px; text-align: center; } .feedbackMessage { border: 1px solid; margin: 10px 10px 10px 0; padding: 10px; width: 100%; } .formButtons { text-align: right; } .submitButton, .cancelButton { width: 100%; margin: 0; padding: 10px; font-weight: bold; color: white; text-transform: uppercase; border-radius: 3px; text-align: center; text-decoration: none; } .submitButton { background-color: rgba(250, 84, 0, 1); } .submitButton:hover { background-color: #666; } .cancelButton { background-color: rgb(153, 153, 153); } .cancelButton:hover { background-color: #666; } .submitbutton:hover { } `}</style> </div> ); } } <pre>
Oracle AjaxCustom Service endpoint
function submitAnswerRating() { $answerID = $this-&gt;input-&gt;get('a_id'); $rating = $this-&gt;input-&gt;get('rate'); $scale = $this-&gt;input-&gt;get('options_count'); if($answerID){ if($this-&gt;model('Answer')-&gt;rate($answerID, $rating, $scale)){ print "submitAnswerRating({'submitted':'true'})"; }else{ print "submitAnswerRating({'submitted':'false'})"; } } } function getNewFormToken() { if($formToken = $this-&gt;input-&gt;get('formToken')) { $newToken = Framework::createTokenWithExpiration(0, false); print "getNewFormToken({'newToken':'" . $newToken . "'})"; } } function submitAnswerFeedback() { AbuseDetection::check(); $answerID = $this->input->get('a_id'); if($answerID === 'null') $answerID = null; $rate = $this->input->get('rate'); $message = $this->input->get('message'); $givenEmail = '...@....com'; $threshold = 3; $optionsCount = 5; $formToken = $this->input->get('f_tok'); $incidentResult = $this->model('Incident')->submitFeedback($answerID, $rate, $threshold, null, $message, $givenEmail, $optionsCount); if($incidentResult->result){ print "submitAnswerFeedback({'ID':'" . $incidentResult->result->ID . "'})"; //$this->_renderJSON(array('ID' => $incidentResult->result->ID)); }else{ if($incidentResult->error){ print "submitAnswerFeedback({'error 2':'" . $incidentResult->error->externalMessage . "'})"; } }