Problem assigning an fileidlist to a category

Started by Carlo Didier, November 22, 2017, 08:11:08 AM

Previous topic - Next topic

Carlo Didier

This code doesn't work. It always throws an error on the IMatch.post (full script attached, relevant lines are from 92-182):
...
                response.categories.forEach(objCategory => {
                    var objNewCategory = {
                        ID           : objCategory.id,
                        Name         : objCategory.name,
                        Description  : objCategory.description,
                        StartIndex   : objCategory.description.substr( 0,12),
                        EndIndex     : objCategory.description.substr(13,12),
                        FileIDs      : []
                    }
                    arrCategories.push(objNewCategory);
                });
...
                            arrCategories[idxCat].FileIDs.push(intFileID);
...
                for (idxCat = 0; idxCat < arrCategories.length; idxCat++) {
                    objCategory = arrCategories[idxCat]
                    if (objCategory.FileIDs.length > 0) {
                        console.log(JSON.stringify(objCategory.ID + " " + objCategory.Name + ": " + objCategory.FileIDs));
                        IMatch.post('v1/categories/assign',{
                            id: objCategory.ID,
                            fileidlist: objCategory.FileIDs
                        }).then(function(response) {
                            console.log(JSON.stringify(response,null,2));
                            if (response.result != 'ok') {
                                console.log(JSON.stringify(response,null,2));
                            }
                        },
                        function(error){
                            console.log(error);
                            console.log(JSON.stringify(error));
                        });
                    }
                }
...


Mario

#1
IMWS tells you in the error message that no files are specified and it is right.

What do you intent by this statement:

fileidlist: objCategory.FileIDs

This cannot work. When you use the fileidlist parameter you must specify the name of an existing id list, not some cooked up array you create in your code.

It looks like you want to hand over a list of ids you collect in your script. If so, just  use the fileid parameter. This parameter takes a comma-separated list of file ids (or ranges).

Probable you meant to do a

fileid: arrCategories[idxCat].FileIDs.join(',')

This takes the arrCategories[idxCat].FileIDs and produces a comma-separated list from it's elements.

Please pay close attention which parameters you use and for which purpose. id is not the same as idlist.

Tip: If you use Chrome/FF debuggers, they show you in the Net(work) tab which parameters you have sent to the server (request header). This reveals quickly when you do something wrong.
-- Mario
IMatch Developer
Forum Administrator
http://www.photools.com  -  Contact & Support - Follow me on 𝕏 - Like photools.com on Facebook

Carlo Didier

Quote from: Mario on November 22, 2017, 09:12:03 AM
fileid: arrCategories[idxCat].FileIDs.join(',')

That was the missing part! I had tried "fileid" too but that didn't work either and I found no detailed explication how the list of IDs should be formated.
It's a bit confusing that the "fileid" parameter can also take list of IDs, just as the "fileidlist", but in some other form ...

Thanks for your help!

Carlo Didier

If I'd now get that progress bar working, everything would be perfect ...

Mario

An idlist is not the same as id.
The format and usage of id, idlist, path is identical for each endpoint.

See the Progress Bar example to lean how to make a progress bar.
Also refer to the Boostrap documentation for progress bars: https://getbootstrap.com/docs/3.3/components/#progress
In short: Set the width of your progress bar to something between 0 and 100. Not hard to do using jQuery
-- Mario
IMatch Developer
Forum Administrator
http://www.photools.com  -  Contact & Support - Follow me on 𝕏 - Like photools.com on Facebook

Carlo Didier

I have taken the progress bar parts from the sample app. It displays, but it doesn't update in the app window until all is done. That's the problem.

Btw, without all the console.log()s for checking, I now ran the script over the whole DB, which means 99111 files, in 40 seconds flat. Not bad.
I don't think I'll need a progress bar for that, but it would still be nice to have it.

Mario

Do you update your progress bar?
Did you solve the "thousands of POST request problem"? This may block your browser so the progress bar is unable to update...
-- Mario
IMatch Developer
Forum Administrator
http://www.photools.com  -  Contact & Support - Follow me on 𝕏 - Like photools.com on Facebook

Carlo Didier

Quote from: Mario on November 22, 2017, 11:09:10 AM
Do you update your progress bar?
Yes:
valPercentage = 90 + ((idxCat * 100) / arrCategories.length / 10);  // we consider these to be the last 10%
console.log(Math.floor(valPercentage) + '%');
$('#pbar').css('width',valPercentage + '%');
$('#pbar').text(Math.floor(valPercentage) + '%');

Full script attached.

Quote from: Mario on November 22, 2017, 11:09:10 AM
Did you solve the "thousands of POST request problem"? This may block your browser so the progress bar is unable to update...
I followed your suggestion and work with an array that collects the fileids per category and then does a single post per category (only if there are files to assign).

The first 90% of the progress bar should run during the loop that compares files with categories and there is no webservice call in that loop anymore.
How can I give the browser time to update? As far as I've found, there is no real way to make a javascript pause ...
And I don't understand how the sample app gives that time to the browser.

