App-Dochazka-WWW

 view release on metacpan or  search on metacpan

Changes  view on Meta::CPAN

- ldapLookup: always display AJAX error
- Improve AJAX error reporting
- Dispatch.pm: revamp/simplify session management
- Rip out entry definitions for deprecated newEmployee target
- Plumb in an empObject prototype distinct from empProfile
- js: make ldapLookupSubmit GET instead of PUT
- dispatch: tweak debug log messages
- js: lower ACL profile of ldapLookupSubmit and privHistory targets
- Revamp LDAP lookup feature (GET first)
- js: handle empty nick in ldapLookupSubmit
- Add "Sync" option to LDAP lookup result miniMenu
- js: simplify LDAP lookup failure handling
- Reinstate "Priv (status) menu" with privHistory target
- Display workforce ID instead of EID in simpleEmployeeBrowser
- Change "Status"/"Since" to "Privlevel"/"Effective"
- dmenu: add Schedule menu
- js: Tweak text of menu entries
- js: rename "searchEmp" to "actionEmplSearch" in emp-lib.js
- js: move dform and dbrowser entries to lib.js

0.139 2016-09-28 19:12 CEST
- Drop LDAPdochazka entry from simpleEmployeeBrowser
- Clarify difference between LDAP and Dochazka employees
- Put masquerade at end of Employee menu
- Dispatch.pm: reduce log verbosity
- Implement LDAP sync miniMenu entry in simpleEmployeeBrowser

0.140 2016-09-29 00:16 CEST
- build/ops: change OBS_PROJECT to Application:Dochazka
- build/ops: require App::MFILE::WWW 0.147 for dtable feature
- Implement basic (read-only) Privhistory table

0.141 2016-11-01 15:40 CET
- Display effective date more readably
- Dispatch.pm: AJAX call session/terminate on logout
- js: Enable active users to "LDAP sync" themselves

0.142 2016-11-05 22:40 CET
- js: implement "REST server details" dform
- js: make REST server details form return to mainMenu
- build/ops: require App::MFILE::WWW 0.152
- Plumb in drowselect target, privhistory edit menu option
- lib.js: add aclProfileWrite prop to pHeffective and pHpriv
- Implement "Add record" option in privhistory drowselect
- emp-lib.js: call lib.displayError() whenever AJAX fails
- Implement "Delete record" option in Privhistory drowselect

0.143 2017-02-25 09:28 CET
- Dispatch.pm: implement user agent lookup table
- Dispatch.pm: refactor session management

Changes  view on Meta::CPAN

- Drop SHID column from schedule history table
- build/ops: designed to work with App::Dochazka::REST >=0.549
- Add scode field to schedhistory dtable and drowselect
- Make schedule menu visible to all
- Implement schedule update dform
- Improve usability of "employee profile edit" feature
- Implement "schedule edit (from schedule display)" feature
- Implement "delete schedule from lookup" feature
- sched-lib.js: refactor schedEditSave and schedDelete
- Implement "schedule edit and delete from browser" feature
- Move "{priv,schedule} history EDIT" to miniMenu

0.148 2017-08-29 15:16 CEST
- schedhistory: make dtable columns visible to inactive+
- Employee Profile: rename priv/status entries
- Employee Profile: show current schedule
- Implement "target stack" feature/redesign
- js: emp-lib: migrate ldapSync from Employee Profile
- js: emp-lib: migrate empProfileEditSave to target stack
- tests: js: first dochazka-www unit test
- tests: js: migrate unit test to QUnit 2.4.0
- build/ops: require App::MFILE::WWW 0.158

0.149 2017-09-24 00:03 CEST
- build/ops: add ext/codepaths file to MANIFEST
- js: tests: add simple test cases for mainMenu targets
- Dispatch.pm: upon login success, expurgate currentUser object
- js: tests: force root user for mainMenu test
- js: tests: refactor and add test for mainEmpl menu
- js: tests: use setTimeout properly
- js: tests/main-menu.js: refactor to do login/logout
- Dispatch.pm: use _prep_ajax_response for logout
- daction-start.js: call loggout instead of logout
- tests/main-menu.js: use current user object correctly
- js: tests: refactor all three existing tests

0.150 2017-09-25 17:36 CEST
- js: emp-lib: migrate ldapLookupSubmit() to target stack

Changes  view on Meta::CPAN

- js: Throw up multi-day interval viewer even for empty query
- js: drop schedHistoryDtable which is no longer used
- js: emp-lib: display "Direct reports" as "(none)" instead of "(undefined)"
- js: let supervisors masquerade as their reports
- js: fix functional tests
- build/ops: require App::MFILE::WWW 0.175 for menu prototype and new fillUserBox() behavior

0.166 2017-11-15 12:11 CET
- js: canned-tests: implement log() - logs messages to both console log and test
  protocol
- js: canned-tests: implement getMenuEntry() - avoids hard-coding of menu entry
  numbers
- js: tests: implement new test "Masquerading as active, set inactive as supervisor"
- js: empProfile: call reports "Supervisees"
- js: Always load employee profile from server

0.167 2017-11-27 13:21 CET
- js: caches: check more carefully if activityCache populated; refactor masqEmployee
- js: allow inactives to view intervals
- js: hide inaccessible functionality from passerbies
- js: implement vetting of privlevels when adding/modifying status records

ext/codepaths  view on Meta::CPAN

dmenu.mainMenu (sets flag)
  dmenu.mainEmpl (sets flag)
    daction.myProfileAction -> empLib.myProfileAction
      dform.empProfile { "xtarget": "mainEmpl" }
        dform.empProfileEdit
          daction.empProfileEditSave
            unwindToFlag()
        daction.ldapSync -> empLib.ldapSync
          unwindToFlag()
    dform.ldapLookup
      daction.ldapLookupSubmit -> empLib.ldapLookupSubmit

