Skip to content

Instantly share code, notes, and snippets.

@chrismckelt
Created December 11, 2018 06:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save chrismckelt/aeb721c7d76b558ba6489cb1b73eefe2 to your computer and use it in GitHub Desktop.
Save chrismckelt/aeb721c7d76b558ba6489cb1b73eefe2 to your computer and use it in GitHub Desktop.
typescript utils for Resco D365 Field Services
import './constants';
import {
Logger
} from "./logger";
import {
Question,
Answer,
ResponseRouting,
ResponseCondition,
ResponseAction
} from './models';
export class Util {
/**
* Convert a byte array buffer into a base64 stringshowAnswers
*
* @param {any} buffer The byte array
* @returns A base64 encoded string
*/
static arrayBufferToBase64(buffer) {
var binary = '';
var bytes = new Uint8Array(buffer);
var len = bytes.byteLength;
for (var i = 0; i < len; i++) {
binary += String.fromCharCode(bytes[i]);
}
return window.btoa(binary);
}
/**
* Generates a text area answer HTML fragment
*
* @param {any} question
* @returns The question object this text area is linked to
*/
public static createTextBoxAnswer(question: Question) {
Logger.debug('createTextBoxAnswer');
return [
"<input type='text' class='answer form-control' ",
" id='" + question.QuestionId + "' ",
" name='" + question.QuestionId + "' ",
" /> "
];
}
public static createTextAreaAnswer(question: Question) {
return [
"<textarea data-answer-field=true rows=3 class='answer form-control' ",
question.Required ? "required=required " : " ",
" id='" + question.QuestionId + "' ",
" name='" + question.QuestionId + "' ",
"></textarea>"
];
}
/**
* Generates a numeric input box answer HTML fragment
*
* @param {any} question The question object this input box is linked to
* @returns
*/
public static createNumericAnswer(question: Question) {
return [
"<input type='number' class='answer form-control'",
" id='" + question.QuestionId + "' ",
" name='" + question.QuestionId + "' ",
" /> "
];
}
/**
* Generates a radio button answer HTML fragment
*
* @param {any} answer The answer object this radio button is linked to
* @returns
*/
public static createRadioButtonAnswer(answer: Answer) {
return [
"<div class='btn-group'>",
"<label class='btn btn-default'>",
"<input class='answer' type='radio' ",
answer.CreateCommentsBoxOnValue ? " data-create-comment-on-press='true' " : " data-answer-id='" + answer.AnswerId + "'",
" name='answer-for-question-" + answer.QuestionId + "'" +
" value='" + answer.Name + "' /> ",
answer.Name,
"</label>",
"</div>"
];
}
/**
* Generates a check box answer HTML fragment
*
* @param {any} answer The answer object this checkbox is linked to
* @returns
*/
public static createCheckBoxAnswer(answer: Answer) {
return [
"<div class='btn-group'>",
"<label class='btn btn-default'>",
"<input type='checkbox'", (answer.CreateCommentsBoxOnValue ? " data-create-comment-on-press='true' " : ""),
" data-answer-id='" + answer.AnswerId + "'",
" name='answer-for-question-" + answer.QuestionId + "'" +
" value='" + answer.Name + "' /> ",
answer.Name,
"</label>",
"</div>"
];
}
public static fetch < T > (entity: object, success: (data: any) => void) {
var fetch = new MobileCRM.FetchXml.Fetch(entity);
fetch.execute(
"DynamicEntities",
success,
Logger.warn,
null);
}
public static fetchById < T > (entityName: string, searchKey: string, searchValue: string, success: (data: any) => void) {
// "msdyn_question"
var entity = new MobileCRM.FetchXml.Entity(entityName);
entity.filter = new MobileCRM.FetchXml.Filter();
// msdyn_surveyid
entity.filter.where(searchKey, "eq", searchValue);
Util.fetch(entity, success);
}
public static getIdOnly(property: any) {
if (!property) return null;
if (typeof property === 'string') {
return property;
}
if ('id' in property) {
return property.id;
}
if ('name' in property) {
return property.name;
}
Logger.warn('Util.getIdOnly what property to use?');
Logger.object('property', property);
}
public static getActionTypeAsString(actionType: number): string {
switch (actionType) {
case ActionTypes.Show:
return "Show";
case ActionTypes.Hide:
return "Hide";
case ActionTypes.ChainSurvey:
return "ChainSurvey";
case ActionTypes.SkipTo:
return "SkipTo";
case ActionTypes.EndSurvey:
return "EndSurvey";
case ActionTypes.ToggleVisibility:
return "ToggleVisibility";
default:
return "Unknown " + actionType;
}
}
public static showAlert(message: string) {
Logger.debug('alert:' + message);
MobileCRM.bridge.alert(message);
}
// add this to the end of the event loop
public static queue(arg: () => void, timeoutMS: number = 0) {
setTimeout(arg, timeoutMS);
}
public static wait(predicate: () => boolean, action:()=>void, retries: number = 10) {
Logger.start('Util.wait');
var counter = 0;
var i = setInterval(function () {
if (predicate()){
Logger.debug('Util.wait predicate = true');
if (counter >= retries) {
clearInterval(i);
}
action();
}
counter++;
Logger.debug('Util.wait predicate = false');
}, 200);
}
}
// constants
const DynamicEntities = "DynamicEntities";
// Enable or disable the debug console
var DEBUG_ENABLED = false; // can be remotely turned on via Survey.msdyn_showtechnicalhelp
const LOCAL_DEV = window.location.hostname === "localhost";
declare var MobileCRM: any;
// QuestionTypes are defined in the CRM msdyn_questiontype entity
const QuestionTypes = {
SINGLE_LINE_OF_TEXT: 1,
MULTIPLE_LINES_OF_TEXT: 2,
NUMERIC: 3,
SINGLE_RESPONSE_OPTION_SET: 4,
MULTI_RESPONSE_OPTION_SET: 5,
DATETIME: 6,
RATING: 9,
DESCRIPTIVE_TEXT: 10,
EMAIL: 11,
WEBSITE: 12,
RANKING: 13,
FIXED_SUM: 15,
FILE: 16
};
const EntityNames = {
Question: "msdyn_question",
QuestionGroup: "resco_QuestionGroup",
QuestionReponse: "msdyn_questionresponse",
QuestionToAnswer: "msdyn_question_answer_n_n",
ResponseAction: "msdyn_responseaction",
ResponseActionToResponseRouting: "msdyn_responserouting_responseaction_else",
ResponseCondition: "msdyn_responsecondition",
ResponseOutcome: "msdyn_responseoutcome",
ResponseRouting: "msdyn_responserouting",
SurveyActivity: "msdyn_surveyinvite",
SurveyResponse: "msdyn_surveyresponse",
}
const Selectors = {
TabTemplate: $("#tabTemplate"),
QuestionTemplate: $("#questionTemplate"),
AnsweredNoTemplate: $("#answeredNoTemplate"),
FileInfoTemplate: $("#fileInfoTemplate"),
SurveyContainer: $("#surveyContainer .tab-content"),
CurrentQuestion: null,
CurrentTab: null,
LoadingOverlay: $(".loading-overlay")
};
const ActionTypes = {
Show: 986540000,
Hide: 986540001,
SkipTo: 986540002,
EndSurvey: 986540003,
ChainSurvey: 986540004,
ToggleVisibility: 986540005
}
const QuestionGroupType = {
Question_and_answer: 986540000,
Grid_of_single_select_questions: 986540002,
Grid_of_multiple_select_questions: 986540003,
Grid_of_image_scales: 986540001,
Fixed_sum_questions: 986540004,
}
const Operator = {
Equals: 986540000,
Greater: 986540001,
LessThan: 986540002,
Selected: 986540003,
}
const Visibiity ={
Visible : 986540000 ,
Hidden : 986540001
}
const Bool ={
Yes : 986540000,
No : 986540001
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment