How to create a local empty JSON Model from OData metadata - sapui5

Is there a way to create a local empty JSON file (with all entities and properties filled in) from the metadata of the oData service? I need this for the create scenario, where I can bind the properties to the view controls. I tried the following code, but did not work. Will appreciate your suggestions.
this.getOwnerComponent().getModel().getMetaModel().getODataEntitySet("EntitySetName");
Error:
Uncaught TypeError: Cannot read property 'getObject' of null
at constructor.h.getODataEntityContainer (ODataMetaModel-dbg.js:692)
at constructor.h.getODataEntitySet (ODataMetaModel-dbg.js:731)
at eval (eval at _prepareCreatePage (ObjectPage.controller.js:74), <anonymous>:1:48)
at f._prepareCreatePage (ObjectPage.controller.js:74)
at f._onObjectPatternMatched (ObjectPage.controller.js:40)
at constructor.b.fireEvent (EventProvider-dbg.js:228)
at constructor.<anonymous>

SAP does very similar stuff in their sample pages: https://sapui5.hana.ondemand.com/#/entity/sap.ui.table.Table/sample/sap.ui.table.sample.OData2/code
Your first part is more or less correct, this is a function to store the meta model in a seperate JSONModel:
function () {
const that = this;
const oModel = this.getOwnerComponent().getModel();
const oMetaModel = oModel.getMetaModel();
oMetaModel.loaded().then(function () {
that.setModel(oMetaModel, "meta");
});
}
The interesting part is how to access stuff:
const sBasePath = "/dataServices/schema/[${namespace}===\'NAME_OF_YOUR_ODATA_SRV\']/entityType/[${name}===\'NameOfYourEntity\']"
const oEntityInformation = oMetaModel.getProperty(sBasePath);
const aKeys = oMetaModel.getProperty(sBasePath + "/key/propertyRef");
const aAllProperties = oMetaModel.getProperty(sBasePath + "/property");
const oSingleProperty = oMetaModel.getProperty(sBasePath + "/property/[${name}===\'NameOfYourProperty\']");
You can even access the model in your XML view:
columns="{
path: 'meta>/dataServices/schema/[${namespace}===\'NAME_OF_YOUR_ODATA_SRV\']/entityType/[${name}===\'NameOfYourEntity\']/property',
factory: '.columnFactory'
}"
Note that NameOfYourEntity has to be the name of the single Entity, so there is no Set at the end.

Not sure, what you want exactly but this script will write the metadata in JSON format in a blob. The save dialog in browser appears after that.
var oDataModel = this.getOwnerComponent().getModel();
oDataModel.attachMetadataLoaded(null, function() {
var oMetaData = oDataModel.getServiceMetadata(); //Read the metadata
var blob = new Blob([JSON.stringify(oMetaData)], {
type: "text/plain;charset=utf-8"
}); //Create a blob with metadata string in JSON format
if (navigator.msSaveBlob) {
return navigator.msSaveBlob(blob, "metadata.json"); //For IE
} else {
//For Chrome and FF we create a Link with a download attribute and trigger the click on it
var sUrl = URL.createObjectURL(blob); //Create the URL for the blob object
var oLink = document.createElement("a"); //Create link element
oLink.download = "metadata.json" //Set download attribute for link
oLink.href = sUrl; //Set href attribute for link
document.body.appendChild(oLink); //Append link to body
oLink.click(); //Click on link
oLink.remove(); //Remove link
}
});

Related

sapui5 upload a file in SAPUI5 and send that file in odata service entityset

My requirement is to
step 1 User and choose a file to upload to sapUI5
step 2 on click of "SAVE" button the file should be uploaded,
step 3 save that uploaded file in a odata entityset and send it to backend. This odata service has two entity set, both of the entity sets should go back to backend in one call.
step
I am using UploadCollection control
<UploadCollection
uploadComplete="onUploadComplete"
typeMissmatch="onTypeMissmatch"
fileSizeExceed="onFileSizeExceed"
filenameLengthExceed="onFilenameLengthExceed"
fileDeleted="onFileDeleted"
change="onChangeAttachments"
noDataDescription="Drag & Drop files or use the "+" button for pending upload"
instantUpload="false"
sameFilenameAllowed="false"
multiple="true"
maximumFileSize="10"
maximumFilenameLength="55"
id="UploadSet"/>
on save button i am calling the method
onStartUpload: function (oEvent) {
var oUploadCollection = this.getView().getID
var cFiles = oUploadCollection.getItems().length;
if (cFiles > 0) {
oUploadCollection.upload();
}
},
My question is on method onUploadComplete how to get the content of the file and save it in the odata entityset.
Thanks
Sonal.
I have found a solution for this.
on click of the save button I am using a file reader to read the selected file as binary, than saving the binary in my model filecontent and than sending it to backend
var base64_marker = "data:" + file.type + ";base64,";
var reader = new FileReader();
reader.onload = (function (thefile) {
return function (evt) {
var base64Index = evt.target.result.indexOf(base64_marker) + base64_marker.length; // locate base64 content
var base64 = evt.target.result.substring(base64Index); // get base64 content
var oAttData = that.getModel("newInitiative").getData().rawAttachment[0];
var oFileData = {};
oFileData.ClaimType = "OFFICE";
oFileData.FileContent = base64;
oFileData.Filename = oAttData.name;
oFileData.Filesize = oAttData.size;
oFileData.Mimetype = oAttData.type;
that.getModel("SupplierModel").getProperty("/VendorFileSet").push(oFileData);
};
}.bind(that))(file);
Thanks.