share/js/dochazka-www/canned-tests.js  view on Meta::CPAN

        containsFunc = function (assert, lookIn, lookInDesc, lookFor) {
            // console.log("containsFunc() looking for ->" + lookFor + "<- in ->" + lookIn + "<-");
            // asserts that the string lookIn contains substring lookFor
            // lookInDesc describes what lookIn represents
            assert.notStrictEqual(
                lookIn.indexOf(lookFor),
                -1,
                lookInDesc + " contains substring \"" + lookFor + "\""
            );
        },
        getMenuEntryFunc = function (assert, htmlbuf, searchKey) {
            var rx = new RegExp('(\\d+)\\.&nbsp;' + searchKey),
                match = htmlbuf.match(rx),
                msg,
                sel;
            logFunc(assert, htmlbuf);
            logFunc(assert, "*** REACHED looking for " + searchKey);
            assert.ok(match !== null, "There is a match 1");
            if (match !== null) {
                assert.ok(match.length >= 1, "There is a match 2");
                sel = match[1];

share/js/dochazka-www/canned-tests.js  view on Meta::CPAN

                    }
                },
                // failure callback
                fc = function (st) {
                    console.log("AJAX: " + rest["path"] + " failure", st);
                    coreLib.displayError(st.payload.message);
                };
            ajax(rest, sc, fc);
        },

        "getMenuEntry": getMenuEntryFunc,

        "log": logFunc,

        "loggout": function (assert) {
            var cu,
                htmlbuf,
                mainarea;
            console.log("TEST: post-logout tests");
            assert.ok(true, '*** REACHED logging out ***');
            cu = currentUser();

share/js/dochazka-www/canned-tests.js  view on Meta::CPAN

            assert.ok(cu, "current user object after login: " + QUnit.dump.parse(cu));
            assert.strictEqual(cu.obj.nick, nick, 'we are now ' + nick);
            assert.strictEqual(cu.priv, priv, nick + ' has ' + priv + ' privileges');
            assert.ok(true, "Starting app in fixture");
            root(); // start app in QUnit fixture
            msg = '*** REACHED commence app start with nick ' + nick;
            console.log(msg);
            assert.ok(true, msg);
        },

        "mainMenu": function (assert) {
            var msg;
            stackFunc(assert, 1, 'starting app', 'dmenu', 'mainMenu');
            mainareaFormFunc(assert, 'mainMenu');
            msg = '*** REACHED main menu';
            console.log(msg);
            assert.ok(true, msg);
            assert.ok(true, $('#mainarea').html());
        },

        "mainareaForm": mainareaFormFunc,

        "mainEmplToLdapLookup": function (assert) {
            var htmlbuf;

share/js/dochazka-www/canned-tests.js  view on Meta::CPAN

                "The searchEmployee form contains a data entry field"
            );
            assert.strictEqual(
                coreLib.focusedItem().name,
                'entry0',
                'Focus is on data entry field'
            );
            assert.ok(true, "*** REACHED searchEmployee dform");
        },

        "mainMenuSelectEmpProfile": function (assert) {
            var htmlbuf,
                mainmarea,
                sel;
            mainareaFormFunc(assert, 'mainMenu');
            sel = $('input[name="sel"]').val();
            assert.strictEqual(sel, '', "Selection form field is empty");
            sel = getMenuEntryFunc(assert, $('#mainarea').html(), 'Profile');
            $('input[name="sel"]').val(sel);
            $('input[name="sel"]').focus();
            // press ENTER -> submit the form
            $('input[name="sel"]').trigger($.Event("keydown", {keyCode: 13}));
            logFunc(assert, "*** REACHED selected Profile in main menu");
        },

        "mainMenuToMainAdmin": function (assert) {
            var htmlbuf,
                mainmarea,
                sel;
            mainareaFormFunc(assert, 'mainMenu');
            sel = $('input[name="sel"]').val();
            assert.strictEqual(sel, '', "Selection form field is empty");
            // press '0' key in sel, but value does not change?
            $('input[name="sel"]').trigger($.Event("keydown", {keyCode: 48})); // press '0' key
            sel = $('input[name="sel"]').val();
            assert.strictEqual(sel, '', "Selection form field is empty even after simulating 0 keypress");
            // simulating keypress doesn't work, so just set the input val
            sel = getMenuEntryFunc(assert, $('#mainarea').html(), 'Admin');
            $('input[name="sel"]').val(sel);
            $('input[name="sel"]').focus();
            // press ENTER -> submit the form
            $('input[name="sel"]').trigger($.Event("keydown", {keyCode: 13}));
            assert.ok(true, $('#mainarea').html());
            stackFunc(assert, 2, 'navigating from mainMenu to mainAdmin', 'dmenu', 'mainAdmin');
            mainareaFormFunc(assert, 'mainAdmin');
            containsFunc(assert, $('#mainarea').html(), "#mainarea", "Admin menu");
            assert.ok(true, "*** REACHED mainAdmin dmenu");
        },

        "mainMenuToMainSched": function (assert) {
            var htmlbuf,
                mainmarea,
                sel;
            mainareaFormFunc(assert, 'mainMenu');
            sel = $('input[name="sel"]').val();
            assert.strictEqual(sel, '', "Selection form field is empty");
            sel = getMenuEntryFunc(assert, $('#mainarea').html(), 'Schedules');
            $('input[name="sel"]').val(sel);
            $('input[name="sel"]').focus();
            // press ENTER -> submit the form
            $('input[name="sel"]').trigger($.Event("keydown", {keyCode: 13}));
            stackFunc(assert, 2, 'navigating from mainMenu to mainSched', 'dmenu', 'mainSched');
            mainareaFormFunc(assert, 'mainSched');
            containsFunc(assert, $('#mainarea').html(), "#mainarea", "Schedule menu");
            assert.ok(true, "*** REACHED mainSched dmenu");
        },

        "mainSchedToSchedLookup": function (assert) {
            var entry0,
                entry1,
                sel;
            assert.ok(true, 'select 1 ("Look up schedule by code or ID") in mainSched as root');
            sel = getMenuEntryFunc(assert, $('#mainarea').html(), 'Look up');
            $('input[name="sel"]').val(sel);
            $('input[name="sel"]').focus();
            $('input[name="sel"]').trigger($.Event("keydown", {keyCode: 13}));
            stackFunc(assert, 3, 'navigating from mainSched to schedLookup', 'dform', 'schedLookup');
            mainareaFormFunc(assert, 'schedLookup');
            containsFunc(assert, $('#mainarea').html(), "#mainarea",
                "Look up schedule by code or ID");
            entry0 = $('form#schedLookup input[name="entry0"]');
            entry1 = $('form#schedLookup input[name="entry1"]');
            assert.ok(entry0, "There is an entry0 in the schedLookup form");

share/js/dochazka-www/daction-init.js  view on Meta::CPAN


        // Interval actions
        target.push('createMultipleIntSave', {
            'name': 'createMultipleIntSave',
            'type': 'daction',
            'menuText': 'Save',
            'aclProfile': 'active',
            'start': dactionStart('createMultipleIntSave'),
            'pushable': false
        });
        target.push('createSingleIntMenuItem', {
            'name': 'createSingleIntMenuItem',
            'type': 'daction',
            'menuText': 'Create single',
            'aclProfile': 'active',
            'start': dactionStart('createSingleIntMenuItem'),
            'pushable': false
        });
        target.push('createSingleIntSave', {
            'name': 'createSingleIntSave',
            'type': 'daction',
            'menuText': 'Save',
            'aclProfile': 'active',
            'start': dactionStart('createSingleIntSave'),
            'pushable': false
        });

share/js/dochazka-www/daction-start.js  view on Meta::CPAN

        "browseAllSchedules": schedLib.browseAllSchedules,
        "actionSchedLookup": schedLib.actionSchedLookup,
        "createSchedule": schedLib.createSchedule,
        "actionDisplaySchedule": schedLib.actionDisplaySchedule,
        "schedEditSave": schedLib.schedEditSave,
        "schedReallyDelete": schedLib.schedReallyDelete,

        // create interval actions
        "createMultipleIntSave": intLib.createMultipleIntSave,
        "createNextScheduledIntervalSave": intLib.createNextScheduledIntervalSave,
        "createSingleIntMenuItem": intLib.createSingleIntMenuItem,
        "createSingleIntSave": intLib.createSingleIntSave,
        "createLockSave": lockLib.createLockSave,
        "deleteSingleInt": intLib.deleteSingleInt,
        "deleteLock": lockLib.deleteLock,
        "updateSingleIntSave": intLib.updateSingleIntSave,
        "viewIntervalsAction": intLib.viewIntervalsAction,
        "viewLocksAction": lockLib.viewLocksAction,
        
        // activity select actions
        "selectActivityAction": appCaches.selectActivityAction,

share/js/dochazka-www/dbrowser-init.js  view on Meta::CPAN


        target.push('simpleEmployeeBrowser', {
            'name': 'simpleEmployeeBrowser',
            'type': 'dbrowser',
            'menuText': 'simpleEmployeeBrowser',
            'title': 'Employee search results',
            'preamble': null,
            'aclProfile': 'admin',
            'entriesRead': [entries.ePnick, entries.ePsec_id, entries.ePfullname,
                        entries.ePemail, entries.ePremark],
            'miniMenu': {
                entries: ['ldapSync', 'empProfileEdit']
            }
        });

        target.push('setSupervisorBrowser', {
            'name': 'setSupervisorBrowser',
            'type': 'dbrowser',
            'menuText': 'setSupervisorBrowser',
            'title': 'Supervisor candidates',
            'preamble': null,
            'aclProfile': 'admin',
            'entriesRead': [entries.ePnick, entries.ePsec_id, entries.ePfullname,
                        entries.ePemail, entries.ePremark],
            'miniMenu': {
                entries: ['empProfileSetSuperChoose']
            }
        });

        target.push('masqueradeCandidatesBrowser', {
            'name': 'masqueradeCandidatesBrowser',
            'type': 'dbrowser',
            'menuText': 'masqueradeCandidatesBrowser',
            'title': 'Masquerade candidates',
            'preamble': null,
            'aclProfile': 'admin',
            'entriesRead': [entries.ePnick, entries.ePsec_id, entries.ePfullname,
                        entries.ePemail, entries.ePremark],
            'miniMenu': {
                entries: ['masqEmployee']
            }
        });

        target.push('simpleScheduleBrowser', {
            'name': 'simpleScheduleBrowser',
            'type': 'dbrowser',
            'menuText': 'Browse schedules',
            'title': 'All schedules',
            'preamble': null,
            'aclProfile': 'admin',
            'entriesRead': [entries.sDid, entries.sDcode,
                        coreLib.emptyLineEntry, entries.sDmon,
                        entries.sDtue, entries.sDwed, entries.sDthu,
                        entries.sDfri, entries.sDsat, entries.sDsun,
                        coreLib.emptyLineEntry, entries.ePremark],
            'miniMenu': {
                entries: ['schedEditFromBrowser', 'schedDeleteFromBrowser']
            }
        });

    };
    
});

