alfresco javascript inheritance and paths - javascript

I am writing a simple script on javascript for Alfresco Community. I have the script runnign everytime a new file is uploaded.
I need to check wether an specific filename (label.txt) exists in the folder. If it exists, I will use the information contained in the file for later treatment.
If I set the filename alone it works as long as the folder itself is the one with the script asigned, it works perfecly.
var labelFile = space.childByNamePath("label.txt");
if (labelFile != null)
{
...
}
When i set the inheritance of the script to lower level folders the script runs but still tries to find the label.txt file in the root folder. I am trying to locate the actual path of the uploaded document:
var dpath = document.displayPath + "/label.txt";
var labelFile = space.childByNamePath(dpath);
logFile.content += "labelFile: " + labelFile.displayPath + "\r\n";
if (labelFile != null)
{
...
}
I am getting a supposedly correct path in the dpath var, but I get a NULL result on the file object so I cannot read the file and its content.
What I am doing wrong?

What is "space" there? Try using "companyhome", see this for further ideas. http://docs.alfresco.com/4.0/references/API-JS-rootscoped.html
The current space ScriptNode (if any). For a script executing from a
rule, the space object is the space in which the rule resides. If the rule is inherited, this may not be the expected space.

The problem was not about inheritance, but space.childByNamePath just accepting relative paths, not absolute, so I ahd to calculate it from the space root:
var dpath = document.displayPath;
var dpatharray = dpath.split("/");
var dpathlength = dpatharray.length;
var spath = space.displayPath;
var spatharray = spath.split("/");
var spathlength = spatharray.length;
var labelpath = "";
for (var i=spathlength + 1; i<dpathlength; i++)
{
labelpath += dpatharray[i] + "/";
}
var labelFile = space.childByNamePath(labelpath + "label.txt");

Related

Javascript - How would you make a record unique by adding a number?