How to allow users to upload files with Google Form without login?

Where can I find code and instruction on how to allow users to upload files with Google Form without login?
I searched all over here and couldn't find any information.
https://developers.google.com/apps-script/reference
Thanks in advance.
The user will be uploading the files to your drive. So, google needs to verify the user. If there is no verification, someone can fill your drive in no time.
It is for your safety to know who has uploaded, so, login is must.
There's a workaround, I'm in a hurry to write the code now, but if you're interested let me know and I'll edit later.
Basically, you set up a web app with apps script, then you setup a custom HTML form, you'll have to manually collect the file, convert is to base64 then json, then when you catch it in apps script you reverse the process and save it wherever you want in your drive.
Since the user will be executing the script as you, there's no verification required
/*
These functions basically go through a file array and reads the files first as binary string (in second function), then converts the files to base64 string (func 1) before stringifying the files (after putting their base64 content into an object with other metadata attached; mime, name e.t.c);
You pass this stringified object into the body part of fetch(request,{body:"stringified object goes here"})
see next code block for how to read in apps script and save the files to google drive
N.B. The body data will be available under doPost(e){e.postData.contents}
*/
async function bundleFilesForUpload(){
let filesDataObj = [];
let copy = {fileInfo:{"ogname":"","meme":""},fileData:""};
for(let i = 0 ; i < counters.localVar.counters.filesForUploadArr.length ; i++){
let tempObj = JSON.parse(JSON.stringify(copy));
let file = counters.localVar.counters.filesForUploadArr[i];
tempObj.fileInfo.ogname = file.name;
tempObj.fileInfo.meme = file.type;
tempObj.fileData = await readFile(file).then((file)=>{
file = btoa(file);
return file;
}).then((file)=>{
return file;
})
filesDataObj.push(tempObj);
}
return filesDataObj;
}
async function readFile (file){
const toBinaryString = file => new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsBinaryString(file);
reader.onload = () => resolve(reader.result);
reader.onerror = error => reject(error);
});
let parsedFile = null;
parsedFile = await toBinaryString(file);
return parsedFile;
}
/*From doPost downward, we read the file Array convert the base64 to blob and make a file in google drive using the blob and metadata we have, you may also see some sheet code, I'm using sheet as db for this */
//in buit function doPost in Code.gs
doPost(e){
const myDataObj = JSON.parse(e.postData.contents);
mainFileFunc(myDataObj.params[0].dataObj.images);
//the actual object structure might look different from yours, console log around
}
function mainFileFunc(fileArr) {
let myArrObj = [{"madeit":"toFileF"}];
let copy = JSON.parse(JSON.stringify(myArrObj[0]));
//sheet.getRange("A1").setValue(JSON.stringify(fileArr.length));
for(let i=0 ; i < fileArr.length ; i++){
myArrObj.push(copy);
let blob = doFileStuff(fileArr[i].data,fileArr[i].info[0].mime,fileArr[i].id);
myArrObj[i] = uploadFileOne(blob,fileArr[i].id);
myArrObj[i].mime = fileArr[i].info[0].mime;
myArrObj[i].realName = fileArr[i].name;
// sheet.getRange("A"+(i+1)).setValue(myArrObj[i].name);
// sheet.getRange("B"+(i+1)).setValue(myArrObj[i].url);
// sheet.getRange("C"+(i+1)).setValue(myArrObj[i].mime);
// sheet.getRange("D"+(i+1)).setValue(myArrObj[i].size);
}
return myArrObj;
}
function doFileStuff(filedata,filetype,filename){
var data = Utilities.base64Decode(filedata, Utilities.Charset.UTF_8);
var blob = Utilities.newBlob(data,filetype,filename);
return blob;
}
function uploadFileOne(data,filename) {
let myObj = {}
myObj["name"] = "";
myObj["realName"] = "Story_Picture";
myObj["url"] = "";
myObj["mime"] = "";
myObj["size"] = "";
myObj["thumb"] = "nonety";
var folders = DriveApp.getFoldersByName("LadhaWeb");
while (folders.hasNext()) {
var folder = folders.next();
folder.createFile(data);
}
var files = DriveApp.getFilesByName(filename);
while (files.hasNext()) {
var file = files.next();
myObj.name = file.getName();
myObj.url = file.getUrl();
myObj.mime = file.getMimeType();
myObj.size = file.getSize();
}
return myObj;
}
You can view the full frontend code for this project here and the backend here.
Hope this helps someone.