Mario

1. I noticed several bad HTML syntax errors. This makes the browser "guess" what the right HTML should be and the results may be not what you intent.
I recommend you install the HTMLHint and ESLint extensions into Visual Studio Code. They will show you syntax errors in HTML and JavaScript in the source code and the "Problem" panel.

2. It sees you update the progress bar in this very tight loop (line 123):

arrFiles.forEach(objFile => {

This is not asynchronous  ;) but runs in the browser's UI thread. No scheduling or yielding takes place, or UI updates possible during that loop. Hence, no scroll bar updating.

A typical solution would be to modify your code to use the next()... approach and break the loop up:

1. The loop is changed to call a function that does the next step:

arrFiles.forEach(objFile => {

   window.setTimeOut(() => {
     processNext(objFile);
   },5);

});

2. The setTimeout waits for the given number of milliseconds (5 in this case) before it calls processNext with the next file.
This short delay gives the browser UI thread a bit of time to update the user interface.
This method is used in the ProcessFiles and ProgressBar examples I referred to in my posts.
-- Mario
IMatch Developer
Forum Administrator
http://www.photools.com  -  Contact & Support - Follow me on 𝕏 - Like photools.com on Facebook

Carlo Didier

Quote from: Mario on November 22, 2017, 01:19:48 PM
This method is used in the ProcessFiles and ProgressBar examples I referred to in my posts.
Ah, ok. I thought that was just so that the app doesn't rush from 0% to 100% in a fraction of a second, which would make the "progress" in the progress bar too fast to see.

I think I'll just leave the progress bar out then.

Carlo Didier

Quote from: Mario on November 22, 2017, 01:19:48 PM
I recommend you install the HTMLHint and ESLint extensions into Visual Studio Code. They will show you syntax errors in HTML and JavaScript in the source code and the "Problem" panel.

After cleaning up the HTML, I can't get my table to size to 95% width and center anymore ...

Mario

Quote from: Carlo Didier on November 22, 2017, 01:41:42 PM
After cleaning up the HTML, I can't get my table to size to 95% width and center anymore ...
You did use some arcane formatting directly in the <table> tag. That's a no-no. Use CSS instead.
Boot strap makes formatting tables very easy. https://getbootstrap.com/docs/3.3/css/#tables
-- Mario
IMatch Developer
Forum Administrator
http://www.photools.com  -  Contact & Support - Follow me on 𝕏 - Like photools.com on Facebook

Carlo Didier

Quote from: Mario on November 22, 2017, 02:01:46 PM
Quote from: Carlo Didier on November 22, 2017, 01:41:42 PM
After cleaning up the HTML, I can't get my table to size to 95% width and center anymore ...
You did use some arcane formatting directly in the <table> tag. That's a no-no. Use CSS instead.
Boot strap makes formatting tables very easy. https://getbootstrap.com/docs/3.3/css/#tables

That doc only gives some examples of fance formating I don't need. Way too complicated to work myself through the whole bootstrapstuff.
Found that this just works fine:
<table id="option-stable" align="center" width="95%" border-spacing="20px">
and HTMLHint says it's fine and it effectively works.

I'll try to get completely rid of the /system/themes/slate/bootstrap.min.css which I use right now. Couldn't even find out how to change the body background color in there. It's too much and too opaque.

Mario

QuoteCouldn't even find out how to change the body background color in there. It's too much and too opaque.
You don't. Bootstrap uses themes to control the color of background, text, buttons and whatnot.
The default these is black on white. The default for apps in IMatch is "IMatch colored" because by default apps include

<link rel="stylesheet" href="/system/themes/slate/imatch.css" />

Remove that line from your index.html and see if the default BS theme is better.

And you can of course always override colors with the body element in your CSS.

To me it looks like you are working very hard against the system. Not liking JS. Not liking HTML. Not liking CSS. Spending time to work-around all that. Waste of time. Go with the flow.
-- Mario
IMatch Developer
Forum Administrator
http://www.photools.com  -  Contact & Support - Follow me on 𝕏 - Like photools.com on Facebook

Carlo Didier

Quote from: Mario on November 22, 2017, 02:35:58 PM
To me it looks like you are working very hard against the system. Not liking JS. Not liking HTML. Not liking CSS. Spending time to work-around all that. Waste of time. Go with the flow.
I think it's more that I'm a control freak. I want to control those things myself and not let a "black box" (in this case css files) decide it all for me 8)

Jingo

Quote from: Carlo Didier on November 22, 2017, 06:25:57 PM
Quote from: Mario on November 22, 2017, 02:35:58 PM
To me it looks like you are working very hard against the system. Not liking JS. Not liking HTML. Not liking CSS. Spending time to work-around all that. Waste of time. Go with the flow.
I think it's more that I'm a control freak. I want to control those things myself and not let a "black box" (in this case css files) decide it all for me 8)

You can override the css with your own css if you want control.. but better to use unique css files that are re-used across multiple programs than coding specifics within each JS/html program.