2022-01-20 20:57:29 +00:00
|
|
|
const frappe = require('frappe');
|
|
|
|
const Observable = require('frappe/utils/observable');
|
|
|
|
const triggerEvent = (name) => frappe.events.trigger(`http:${name}`);
|
2018-01-12 12:25:07 +00:00
|
|
|
|
2018-02-19 16:41:10 +00:00
|
|
|
module.exports = class HTTPClient extends Observable {
|
2018-08-18 15:54:17 +00:00
|
|
|
constructor({ server, protocol = 'http' }) {
|
|
|
|
super();
|
2018-02-19 16:41:10 +00:00
|
|
|
|
2018-08-18 15:54:17 +00:00
|
|
|
this.server = server;
|
|
|
|
this.protocol = protocol;
|
|
|
|
frappe.config.serverURL = this.getURL();
|
2018-01-12 12:25:07 +00:00
|
|
|
|
2018-08-18 15:54:17 +00:00
|
|
|
// if the backend is http, then always client!
|
|
|
|
frappe.isServer = false;
|
|
|
|
|
|
|
|
this.initTypeMap();
|
|
|
|
}
|
|
|
|
|
2022-01-20 20:57:29 +00:00
|
|
|
connect() {}
|
2018-08-18 15:54:17 +00:00
|
|
|
|
|
|
|
async insert(doctype, doc) {
|
|
|
|
doc.doctype = doctype;
|
|
|
|
let filesToUpload = this.getFilesToUpload(doc);
|
|
|
|
let url = this.getURL('/api/resource', doctype);
|
|
|
|
|
|
|
|
const responseDoc = await this.fetch(url, {
|
|
|
|
method: 'POST',
|
2022-01-20 20:57:29 +00:00
|
|
|
body: JSON.stringify(doc),
|
2018-08-18 15:54:17 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
await this.uploadFilesAndUpdateDoc(filesToUpload, doctype, responseDoc);
|
|
|
|
|
|
|
|
return responseDoc;
|
|
|
|
}
|
|
|
|
|
|
|
|
async get(doctype, name) {
|
|
|
|
name = encodeURIComponent(name);
|
|
|
|
let url = this.getURL('/api/resource', doctype, name);
|
|
|
|
return await this.fetch(url, {
|
|
|
|
method: 'GET',
|
2022-01-20 20:57:29 +00:00
|
|
|
headers: this.getHeaders(),
|
|
|
|
});
|
2018-08-18 15:54:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
async getAll({ doctype, fields, filters, start, limit, sortBy, order }) {
|
|
|
|
let url = this.getURL('/api/resource', doctype);
|
|
|
|
|
2022-01-20 20:57:29 +00:00
|
|
|
url =
|
|
|
|
url +
|
|
|
|
'?' +
|
|
|
|
frappe.getQueryString({
|
|
|
|
fields: JSON.stringify(fields),
|
|
|
|
filters: JSON.stringify(filters),
|
|
|
|
start: start,
|
|
|
|
limit: limit,
|
|
|
|
sortBy: sortBy,
|
|
|
|
order: order,
|
|
|
|
});
|
2018-08-18 15:54:17 +00:00
|
|
|
|
|
|
|
return await this.fetch(url, {
|
|
|
|
method: 'GET',
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
async update(doctype, doc) {
|
|
|
|
doc.doctype = doctype;
|
|
|
|
let filesToUpload = this.getFilesToUpload(doc);
|
|
|
|
let url = this.getURL('/api/resource', doctype, doc.name);
|
|
|
|
|
|
|
|
const responseDoc = await this.fetch(url, {
|
|
|
|
method: 'PUT',
|
2022-01-20 20:57:29 +00:00
|
|
|
body: JSON.stringify(doc),
|
2018-08-18 15:54:17 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
await this.uploadFilesAndUpdateDoc(filesToUpload, doctype, responseDoc);
|
|
|
|
|
|
|
|
return responseDoc;
|
|
|
|
}
|
|
|
|
|
|
|
|
async delete(doctype, name) {
|
|
|
|
let url = this.getURL('/api/resource', doctype, name);
|
|
|
|
|
|
|
|
return await this.fetch(url, {
|
|
|
|
method: 'DELETE',
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
async deleteMany(doctype, names) {
|
|
|
|
let url = this.getURL('/api/resource', doctype);
|
|
|
|
|
|
|
|
return await this.fetch(url, {
|
|
|
|
method: 'DELETE',
|
2022-01-20 20:57:29 +00:00
|
|
|
body: JSON.stringify(names),
|
2018-08-18 15:54:17 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
async exists(doctype, name) {
|
|
|
|
return (await this.getValue(doctype, name, 'name')) ? true : false;
|
|
|
|
}
|
|
|
|
|
|
|
|
async getValue(doctype, name, fieldname) {
|
|
|
|
let url = this.getURL('/api/resource', doctype, name, fieldname);
|
|
|
|
|
2022-01-20 20:57:29 +00:00
|
|
|
return (
|
|
|
|
await this.fetch(url, {
|
|
|
|
method: 'GET',
|
|
|
|
})
|
|
|
|
).value;
|
2018-08-18 15:54:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
async fetch(url, args) {
|
2018-09-30 13:14:40 +00:00
|
|
|
triggerEvent('ajaxStart');
|
|
|
|
|
2018-08-18 15:54:17 +00:00
|
|
|
args.headers = this.getHeaders();
|
|
|
|
let response = await frappe.fetch(url, args);
|
2018-09-29 07:17:43 +00:00
|
|
|
|
2018-09-30 13:14:40 +00:00
|
|
|
triggerEvent('ajaxStop');
|
|
|
|
|
|
|
|
if (response.status === 200) {
|
|
|
|
let data = await response.json();
|
|
|
|
return data;
|
2018-09-29 07:17:43 +00:00
|
|
|
}
|
2018-03-05 16:45:21 +00:00
|
|
|
|
2018-09-30 13:14:40 +00:00
|
|
|
if (response.status === 401) {
|
|
|
|
triggerEvent('unauthorized');
|
2018-01-12 12:25:07 +00:00
|
|
|
}
|
|
|
|
|
2018-09-30 13:14:40 +00:00
|
|
|
throw Error(await response.text());
|
2018-08-18 15:54:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
getFilesToUpload(doc) {
|
|
|
|
const meta = frappe.getMeta(doc.doctype);
|
|
|
|
const fileFields = meta.getFieldsWith({ fieldtype: 'File' });
|
|
|
|
const filesToUpload = [];
|
|
|
|
|
|
|
|
if (fileFields.length > 0) {
|
2022-01-20 20:57:29 +00:00
|
|
|
fileFields.forEach((df) => {
|
2018-08-18 15:54:17 +00:00
|
|
|
const files = doc[df.fieldname] || [];
|
|
|
|
if (files.length) {
|
|
|
|
filesToUpload.push({
|
|
|
|
fieldname: df.fieldname,
|
2022-01-20 20:57:29 +00:00
|
|
|
files: files,
|
|
|
|
});
|
2018-08-18 15:54:17 +00:00
|
|
|
}
|
|
|
|
delete doc[df.fieldname];
|
|
|
|
});
|
2018-02-08 09:38:47 +00:00
|
|
|
}
|
|
|
|
|
2018-08-18 15:54:17 +00:00
|
|
|
return filesToUpload;
|
|
|
|
}
|
2018-02-08 09:38:47 +00:00
|
|
|
|
2018-08-18 15:54:17 +00:00
|
|
|
async uploadFilesAndUpdateDoc(filesToUpload, doctype, doc) {
|
|
|
|
if (filesToUpload.length > 0) {
|
|
|
|
// upload files
|
|
|
|
for (const fileToUpload of filesToUpload) {
|
2022-01-20 20:57:29 +00:00
|
|
|
const files = await this.uploadFiles(
|
|
|
|
fileToUpload.files,
|
|
|
|
doctype,
|
|
|
|
doc.name,
|
|
|
|
fileToUpload.fieldname
|
|
|
|
);
|
2018-08-18 15:54:17 +00:00
|
|
|
doc[fileToUpload.fieldname] = files[0].name;
|
|
|
|
}
|
2018-02-08 09:38:47 +00:00
|
|
|
}
|
2018-08-18 15:54:17 +00:00
|
|
|
}
|
2018-02-08 09:38:47 +00:00
|
|
|
|
2018-08-18 15:54:17 +00:00
|
|
|
async uploadFiles(fileList, doctype, name, fieldname) {
|
|
|
|
let url = this.getURL('/api/upload', doctype, name, fieldname);
|
2018-02-09 12:55:55 +00:00
|
|
|
|
2018-08-18 15:54:17 +00:00
|
|
|
let formData = new FormData();
|
|
|
|
for (const file of fileList) {
|
|
|
|
formData.append('files', file, file.name);
|
2018-01-12 12:25:07 +00:00
|
|
|
}
|
|
|
|
|
2018-08-18 15:54:17 +00:00
|
|
|
let response = await frappe.fetch(url, {
|
|
|
|
method: 'POST',
|
2022-01-20 20:57:29 +00:00
|
|
|
body: formData,
|
2018-08-18 15:54:17 +00:00
|
|
|
});
|
2018-02-08 09:38:47 +00:00
|
|
|
|
2018-08-18 15:54:17 +00:00
|
|
|
const data = await response.json();
|
|
|
|
if (response.status !== 200) {
|
|
|
|
throw Error(data.error);
|
2018-01-23 13:18:37 +00:00
|
|
|
}
|
2018-08-18 15:54:17 +00:00
|
|
|
return data;
|
|
|
|
}
|
|
|
|
|
|
|
|
getURL(...parts) {
|
|
|
|
return this.protocol + '://' + this.server + (parts || []).join('/');
|
|
|
|
}
|
|
|
|
|
|
|
|
getHeaders() {
|
|
|
|
const headers = {
|
2022-01-20 20:57:29 +00:00
|
|
|
Accept: 'application/json',
|
|
|
|
'Content-Type': 'application/json',
|
2018-08-18 15:54:17 +00:00
|
|
|
};
|
|
|
|
if (frappe.session && frappe.session.token) {
|
|
|
|
headers.token = frappe.session.token;
|
2022-01-20 20:57:29 +00:00
|
|
|
}
|
2018-08-18 15:54:17 +00:00
|
|
|
return headers;
|
|
|
|
}
|
|
|
|
|
|
|
|
initTypeMap() {
|
|
|
|
this.typeMap = {
|
2022-01-20 20:57:29 +00:00
|
|
|
AutoComplete: true,
|
|
|
|
Currency: true,
|
|
|
|
Int: true,
|
|
|
|
Float: true,
|
|
|
|
Percent: true,
|
|
|
|
Check: true,
|
|
|
|
'Small Text': true,
|
|
|
|
'Long Text': true,
|
|
|
|
Code: true,
|
|
|
|
'Text Editor': true,
|
|
|
|
Date: true,
|
|
|
|
Datetime: true,
|
|
|
|
Time: true,
|
|
|
|
Text: true,
|
|
|
|
Data: true,
|
|
|
|
Link: true,
|
|
|
|
DynamicLink: true,
|
|
|
|
Password: true,
|
|
|
|
Select: true,
|
|
|
|
'Read Only': true,
|
|
|
|
File: true,
|
|
|
|
Attach: true,
|
|
|
|
'Attach Image': true,
|
|
|
|
Signature: true,
|
|
|
|
Color: true,
|
|
|
|
Barcode: true,
|
|
|
|
Geolocation: true,
|
|
|
|
};
|
2018-08-18 15:54:17 +00:00
|
|
|
}
|
2018-01-12 12:25:07 +00:00
|
|
|
|
2022-01-20 20:57:29 +00:00
|
|
|
close() {}
|
|
|
|
};
|