Right now when file already exist I added prefix which is a timestamp to the filename to make it unique.
But instead of using timestamp I want to use ordinal suffix or add a number to the filename.
I would add an incremented number to the filename if the file exists. But can't quite wrap my head around how to do this in a good way.
Using timestamp works but its too long like when we display the filename it would be like for example so instead of using timestamp I just want to increment a number to a filename.
Hellworldfilename - 1593024232 - timestamp is too long , not a good idea.
It should based from existing records in the database . If for example I add a file with filename Hellworldfilename and it already existed then the new filename would be Hellworldfilename-1 , and if I add Hellworldfilename again the new filename would be Hellworldfilename-2 and so on and so forth. Any idea how we can make a filename everytime unique ?
Let me give an example. let us say I have 3 files in the database with filesname
DOC
DOC-1
DOC-2
If I add a file with filename DOC the new filename would be now DOC-3.
#Code for checking if file exists
const file = await context.service.Model.findOne({
where: { humanId: record.id, filename: data.filename },
paranoid: false,
});
if (file) {
const prefix = Date.now().toString();
// eslint-disable-next-line no-undef
const fileParts = data.filename.split('.');
filename = `${fileParts[0]}-${prefix}.${fileParts[1]}`;
You will need to check whether the filename ends with -somenumber. If so, then you can extract that number and increment it. Otherwise put 1 into the result:
function getNumberedFileName(fileN) {
//These are value initializations to cope with the situation when the file does not have a .
var fileName = fileN;
var fileExtension = "";
var lastDotIndex = fileN.lastIndexOf(".");
if ((lastDotIndex > 0) && (lastDotIndex < fileN.length - 1)) { //We are not interested in file extensions for files without an extension hidden in UNIX systems, like .gitignore and we are not interested in file extensions if the file ends with a dot
fileName = fileN.substring(0, lastDotIndex);
fileExtension = "." + fileN.substring(lastDotIndex + 1);
}
var lastDashIndex = fileName.lastIndexOf("-");
if ((lastDashIndex > 0) && (lastDashIndex < fileName.length - 1)) {
var lastPart = fileName.substring(lastDashIndex + 1);
if (!isNaN(lastPart)) {
var index = parseInt(lastPart) + 1;
return fileName.substring(0, lastDashIndex) + "-" + index + fileExtension;
}
}
return fileName + "-1" + fileExtension;
}
You could declare an object filenames in the global scope like
const filenames={};
and use it for keeping track of already opened files.
Below I defined a function makeUnique() hilighting the ideas I mentioned here before. It turns out I had to tweak my code a little bit but here is a working snippet:
const makeUnique=(function(){
const filenames={};
return function(fn){
const fileParts=fn.split(".");
const prefix=filenames[fn]!=null
? ++filenames[fn]
: filenames[fn]=0;
if (prefix) fileParts[Math.max(fileParts.length-2,0)]+='-'+prefix;
return fileParts.join('.')
}
})();
console.log(["abc","d.e.f.c","abc","ghi","abc","abc.txt","def",
"abc.txt","d.e.f.c","abc.txt","abc"].map(makeUnique))
.as-console-wrapper {max-height:100% !important}
I used an IIFE to generate a protected scope for the static object filenames. This is now accessible by all calls of makeUnique() but otherwise "private", i. e. cannot be modified accidentally from anywhere else.

Convert path string from unc to uri, replacing slashes with backslashes in Google Apps Script

I need to convert a path this UNC. I have searched and search and cannot piece anything together.
"\\NAS_01\GlobalShare\Docs\Customers\2017\S\Smith, John\photo1.jpg"
I need to remove the "\NAS_01\GlobalShare\Docs\Customers\" portion of the path and also "photo1.jpg" and end up with:
2017\S\Smith, John\
so that I can pass it to the following function:
function getDriveFolderNoCreate(path, rootFolder) {
var name, folder, search, fullpath;
// Remove extra slashes and trim the path
fullpath = path.replace(/^\/*|\/*$/g, '').replace(/^\s*|\s*$/g, '').split("/");
// Always start with the main Drive folder
folder = rootFolder;
for (var subfolder in fullpath) {
name = fullpath[subfolder];
search = folder.getFoldersByName(name);
if (search.hasNext()) {
var folder = search.next;
var folderID = folder.getId();
return folderID;
}
}
}
My intention is to return a url to open the Google Drive folder with the same path.
I ended up with a multi-part solution that works very well.
I paste the fill UNC path to cell B2.
This formula is in B3 =Index(split(B2, "\"), 0, 8)
It returns the exact folder name i need.
Then in my gs file:
function findDriveFolder() {
var pFId = "XYZ1233333333333";
var input = SpreadsheetApp.getActive().getRange("B3").getValue();
var folders = DriveApp.getFoldersByName(input);
Logger.log("folders: " + folders[0]);
while (folders.hasNext()) {
var folder = folders.next();
var url = folder.getUrl();
showAnchor("View Folder", url);
}
}
function showAnchor(name,url) {
var html = '<html><body>'+name+'</body></html>';
var ui = HtmlService.createHtmlOutput(html)
SpreadsheetApp.getUi().showModelessDialog(ui,"Files Folder");
}
I have not implemented the searchFolders part yet that I hope will speed it up. At least it's working for now.
Apps Script needs your input backslashes to be escaped if you are writing the string yourself (i.e. testing input).
wrong:
input = "\\NAS_01\GlobalShare\Docs\Customers\2017\S\Smith, John\photo1.jpg"
right:
input = "\\\\NAS_01\\GlobalShare\\Docs\\Customers\\2017\\S\\Smith, John\\photos1.jpg"
In Apps Script then, I am able to get the matching portion with the following regex:
/\d{4}\\[A-Z]\\.+\\/
i.e:
function unc2uri(input) {
const forwardSlash = String.fromCharCode(47);
const backSlash = String.fromCharCode(92);
if(!input)
input = '\\\\NAS_01\\GlobalShare\\Docs\\Customers\\2017\\S\\Smith, John\\photo1.jpg';
// Should show \\NAS_01\GlobalShare\Docs\Customers\2017\S\Smith, John\photo1.jpg
Logger.log(input);
const matcher = /\d{4}\\[A-Z]\\.+\\/;
const arrayOfMatches = input.match(matcher);
// Should show [2017\S\Smith, John\].
Logger.log(arrayOfMatches);
}
To verify, ask for the input string from someplace else (example, Browser.inputBox) and pass that to the above as input:
function readInput() {
unc2uri(Browser.inputBox("What's the path?"));
}
In the inputBox, you would enter the string you expect to be sent, as we view it, i.e. \\NAS_01\GlobalShare\Docs\Customers\2017\S\Smith, John\photo1.jpg

Recursive processing of a directory not working correctly

I've been combing this forum looking at other examples of code similar to mine but I still have not been able to solve the issue.
I am processing images in Fiji/imageJ using a macro code. The code is meant to recursively search a given directory for image files (in this case .vsi files) and convert them to .tiff using the built in bioformats functions.
I have cobbled the following code together from several examples (I am not a programmer, I have a biology degree), and I am returning an error that the specified file does not exist just as I am about to actually process a file.
All of my images have the following general directory structure:
~/Brain_01/Slice_01/Slice_01_01.vsi
An actual example is as follows for the second image in this set:
~/K259_tlx3cre/K259_1of3_02/K259_1of3_01_02.vsi
I really, really appreciate all the help you guys provide! I am completely stuck right now and am just banging my head against the keyboard at this point. Also, I think I've followed all the rules for posting. If not please just point out the error of my ways.
Finally here is the macro code I have written so far:
Dialog.create("File type");
Dialog.addString("File suffix: ", ".vsi", 5);
Dialog.show();
suffix = Dialog.getString();
inDir = getDirectory("Choose Directory Containing " + suffix + " Files ");
outDir = getDirectory("Choose Directory for TIFF Output ");
setBatchMode(true);
processFiles(inDir, outDir, "");
print("Done!");
function processFiles(inBase, outBase, sub) {
flattenFolders = false; // this flag controls output directory structure
print("Processing folder: " + sub);
list = getFileList(inBase + sub);
if (!flattenFolders) File.makeDirectory(outBase + sub);
for (i=0; i<list.length; i++) {
path = sub + list[i];
//upath = toUpperCase(path);
upath = path; //the previous line cause some problems
if (endsWith(path, "/")) {
processFiles(inBase, outBase, path);
}
else if (endsWith(upath, suffix)) {
print("Importing " + suffix + " = " + list[i]);
run("Bio-Formats Windowless Importer", "open=path color_mode=Default view=Hyperstack stack_order=XYCZT");
print("Blue...");
selectImage(1);
title1 = getTitle();
run("Blue");
print("Green...");
selectImage(2);
title2 = getTitle();
run("Green");
print("Red...");
selectImage(3);
title3 = getTitle();
run("Red");
print("Merging Channels...");
run("Merge Channels...", "red=&title3 green=&title2 blue=&title1 gray=*None* cyan=*None* magenta=*None* yellow=*None* create keep");
print("Converting to RGB");
run("RGB Color");
saveAs("Tiff", path);
run("Close All");
}
}
}
Thanks to some great help from Jan, and the people on the ImageJ mailing list, I was able to get my code working well enough to do what I need to do! The code below is working well enough to batch convert a directory full of .vsi files to .tiff using the functions I need. I haven't tried changing my code to Michael's suggestion to change endsWith(path, "/"... if i get that working in the future I will post it also.
Dialog.create("File type");
Dialog.addString("File suffix: ", ".vsi", 5);
Dialog.show();
suffix = Dialog.getString();
inDir = getDirectory("Choose Directory Containing " + suffix + " Files ");
outDir = getDirectory("Choose Directory for TIFF Output ");
setBatchMode(true);
processFiles(inDir, outDir, "");
print("Done!");
function processFiles(inBase, outBase, sub) {
flattenFolders = true; // this flag controls output directory structure
print("Processing folder: " + sub);
list = getFileList(inBase + sub);
if (!flattenFolders) File.makeDirectory(outBase + sub);
for (i=0; i<list.length; i++) {
path = sub + list[i];
//upath = toUpperCase(path); only need if the file extension is case sensitive
upath = path; //avoids the previous line
if (endsWith(path, "/")) {
processFiles(inBase, outBase, path);
}
else if (endsWith(upath, suffix)) {
print("Importing " + suffix + " = " + list[i]);
run("Bio-Formats Windowless Importer", "open=["+inBase + path+"] color_mode=Default view=Hyperstack stack_order=XYCZT");
print("Stack to Images...");
run("Stack to Images");
print("Blue...");
selectImage(1);
title1 = getTitle();
run("Blue");
print("Green...");
selectImage(2);
title2 = getTitle();
run("Green");
print("Red...");
selectImage(3);
title3 = getTitle();
run("Red");
print("Merging Channels...");
run("Merge Channels...", "red=&title3 green=&title2 blue=&title1 gray=*None* cyan=*None* magenta=*None* yellow=*None* create keep");
print("Converting to RGB");
run("RGB Color");
saveAs("Tiff", outBase + path);
run("Close All");
}
}
}
By looking at the error message you get, you should be able to spot the issue: while your file sits at e.g. inBase + sub + list[i], your path variable contains just sub + list[i]. So you should use something like:
run("Bio-Formats Windowless Importer", "open=[" + inBase + path + "] color_mode=Default view=Hyperstack stack_order=XYCZT");
for opening the file, and:
saveAs("Tiff", outBase + path);
for saving the output file.
If you also want to use the flattenFolders flag in your code, you should build your output path dependent on the state of flattenFolders, such as:
outputPath = outBase;
if (!flattenFolders) outputPath += sub;
outputPath += list[i];
By the way, there's no need to convert your path to uppercase with toUpperCase(path), unless you want to use a case-insensitive file suffix. In that case, you can write:
if (endsWith(toUpperCase(path), toUpperCase(suffix))) {
// process your file here
}
to allow both .vsi and .VSI as an input.
Note: The script editor of the Fiji distribution of ImageJ offers a macro template to process folders recursively, you can open it via Templates > Macros > Process Folder in the editor.

Is there a way to limit number of characters in input type file

I have an input of type file, my question is: after I select the file, can the file name be limited to a certain number of characters ?
You can get the file name using
var filename = document.getElementById('file-id').value;
filename = filename.replace(/^.*[\\\/]/, '');
But limitation in sense, after uploading the file you can get the file name using above approach.
Then you can have
if (filename.length < 100 ) {
//do something
}
FYI: Evert thing happens only after the file being uploaded in client side. There is no use in limiting the filepath before uploaded to server.
Do you mean like this?
var limit = 8;
var fileName = document.getElementById("file-name-field").value();
// get both parts
var fileNameExtension = "." + fileName.split(".").pop();
var fileNameBase = fileName.substring(0, fileName.length()-fileNameExtension.length());
if(fileNameBase.length()>limit){
// now limit it and set it as fileName
fileName = fileNameBase.substring(0, limit) + fileNameExtension;
}
Most browsers don't allow modification of the value attribute of file fields. It's a security hole, because it would allow a malicious page to retrieve an arbitrary file using a hidden field.
Please try following JavaScript to check length of the file name.
function valueCheck()
{
var filePath = document.getElementById("file").value;
var fileName = filePath.replace(/[^\\\/]+$/, "");
if(fileName !=null && fileName.length >10)
{
alert('Filename if bigger');
}
}
Demo URL : http://jsfiddle.net/BhaveshKachhadiya/6EPvg/6/

How do I change file extension with javascript

Does anyone know an easy way to change a file extension in Javascript?
For example, I have a variable with "first.docx" but I need to change it to "first.html".
This will change the string containing the file name;
let file = "first.docx";
file = file.substr(0, file.lastIndexOf(".")) + ".htm";
For situations where there may not be an extension:
let pos = file.lastIndexOf(".");
file = file.substr(0, pos < 0 ? file.length : pos) + ".htm";
In Node.js:
path.join(path.dirname(file), path.basename(file, path.extname(file)) + '.md')
or more readably:
// extension should include the dot, for example '.html'
function changeExtension(file, extension) {
const basename = path.basename(file, path.extname(file))
return path.join(path.dirname(file), basename + extension)
}
Unlike the accepted answer, this works for edge cases such as if the file doesn't have an extension and one of the parent directories has a dot in their name.
I'd use this:
path.format({ ...path.parse('/path/to/file.txt'), base: '', ext: '.md' })
to change "/path/to/file.txt" to "/path/to/file.md".
file = file.replace(/\.[^.]+$/, '.html');
This probably won't get many upvotes but I couldn't resist.
This code will deal with the edge case where a file might not have an extension already (in which case it will add it). It uses the "tilde trick"
function changeExt (fileName, newExt) {
var _tmp
return fileName.substr(0, ~(_tmp = fileName.lastIndexOf('.')) ? _tmp : fileName.length) + '.' + newExt
}
EDITED: thanks #kylemit for a much better gist which uses the same logic, but in a much much neater way:
function changeExt(fileName, newExt) {
var pos = fileName.includes(".") ? fileName.lastIndexOf(".") : fileName.length
var fileRoot = fileName.substr(0, pos)
var output = `${fileRoot}.${newExt}`
return output
}
console.log(changeExt("img.jpeg", "jpg")) // img.jpg
console.log(changeExt("img.name.jpeg", "jpg")) // img.name.jpg
console.log(changeExt("host", "csv")) // host.csv
console.log(changeExt(".graphqlrc", "graphqlconfig")) // .graphqlconfig
path.parse("first.docx").name + ".html"
var file = "first.docx";
file = file.split(".");
file = file[0]+".html";

Categories