Protractor: use variable from helper file in spec file

I have perhaps unusual situation where I have to get text out of an element in a helper file and then compare this text in spec file. For example:
Both page files:
this.matchText = function(elem) {
return elem.getText();
};
Helper file:
// page objects
var calculationPage = require('../calculation_page/calculation_page.js');
// variables
var globalPrice = "";
module.exports = exports = function() {
describe('...
it('...
// initialize page object
var calculation = new calculationPage();
// store price into global variable
calculation.matchText(calculation.price).then(function(text) {
globalPrice = text;
});
// verify price equals expected
expect(calculation.matchText(calculation.priceSum)).toContain(globalPrice);
???
});
});
}
How to store globalPrice as a variable that could be passed to spec file?
Spec file:
// page objects
var homePage = require('../home_page/home_page.js');
// helpers
var getPrice = require('../helpers/get_price.js');
describe('...
it('...
// helper - get price
getPrice();
// initialize page object
var home = new homePage();
// verify if price equals expected
expect(home.matchText(home.price)).toContain(???);
});
});
How to read global variable from helper file in spec file?
You can dump any values you need globally onto Protractor global object - browser.
Lets say .. in helper file you need to store the value. Then do this - browser.globalPrice = text
And then this value would be available in your spec file. Access it from the browser object like any other value expect(home.matchText(home.price)).toContain(browser.globalPrice);
Please refer my answer #Protractor: initialise Global variable in one js and use the same var in other js

How can I delete a row from a Table in SAPUI5 Application when I used Model as XMLModel?

I have created SAPUI5 application, in that I have loaded data from external .xml file into a table, it was fine. Now, I am trying to delete a specific row from that table.
For this purpose, I use this code:
var oModel = new sap.ui.model.xml.XMLModel();
oModel.loadData("Deployments.xml", "", false);
sap.ui.getCore().setModel(oModel);
oTable.bindRows("/service"); // here "service" is the root element of xml file
var oTable = new sap.ui.commons.Button({
text: "Delete Service",
press: function() {
var idx = oTable.getSelectedIndex();
if (idx !== -1) {
var m = oTable.getModel();
var data = m.getData();
var removed = data.splice(idx, 1); // error showing at this line
m.setData(data);
sap.m.MessageToast.show(JSON.stringify(removed[0]) + 'is removed');
} else {
sap.m.MessageToast.show('Please select a row');
}
}
});
But, I am getting error at the line: var removed = data.splice(idx, 1);. However, the same code is good for when model is JSON. How can I delete a specific row from a table when model XMLModel?
It is a lot easier an more reliable to use a Bindings BindingPath to manipulate data belonging to a particular binding. Here is your adapted sample for a XMLModel:
press: function() {
var iIdx = oTable.getSelectedIndex();
var sPath = oTable.getContextByIndex(iIdx).getPath();
var oObj = oTable.getModel().getObject(sPath);
oObj.remove();
oTable.getModel().refresh();
}
This way you save the hazzle of dealing with the XML structure and furthermore this will scale with any change in the binding path you might introduce in the future.
BR
Chris
var data = m.getData();
data is not an Array. It is a XML document.
To remove an entry from the document:
var root = data.childNodes[0];
var aEntry = root.getElementsByTagName("entry");
root.removeChild(aEntry[idx]);

Export MS Word Document pages to Images

I want to export MS word(docx/doc) document pages to Image(jpeg/png).
I am doing same for presentation(pptx/ppt) using office interop export api for each slide, but didn't found corresponding API for word.
Need suggestion for API/alternate approach for achieving this.
Based on this similar question: "Saving a word document as an image" you could do something like this:
const string basePath = #"C:\Users\SomeUser\SomePath\";
var docPath = Path.Combine(basePath, "documentA.docx");
var app = new Application()
{
Visible = true
};
var doc = app.Documents.Open(docPath);
foreach (Window window in doc.Windows)
{
foreach (Pane pane in window.Panes)
{
for (var i = 1; i <= pane.Pages.Count; i++)
{
var page = pane.Pages[i];
var bits = page.EnhMetaFileBits;
var target = Path.Combine(basePath, string.Format("page-no-{0}", i));
using (var ms = new MemoryStream(bits))
{
var image = Image.FromStream(ms);
var pngTarget = Path.ChangeExtension(target, "png");
image.Save(pngTarget, ImageFormat.Png);
}
}
}
}
app.Quit();
Basically, I'm using the Page.EhmMetaFileBits property which, according to the documentation:
Returns a Object that represents a picture representation of how a
page of text appears.
... and based on that, I create an image and save it to the disk.