share/js/dochazka-www/dcallback-init.js  view on Meta::CPAN


    return function () {

        target.push('multiDayViewer', {
            'name': 'multiDayViewer',
            'type': 'dcallback',
            'menuText': 'multiDayViewer',
            'aclProfile': 'inactive',
            'callback': viewer.multiDayViewer,
            'rememberState': true,
            'miniMenu': {
                entries: ['viewIntervalsMultiDayRaw'],
            }
        });

        target.push('viewIntervalsMultiDayRaw', {
            'name': 'viewIntervalsMultiDayRaw',
            'type': 'dcallback',
            'menuText': 'Raw JSON',
            'title': 'Multi-day interval viewer (RAW)',
            'preamble': 'Attendance intervals from [BEGIN] to [END]',
            'aclProfile': 'inactive',
            'callback': intLib.viewIntervalsMultiDayCallbackRaw,
            'miniMenu': {
                entries: [],
            }
        });

    };
    
});

share/js/dochazka-www/dform-init.js  view on Meta::CPAN

                coreLib.emptyLineEntry,
                entries.iNtoBeCreated,
            ],
            'entriesWrite': [
                entries.iNdate,
                entries.iNtimerange,
                entries.iNact,
                entries.iNdesc,
            ],
            'rememberState': true,
            'miniMenu': {
                entries: ['createSingleIntSave'],
            }
        }); // createLastPlusOffset

        target.push('createMultipleInt', {
            'name': 'createMultipleInt',
            'type': 'dform',
            'menuText': 'Create multiple',
            'title': 'Create multiple intervals according to schedule',
            'preamble': "Hints: (1) TAB or ENTER to validate and advance to next field " +

share/js/dochazka-www/dform-init.js  view on Meta::CPAN

                entries.iNyearHidden,
            ],
            'entriesWrite': [
                entries.iNyear,
                entries.iNmonth,
                entries.iNdaylist,
                entries.iNact,
                entries.iNdesc,
            ],
            'rememberState': true,
            'miniMenu': {
                entries: ['selectActivityAction', 'createMultipleIntSave', 'viewIntervalsAction']
            }
        }); // createMultipleInt

        target.push('createNextScheduled', {
            // before doing any calculations, look up/calculate:
            // - employee's schedule
            // - existing intervals on date
            // - schedule intervals on date
            // timerange will be:

share/js/dochazka-www/dform-init.js  view on Meta::CPAN

                coreLib.emptyLineEntry,
                entries.iNtoBeCreated,
            ],
            'entriesWrite': [
                entries.iNdate,
                entries.iNtimerange,
                entries.iNact,
                entries.iNdesc,
            ],
            'rememberState': true,
            'miniMenu': {
                entries: ['selectActivityAction', 'createSingleIntSave'],
            }
        }); // createNextScheduled

        target.push('createSingleInt', {
            'name': 'createSingleInt',
            'type': 'dform',
            'menuText': 'Create',
            'title': 'Create an arbitrary interval',
            'preamble': "Hints: (1) TAB or ENTER to validate and advance to next field " +
                        "(2) date YYYY-MM-DD; year is optional " +
                        "(3) time range HH:MM-HH:MM or HH:MM+HH:MM (start time plus offset) " +
                        "or +HH:MM (last existing interval plus offset) or + (next scheduled " +
                        "interval) (4) Use 'Select activity' if you don't know activity code " +
                        '(5) Description is optional',
            'aclProfile': 'active',
            'entriesWrite': [entries.iNdate, entries.iNtimerange, entries.iNact, entries.iNdesc,],
            'rememberState': true,
            'miniMenu': {
                entries: ['selectActivityAction', 'createSingleIntSave']
            }
        }); // createSingleInt

        target.push('createLock', {
            'name': 'createLock',
            'type': 'dform',
            'menuText': 'Create',
            'title': 'Create a Lock',
            'preamble': "Hints: (1) TAB or ENTER to validate and advance to next field ",
            'aclProfile': 'active',
            'entriesWrite': [entries.iNyear, entries.iNmonth,],
            'rememberState': true,
            'miniMenu': {
                entries: ['createLockSave']
            }
        }); // createLock

        target.push('createSingleIntFixedDay', {
            'name': 'createSingleIntFixedDay',
            'type': 'dform',
            'menuText': 'Create',
            'title': 'Create an arbitrary interval',
            'preamble': "Hints: (1) TAB or ENTER to validate and advance to next field " +
                        "(2) time range HH:MM-HH:MM " +
                        "(3) Use 'Select activity' if you don't know activity code " +
                        '(4) Description is optional',
            'aclProfile': 'active',
            'entriesRead': [entries.iNdate,],
            'entriesWrite': [entries.iNtimerangeNoOffset, entries.iNact, entries.iNdesc,],
            'rememberState': true,
            'miniMenu': {
                entries: ['selectActivityAction', 'createSingleIntSave']
            }
        }); // createSingleIntFixedDay

        target.push('displaySingleInt', {
            'name': 'displaySingleInt',
            'type': 'dform',
            'menuText': 'Single interval',
            'title': 'Display a single interval',
            'aclProfile': 'active',
            'entriesRead': [entries.iNdaterange, entries.iNtimerange, entries.iNact, entries.iNdesc,],
            'miniMenu': {
                entries: []
            }
        }); // displaySingleInt

        target.push('empProfile', {
            'name': 'empProfile',
            'type': 'dform',
            'menuText': 'Profile',
            'title': 'Employee profile',
            'preamble': null,

share/js/dochazka-www/dform-init.js  view on Meta::CPAN

                entries.ePfullname, entries.ePnick,
                entries.ePsec_id, entries.ePemail,
                entries.ePremark,
                coreLib.emptyLineEntry,
                entries.ePsuperNick, entries.ePhasReports,
                coreLib.emptyLineEntry,
                entries.ePpriv, entries.ePprivEffective,
                coreLib.emptyLineEntry,
                entries.ePscode, entries.ePsid, entries.ePschedEffective
            ],
            'miniMenu': {
                entries: [
                    'actionPrivHistory',
                    'actionSchedHistory',
                    'empProfileEdit',
                    'ldapSync',
                    'empProfileSetSuperSearch',
                    'empProfileSetSuperDelete',
                ]
            }
        }); // empProfile

