//** REQUEST TYPES **// export const REQUEST_TYPE_POST = "POST"; export const REQUEST_TYPE_GET = "GET"; export const REQUEST_TYPE_PUT = "PUT"; export const REQUEST_TYPE_DELETE = "DELETE"; //** POST CONTENT TYPES **// export const CONTENT_TYPE_JSON = "json"; export const CONTENT_TYPE_FORM = "x-www-form-urlencoded"; //** API URLS **// export const API_STATUS = "/api/v1/status"; export const API_GET_SETTINGS = "/api/v1/settings/site"; export const API_GET_MEMBER_INFO = "/api/v1/settings/member"; export const API_NEW_PAGE = "/api/v1/page/create"; export const API_EDIT_PAGE = "/api/v1/page/write"; export const API_DELETE_PAGE = "/api/v1/page/delete"; export const API_SETTINGS_SYNC = "/api/v1/settings/sync"; export const API_PUBLISH_PAGES = "/api/v1/settings/publish"; export const API_NAV_SYNC = "/api/v1/settings/nav-sync"; export const API_REINDEX_PAGES = "/api/v1/settings/reindex"; export const API_SEND_MAIL = "/api/v1/mailer"; export const API_LOGIN = "/api/v1/login"; //** API TASKS **// export const AUTH_STATUS = "getAuthStatus"; export const TASK_SETTINGS_WRITE = "writeSettings"; export const TASK_PUBLISH_SITE = "publishSite"; export const TASK_PAGE_CREATE = "createNewPage"; export const TASK_PAGE_EDIT = "editPage"; export const TASK_PAGE_DELETE = "deletePage"; export const TASK_SEND_MAIL = "sendMail"; export const TASK_REINDEX_PAGE = "reIndexPages"; export const TASK_SYNC_SETTNIGS = "syncSite"; export const TASK_SYNC_NAV = "syncNav"; export const TASK_GET_SETTINGS = "getSiteSettings"; export const TASK_GET_MEMBER_INFO = "getMemberInfo"; //** API STATUS **// export const API_ACCESS_GOOD = "apiUseAuthorized"; export const API_ACCESS_BAD = "apiUseNotAuthorized"; /** * A can of methods used to edit install settings, navigation pages and content pages */ class FipamoAdminAPI { /** * @constructor * @param {string} baseURL - url of site; uses local when empty * @param {string} key - user api key */ constructor(baseURL = null, key = null) { this.percentComplete = 0; //for later this.token = null; this.baseURL = null; this.key = null; if (key) this.key = key; if (baseURL) this.baseURL = baseURL; //if key is valid, checks to see if a session is active and returns this._request( this.baseURL ? this.baseURL + API_STATUS + "?key=" + this.key : API_STATUS + "?key=" + this.key ).then((response) => { if (response.type === API_ACCESS_GOOD) { this.token = response.token; } else { //don't set token //console.log("NO TOKEN"); } }); } /** * Promise method for authenticating and starting a session\ * **POST**`/api/v1/login` * @param {Object[]} data - json object that contains data for set up * @param {string} data[].handle - handle for site user * @param {string} data[].password - password for site user * @example * api.login(data).then(response=>{ * console.log("RESPONSE", response); * }) * @returns {object} json object that contains type and status of login request ``` { "message":"Example Message of Affirmation or what you're missing!", "type":"exampleType", } ``` */ login(data) { return new Promise((resolve, reject) => { this.baseURL ? (data.remote = true) : (data.remote = false); this.key ? (data.key = this.key) : (data.key = null); this._request( this.baseURL ? this.baseURL + API_LOGIN : API_LOGIN, AUTH_STATUS, REQUEST_TYPE_POST, CONTENT_TYPE_JSON, data ) .then((result) => { resolve(result); }) .catch((err) => { reject(err); }); }); } /** * Method for saving site and navigation settings\ * **POST**`/api/v1/settings/:task` * @param {string} task - settings being synced `config | navigation` * @param {object[]} data - json object that contains settings data for [site] or [nav] * @param {string} data[].global.base_url - base url for site [site] * @param {string} data[].global.title - site title [site] * @param {string} data[].global.descriptions - brief site summary [site] * @param {string} data[].global.background - url for site feature image for header [site] * @param {boolean} data[].global.private - privacy state for site [disabled] [site] * @param {boolean} data[].global.renderOnSave - property for publishing site when page saved [disabled] [site] * @param {string} data[].global.theme - current theme for site [site] * @param {boolean} data[].global.externalAPI - toggle for external API access [site] * @param {string} data[].member.handle - current member handle [site] * @param {string} data[].member.email - current member email [site] * @param {string} data[].email.active - current email protocol being used [site] * @param {string} data[].email.smtp.domain - url of smtp service being [site] * @param {string} data[].email.smtp.email - email account of smtp service [site] * @param {string} data[].email.smtp.password - password for email of smtp service [site] * @param {string} data[].email.mailgun.domain - mailgun domain url [site] * @param {string} data[].email.mailgun.key - mailgun key [site] * * @param {string} data[].item.title - page title [nav] * @param {string} data[].item.slug - url safe title [nav] * @param {string} data[].item.uuid - unique identifier [nav] * @param {string} data[].item.path - directory path to associated markdown file [nav] * @example * api.sync(TASK, data).then(response=>{ * console.log("RESPONSE", response); * }) * @returns {object} json object that contains type and status of sync request ``` * { "message":"Example Message of Affirmation!", "type":"exampleType", } ``` */ sync(task, data) { return new Promise((resolve, reject) => { let url = ""; switch (task) { case "syncSite": url = API_SETTINGS_SYNC; break; case "syncNav": url = API_NAV_SYNC; break; } this._request( this.baseURL ? this.baseURL + url + "?key=" + this.key : url + "?key=" + this.key, TASK_SETTINGS_WRITE, REQUEST_TYPE_POST, CONTENT_TYPE_JSON, data ) .then((result) => { resolve(result); }) .catch((err) => { reject(err); }); }); } /** * Method for retrieving user authorizing user login * @param {object[]} data - json object that contains task * @param {string} data[].task - publishing task * @example * api.publish(TASK).then(response=>{ * console.log("RESPONSE", response); * }) * @returns {object} json object that contains type and status of publis request * ``` { "message":"Example Message of Affirmation!", "type":"exampleType", } * ``` */ publish(data) { return new Promise((resolve, reject) => { this._request( //API_PUBLISH_PAGES, this.baseURL ? this.baseURL + API_PUBLISH_PAGES : API_PUBLISH_PAGES, TASK_PUBLISH_SITE, REQUEST_TYPE_POST, CONTENT_TYPE_JSON, data ) .then((result) => { resolve(result); }) .catch((err) => { reject(err); }); }); } /** * Method for handling page creating and editing\ * **POST**`/api/v1/page/:task` * @param {string} task - current page action * @param {object[]} form - form object that contains info for current page being edited/created * @param {string} form[].id - sequence id for page, leave empty for new page * @param {string} form[].uuid - unique identifier for page, leave empty for new page * @param {string} form[].layout - current page layout * @param {string} form[].current_title - saved url save title for persistence when changing title, leave empty for new page * @param {string} form[].content - markdown body of page * @param {string} form[].title - current title of page * @param {string} form[].created - date page was created, leave empty for new page * @param {string} form[].slug - url safe string of page title * @param {string} form[].tags - comma separated list of tags * @param {boolean} form[].menu - property that indicates page is included in site menu * @param {boolean} form[].featured - property that indicates page is featured * @param {boolean} form[].published - property that indicates page is public * @param {input} form[].feature_image - main image for page * @example * api.pageActions(TASK, data).then(response=>{ * console.log("RESPONSE", response); * }) * @returns {object} json object that contains type and status of page edit request ``` { "message":"Example Message of Affirmation!", "type":"exampleType", } ``` */ pageActions(task, data) { let url, event, content; switch (task) { case TASK_PAGE_CREATE: url = API_NEW_PAGE; event = TASK_PAGE_CREATE; content = CONTENT_TYPE_FORM; break; case TASK_PAGE_EDIT: url = API_EDIT_PAGE; event = TASK_PAGE_EDIT; content = CONTENT_TYPE_FORM; break; case TASK_PAGE_DELETE: url = API_DELETE_PAGE; event = TASK_PAGE_DELETE; content = CONTENT_TYPE_JSON; break; default: break; } if (this.baseURL) { data.key = this.key; data.remote = true; } else { data.remote = false; } return new Promise((resolve, reject) => { this._request( this.baseURL ? this.baseURL + url : url, event, REQUEST_TYPE_POST, content, data ) .then((result) => { resolve(result); }) .catch((err) => { reject(err); }); }); } /** * Method for sending mail (if completed in settings)\ * **POST**`/api/v1/mailer` * @param {object[]} message - json object that contains items to be included in main site navigation * @param {string} message[].content - message to send * @example * api.sendMail(message).then(response=>{ * console.log("RESPONSE", response); * }) * @returns {object} json object that contains type and status of page edit request ``` { "message":"Example Message of Affirmation!", "type":"exampleType" } ``` */ sendMail(message) { return new Promise((resolve, reject) => { this._request( this.baseURL ? this.baseURL + API_SEND_MAIL : API_SEND_MAIL, TASK_SEND_MAIL, REQUEST_TYPE_POST, CONTENT_TYPE_JSON, message ) .then((result) => { resolve(result); }) .catch((err) => { reject(err); }); }); } /** * *Promise method for retrieving site and member info*\ * **GET** `/api/v1/settings/:type` * @param {string} type - type of info requested * @example * api.getInfo("type").then(data=>{ console.log("Info Object", data); * }) * @returns {object} json object that contains data for requested information * * *info object example* * ``` { "message":"message of affirmation!", "task":"type of info request", "data":json-data-object, } * ``` */ getInfo(type) { let url, task; if (type == "site") { url = API_GET_SETTINGS; task = TASK_GET_SETTINGS; } else { url = API_GET_MEMBER_INFO; task = TASK_GET_MEMBER_INFO; } return new Promise((resolve, reject) => { this._request(this.baseURL ? this.baseURL + url : url, task) .then((result) => { resolve(result); }) .catch((err) => { reject(err); }); }); } //-------------------------- // private //-------------------------- _request( requestURL, eventType, requestType = REQUEST_TYPE_GET, contentType = CONTENT_TYPE_JSON, requestData = null ) { var self = this; return new Promise(function (resolve, reject) { var request = new XMLHttpRequest(); request.upload.onprogress = self.handleLoadProgress; request.open(requestType, requestURL, true); request.onload = () => { if (request.status == 200) { let response = JSON.parse(request["response"]); resolve(response); } else { let error = JSON.parse(request["response"]); reject(error); } }; if (requestType == REQUEST_TYPE_PUT || requestType == REQUEST_TYPE_POST) { if ( eventType === TASK_SETTINGS_WRITE || eventType === TASK_PAGE_EDIT || eventType === TASK_PAGE_CREATE || eventType === TASK_PAGE_DELETE || eventType === TASK_PUBLISH_SITE || eventType === TASK_REINDEX_PAGE ) request.setRequestHeader("fipamo-access-token", self.token); switch (contentType) { case CONTENT_TYPE_JSON: request.setRequestHeader( "Content-type", "application/" + contentType ); request.send(JSON.stringify(requestData)); break; case CONTENT_TYPE_FORM: request.send(requestData); break; } } else { if ( eventType === TASK_GET_SETTINGS || eventType === TASK_GET_MEMBER_INFO ) { request.setRequestHeader("fipamo-access-token", self.token); } request.send(); } }); } //-------------------------- // event handlers //-------------------------- handleLoadProgress(e) { this.percentComplete = Math.ceil((e.loaded / e.total) * 100); //pass element to display request progress } } export { FipamoAdminAPI as default };