Skip to Content

Back to Getting Started With Kapsel

Document Service

The SAP Cloud Platform document service provides an on-demand content repository for unstructured or semi-structured content. Applications access it using the OASIS standard protocol Content Management Interoperability Services (CMIS).

Document Service Sample App

The following example will enable the document store to be browsed and modified from a Kapsel app.

  • Replace Replace www\index.html with
    <!DOCTYPE html>
    <html>
        <head>
            <meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width">
            <script type="text/javascript" charset="utf-8" src="serverContext.js"></script>
            <script type="text/javascript" charset="utf-8" src="cordova.js"></script>
            <!--Required by Document Service-->
            <script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
            <script src="https://svn.apache.org/repos/asf/chemistry/parts/trunk/cmis-js/lib/cmis.js"></script>
            <script>
                var applicationContext = null;
                
                window.onerror = onError;
                
                function onError(msg, url, line) {
                    var idx = url.lastIndexOf("/");
                    var file = "unknown";
                    if (idx > -1) {
                        file = url.substring(idx + 1);
                    }
                    alert("An error occurred in " + file + " (at line # " + line + "): " + msg);
                    return false; //suppressErrorAlert;
                }
                
                function init() {
                    updateStatus1("Calling Logon.init");
    
                    if (sap.Logger) {
                        sap.Logger.setLogLevel(sap.Logger.DEBUG);  //enables the display of debug log messages from the Kapsel plugins.
                        sap.Logger.debug("EventLogging: Log level set to DEBUG");
                    }
                    
                    if (navigator.notification) { // Override default HTML alert with native dialog. alert is not supported on Windows
                        window.alert = navigator.notification.alert;
                    }
                    
                    sap.Logon.init(logonSuccessCallback, logonErrorCallback, appId, context);
                    console.log("EventLogging: init completed");
                }
                
                function logonSuccessCallback(result) {
                    updateStatus1("logonSuccessCallback called");
    
                    console.log("EventLogging:  logonSuccessCallback " + JSON.stringify(result));
                    applicationContext = result;
                    connectCMIS("/");
                    showScreen("MainDiv");
                }
    
                function logonErrorCallback(error) {   //this method is called if the user cancels the registration.
                    alert("An error occurred:  " + JSON.stringify(error));
                    if (device.platform == "Android") {  //Not supported on iOS
                        navigator.app.exitApp();
                    }
                }
    
                function errorCallback(e) {
                    alert("An error occurred: " + JSON.stringify(e));
                    console.log("EventLogging: errorCallback " + JSON.stringify(e));
                    showScreen("MainDiv");
                }
    
                function showScreen(screenIDToShow) {
                    var screenToShow = document.getElementById(screenIDToShow);
                    screenToShow.style.display = "block";
                    var screens = document.getElementsByClassName('screenDiv');
                    for (var i = 0; i < screens.length; i++) {
                        if (screens[i].id != screenToShow.id) {
                            screens[i].style.display = "none";
                        }
                    }
                }
    
                function updateStatus1(msg) {
                    document.getElementById('statusID').innerHTML = msg + " ";
                    console.log("EventLogging: " + msg + " ");
                }
                
                function addZero(input) {
                    if (input < 10) {
                         return "0" + input;
                    }
                    return input;
                }
                
                function onLoad() {
                    console.log("EventLogging: onLoad");
                    var fileUpload = document.getElementById("file");
                    fileUpload.onchange = function(e) { //trigger the logic to get a name of the selected file and start to upload the image after something was selected with the file input element.
                        uploadImage();
                    }
                }
    
                function onPause() {
                    console.log("EventLogging: onPause");
                }
    
                function onResume() {
                    console.log("EventLogging: onResume");
                }
    
                function onSapResumeSuccess() {
                    console.log("EventLogging: onSapResumeSuccess");
                }
    
                function onSapLogonSuccess() {
                    console.log("EventLogging: onSapLogonSuccess");
                }
    
                function onSapResumeError(error) {
                    console.log("EventLogging: onSapResumeError " + JSON.stringify(error));
                }
                
                document.addEventListener("deviceready", init, false);
                document.addEventListener("pause", onPause, false);
                document.addEventListener("resume", onResume, false);
                document.addEventListener("onSapResumeSuccess", onSapResumeSuccess, false);
                document.addEventListener("onSapLogonSuccess", onSapLogonSuccess, false);
                document.addEventListener("onSapResumeError", onSapResumeError, false);
    
                //CMIS
                var cmisURL;
                var session;
                var rootObject;
                var myfileId;
                var currentFolder;
                
                // Establish a connection with the Document Service 
                // and try to download the image of the product
                function connectCMIS(fname) {
                    cmisURL = "https://" + applicationContext.registrationContext.serverHost + "/mobileservices/persistence/v1/json/" + appId;
                    session = cmis.createSession(cmisURL + "/$metadata?rand=" + Math.random());
    
                    session.setCredentials(applicationContext.registrationContext.user, applicationContext.registrationContext.password).loadRepositories( {
                        request : {
                            success : function(data) {
                                updateStatus1("Connected to Document Service ");
                                //once the connection has been established, it gets the root object
                                getRootObject(fname);
                            },
                            error : function(e) {
                                if (e.responseJSON)
                                    console.log( "Error during the request: " + e.responseJSON.message);
                                else
                                    console.log( "Error during the request: " + e.statusText);
                            }
                        }
                    });
                }
    
                //Gets a reference to the root directory to be able to navigate through the repository
                function getRootObject(fname) {
                    session.getObjectByPath("/", {
                        includeRelationships : 'both',
                        request : {
                            success : function(data) {
                                console.log("Get Object By Path: SUCCESS");
                                console.log("Get Object By Path", JSON.stringify(data));
                                rootObject = data;
                                console.log("Root:"+ data.properties['cmis:name'].value +" "+ data.properties['cmis:objectId'].value);
                                currentFolder = "/";
                                //Once the root directory is accessible, it tries to download 
                                //an image associated with the product name
                                //showPictureByName(fname);
    
                            },
                            error : function(e) {
                                console.log("Error during the request: " + e.responseJSON.message);
                            }
                        }
                    });
                }
    
                //Ask the user to enter a name, search for it in the current diretory and if found display on the screen
                function showPictureByName() {
                    setImageProperties("ProductImg", true, "");  //clear any previously displayed picture by setting the URL to empty.
                    navigator.notification.prompt(
                        'Enter the name of the image to show',  // message
                        onPrompt,                // callback to invoke
                        'Show Image',            // title
                        ['Ok','Exit'],           // buttonLabels
                        ''                       // defaultText
                    );
                    
                    function onPrompt(results) {
                        if (results.buttonIndex == 1) {
                            updateStatus1("Attempting to show image " + results.input1);
                            var randParam = "?rand=" + Math.random();
                            var url = "https://" + applicationContext.registrationContext.serverHost + "/mobileservices/persistence/v1/json/" + appId + currentFolder;
                            var xmlhttp = new XMLHttpRequest();
    
                            xmlhttp.onreadystatechange = function() {
                                if (xmlhttp.readyState == 4) {
                                    if (xmlhttp.status == 200) {
                                        var children = obj = JSON.parse(this.responseText);
                                        for (var i = 0; i < children.objects.length; i++) {
                                            if (children.objects[i].object.properties['cmis:objectTypeId'].value == "cmis:document") {
                                                if (children.objects[i].object.properties['cmis:name'].value == results.input1) {
                                                    var url2 = cmisURL + "?objectId="+children.objects[i].object.properties['cmis:objectId'].value +"&cmisselector=content";
                                                    setImageProperties("ProductImg", true, url2);
                                                    updateStatus1(results.input1 + " displayed");
                                                    break;
                                                }
                                            }
                                            if (i == children.objects.length - 1) {
                                                updateStatus1("Image " + results.input1 + " not found");
                                            }
                                        }
                                        if (children.objects.length == 0) {
                                            updateStatus1("No images found");
                                        }
                                    }
                                }
                            }
    
                            xmlhttp.open("GET", url + randParam, true);
                            xmlhttp.setRequestHeader("Accept", "application/xml");  //setting this so it is easier to view response in Network > Preview tab.
                            xmlhttp.send();
                        }
                    }
    
                }
    
                //Ask the user to enter a name, delete it from the current diretory 
                function deletePictureByName() {
                    setImageProperties("ProductImg", false, "");  //clear any previously displayed picture by setting the URL to empty.
                    navigator.notification.prompt(
                        'Enter the name of the image to delete from the current folder',  // message
                        onPrompt,                // callback to invoke
                        'Delete Image',            // title
                        ['Ok','Exit'],           // buttonLabels
                        ''                       // defaultText
                    );
                    
                    function onPrompt(results) {
                        if (results.buttonIndex == 1) {
                            updateStatus1("Attempting to delete image " + results.input1);
                            var randParam = "?rand=" + Math.random();
                            var url = "https://" + applicationContext.registrationContext.serverHost + "/mobileservices/persistence/v1/json/" + appId + currentFolder;
                            var xmlhttp = new XMLHttpRequest();
    
                            xmlhttp.onreadystatechange = function() {
                                if (xmlhttp.readyState == 4) {
                                    if (xmlhttp.status == 200) {
                                        var children = obj = JSON.parse(this.responseText);
                                        for (var i = 0; i < children.objects.length; i++) {
                                            if (children.objects[i].object.properties['cmis:objectTypeId'].value == "cmis:document") {
                                                if (children.objects[i].object.properties['cmis:name'].value == results.input1) {
                                                    updateStatus1("Calling Delete on " + session.deleteObject(children.objects[i].object.properties['cmis:objectId'].value));
                                                    session.deleteObject(children.objects[i].object.properties['cmis:objectId'].value, true /*, options*/);
                                                    refreshList();
                                                    break;
                                                }
                                            }
                                            if (i == children.objects.length - 1) {
                                                updateStatus1("Image " + results.input1 + " not found");
                                            }
                                        }
                                        if (children.objects.length == 0) {
                                            updateStatus1("No images found");
                                        }
    
                                    }
                                }
                            }
    
                            xmlhttp.open("GET", url + randParam, true);
                            xmlhttp.setRequestHeader("Accept", "application/xml");  //setting this so it is easier to view response in Network > Preview tab.
                            xmlhttp.send();
                        }
                    }
                }
    
                //Create an image in the repository 
                function uploadImage() {
                    console.log("trying to get picture");
                    var file = document.getElementById("file").files[0];
                    navigator.notification.prompt(
                        'Enter the name of the image',  // message
                        onPrompt,                // callback to invoke
                        'Image Name',            // title
                        ['Ok','Exit'],           // buttonLabels
                        file.name                // defaultText
                    );
    
                    function onPrompt(results) {
                        if (results.buttonIndex == 1) {
                            var fname = results.input1;
                            var file = document.getElementById("file").files[0];
                            uploadFile(file, fname);
                        }
                        var fileUpload = document.getElementById("file");
                        fileUpload.value = ""; //if not set, unable to upload the same image twice.
                    }
                }
    
                function uploadFile(file, filename) {
                    var folderId = rootObject.properties['cmis:objectId'].value;
    
                    session.createDocument(folderId, file, filename , "image/jpeg", "major", null, null, null, {
                        request : {
                            success : function(data) {
                                myfileId = data.properties["cmis:objectId"].value;
                                console.log( "Create Document: SUCCESS");
                                
                                //upload content
                                session.setContentStream(myfileId, file, true, "image/jpeg", {
                                    request : {
                                        success : function(data) {
                                            fileId = data.properties["cmis:objectId"].value;
                                            console.log("Set Content Stream: SUCCESS");
                                            updateStatus1("Uploaded " + filename);
                                            refreshList();
                                        },
                                        error : function(e) {
                                            updateStatus1("Failed to upload image: " + e.statusText);
                                        }
                                    }
                                });
                            },
                            error : function(e) {
                                updateStatus1("Failed to upload image: " + e.statusText);
                            }
                        }
                    })
                }
    
                function showPictureById(fileId){
                    var url = cmisURL + "?objectId=" + fileId + "&cmisselector=content";
                    setImageProperties("ProductImg", true, url);
                }
    
                function setImageProperties(id, visible, url) {
                    var img = document.getElementById(id);
                    img.style.visibility = (visible ? 'visible' : 'hidden');
                    img.src = url;
                }
    
                //Allows lists the files of the root of the repository or one level deep folder.
                function listFiles(subFolderToOpen, previousFolder) {
                    updateStatus1("Updating File List");
                    setImageProperties("ProductImg", false, "");
                    var sfToOpen = subFolderToOpen;
    
                    if (previousFolder == undefined) {
                        previousFolder = "";
                    }
                    if (sfToOpen == undefined) {  
                        sfToOpen = ""; 
                    }
                    else if (subFolderToOpen == "..") { //goback one level
                        previousFolder = previousFolder.substring(0, previousFolder.lastIndexOf("/"));
                        sfToOpen = "";
                    }
                    var randParam = "?rand=" + Math.random();
                    var url = "https://" + applicationContext.registrationContext.serverHost + "/mobileservices/persistence/v1/json/" + appId + "/" + previousFolder + '/' + sfToOpen;
                    var xmlhttp = new XMLHttpRequest();
    
                    xmlhttp.onreadystatechange = function() {
                        if (xmlhttp.readyState == 4) {
                            if (xmlhttp.status == 200) {
                                var children = obj = JSON.parse(this.responseText);
                                var prevFolder = "";
                                if (previousFolder) {
                                    prevFolder = previousFolder;                                                                        
                                }
                                if (sfToOpen) {
                                    prevFolder = prevFolder + "/" + sfToOpen;             
                                }
                                
                                var str = '';
                                //decide when to include a .. to navigate back.  
                                if (subFolderToOpen == undefined || (subFolderToOpen == ".." && previousFolder == "")) {
                                    str = '<ul>';
                                }
                                else {
                                    var deleteIndex = prevFolder.lastIndexOf("/");
                                    var url3 = prevFolder.substring(0, deleteIndex);
                                    str = '<ul><li><a href="javascript:void(0)" onclick="getObject(\'' + url3 + '\'); listFiles(\'..\', \'' + prevFolder + '\')">.. (Folder)</a></li>';
                                }
    
                                for (var i = 0; i <children.objects.length; i++) {
                                    if (children.objects[i].object.properties["cmis:baseTypeId"].value == 'cmis:folder') {
                                        var folderName = children.objects[i].object.properties["cmis:name"].value;
                                        var url2 = prevFolder + '/' + folderName;
                                        str += '<li><a href="javascript:void(0)" onclick="getObject(\'' + url2 + '\'); listFiles(\'' + folderName + '\', \'' + prevFolder + '\')">' + folderName + ' (Folder)</a></li>';
                                        
                                    } else {
                                        var name = children.objects[i].object.properties["cmis:name"].value;
                                        str += '<li><a target= "_blank" href="' + url + "/" + name + randParam + '">' + name + '</a></li>';
                                    }
                                }
                                str += "</ul>";
                                document.getElementById("listID").innerHTML = str;
                                updateStatus1("File List Updated");
                            }
                            else {
                                updateStatus1("Request to List files returned " + xmlhttp.status);
                            }
                        }
                    }
    
                    xmlhttp.open("GET", url + randParam, true);
                    xmlhttp.setRequestHeader("Accept", "application/xml");  //setting this so it is easier to view response in Network > Preview tab.
                    xmlhttp.send();
                }
    
                function getObject(path) {
                    if (path == "") {
                        path = "/";
                    }
                    session.getObjectByPath(path, {
                        includeRelationships : 'both',
                        request : {
                            success : function(data) {
                                console.log("Get Object By Path: SUCCESS");
                                console.log("Get Object By Path", JSON.stringify(data));
                                rootObject = data;
                                console.log("Root:"+ data.properties['cmis:name'].value +" "+ data.properties['cmis:objectId'].value);
                                currentFolder = path;
                            },
                            error : function(e) {
                                console.log("Error during the request: " + e.responseJSON.message);
                            }
                        }
                    });
                }
    
                function refreshList() {
                    if (currentFolder.length == 1) {
                        listFiles();
                    } else {
                        var lastSlash = currentFolder.lastIndexOf("/");
                        var subFolderToOpen = currentFolder.substring(lastSlash + 1);
                        var previousFolder;
                        if (lastSlash == 0) {
                            previousFolder = "";
                        } else {
                            previousFolder = currentFolder.substring(0, lastSlash);
                        }
                        listFiles(subFolderToOpen, previousFolder);
                    }
                    console.log("Current Folder: " + currentFolder);
                }
    
            </script>
        </head>
        <body onLoad="onLoad()">
            <div class="screenDiv" id="LoadingDiv">
                <h1>Loading ...</h1>
            </div>
            <div class="screenDiv" id="MainDiv" style="display: none">
                <h2>Document Service Sample</h2>
                <span id="statusID"></span><br>
                <hr>
                <button onClick="listFiles(); getObject('/')">List Files</button>
                <button id="showImage" onClick="showPictureByName()">Show Image</button>
                <input type="file" id="file" accept="image/*" style="display:none;"></input>
                <input type="button" id="loadFile" value="Upload Image" onclick="document.getElementById('file').click();" />
                <button id="deleteImage" onClick="deletePictureByName()">Delete Image</button>
                <span id="listID"></span><br>
                <img id="ProductImg" height="100" width="100" src=""  style="float: none;visibility: hidden"><br>
            </div>
            <div class="screenDiv" id="UploadDiv" style="display: none">
            </div>
        </body>
    </html>​
  • Add the attachment viewer plugin.
    cordova plugin add kapsel-plugin-attachmentviewer --searchpath %KAPSEL_HOME%/plugins
    or
    cordova plugin add kapsel-plugin-attachmentviewer --searchpath $KAPSEL_HOME/plugins
  • If deploying to iOS, edit the plist file and add the following entry.
    <key>NSPhotoLibraryUsageDescription</key>
    <string>Upload images to the SAP Cloud Platform Document Service</string>
    <key>NSCameraUsageDescription</key>
    <string>Upload images to the SAP Cloud Platform Document Service</string>
  • Prepare, build and deploy the app with the following command.
    cordova run android
    or
    
    cordova run ios
    
    or
    cordova run windows -- --archs=x64
    or
    cordova run windows --device -- --archs=arm --phone
    
    
  • Click on Upload Image to upload an image to the document store.

    Note the android.png link can be clicked on to open the image in a new window or it can be shown on the same page using the Show Image button.
  • The SAP Cloud Platform Mobile Services cockpit enables the browsing and modifying of the document service.  Each application has its own document service.
    Click on Mobile Applications -> Native/Hybrid.
    Choose the application you want to add the Document Service to. On the Assigned Features list, click on the add symbol on the top right. Add the Document Repository feature.

    Note, it is possible to create a set of folders and sub-folders with the management cockpit UI.

Back to Getting Started With Kapsel

To report this post you need to login first.

Be the first to leave a comment

You must be Logged on to comment or reply to a post.

Leave a Reply