share/js/dochazka-www/dform-init.js  view on Meta::CPAN

            'name': 'empProfileEdit',
            'type': 'dform',
            'menuText': 'Edit remark',
            'title': 'Employee profile edit',
            'preamble': 'Only the remark field can be modified;<br>' +
                        'All other fields are synced from LDAP',
            'aclProfile': 'admin',
            'entriesRead': [entries.ePfullname, entries.ePnick,
                entries.ePsec_id, entries.ePemail],
            'entriesWrite': [entries.ePremark],
            'miniMenu': {
                entries: ['empProfileEditSave']
            }
        }); // empProfileEdit

        target.push('empProfileSetSuperConfirm', {
            'name': 'empProfileSetSuperConfirm',
            'type': 'dform',
            'menuText': 'empProfileSetSuperConfirm',
            'title': 'Set employee supervisor - confirmation',
            'preamble': 'Do you really want to do this?',
            'aclProfile': 'admin',
            'entriesRead': [
                entries.ePsetsuperofEID,
                entries.ePsetsupertoEID,
                entries.ePsetsuperof,
                entries.ePsetsuperto,
            ],
            'miniMenu': {
                entries: ['empProfileSetSuperCommit']
            }
        }); // empProfileEdit

        target.push('ldapDisplayEmployee', {
            'name': 'ldapDisplayEmployee',
            'type': 'dform',
            'title': 'LDAP employee record',
            'preamble': null,
            'aclProfile': 'active',
            'entriesRead': [entries.ePfullname, entries.ePnick,
                entries.ePsec_id, entries.ePemail, entries.LDAPdochazka],
            'miniMenu': {
                entries: ['ldapSync']
            }
        }); // ldapDisplayEmployee

        target.push('ldapLookup', {
            'name': 'ldapLookup',
            'type': 'dform',
            'menuText': 'Look up an LDAP employee',
            'title': 'Look up an LDAP employee',
            'preamble': 'Enter employee nick for exact (case insensitive) match',
            'aclProfile': 'active',
            'entriesWrite': [entries.ePnick],
            'rememberState': true,
            'miniMenu': {
                entries: ['ldapLookupSubmit']
            }
        }); // ldapLookup

        target.push('privHistoryAddRecord', {
            'name': 'privHistoryAddRecord',
            'type': 'dform',
            'menuText': 'Add record',
            'title': 'Add privhistory (status) record',
            'preamble': '<b>Effective</b> date format YYYY-MM-DD;<br>' +
                        '<b>Priv</b> one of (passerby, inactive, active, admin)',
            'aclProfile': 'admin',
            'entriesRead': [entries.ePnick], 
            'entriesWrite': [entries.pHeffective, entries.pHpriv],
            'miniMenu': {
                entries: ['privHistorySaveAction']
            }
        }); // privHistoryAddRecord

        target.push('schedHistoryAddRecord', {
            'name': 'schedHistoryAddRecord',
            'type': 'dform',
            'menuText': 'Add record',
            'title': 'Add schedule history record',
            'preamble': '<b>Effective date</b> format YYYY-MM-DD;<br>' +
                        'Enter schedule ID or schedule code - not both',
            'aclProfile': 'admin',
            'entriesRead': [entries.ePnick],
            'entriesWrite': [entries.pHeffective, entries.sDid, entries.sDcode],
            'miniMenu': {
                entries: ['schedHistorySaveAction']
            }
        }); // schedHistoryAddRecord

        target.push('restServerDetails', {
            'name': 'restServerDetails',
            'type': 'dform',
            'menuText': 'REST server',
            'title': 'REST server details',
            'aclProfile': 'admin',
            'entriesRead': [entries.rSDurl, entries.rSDversion],
            'miniMenu': {
                entries: []
            }
        }); // restServerDetails

        target.push('schedDisplay', {
            'name': 'schedDisplay',
            'type': 'dform',
            'menuText': 'schedDisplay',
            'title': 'Schedule',
            'aclProfile': 'passerby',
            'entriesRead': [entries.sDid, entries.sDcode,
                            coreLib.emptyLineEntry, entries.sDmon,
                            entries.sDtue, entries.sDwed, entries.sDthu,
                            entries.sDfri, entries.sDsat, entries.sDsun,
                            coreLib.emptyLineEntry, entries.ePremark],
            'miniMenu': {
                entries: ['schedEdit', 'schedDelete']
            }
        }); // schedDisplay

        var schedEditObj = {
                'type': 'dform',
                'menuText': 'Edit',
                'title': 'Schedule edit',
                'preamble': 'Only schedule code and remark can be modified<br>' +
                            'Note: code change will affect <b>all employees</b> with this schedule',
                'aclProfile': 'admin',
                'entriesRead': [entries.sDid,
                                coreLib.emptyLineEntry, entries.sDmon,
                                entries.sDtue, entries.sDwed, entries.sDthu,
                                entries.sDfri, entries.sDsat, entries.sDsun],
                'entriesWrite': [entries.sDcode, entries.ePremark],
                'miniMenu': {
                    entries: ['schedEditSave']
                }
            },
            schedEditFromBrowserObj = coreLib.shallowCopy(schedEditObj);

        schedEditObj['name'] = 'schedEdit';
        target.push('schedEdit', schedEditObj);
        schedEditFromBrowserObj['name'] = 'schedEditFromBrowser';
        target.push('schedEditFromBrowser', schedEditFromBrowserObj);

share/js/dochazka-www/dform-init.js  view on Meta::CPAN

                'menuText': 'Delete',
                'title': 'Schedule delete',
                'preamble': 'If you are really sure you want to delete this schedule,<br>' +
                            'select "Yes, I really mean it" below',
                'aclProfile': 'admin',
                'entriesRead': [entries.sDid, entries.sDcode,
                                coreLib.emptyLineEntry, entries.sDmon,
                                entries.sDtue, entries.sDwed, entries.sDthu,
                                entries.sDfri, entries.sDsat, entries.sDsun,
                                coreLib.emptyLineEntry, entries.ePremark],
                'miniMenu': {
                    entries: ['schedReallyDelete']
                }
            },
            schedDeleteFromBrowserObj = coreLib.shallowCopy(schedDeleteObj);

        schedDeleteObj.name = 'schedDelete';
        target.push('schedDelete', schedDeleteObj);
        schedDeleteFromBrowserObj['name'] = 'schedDeleteFromBrowser';
        target.push('schedDeleteFromBrowser', schedDeleteFromBrowserObj);

        target.push('schedLookup', {
            'name': 'schedLookup',
            'type': 'dform',
            'menuText': 'Look up schedule by code or ID',
            'title': 'Look up schedule by code or ID',
            'preamble': 'Enter a schedule code or ID (must be an exact match)',
            'aclProfile': 'passerby',
            'entriesWrite': [entries.sScode, entries.sSid],
            'rememberState': true,
            'miniMenu': {
                entries: ['actionSchedLookup']
            }
        }); // schedLookup

        target.push('schedNewBoilerplate', {
            'name': 'schedNewBoilerplate',
            'type': 'dform',
            'menuText': 'Boilerplate (quick form for Mon-Fri schedules)',
            'title': 'Create a new schedule - boilerplate',
            'preamble': 'Hint: separate schedule intervals by semi-colon<br>' +
                        'Example: 8:00-12:00; 12:30-16:30<br>' +
                        '<b>Schedule intervals will be replicated for Monday-Friday</b><br>' +
                        'Note: schedule code is optional',
            'aclProfile': 'admin',
            'entriesRead': [entries.sDid],
            'entriesWrite': [entries.sCboiler, entries.sDcode],
            'miniMenu': {
                entries: ['createSchedule']
            }
        }); // schedNewBoilerPlate

        target.push('schedNewCustom', {
            'name': 'schedNewCustom',
            'type': 'dform',
            'menuText': 'Custom (long form)',
            'title': 'Create a new schedule - custom',
            'preamble': 'Hint: separate schedule intervals by semi-colon<br>' +
                        'Example: 8:00-12:00; 12:30-16:30<br>' +
                        'Note: schedule code is optional',
            'aclProfile': 'admin',
            'entriesRead': [entries.sDid],
            'entriesWrite': [entries.sDmon, entries.sDtue,
                             entries.sDwed, entries.sDthu, entries.sDfri,
                             entries.sDsat, entries.sDsun, entries.sDcode],
            'miniMenu': {
                entries: ['createSchedule']
            }
        }); // schedNewCustom

        target.push('searchEmployee', {
            'name': 'searchEmployee',
            'type': 'dform',
            'menuText': 'Search Dochazka employees',
            'title': 'Search Dochazka employees',
            'preamble': 'Enter search key, % is wildcard',
            'aclProfile': 'admin',
            'entriesWrite': [entries.sEnick],
            'miniMenu': {
                entries: ['actionEmplSearch']
            }
        }); // searchEmployee

        target.push('updateSingleInt', {
            'name': 'updateSingleInt',
            'type': 'dform',
            'menuText': 'Update',
            'title': 'Update an interval',
            'preamble': "Hints: (1) TAB or ENTER to validate and advance to next field " +
                        "(2) time range HH:MM-HH:MM " +
                        "(3) Use 'Select activity' if you don't know activity code " +
                        '(4) Description is optional',
            'aclProfile': 'active',
            'entriesRead': [entries.iNdate, entries.acTaid],
            'entriesWrite': [entries.iNtimerangeNoOffset, entries.iNact, entries.iNdesc,],
            'rememberState': true,
            'miniMenu': {
                entries: ['selectActivityAction', 'updateSingleIntSave']
            }
        }); // updateSingleInt

        target.push('viewIntervalsPrep', {
            'name': 'viewIntervalsPrep',
            'type': 'dform',
            'menuText': 'View',
            'title': 'View intervals for date or range of dates',
            'preamble': "Hints: (1) TAB or ENTER to validate and advance to next field " +

share/js/dochazka-www/dform-init.js  view on Meta::CPAN

                entries.iNdaterangeBegin,
                entries.iNdaterangeEnd,
                entries.iNyearHidden,
            ],
            'entriesWrite': [
                entries.iNyear,
                entries.iNmonth,
                entries.iNdayrange,
            ],
            'rememberState': true,
            'miniMenu': {
                entries: ['viewIntervalsAction']
            }
        }); // viewIntervalsPrep

        target.push('viewLocksPrep', {
            'name': 'viewLocksPrep',
            'type': 'dform',
            'menuText': 'View',
            'title': 'View locks',
            'preamble': "Hints: (1) TAB or ENTER to validate and advance to next field " +
                        "(2) enter month by name (e.g. \"June\") or number (e.g. \"6\"); " +
                        "DEFAULT: current month ",
            'aclProfile': 'inactive',
            'entriesWrite': [
                entries.iNyear,
            ],
            'rememberState': true,
            'miniMenu': {
                entries: ['viewLocksAction']
            }
        }); // viewLocksPrep

    }; // return function ()
    
});

