//** 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 {object} progressBar - element to be used to display upload progress */ constructor(baseURL = null, progressBar = null) { this.percentComplete = 0; //for later this.baseURL = null; this.progressBar = progressBar; this.status = false; if (baseURL) this.baseURL = baseURL; //asks server if a session is active this._request(this.baseURL ? this.baseURL + API_STATUS : API_STATUS).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 : url, 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 {string} form[].form_token - hidden property to authenticate form submission * @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, type; switch (task) { case TASK_PAGE_CREATE: url = API_NEW_PAGE; event = TASK_PAGE_CREATE; content = CONTENT_TYPE_JSON; type = REQUEST_TYPE_POST; break; case TASK_PAGE_EDIT: url = API_EDIT_PAGE; event = TASK_PAGE_EDIT; content = CONTENT_TYPE_JSON; type = REQUEST_TYPE_PUT; break; case TASK_PAGE_DELETE: url = API_DELETE_PAGE; event = TASK_PAGE_DELETE; content = CONTENT_TYPE_JSON; type = REQUEST_TYPE_DELETE; 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, type, 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 ['site'|'member']; * @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.addEventListener('progress', e => self.handleLoadProgress(e, self.progressBar) ); 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, progressBar) { let percent = Math.ceil((e.loaded / e.total) * 100); //if a progress bar element is present, talk to it if (progressBar != null) { progressBar.style.width = percent + '%'; } } } export { FipamoAdminAPI as default };