share/js/dochazka-www/dmenu-init.js  view on Meta::CPAN

            'aclProfile': 'admin',
            'entries': ['ldapLookup', 'searchEmployee', 'restServerDetailsAction']
        });

        target.push('mainInt', {
            'name': 'mainInt',
            'type': 'dmenu',
            'menuText': 'Intervals',
            'title': 'Interval menu',
            'aclProfile': 'inactive',
            'entries': ['viewIntervalsPrep', 'createSingleIntMenuItem', 'createMultipleInt',],
        });

        target.push('mainLock', {
            'name': 'mainLock',
            'type': 'dmenu',
            'menuText': 'Locks',
            'title': 'Lock menu',
            'aclProfile': 'inactive',
            'entries': ['viewLocksPrep', 'createLock',],
        });

        target.push('mainMenu', {
            'name': 'mainMenu',
            'type': 'dmenu',
            'menuText': 'Main',
            'title': 'Main menu',
            'aclProfile': 'passerby',
            'entries': ['myProfileAction', 'mainInt', 'mainLock', 'mainSched', 'masqEmployee',
                        'mainAdmin']
        });

        target.push('mainSched', {
            'name': 'mainSched',

share/js/dochazka-www/dnotice-init.js  view on Meta::CPAN

    return function () {

        // demo notice from App::MFILE::WWW
        target.push('demoNotice', {
            'name': 'demoNotice',
            'type': 'dnotice',
            'menuText': 'Demo notice',
            'title': 'Demo notice',
            'preamble': 'This is just an illustration',
            'aclProfile': 'passerby',
            'back': 'demoMenu'
        });

    };

});

share/js/dochazka-www/drowselect-init.js  view on Meta::CPAN

    return function () {

        target.push('privHistoryDrowselect', {
            'name': 'privHistoryDrowselect',
            'type': 'drowselect',
            'menuText': 'privHistoryDrowselect',
            'title': 'Status history - edit',
            'preamble': null,
            'aclProfile': 'admin',
            'entriesRead': [entries.ePnick, entries.pHeffective, entries.pHpriv],
            'miniMenu': {
                entries: ['privHistoryAddRecordAction', 'privHistoryDeleteAction']
            }
        });

        target.push('schedHistoryDrowselect', {
            'name': 'schedHistoryDrowselect',
            'type': 'drowselect',
            'menuText': 'schedHistoryDrowselect',
            'title': 'Schedule history',
            'preamble': null,
            'aclProfile': 'inactive',
            'entriesRead': [entries.pHeffective, entries.sDid, entries.sDcode],
            'miniMenu': {
                entries: ['actionSchedLookup', 'schedHistoryAddRecordAction', 'schedHistoryDeleteAction'],
            }
        });

        target.push('selectActivity', {
            'name': 'selectActivity',
            'type': 'drowselect',
            'menuText': 'Select activity',
            'title': 'Select activity',
            'preamble': null,
            'aclProfile': 'active',
            'entriesRead': [entries.acTcode, entries.acTaid, entries.acTdesc],
            'submitAction': 'selectActivityGo',
            'miniMenu': {
                entries: [],
            }
        });

        target.push('viewIntervalsDrowselect', {
            'name': 'viewIntervalsDrowselect',
            'type': 'drowselect',
            'menuText': 'View',
            'title': 'Intervals in date',
            'preamble': null,
            'aclProfile': 'passerby',
            'entriesRead': [
                entries.iNdate, entries.iNtimerange, entries.iNiid, entries.acTcode,
                entries.iNshortDesc,
            ],
            'miniMenu': {
                entries: ['createSingleIntFixedDay', 'updateSingleInt', 'deleteSingleInt'],
            }
        }); // viewIntervalsDrowselect

        target.push('viewLocksDrowselect', {
            'name': 'viewLocksDrowselect',
            'type': 'drowselect',
            'menuText': 'View',
            'title': 'Lock list',
            'preamble': null,
            'aclProfile': 'passerby',
            'entriesRead': [
                entries.lOintvl, entries.lOlid,
            ],
            'miniMenu': {
                entries: ['deleteLock'],
            }
        }); // viewLocksDrowselect

    };
});

share/js/dochazka-www/dtable-init.js  view on Meta::CPAN

    return function () {

        target.push('privHistoryDtable', {
            'name': 'privHistoryDtable',
            'type': 'dtable',
            'menuText': 'Status history',
            'title': 'Status history',
            'preamble': null,
            'aclProfile': 'passerby',
            'entriesRead': [entries.ePnick, entries.pHeffective, entries.pHpriv],
            'miniMenu': {
                entries: ['actionPrivHistoryEdit']
            }
        });

    };

});

share/js/dochazka-www/int-lib.js  view on Meta::CPAN

                    );
                } else if (st.code === "DISPATCH_FILLUP_NO_INTERVALS_CREATED") {
                    coreLib.displayResult("The dates in question already have 100% schedule fulfillment");
                } else {
                    coreLib.displayError(st.text);
                }
            };
            ajax(rest, sc);
        },

        createSingleIntMenuItem = function (obj) {
            stack.push('createSingleInt');
        },

        createSingleIntSave = function (obj) {
            var caller = stack.getTarget().name,
                cu = currentUser('obj'),
                rest,
                sc = function (st) {
                    if (caller === 'createSingleIntFixedDay') {
                        stack.unwindToTarget('viewIntervalsAction');

share/js/dochazka-www/int-lib.js  view on Meta::CPAN

            }
            r += "</pre><br>";
            return r;
        }
        ;

    // here is where we define methods implementing the various
    // interval-related actions (see daction-start.js)
    return {
        createMultipleIntSave: createMultipleIntSave,
        createSingleIntMenuItem: createSingleIntMenuItem,
        createSingleIntSave: createSingleIntSave,
        deleteSingleInt: deleteSingleInt,
        vetDayList: vetDayList,
        vetDayRange: vetDayRange,
        updateSingleIntSave: updateSingleIntSave,
        viewIntervalsAction: viewIntervalsAction,
        viewIntervalsMultiDayCallback: viewIntervalsMultiDayCallback,
        viewIntervalsMultiDayCallbackRaw: viewIntervalsMultiDayCallbackRaw,
    };

share/js/dochazka-www/sched-history-lib.js  view on Meta::CPAN

                // success callback
                sc = function (st) {
                    if (st.code === 'DOCHAZKA_CUD_OK') {
                        console.log("Payload is", st.payload);
                        stack.unwindToTarget("actionSchedHistory");
                    }
                },
                fc = function (st) {
                    lib.displayError(st.payload.message);
                    if (st.payload.code === '404') {
                        // go back to miniMenu listener
                        $('input[name="sel"]').val('').focus();
                    }
                };
            ajax(rest, sc, fc);
            // start.drowselectListen();
        },

        schedHistoryDeleteAction = function () {
            var shid,
                set = lib.drowselectState.set,

share/js/dochazka-www/target-init.js  view on Meta::CPAN


            // populate target objects
            initRoundTwo('dform');
            initRoundTwo('dmenu');
            initRoundTwo('dcallback');
            initRoundTwo('dbrowser');
            initRoundTwo('dnotice');
            initRoundTwo('dtable');
            initRoundTwo('drowselect');

            stack.push('mainMenu');
            populateContinue(populateArray);
        };

    return function () {

        // round one - set up the targets
        console.log("dochazka-www/target-init.js: round one");
        dactionInitRoundOne();
        dcallbackInitRoundOne();
        dformInitRoundOne();

share/js/dochazka-www/test.js  view on Meta::CPAN

    'QUnit',
    'app/tests/dummy',
    'app/tests/01-users',
    'app/tests/main-menu',
    'app/tests/main-empl',
    'app/tests/main-sched',
], function (
    QUnit,
    dummyTests,
    createTestingUsers,
    mainMenuTests,
    mainEmplTests,
    mainSchedTests,
) {
    QUnit.module("dochazka-www");
    dummyTests();
    createTestingUsers();
    mainMenuTests();
    mainEmplTests();
    mainSchedTests();
});

share/js/dochazka-www/tests/01-users.js  view on Meta::CPAN

        QUnit.test(test_desc, function (assert) {
            console.log('***TEST*** ' + prefix + test_desc);
            var done = assert.async(6);
            assert.expect(25);
            login({"nam": "root", "pwd": "immutable"});
            setTimeout(function () {
                ct.login(assert, "root", "admin");
                done();
            }, 1000);
            setTimeout(function () {
                ct.mainMenu(assert);
                done();
            }, 2000);
            setTimeout(function () {
                // create the employees
                ct.employeeCreate(assert, "active");
                ct.employeeCreate(assert, "inactive");
                done();
            }, 2400);
            setTimeout(function () {
                // add privhistory records

share/js/dochazka-www/tests/ldap.js  view on Meta::CPAN


    return function () {

        test_desc = 'LDAP lookup - success';
        QUnit.test(test_desc, function (assert) {
            console.log('***TEST*** ' + prefix + test_desc);
            var done = assert.async(4);
            login({"nam": "root", "pwd": "immutable"});
            setTimeout(function () {
                ct.login(assert, "root", "admin");
                ct.mainMenuToMainEmpl(assert);
                ct.mainEmplToLdapLookup(assert);
                ct.submitLdapLookup(assert, 'ncutler');
                done();
            }, 1000);
            setTimeout(function () {
                var ldapDochazka;
                ct.stack(
                    assert,
                    4,
                    'Displaying LDAP employee after successful LDAP lookup',

share/js/dochazka-www/tests/ldap.js  view on Meta::CPAN

                    ldapDochazka === "YES" || ldapDochazka === "NO",
                    "Answer to whether ncutler is in Dochazka (" + ldapDochazka + ") makes sense",
                );
                assert.ok(true, "*** REACHED Employee LDAP lookup success");
                ct.contains(
                    assert,
                    $('#mainarea').html(),
                    "#mainarea html",
                    "0. LDAP sync",
                );
                assert.ok(true, "*** REACHED miniMenu contains 0. LDAP sync");
                // choose '0' for ldapSync
                $('input[name="sel"]').val('0');
                $('input[name="sel"]').focus();
                start.mmKeyListener($.Event("keydown", {keyCode: 13}));
                assert.ok(true, "*** REACHED pressed 0 for LDAP sync");
                done();
            }, 3000);
            setTimeout(function () {
                var ldapDochazka = $('#LDAPdochazka').text();
                ct.stack(

share/js/dochazka-www/tests/ldap.js  view on Meta::CPAN

            }, 5500);
        });

        test_desc = 'LDAP lookup - failure';
        QUnit.test(test_desc, function (assert) {
            console.log('***TEST*** ' + prefix + test_desc);
            var done = assert.async(4);
            login({"nam": "root", "pwd": "immutable"});
            setTimeout(function () {
                ct.login(assert, "root", "admin");
                ct.mainMenuToMainEmpl(assert);
                ct.mainEmplToLdapLookup(assert);
                ct.submitLdapLookup(assert, 'NONEXISTENTfoobarbazblatFISHBEAR');
                done();
            }, 1000);
            setTimeout(function () {
                ct.stack(
                    assert,
                    3,
                    'failed LDAP lookup',
                    'dform',

share/js/dochazka-www/tests/main-empl.js  view on Meta::CPAN

        QUnit.test(test_desc, function (assert) {
            var done = assert.async(4),
                fullProfile;
            console.log("***TEST*** " + prefix + test_desc);
            login({"nam": "demo", "pwd": "demo"});
            setTimeout(function() {
                ct.login(assert, "demo", "passerby");
                done();
            }, 1500);
            setTimeout(function () {
                ct.mainMenu(assert);
                // assert.ok(true, "Employee profile cache: " + QUnit.dump.parse(appCaches.profileCache));
                assert.ok(appCaches.profileCacheLength() > 0, "Employee profile cache populated");
                fullProfile = appCaches.getProfileByNick('demo');
                assert.ok("emp" in fullProfile, "Employee profile cache populated with an employee");
                assert.strictEqual(
                    fullProfile.emp.nick,
                    "demo",
                    "Employee profile cache populated with employee \"demo\""
                );
                assert.ok(true, 'select 1 ("Profile") in mainMenu as demo');
                $('input[name="sel"]').val('1');
                $('input[name="sel"]').focus();
                $('input[name="sel"]').trigger($.Event("keydown", {keyCode: 13}));
                // no AJAX call is initiated, because the profile is already in the cache
                // ct.ajaxCallInitiated(assert);
                done();
            }, 2000);
            setTimeout(function() {
                // assert.ok(true, $("#mainarea").html());
                ct.mainareaForm(assert, 'empProfile');

share/js/dochazka-www/tests/main-empl.js  view on Meta::CPAN

        QUnit.test(test_desc, function (assert) {
            console.log('***TEST*** ' + prefix + test_desc);
            var done = assert.async(5);
            login({"nam": "root", "pwd": "immutable"});
            setTimeout(function () {
                ct.login(assert, "root", "admin");
                done();
            }, 1500);
            setTimeout(function () {
                var sel;
                ct.mainMenu(assert);
                ct.mainMenuToMainAdmin(assert);
                ct.mainAdminToSearchEmployee(assert);
                // enter search term into form
                $('#searchEmployee input[name="entry0"]').val('inactive');
                sel = ct.getMenuEntry(assert, $('#minimenu').html(), 'Search');
                $('input[name="sel"]').val(sel);
                $('input[name="sel"]').focus();
                start.mmKeyListener($.Event("keydown", {keyCode: 13}));
                ct.log(assert, "*** REACHED initiated search for Dochazka employee inactive");
                done();
            }, 2000);
            setTimeout(function () {
                var htmlbuf = $("#mainarea").html();
                ct.log(assert, htmlbuf);
                ct.stack(

share/js/dochazka-www/tests/main-empl.js  view on Meta::CPAN

                    $('#ePnick').text(),
                    "inactive",
                    "Dochazka employee search succeeded - nick inactive displayed",
                );
                ct.contains(
                    assert,
                    $('#minimenu').html(),
                    "#minimenu html",
                    ".&nbsp;LDAP&nbsp;sync",
                );
                assert.ok(true, "*** REACHED miniMenu contains substring '. LDAP sync'");
                // // choose '0' for ldapSync
                // $('input[name="sel"]').val('0');
                // $('input[name="sel"]').focus();
                // start.mmKeyListener($.Event("keydown", {keyCode: 13}));
                // assert.ok(true, "*** REACHED pressed 0 for LDAP sync");
                done();
            }, 3000);
            setTimeout(function () {
                // ct.contains(
                //     assert,

share/js/dochazka-www/tests/main-empl.js  view on Meta::CPAN

            console.log('***TEST*** ' + prefix + test_desc);
            var done = assert.async(10);
            login({"nam": "root", "pwd": "immutable"});
            setTimeout(function () {
                ct.login(assert, "root", "admin");
                done();
            }, 1500);
            setTimeout(function () {
                var mainarea,
                    sel;
                ct.mainMenu(assert);
                assert.strictEqual($('#userbox').text(), 'Employee: root ADMIN');
                ct.mainareaForm(assert, 'mainMenu');
                sel = ct.getMenuEntry(assert, $('#mainarea').html(), 'Masquerade');
                $('input[name="sel"]').val(sel);
                $('input[name="sel"]').focus();
                // press ENTER -> submit the form
                $('input[name="sel"]').trigger($.Event("keydown", {keyCode: 13}));
                ct.stack(assert, 2, 'navigating from mainMenu to searchEmployee', 'dform', 'searchEmployee');
                mainarea = $('#mainarea').html();
                ct.contains(assert, mainarea, "#mainarea", "Search Dochazka employees");
                assert.ok(true, "*** REACHED searchEmployee dform");
                done();
            }, 2000);
            setTimeout(function () {
                var minimenu,
                    sel;
                // enter a search string
                $('input[id="sEnick"]').val('act%');
                assert.strictEqual($('input[id="sEnick"]').val(), 'act%', "Search string entered into form");
                minimenu = $('#minimenu').html();
                ct.contains(assert, minimenu, "searchEmployee miniMenu", ".&nbsp;Search");
                sel = ct.getMenuEntry(assert, minimenu, 'Search')
                ct.log(assert, "searchEmployee miniMenu contains Search as selection " + sel);
                $('input[name="sel"]').val(sel);
                $('input[name="sel"]').focus();
                $('input[name="sel"]').trigger($.Event("keydown", {keyCode: 13}));
                done();
            }, 2500);
            setTimeout(function () {
                var mainarea,
                    minimenu,
                    sel;
                ct.stack(assert, 3, 'browsing results of successful Dochazka employee search',
                         'dbrowser', 'masqueradeCandidatesBrowser');
                assert.ok(true, "*** REACHED masqueradeCandidatesBrowser dform");
                mainarea = $('#mainarea').html();
                minimenu = $('#minimenu').html();
                ct.contains(assert, mainarea, "Masquerade candidates browser", 'Masquerade candidates');
                ct.contains(assert, minimenu, "Masquerade selection in miniMenu", ".&nbsp;Masquerade");
                assert.ok(true, "*** REACHED Masquerade selection in masqueradeCandidatesBrowser miniMenu");
                sel = ct.getMenuEntry(assert, minimenu, 'Masquerade');
                assert.ok(true, "masqueradeCandidatesBrowser miniMenu contains Masquerade as selection " + sel);
                // select Masquerade (first time - begin)
                $('input[name="sel"]').val(sel);
                $('input[name="sel"]').focus();
                // press ENTER -> submit the form
                $('input[name="sel"]').trigger($.Event("keydown", {keyCode: 13}));
                ct.stack(assert, 1, 'selected Masquerade in masqueradeCandidatesBrowser', 'dmenu', 'mainMenu');
                assert.strictEqual($('#userbox').text(), '!!! Employee: active (MASQUERADE) !!!');
                assert.ok(true, "*** REACHED masquerading as employee \"active\"");
                done();
            }, 3000);
            setTimeout(function () {
                ct.mainMenuSelectEmpProfile(assert);
                done();
            }, 3500);
            setTimeout(function () {
                var htmlbuf,
                    sel;
                // mainMenu, myProfileAction, empProfile
                ct.stack(assert, 3, 'navigating from mainMenu to empProfile', 'dform', 'empProfile');
                ct.mainareaForm(assert, 'empProfile');
                ct.contains(assert, $('#mainarea').html(), "#mainarea", "Employee profile");
                ct.log(assert, "*** REACHED empProfile dform");
                // Whatever the supervisor is, delete it
                sel = ct.getMenuEntry(assert, $('#minimenu').html(), "Remove&nbsp;supervisor");
                assert.ok(true, "Selection is " + sel);
                $('input[name="sel"]').val(sel);
                $('input[name="sel"]').focus();
                // press ENTER -> submit the form
                $('input[name="sel"]').trigger($.Event("keydown", {keyCode: 13}));
                // mainMenu, myProfileAction, empProfile, searchEmployee
                ct.stack(
                    assert,
                    4,
                    'selected Delete supervisor in empProfile',
                    'dform',
                    'empProfileSetSuperConfirm'
                );
                htmlbuf = $("#mainarea").html(),
                ct.contains(
                    assert,
                    htmlbuf,
                    "#mainarea html",
                    "Set employee supervisor - confirmation",
                );
                ct.mainareaForm(assert, "empProfileSetSuperConfirm");
                sel = ct.getMenuEntry(assert, $('#minimenu').html(), 'Yes,&nbsp;I&nbsp;really&nbsp;do');
                assert.ok(true, "Selection is " + sel);
                $('input[name="sel"]').val(sel);
                $('input[name="sel"]').focus();
                // press ENTER -> submit the form
                $('input[name="sel"]').trigger($.Event("keydown", {keyCode: 13}));
                done();
            }, 4000);
            setTimeout(function () {
                var sel;
                ct.stack(

share/js/dochazka-www/tests/main-empl.js  view on Meta::CPAN

                    'empProfile'
                );
                ct.log(assert, $('#mainarea').html());
                ct.contains(
                    assert,
                    $('#ePsuperNick').text(),
                    "#ePsuperNick text",
                    "(none)",
                );
                ct.log(assert, "*** REACHED supervisor deleted; no supervisor is set");
                sel = ct.getMenuEntry(assert, $('#minimenu').html(), "Set&nbsp;supervisor");
                assert.ok(true, "Selection is " + sel);
                $('input[name="sel"]').val(sel);
                $('input[name="sel"]').focus();
                // press ENTER -> submit the form
                $('input[name="sel"]').trigger($.Event("keydown", {keyCode: 13}));
                // mainMenu, myProfileAction, empProfile, searchEmployee
                ct.stack(assert, 4, 'selected Set supervisor in empProfile', 'dform', 'searchEmployee');
                // enter search term into form
                $('#searchEmployee input[name="entry0"]').val('inactive');
                sel = ct.getMenuEntry(assert, $('#minimenu').html(), 'Search');
                $('input[name="sel"]').val(sel);
                $('input[name="sel"]').focus();
                start.mmKeyListener($.Event("keydown", {keyCode: 13}));
                assert.ok(true, "*** REACHED initiated search for Dochazka employee inactive");
                done();
            }, 4500);
            setTimeout(function () {
                var htmlbuf,
                    sel;
                ct.stack(

share/js/dochazka-www/tests/main-empl.js  view on Meta::CPAN

                    $('#ePnick').text(),
                    "inactive",
                    "Dochazka employee search succeeded - nick inactive displayed",
                );
                ct.contains(
                    assert,
                    $('#minimenu').html(),
                    "#minimenu html",
                    ".&nbsp;Set&nbsp;supervisor",
                );
                assert.ok(true, "*** REACHED miniMenu contains substring '.&nbsp;Set&nbsp;supervisor'");
                sel = ct.getMenuEntry(assert, $('#minimenu').html(), 'Set&nbsp;supervisor');
                assert.ok(true, "Selection is " + sel);
                $('input[name="sel"]').val(sel);
                $('input[name="sel"]').focus();
                // press ENTER -> submit the form
                $('input[name="sel"]').trigger($.Event("keydown", {keyCode: 13}));
                ct.stack(
                    assert,
                    6,
                    'selected Set supervisor in setSupervisorBrowser',
                    'dform',
                    'empProfileSetSuperConfirm'
                );
                htmlbuf = $("#mainarea").html(),
                ct.contains(
                    assert,
                    htmlbuf,
                    "#mainarea html",
                    "Set employee supervisor - confirmation",
                );
                ct.mainareaForm(assert, "empProfileSetSuperConfirm");
                sel = ct.getMenuEntry(assert, $('#minimenu').html(), 'Yes,&nbsp;I&nbsp;really&nbsp;do');
                assert.ok(true, "Selection is " + sel);
                $('input[name="sel"]').val(sel);
                $('input[name="sel"]').focus();
                // press ENTER -> submit the form
                $('input[name="sel"]').trigger($.Event("keydown", {keyCode: 13}));
                done();
            }, 5000);
            setTimeout(function () {
                var sel;
                ct.stack(

share/js/dochazka-www/tests/main-empl.js  view on Meta::CPAN

                    "inactive",
                );
                ct.log(assert, "*** REACHED supervisor set to inactive");
                $('input[name="sel"]').val('x');
                $('input[name="sel"]').focus();
                // press ENTER -> submit the form
                $('input[name="sel"]').trigger($.Event("keydown", {keyCode: 13}));
                ct.stack(
                    assert,
                    1,
                    'back to mainMenu after setting supervisor',
                    'dmenu',
                    'mainMenu'
                );
                // turn off masquerade
                sel = ct.getMenuEntry(assert, $('#mainarea').html(), 'Masquerade');
                $('input[name="sel"]').val(sel);
                $('input[name="sel"]').focus();
                // press ENTER -> submit the form
                $('input[name="sel"]').trigger($.Event("keydown", {keyCode: 13}));
                assert.strictEqual($('#userbox').text(), 'Employee: root ADMIN');
                loggout();
                done();
            }, 5500);
            setTimeout(function () {
                ct.loggout(assert);

share/js/dochazka-www/tests/main-menu.js  view on Meta::CPAN

// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
// *************************************************************************
//
// app/tests/main-menu.js
//
// Tests exercising the "mainMenu" dmenu
//
"use strict";

define ([
  'QUnit',
  'jquery',
  'app/canned-tests',
  'lib',
  'login',
  'loggout',

share/js/dochazka-www/tests/main-menu.js  view on Meta::CPAN

            var done = assert.async(3),
                mainarea,
                htmlbuf,
                cu;
            login({"nam": "root", "pwd": "immutable"});
            setTimeout(function () {
                ct.login(assert, "root", "admin");
                done();
            }, 1000);
            setTimeout(function () {
                ct.mainMenu(assert);
                loggout();
                done();
            }, 1500);
            setTimeout(function () {
                ct.loggout(assert);
                done();
            }, 2000);
        });

        test_desc = 'masquerade as employee "active"';

share/js/dochazka-www/tests/main-menu.js  view on Meta::CPAN

                htmlbuf,
                sel,
                cu;
            assert.expect(66);
            login({"nam": "root", "pwd": "immutable"});
            setTimeout(function () {
                ct.login(assert, "root", "admin");
                done();
            }, 1000);
            setTimeout(function () {
                ct.mainMenu(assert);
                assert.strictEqual($('#userbox').text(), 'Employee: root ADMIN');
                ct.mainareaForm(assert, 'mainMenu');
                sel = ct.getMenuEntry(assert, $('#mainarea').html(), 'Masquerade');
                if (! coreLib.isInteger(sel)) {
                    console.log("BAILING OUT");
                    assert.ok(false, "BAILING OUT");
                    done();
                }
                console.log("Main menu contains Masquerade as selection " + sel);
                assert.ok(true, "Main menu contains Masquerade as selection " + sel);
                $('input[name="sel"]').val(sel);
                $('input[name="sel"]').focus();
                // press ENTER -> submit the form
                $('input[name="sel"]').trigger($.Event("keydown", {keyCode: 13}));
                ct.stack(assert, 2, 'navigating from mainMenu to searchEmployee', 'dform', 'searchEmployee');
                mainarea = $('#mainarea').html();
                ct.contains(assert, mainarea, "#mainarea", "Search Dochazka employees");
                assert.ok(true, "*** REACHED searchEmployee dform");
                done();
            }, 2000);
            setTimeout(function () {
                // enter a search string
                $('input[id="sEnick"]').val('act%');
                assert.strictEqual($('input[id="sEnick"]').val(), 'act%', "Search string entered into form");
                minimenu = $('#minimenu').html();
                ct.contains(assert, minimenu, "searchEmployee miniMenu", ".&nbsp;Search");
                sel = ct.getMenuEntry(assert, minimenu, 'Search')
                ct.log(assert, "searchEmployee miniMenu contains Search as selection " + sel);
                $('input[name="sel"]').val(sel);
                $('input[name="sel"]').focus();
                $('input[name="sel"]').trigger($.Event("keydown", {keyCode: 13}));
            }, 2500);
            setTimeout(function () {
                ct.stack(assert, 3, 'browsing results of successful Dochazka employee search',
                         'dbrowser', 'masqueradeCandidatesBrowser');
                assert.ok(true, "*** REACHED masqueradeCandidatesBrowser dform");
                mainarea = $('#mainarea').html();
                minimenu = $('#minimenu').html();
                ct.contains(assert, mainarea, "Masquerade candidates browser", 'Masquerade candidates');
                ct.contains(assert, minimenu, "Masquerade selection in miniMenu", ".&nbsp;Masquerade");
                assert.ok(true, "*** REACHED Masquerade selection in masqueradeCandidatesBrowser miniMenu");
                sel = ct.getMenuEntry(assert, minimenu, 'Masquerade');
                assert.ok(true, "masqueradeCandidatesBrowser miniMenu contains Masquerade as selection " + sel);
                // select Masquerade (first time - begin)
                $('input[name="sel"]').val(sel);
                $('input[name="sel"]').focus();
                // press ENTER -> submit the form
                $('input[name="sel"]').trigger($.Event("keydown", {keyCode: 13}));
                ct.stack(assert, 1, 'selected Masquerade in masqueradeCandidatesBrowser', 'dmenu', 'mainMenu');
                assert.strictEqual($('#userbox').text(), '!!! Employee: active (MASQUERADE) !!!');
                assert.ok(true, "*** REACHED masquerading as employee \"active\"");
                done();
            }, 3000);
            setTimeout(function () {
                ct.mainareaForm(assert, 'mainMenu');
                htmlbuf = $('#mainarea').html();
                sel = ct.getMenuEntry(assert, htmlbuf, 'Masquerade');
                assert.ok(true, "Main menu contains Masquerade as selection " + sel);
                // select Masqerade (second time - end)
                $('input[name="sel"]').val(sel);
                $('input[name="sel"]').focus();
                // press ENTER -> submit the form
                $('input[name="sel"]').trigger($.Event("keydown", {keyCode: 13}));
                assert.strictEqual($('#userbox').text(), 'Employee: root ADMIN');
                loggout();
                done();
            }, 3500);

share/js/dochazka-www/tests/main-sched.js  view on Meta::CPAN

        test_desc = 'schedule menu appears';
        QUnit.test(test_desc, function (assert) {
            console.log('***TEST*** ' + prefix + test_desc);
            var done = assert.async(3);
            login({"nam": "root", "pwd": "immutable"});
            setTimeout(function () {
                ct.login(assert, "root", "admin");
                done();
            }, 1000);
            setTimeout(function () {
                ct.mainMenu(assert);
                ct.mainMenuToMainSched(assert);
                loggout();
                done();
            }, 1500);
            setTimeout(function () {
                ct.loggout(assert);
                done();
            }, 2200);
        });

        test_desc = 'schedule lookup - bogus ID';
        QUnit.test(test_desc, function (assert) {
            console.log('***TEST*** ' + prefix + test_desc);
            var done = assert.async(4);
            login({"nam": "root", "pwd": "immutable"});
            setTimeout(function () {
                ct.login(assert, "root", "admin");
                done();
            }, 1000);
            setTimeout(function () {
                var entry1;
                ct.mainMenu(assert);
                ct.mainMenuToMainSched(assert);
                ct.mainSchedToSchedLookup(assert);
                entry1 = $('form#schedLookup input[name="entry1"]');
                entry1.val('BOGOSITYWHELP');
                assert.strictEqual(entry1.val(), 'BOGOSITYWHELP', "Form filled out with bogus data");
                $('input[name="sel"]').val('1');
                $('input[name="sel"]').focus();
                start.mmKeyListener($.Event("keydown", {keyCode: 13}));
                assert.ok(true, "*** REACHED schedLookup form submitted");
                ct.ajaxCallInitiated(assert);
                done();



( run in 0.839 second using v1.01-cache-2.11-cpan-49f99fa48dc )