CallBackery

 view release on metacpan or  search on metacpan

CHANGES  view on Meta::CPAN


0.58.0 2026-07-15 17:23:33 +0200 Tobias Oetiker <tobi@oetiker.ch>

 - Session expiry now surfaces as a dedicated RPC code 7 ("session
   expired"), distinct from code 6 ("login required"). allow_rpc_access
   guards plugin instantiation so an expired session no longer escapes as
   a generic error. CallBackery::User gains a per-request `sessionExpired`
   flag for subclasses that enforce a cookie max-age.

 - Frontend data.Server: session expiry shows a single deduplicated
   "Session Expired -> Reload" prompt instead of a storm of error popups.
   Communication failures (server unreachable / proxy returning garbage)
   now retry silently for idempotent reads, then show one "Connection
   problem" dialog with Retry / Reload. MsgBox gains reload/retry buttons.

0.57.0 2026-06-16 08:58:42 +0200 Tobias Oetiker <tobi@oetiker.ch>

 - We are on JSON-RPC 2.0 now. callbackery.data.Server now uses
   qx.io.jsonrpc.Client (qooxdoo 7.x) instead of the deprecated
   qx.io.remote.Rpc. 

CHANGES  view on Meta::CPAN

0.55.3 2025-08-25 16:37:31 +0200 Tobias Oetiker <tobi@oetiker.ch>

 - fix spelling Runnning -> Running

0.55.2 2025-06-12 17:35:56 +0200 Tobias Oetiker <tobi@oetiker.ch>

 - fix fake login page format

0.55.1 2025-06-12 17:28:21 +0200 Tobias Oetiker <tobi@oetiker.ch>

 - properly close the popup after download if so configured

0.55.0 2025-06-12 15:24:25 +0200 Tobias Oetiker <tobi@oetiker.ch>

 - download displays a busy message which can be configured using
   busyMessage property
 - upon download completing popup will close if closeAfterDownload => true,
   is set

0.54.0 2025-06-12 14:52:06 +0200 Tobias Oetiker <tobi@oetiker.ch>

 - upload actions are now busy during upload
   use the busyMessage property to display a custom message during upload

0.53.1 2025-06-04 18:04:46 +0200 Tobias Oetiker <tobi@oetiker.ch>

 - only log slow getters

CHANGES  view on Meta::CPAN

0.50.3 2024-09-19 16:02:07 +0200 Tobias Oetiker <tobi@oetiker.ch>

 - filter menuButtonProperties to make card view work again

0.50.2 2024-09-18 16:42:18 +0200 Tobias Oetiker <tobi@oetiker.ch>

 - fix regression with missing defaults for app and log in user object

0.50.1 2024-08-30 12:27:22 +0200 Tobias Oetiker <tobi@oetiker.ch>

 - show a popup before reloading the page

0.50.0 2024-08-29 17:12:41 +0200 Tobias Oetiker <tobi@oetiker.ch>

 - reload the browser window when an exception with status 7 is returned
 - warn if trm() is called with undefined arguments

0.49.6 2024-07-17 17:25:39 +0200 Tobias Oetiker <tobi@oetiker.ch>

 - fix some more memory loops

CHANGES  view on Meta::CPAN


0.42.1 2022-05-12 22:56:43 +0200 Tobias Oetiker <tobi@oetiker.ch>

 - Apply buttonSet hash on menu action button

0.42.0 2022-04-27 08:48:54 +0200 Tobias Oetiker <tobi@oetiker.ch>

 - add btCfg.testingIdPostfix for action menues with generic Popup
   (e.g. CredMgr OAuth)

 - add check to enforce unique none-popup action keys

0.41.6 2022-04-05 14:28:48 +0200 Tobias Oetiker <tobi@oetiker.ch>

 - make sure LC_TIME and LC_NUMERIC are C and not set to some local
   variant as this will cause all sorts of fun effects with localized
   numbers and date strings

0.41.5 2022-03-31 16:00:42 +0200 Tobias Oetiker <tobi@oetiker.ch>

 - translate button labels

CHANGES  view on Meta::CPAN

0.38.7 2021-06-24 08:11:49 +0200 Tobias Oetiker <tobi@oetiker.ch>

 - make sure to set the the foreign key pragma before internal migrations

0.38.6 2021-06-02 22:15:24 +0200 Tobias Oetiker <tobi@oetiker.ch>

 - fix access checker promise blocker

0.38.5 2021-05-27 11:37:03 +0200 Tobias Oetiker <tobi@oetiker.ch>

 - fix binding for confirmation popup box

0.38.4 2021-05-21 08:42:39 +0200 Tobias Oetiker <tobi@oetiker.ch>

 - allow for multiple actions to share the same plugin instance as long as they share the same config

0.38.3 2021-05-17 16:12:40 +0200 Tobias Oetiker <tobi@oetiker.ch>

 - run the mayAnonymous check as a last ditch effort ... 

0.38.2 2021-05-17 15:44:51 +0200 Tobias Oetiker <tobi@oetiker.ch>

CHANGES  view on Meta::CPAN

0.37.0 2021-05-06 16:31:40 +0200 Tobias Oetiker <tobi@oetiker.ch>
 New Features

 - access registration app as app=registration
 - access passwordreset app as app=passwordreset
 - prefill form fields with set_{$key}=value
 - cleanup hash url with cleanup=1

 Bugfix

 - do not close popup on showMessage 
 - emit selection event on change selection in popup

 Example:

  http://127.0.0.1:3626/#app=registration;set_email=dummy@address;set_token=ebc4g90d2;cleanup=1

0.36.9 2021-05-05 18:06:10 +0200 Tobias Oetiker <tobi@oetiker.ch>

 - fix eventhandling in frontend code

0.36.8 2021-05-02 13:47:46 +0200 Tobias Oetiker <tobi@oetiker.ch>

CHANGES  view on Meta::CPAN

 - allow for incremental search in selectbox dropdowns
   thanks to fritz zaucker for the contrib

0.35.15 2021-04-09 15:08:19 +0200 Tobias Oetiker <tobi@oetiker.ch>

 - fix regression ; -> :

0.35.14 2021-04-09 14:36:56 +0200 Tobias Oetiker <tobi@oetiker.ch>

 - no double translation
 - support dataModified in popup.js

0.35.13 2021-04-09 13:31:23 +0200 Tobias Oetiker <tobi@oetiker.ch>

 - fix msgbox regression

0.35.12 2021-03-31 18:24:31 +0200 Tobias Oetiker <tobi@oetiker.ch>

 - make calls to postProcessCfg idempotent
 - provid eq overload for tra objects

CHANGES  view on Meta::CPAN


0.35.8 2021-03-22 16:21:48 +0100 Tobias Oetiker <tobi@oetiker.ch>

 - Handle SelectBox as part of Cards
 - Make updates work generically for every text field
 - Add some checks for undefined data


0.35.7 2021-03-04 15:28:49 +0100 Tobias Oetiker <tobi@oetiker.ch>

 - fix popup form regresson ... some debug code had made it into the releasse

0.35.6 2021-02-26 11:13:21 +0100 Tobias Oetiker <tobi@oetiker.ch>

 - add path option to Config::getTranslations call ... allow to override
   translation location

0.35.5 2021-01-26 13:28:43 +0100 Tobias Oetiker <tobi@oetiker.ch>

 - fix form loading (regression from 0.35.4)

CHANGES  view on Meta::CPAN


 - only accept POST requests as the qx plugin is very
   lax with handling GET requests regarding header security

0.34.17 2020-10-08 16:03:27 +0200 Tobias Oetiker <tobi@oetiker.ch>

 - fix UserList range

0.34.16 2020-09-05 07:53:26 +0200 Tobias Oetiker <tobi@oetiker.ch>

  - make sure the blocker overlays popup windows too

0.34.15 2020-08-24 14:10:23 +0200 Tobias Oetiker <tobi@oetiker.ch>

 - mkerror not merror

0.34.14 2020-08-24 14:02:24 +0200 Tobias Oetiker <tobi@oetiker.ch>

 - replace module loading code to prevent double loading modules

0.34.13 2020-08-19 01:05:57 +0200 Tobias Oetiker <tobi@oetiker.ch>

CHANGES  view on Meta::CPAN

0.34.11 2020-08-19 00:16:55 +0200 Tobias Oetiker <tobi@oetiker.ch>

 - fixed copy success message

0.34.10 2020-08-17 20:33:34 +0200 Tobias Oetiker <tobi@oetiker.ch>

 - translate headers in excel export

0.34.9 2020-08-15 11:06:17 +0200 Tobias Oetiker <tobi@oetiker.ch>

 - fix popup resizing regression

0.34.8 2020-08-13 10:34:13 +0200 Tobias Oetiker <tobi@oetiker.ch>

 - placeholder translation in notes fixed
 - add automatic response to available space on login and popup dialog

0.34.7 2020-08-12 14:35:31 +0200 Tobias Oetiker <tobi@oetiker.ch>

 - fix regression in popup disposal code

0.34.6 2020-08-12 14:06:26 +0200 Tobias Oetiker <tobi@oetiker.ch>

 - reposition login window as the logo loads
 - move max size logic into the popup window code

0.34.5 2020-08-07 16:05:10 +0200 Tobias Oetiker <tobi@oetiker.ch>

 - false was treated as null in the required field check ... 

0.34.4 2020-08-06 14:52:40 +0200 Tobias Oetiker <tobi@oetiker.ch>

 - make sure that no reconf requests get lost if data is entered into the form while it is still loading

0.34.3 2020-08-06 09:41:36 +0200 Tobias Oetiker <tobi@oetiker.ch>

CHANGES  view on Meta::CPAN

 - sync the visibility setting to 'note' properties
 - allow visibility seting on header elements in forms
 - improve left side spacing for forms with header sections and no side notes

0.34.2 2020-07-31 13:49:05 +0200 Tobias Oetiker <tobi@oetiker.ch>

 - translate on selectbox content reconfiguration

0.34.1 2020-07-27 09:28:23 +0200 Tobias Oetiker <tobi@oetiker.ch>

 - if popup windows have not set maxWidth/maxHeight, set according the
   appliaction Root

0.34.0 2020-07-26 12:55:39 +0200 Tobias Oetiker <tobi@oetiker.ch>

 - the AbstractTable module now contains an action generator called
   makeExportAction which places an export button into the action row
   of a table of your choice ... note that this addition also requires you to add the
   modules Text::CSV and Excel::Writer::XLSX to your dependencies.
   Contribution by @maettu

CHANGES  view on Meta::CPAN


 - make work when mounted 'non root'

0.31.0 2020-03-26 17:27:54 +0100 Tobias Oetiker <tobi@oetiker.ch>

 - fix login save trick to work with new compiler
 - GuiPlugins can now have an 'mayAnonymous' property which lets them display without login
   this is used for implementing password reset and account creation plugins
 - hide user comment from non admin users
 - tag more error messages for translation
 - frontend new config options registration_popup and registration_popup they must point to an entry in the PLUGINS section
 - plugins can be hidden from the plugin list using the 'unlisted' property.

0.30.1 2020-03-05 13:54:01 +0100 Tobias Oetiker <tobi@oetiker.ch>

 - make table context menu button track the changes
 - do not execute default action if button is not enabled

0.30.0 2020-03-04 18:08:25 +0100 Tobias Oetiker <tobi@oetiker.ch>

 - Table rows with an '_actionSet' key containing a hash with key

CHANGES  view on Meta::CPAN


 - stringify arguments in translation array objects
 - translate invalid field messages

0.29.3 2020-02-28 09:57:50 +0100 Tobias Oetiker <tobi@oetiker.ch>

 - do not translate empty strings

0.29.2 2020-02-27 14:14:03 +0100 Tobias Oetiker <tobi@oetiker.ch>

 - fix popup instanciation with new YAML config

0.29.1 2020-02-21 16:55:09 +0100 Tobias Oetiker <tobi@oetiker.ch>

 - callbackery.locale.MTranslation was missing from MANIFEST and
   thus from distro

0.29.0 2020-02-21 15:37:33 +0100 Tobias Oetiker <tobi@oetiker.ch>

 - trm with placeholder and arguments work now trm('Hello %1',$name)
 - in qooxdoo frontend code, use this.xtr(backendData) to translate

CHANGES  view on Meta::CPAN

0.26.2 2020-01-23 10:44:20 +0100 Tobias Oetiker <tobi@oetiker.ch>

 - updated wording and translations

0.26.1 2020-01-20 15:59:33 +0100 Tobias Oetiker <tobi@oetiker.ch>

 - fixed js syntax (excess ,)

0.26.0 2020-01-20 15:27:13 +0100 Tobias Oetiker <tobi@oetiker.ch>

 - pop config option cancelLabel to override label on calcle button in popups
 - form field option 'copyOnTap' added to copy readOnly field content to
   clipboard on tap.

0.25.1 2019-12-16 09:50:38 +0100 Tobias Oetiker <tobi@oetiker.ch>

 - merge translations

0.25.0 2019-12-16 09:44:32 +0100 Tobias Oetiker <tobi@oetiker.ch>

 - pass the output of config.getUrlConfig under the key urlConfig to the getUserConfig backend call

CHANGES  view on Meta::CPAN

* 5898387 - add a cache-control header for all requests but those going for the resource files. (1 year, 1 month ago) <Tobias Oetiker>
* bd53c60 - (tag: v0.12.0) v0.12.0 (1 year, 2 months ago) <Tobias Oetiker>
* 4e0dfba - additional types supported for table columns: - string - number   including format option (1 year, 2 months ago) <Tobias Oetiker>
* 8d5425f - qxclass changes (1 year, 2 months ago) <Tobias Oetiker>
* 6494665 - local class (1 year, 2 months ago) <Tobias Oetiker>
* ae4f5ed - local class (1 year, 2 months ago) <Tobias Oetiker>
* 851f7d3 - add bin makefile handle qxpath seperately (1 year, 2 months ago) <Tobias Oetiker>
* 6c7450c - app names with - and not _ please (1 year, 2 months ago) <Tobias Oetiker>
* 603bd0e - update to latest CallBackery (1 year, 2 months ago) <Tobias Oetiker>
* 7c52763 - (tag: v0.11.2) handle text fields with 0 (numeric) content properly (1 year, 3 months ago) <Tobias Oetiker>
* 901ce64 - (tag: v0.11.1) fix popup regression (1 year, 4 months ago) <Tobias Oetiker>
* 683f147 - (tag: v0.11.0) make visibility propagation actually work (1 year, 5 months ago) <Tobias Oetiker>
* 8eb8770 - a bunch of changes to enable plugins to hide themselves if they want to (1 year, 5 months ago) <Tobias Oetiker>
* f3c697c - * improve handling of user objects * add support for #focusApp=xxx  location argument (1 year, 5 months ago) <Tobias Oetiker>
* 874ba3c - (tag: v0.10.9) no more transitions for blocker (1 year, 9 months ago) <Tobias Oetiker>
* e1e5f4a - (tag: v0.10.8) 0.10.8 (1 year, 9 months ago) <Tobias Oetiker>
* a401b20 - make download work again (1 year, 9 months ago) <Tobias Oetiker>
* 8a9f180 - do not recursively define SHARE (1 year, 9 months ago) <Tobias Oetiker>
* d04d959 - move blocker tuneing into separate method, so that alternate implemenations are simple (1 year, 9 months ago) <Tobias Oetiker>
* 48146ac - (tag: v0.10.7) blurring blocker effect added (1 year, 9 months ago) <Tobias Oetiker>
* b61ada6 - (tag: v0.10.6) de-slurpify (1 year, 10 months ago) <Tobias Oetiker>

CHANGES  view on Meta::CPAN

* 4275dcc - better readme (2 years, 3 months ago) <Tobias Oetiker>
* 0c6b5e6 - better readme (2 years, 3 months ago) <Tobias Oetiker>
* b7b4b10 - this.tr is not available in server.js. fix for #29 (2 years, 3 months ago) <Tobias Oetiker>
* 25418af - (tag: v0.8.4) v0.8.4 (2 years, 3 months ago) <Tobias Oetiker>
* 847b0b1 - allow html in header (2 years, 3 months ago) <Tobias Oetiker>
* 02d43ea - translate busy message (2 years, 3 months ago) <Tobias Oetiker>
* 762bf8e - fix loading animation (2 years, 3 months ago) <Tobias Oetiker>
* 2cd7746 - fix args regression (2 years, 4 months ago) <Tobias Oetiker>
* 9ec77b6 - 0.8.2 (2 years, 4 months ago) <Tobias Oetiker>
* 55cfdca - args should alwais at least contain a hash ... this is only a stop gap fix ... we realy have to pass the partenArgs every time we interact with the plugin (2 years, 4 months ago) <Tobias Oetiker>
* c28ab41 - (tag: v0.8.1) 0.8.1  * allow escape to cancle popupClosed (2 years, 4 months ago) <Tobias Oetiker>
* 7c674ff - (tag: v0.7.1) fix readme issue (2 years, 4 months ago) <Tobias Oetiker>
* 80ef5e1 - cpanmin.us seems unstable (2 years, 4 months ago) <Tobias Oetiker>
* 061b82c - (tag: v0.7.0) added context menu and default action to table widget (2 years, 4 months ago) <Tobias Oetiker>
* a23d65a - handle validation on selectboxes without content (2 years, 5 months ago) <Tobias Oetiker>
* b485eb7 - be more careful with the server handler (2 years, 5 months ago) <Tobias Oetiker>
* ca89896 - better sample build app (2 years, 5 months ago) <Tobias Oetiker>
* 02a4dea - re-indent (2 years, 5 months ago) <Tobias Oetiker>
* 17493a7 - improved build system (2 years, 5 months ago) <Tobias Oetiker>
* 2325ae2 - (tag: v0.6.5) release 0.6.5 (2 years, 6 months ago) <Tobias Oetiker>
*   84b7e2b - Merge pull request #28 from samoser/PopUpPopUp (2 years, 6 months ago) <Tobias Oetiker>

lib/CallBackery/Controller/RpcService.pm  view on Meta::CPAN

    if (not exists $allow{$method}){
        return 0;
    }
    for ($allow{$method}){
        /1/ && return 1;                                 # public method
        return 1 if ($self->user->isUserAuthenticated); # forces cookieConf (sets sessionExpired)
        /3/ && do {
            # Level-3: allowed only for plugins that opt into anonymous access.
            # Guard the instantiation: for an unauthenticated user it commonly
            # dies (plugins read user rights/config); that death must resolve to
            # "not anonymous" here, never escape as a generic code-9999 popup.
            my $plugin = $self->rpcParams->[0];
            my $anon = eval {
                $self->config->instantiatePlugin($plugin,$self->user)->mayAnonymous
            };
            return 1 if $anon;
        };
        # Method needs auth and the user is not authenticated. If a session was
        # present and merely expired, signal that distinctly (code 7 -> reload);
        # otherwise fall through to code 6 (login dialog).
        die mkerror(RPC_SESSION_EXPIRED,

lib/CallBackery/GuiPlugin/AbstractAction.pm  view on Meta::CPAN

=cut

has actionCfg => sub {
   [];
};

=head2 actionCfgMap

Lookup table for action plugins.

NOTE: Unique keys are not checked for popup plugins as they don't have
      action handlers.
      This allows multiple popup actions using the same plugin instance.
      In this case an additional cfg parameter C<testingIdPostfix> must be
      used to make the QoxdooObjectIds unique used from frontend testing.

=cut

has actionCfgMap => sub {
    my $self = shift;
    my %map;
    for my $row (@{$self->actionCfg}){
        next unless $row->{action} =~ /^(submit|upload|download|display|autoSubmit|save)/;

lib/CallBackery/GuiPlugin/AbstractAction.pm  view on Meta::CPAN

hash.

=cut

sub massageConfig {
    my $self = shift;
    my $cfg = shift;
    $self->__fixActionCfg;
    my $actionCfg = $self->actionCfg;
    for my $button (@$actionCfg){
        if ($button->{action} =~ /popup|wizzard/) {
            my $name = $button->{name};
            # allow same plugin multiple times
            $button->{name} = $name;
            if ($cfg->{PLUGIN}{prototype}{$name}) {
                my $newCfg = encode_json($button->{backend});
                my $oldCfg = encode_json($cfg->{PLUGIN}{prototype}{$name}{backend});
                if ($oldCfg ne 'null' and $newCfg ne $oldCfg) {
                    $self->log->warn("oldCfg=" . dumper $oldCfg);
                    $self->log->warn("newCfg=", dumper $newCfg);
                    die "Not unique plugin instance name $name not allowed as backend config is different\n";
                }
            }
            my $popup = $cfg->{PLUGIN}{prototype}{$name}
                = $self->app->config->loadAndNewPlugin($button->{backend}{plugin});
            $popup->config($button->{backend}{config});
            $popup->name($name);
            $popup->app($self->app);
            $popup->massageConfig($cfg);
        }
    }
    if (ref $self->user eq 'MockUser') {
        # $self->log->debug("massageConfig is done. undefining user");
        $self->user(undef);
    }
    return;
}

=head2 __fixActionCfg

lib/CallBackery/GuiPlugin/AbstractAction.pm  view on Meta::CPAN

             . " name=$action->{name}"
            );
        }
        if (not $action->{key}) {
            $self->log->warn(
               $pkg . " action should have a key attribute,"
             . " created a key from name=$action->{name} instead"
            );
            $action->{key} = $action->{name};
        }
        # popups and wizzards do need a name internally
        if ($action->{action} =~ /popup|wizzard/) {
            $action->{name} = "${name}_$action->{key}";
        }
    }
    $self->{__action_cfg_fixed} = 1;
    return $self;
}


1;
__END__

lib/CallBackery/GuiPlugin/Users.pm  view on Meta::CPAN


=cut

has actionCfg => sub {
    my $self = shift;
    # we must be in admin mode if no user property is set to have be able to prototype all forms variants
    my $admin = ( not $self->user or $self->user->may('admin'));
    return [
        $admin ? ({
            label => trm('Add User'),
            action => 'popup',
            addToContextMenu => true,
            key => 'add',
            popupTitle => trm('New User'),
            backend => {
                plugin => 'UserForm',
                config => {
                    type => 'add'
                }
            }
        }) : (),
        {
            label => trm('Edit User'),
            action => 'popup',
            addToContextMenu => true,
            defaultAction => true,
            key => 'edit',
            popupTitle => trm('Edit User'),
            actionHandler => sub {
                my $self = shift;
                my $args = shift;
                my $id = $args->{selection}{cbuser_id};
                die mkerror(393,trm('You have to select a user first'))
                    if not $id;
            },
            set => {
                height => 340,
                width => 500

lib/CallBackery/Model/ConfigJsonSchema.pm  view on Meta::CPAN

            },
            required => [ $name ],
            additionalProperties => false,
        };
    }

    $schema->{properties}{PLUGIN}{items} = {
        anyOf => \@items
    };

    $schema->{properties}{FRONTEND}{properties}{$_.'_popup'}
        {properties}{plugin}{enum} = \@fullPluginList 
            for qw(registration passwordreset);

    # warn YAML::XS::Dump $schema;
    # second pass with data structures from plugins integrated
    if (my @errors = $self->validator->validate($cfg)){
        Mojo::Exception->throw(join "\n",@errors);
    }

    $cfg->{PLUGIN} = {
        prototype => \%pluginMap,
        list => \@pluginList
    };

    for (qw(registration passwordreset)) {
        if (my $popup = $cfg->{FRONTEND}{$_.'_popup'}){
            my $plugin = delete $popup->{plugin};
            my $obj = $pluginMap{$plugin};
            $cfg->{FRONTEND}{$_.'_popup'} = {
                popupTitle => $obj->config->{'tab-name'},
                name => $plugin,
                %$popup,
            };
        }
    }
    #warn YAML::XS::Dump($cfg->{FRONTEND})
    for my $name (@fullPluginList) {
        $pluginMap{$name}->massageConfig($cfg);
    }

    $cfg->{FRONTEND}{TRANSLATIONS} = $self->getTranslations();
    return $cfg;

lib/CallBackery/Model/ConfigJsonSchema.pm  view on Meta::CPAN

        description: hide password dialog icon
        default: false
      hide_release:
        type: boolean
        description: hide release string on login screen
        default: false
      hide_company:
        type: boolean
        description: hide company string on login screen
        default: false
      registration_popup:
        $ref: "#/definitions/plugin"
      passwordreset_popup:
        $ref: "#/definitions/plugin"

  PLUGIN:
    type: array
    items:
        type: object
        maxProperties: 1
        minProperties: 1
        patternProperty:
            ^\S+$:

lib/CallBackery/qooxdoo/callbackery/source/class/callbackery/ui/Login.js  view on Meta::CPAN

                alignX: 'right'
            })
        ).set({
            paddingTop: 10
        });
        this.add(extraActions, {
            row: 5,
            column: 0,
            colSpan: 3
        });
        if (cfg.passwordreset_popup) {
            let btn = this.__passwordresetBtn = this.__makeExtraButton(
                cfg.passwordreset_popup,this.tr("Reset Password")
            );
            extraActions.add(btn);
            

        }
        if (cfg.registration_popup) {
            let btn = this.__registrationBtn = this.__makeExtraButton(
                cfg.registration_popup,this.tr("Register New Account")
            );
            extraActions.add(btn);
        }
        
        if ( cfg.company_name && !cfg.hide_company){
            var who = '';
            if (cfg.company_url){
                who += '<a href="' + cfg.company_url + '" style="color: #444;" target="_blank">' + cfg.company_name + '</a>';
            }
            else {

lib/CallBackery/qooxdoo/callbackery/source/class/callbackery/ui/Login.js  view on Meta::CPAN

                this.setEnabled(true);
            }
        },
        __makeExtraButton: function(cfg,label) {
            var ul = this.tr('<span style="text-decoration: underline;">%1</span>',label);
            var button = new qx.ui.basic.Label(ul).set({
                cursor: 'pointer',
                rich: true
            });
            button.addListener('tap',function(e) {
                var popup = new callbackery.ui.Popup(cfg);
                popup.addListenerOnce('close', function(e) {
                    this.getApplicationRoot().remove(popup);
                    popup.dispose();
                    this.setModal(true);
                },this);
                this.setModal(false);
                popup.open();
            },this);
            return button;
        },
        __setMaxWidth: function() {
            let bounds = this.getApplicationRoot().getBounds();
            // make sure the window does not get larger than the screen by default ... 
            if (bounds) {
                this.setMaxWidth(bounds.width-20);
            }
        }

lib/CallBackery/qooxdoo/callbackery/source/class/callbackery/ui/MsgBox.js  view on Meta::CPAN

        __setIcons: function(icons) {
            if (icons && icons.caption) {
                this.setIcon(icons.caption);
            }
            if (icons && icons.body) {
                this.__body.setIcon(icons);
            }
        },

        /**
         * Open the Error popup
         *
         * @param title {String} title
         * @param text {String} body
         * @param html {Boolean} allow HTML if true
         * @param icons {Map} of body, button, and title icon strings
         * @param size {Map} of width and height
         * @return {void} 
         */
        error : function(title, text, html, icons, size) {
            this.__setIcons(icons);

lib/CallBackery/qooxdoo/callbackery/source/class/callbackery/ui/MsgBox.js  view on Meta::CPAN

            //    },this);
            // }

            // no HTML
            this.__open(this.tr('RPC Error %1', exc.code), this.xtr(exc.message), false);
            return this;
        },


        /**
         * Open the Info popup
         *
         * @param title {String} title
         * @param text {String} body
         * @param html {Boolean} allow HTML if true
         * @param icons {Map} of body, button, and title icon strings
         * @return {void} 
         */
        info : function(title, text, html, icons, size) {
            this.__setIcons(icons);
            this.__show_btn(['ok'], icons);
            this.__open(title, text, html, size);
            return this;
        },


        /**
         * Open the Warning popup with optional callback
         *
         * @param title {String} window title
         * @param text {String} content
         * @param html {Boolean} allow HTML if true
         * @param icons {Map} of body, button, and title icon strings
         * @param size {Map} of width and height
         * @return {void} 
         */
        warn : function(title, text, html, icons, size) {
            this.__setIcons(icons);
            this.__show_btn(['cancel','apply'], icons);
            this.__open(title, text, html, size);
            return this;
        },
        /**
         * Open the Warning popup with optional callback
         *
         * @param title {String} window title
         * @param text {String} content
         * @param html {Boolean} allow HTML if true
         * @param icons {Map} of body, button, and title icon strings
         * @param size {Map} of width and height
         * @return {void} 
         */
        yesno : function(title, text, html, icons, size) {
            this.__setIcons(icons);

lib/CallBackery/qooxdoo/callbackery/source/class/callbackery/ui/Popup.js  view on Meta::CPAN

qx.Class.define("callbackery.ui.Popup", {
    extend : qx.ui.window.Window,
    /**
     * create a page for the View Tab with the given title
     *
     * @param vizWidget {Widget} visualization widget to embedd
     */
    construct : function(cfg,getParentFormData) {
        /* using syntax trick to not get a warning for translating
           a variable */
        this.base(arguments, this.xtr(cfg.popupTitle));
        this.set({
            layout: new qx.ui.layout.Grow(),
            height: 600,
            width: 800,
            modal: true,
            allowMinimize: false,
            showMinimize: false,
            showStatusbar: false,
            centerOnContainerResize: true,
            centerOnAppear: true

lib/CallBackery/qooxdoo/callbackery/source/class/callbackery/ui/form/DateTime.js  view on Meta::CPAN


   Authors:
     * Martin Wittemann (martinwittemann)
     * Fritz Zaucker

************************************************************************ */

// FIX ME: should be derived from Qooxdoo DateField.

/**
 * A *date field* is like a combo box with the date as popup. As button to
 * open the calendar a calendar icon is shown at the right to the datefield.
 *
 * In addition a time textfield.
 *
 * To be conform with all form widgets, the {@link qx.ui.form.IForm} interface
 * is implemented.
 *
 * The following example creates a date field and sets the current
 * date as selected.
 *
 * <pre class='javascript'>
 * var dateTimeField = new callbackery.ui.form.DateTime();
 * this.getRoot().add(dateTimeField, {top: 20, left: 20});
 * dateField.setValue(new Date());
 * </pre>
 *
 * @childControl list {qx.ui.control.DateChooser} date chooser component
 * @childControl popup {qx.ui.popup.Popup} popup which shows the list control
 * @childControl datefield {qx.ui.form.TextField} text field for manual date entry
 * @childControl timefield {qx.ui.form.TextField} text field for manual date entry
 * @childControl button {qx.ui.form.Button} button that opens the list control
 */
qx.Class.define("callbackery.ui.form.DateTime",
{
  extend : qx.ui.core.Widget,
  include : [
    qx.ui.core.MRemoteChildrenHandling,
    qx.ui.form.MForm

lib/CallBackery/qooxdoo/callbackery/source/class/callbackery/ui/form/DateTime.js  view on Meta::CPAN

    /*
    ---------------------------------------------------------------------------
      PUBLIC METHODS
    ---------------------------------------------------------------------------
    */


    /**
    * This method sets the date, which will be formatted according to
    * #dateFormat to the date field. It will also select the date in the
    * calendar popup.
    *
    * @param value {Date} The date to set.
     */
    setValue : function(value)
    {
      // set the date to the textfield

      if (value != null) {      
          this.getChildControl("datefield").setValue(this.getDateFormat().format(value));

lib/CallBackery/qooxdoo/callbackery/source/class/callbackery/ui/form/DateTime.js  view on Meta::CPAN

    },


    /*
    ---------------------------------------------------------------------------
      LIST STUFF
    ---------------------------------------------------------------------------
    */

    /**
     * Shows the date chooser popup.
     */
    open : function()
    {
      var popup = this.getChildControl("popup");

      popup.placeToWidget(this, true);
      popup.show();
    },


    /**
     * Hides the date chooser popup.
     */
    close : function() {
      this.getChildControl("popup").hide();
    },


    /**
     * Toggles the date chooser popup visibility.
     */
    toggle : function()
    {
      var isListOpen = this.getChildControl("popup").isVisible();
      if (isListOpen) {
        this.close();
      } else {
        this.open();
      }
    },


    /*
    ---------------------------------------------------------------------------

lib/CallBackery/qooxdoo/callbackery/source/class/callbackery/ui/form/DateTime.js  view on Meta::CPAN

          this._add(control);
          break;

        case "list":
          control = new qx.ui.control.DateChooser();
          control.setFocusable(false);
          control.setKeepFocus(true);
          control.addListener("execute", this._onChangeDate, this);
          break;

        case "popup":
          control = new qx.ui.popup.Popup(new qx.ui.layout.VBox);
          control.setAutoHide(false);
          control.add(this.getChildControl("list"));
          control.addListener("pointerup", this._onChangeDate, this);
          control.addListener("changeVisibility", this._onPopupChangeVisibility, this);
          break;
      }

      return control || this.base(arguments, id);
    },




   /*
   ---------------------------------------------------------------------------
     EVENT LISTENERS
   ---------------------------------------------------------------------------
   */

   /**
    * Handler method which handles the tap on the calender popup.
    *
    * @param e {qx.event.type.Pointer} The pointer event.
    */
    _onChangeDate : function(e)
    {
        var dateField = this.getChildControl("datefield");

        var selectedDate = this.getChildControl("list").getValue();
        var timefield = this.getChildControl("timefield");
        var time        = timefield.getValue();
        var defaultTime = timefield.getPlaceholder();
        dateField.setValue(this.getDateFormat().format(selectedDate));
        if (time == null && defaultTime != null) {
            timefield.setValue(defaultTime);
        }
        this.close();
    },


    /**
     * Toggles the popup's visibility.
     *
     * @param e {qx.event.type.Pointer} Pointer tap event
     */
    _onTap : function(e) {
      this.close();
    },


    /**
     * Handler for the blur event of the current widget.

lib/CallBackery/qooxdoo/callbackery/source/class/callbackery/ui/form/DateTime.js  view on Meta::CPAN

     * @param e {qx.event.type.Focus} The blur event.
     */
    _onBlur : function(e) {
      this.close();
    },


    /**
     * Handler method which handles the key press. It forwards all key event
     * to the opened date chooser except the escape key event. Escape closes
     * the popup.
     * If the list is cloned, all key events will not be processed further.
     *
     * @param e {qx.event.type.KeySequence} Keypress event
     */
    _onKeyPress : function(e)
    {
      // get the key identifier
      var iden = e.getKeyIdentifier();
      if (iden == "Down" && e.isAltPressed())
      {
        this.toggle();
        e.stopPropagation();
        return;
      }

      // if the popup is closed, ignore all
      var popup = this.getChildControl("popup");
      if (popup.getVisibility() == "hidden") {
        return;
      }

      // hide the list always on escape
      if (iden == "Escape")
      {
        this.close();
        e.stopPropagation();
        return;
      }

      // Stop navigation keys when popup is open
      if (iden === "Left" || iden === "Right" || iden === "Down" || iden === "Up") {
        e.preventDefault();
      }

      // forward the rest of the events to the date chooser
      this.getChildControl("list").handleKeyPress(e);
    },


    /**
     * Redirects changeVisibility event from the list to this widget.
     *
     * @param e {qx.event.type.Data} Property change event
     */
    _onPopupChangeVisibility : function(e)
    {
      e.getData() == "visible" ? this.addState("popupOpen") : this.removeState("popupOpen");

      // Synchronize the chooser with the current value on every
      // opening of the popup. This is needed when the value has been
      // modified and not saved yet (e.g. no blur)
      var popup = this.getChildControl("popup");
      var chooser = this.getChildControl("list");
      if (popup.isVisible())
      {
          var date = this.getValue();
          if (date != null) {
              chooser.setValue(date);
          }
      }
    },


    /**
     * Reacts on value changes of the text field and syncs the
     * value to the combobox.
     *
     * @param e {qx.event.type.Data} Change event
     */
    _onDateFieldChangeValue : function(e)
    {
      // Apply to popup
      var date = e.getData();
      if (date != null && date != '')
      {

        var timefield = this.getChildControl("timefield");
        var time        = timefield.getValue();
        var defaultTime = timefield.getPlaceholder();
        var today = new Date();
          var dateValue;
        try {

lib/CallBackery/qooxdoo/callbackery/source/class/callbackery/ui/plugin/Action.js  view on Meta::CPAN

                    button.execute();
                    // only do it once for the time being
                    config.removeUrlConfigEntry(urlAction.key);
                }
            });
        }, this);
    },

    events: {
        actionResponse: 'qx.event.type.Data',
        popupClosed: 'qx.event.type.Event'
    },

    properties: {
        selection: {}
    },

    members: {
        _cfg: null,
        _plugin: null,
        _tableMenu: null,

lib/CallBackery/qooxdoo/callbackery/source/class/callbackery/ui/plugin/Action.js  view on Meta::CPAN

                            let mmBtnId = btCfg.key
                                + (btCfg.testingIdPostfix ? btCfg.testingIdPostfix : '')
                                + 'mmButton';
                            this.addOwnedQxObject(mmButton, mmBtnId);
                        }
                        this._bindButtonProperties(button, mmButton);
                        return;
                    case 'save':
                    case 'submitVerify':
                    case 'submit':
                    case 'popup':
                    case 'wizzard':
                    case 'logout':
                    case 'cancel':
                    case 'download':
                    case 'display':
                        mmButton = new qx.ui.menu.Button(menuLabel || label);
                        if (btCfg.addToMenu != null) {
                            button = new qx.ui.menu.Button(label);
                        }
                        else {

lib/CallBackery/qooxdoo/callbackery/source/class/callbackery/ui/plugin/Action.js  view on Meta::CPAN

                        case 'wizzard':
                            var parent = that.getLayoutParent();
                            while (!parent.classname.match(/Page|Popup/)) {
                                parent = parent.getLayoutParent();
                            }
                            // This could in principal work for Page although.
                            if (parent.classname.match(/Popup/)) { // parent already exists, replace content
                                parent.replaceContent(btCfg, getFormData);
                                break;
                            }
                        // fall through intended to create first popup content
                        case 'popup':
                            if (!btCfg.noValidation) { // backward incompatibility work around
                                var formData = getFormData();
                                if (formData === false) {
                                    callbackery.ui.MsgBox.getInstance().error(
                                        this.tr("Validation Error"),
                                        this.tr("The form can only be submitted when all data fields have valid content.")
                                    );
                                    return;
                                }
                            }
                            var popup = new callbackery.ui.Popup(btCfg, getFormData, this);

                            var appRoot = that.getApplicationRoot();

                            popup.addListenerOnce('close', function () {
                                // wait for stuff to happen before we rush into
                                // disposing the popup
                                qx.event.Timer.once(function () {
                                    appRoot.remove(popup);
                                    popup.dispose();
                                    this.fireEvent('popupClosed');
                                }, that, 100);
                                if (!(btCfg.options && btCfg.options.noReload)) {
                                    this.fireDataEvent('actionResponse', { action: (btCfg.options && btCfg.options.reloadStatusOnClose) ? 'reloadStatus' : 'reload' });
                                }
                            }, that);
                            popup.open();
                            break;
                        case 'logout':
                            that.fireDataEvent('actionResponse', { action: 'logout' });
                            break;

                        default:
                            this.debug('Invalid execute action:' + btCfg.action);
                    }
                }; // var action = function() { ... };

lib/CallBackery/qooxdoo/callbackery/source/class/callbackery/ui/plugin/ActionForm.js  view on Meta::CPAN

                    }
                    break;
                default:
                    console.error('Unknown action:', data.action);
                    break;
            }
        },this);
    },
    events: {
        actionResponse: 'qx.event.type.Data',
        popupClosed: 'qx.event.type.Event'
    },
    properties: {
        selection: {}
    },
    members: {
        _cfg: null,
        _form: null,
        _grid : null,
        _btnRow : null,
        _tableMenu: null,

lib/CallBackery/qooxdoo/callbackery/source/class/callbackery/ui/plugin/ActionForm.js  view on Meta::CPAN

                                description = new qx.ui.basic.Label(this.xtr(btCfg.description));
                                description.setRich(true);
                                this._form.add(description, { row : row++, column :  btCfg.descColumn || descColumn});
                            }
                        }
                        grid.addOwnedQxObject(button, btCfg.key + 'Button');
                        this._buttonMap[btCfg.key]=button;
                        return;
                        break;
                    case 'submit':
                    case 'popup':
                    case 'wizzard':
                    case 'logout':
                    case 'cancel':
                        if (btCfg.addToMenu != null) {
                            button = new qx.ui.menu.Button(label);
                        }
                        else {
                            button = new buttonClass(label);
                        }
                        if (btCfg.key){

lib/CallBackery/qooxdoo/callbackery/source/class/callbackery/ui/plugin/ActionForm.js  view on Meta::CPAN

                                callbackery.data.Server.getInstance().callAsyncSmartBusy(function(ret){
                                    that.fireDataEvent('actionResponse',ret || {});
                                },'processPluginData',cfg.name,{ "key": key, "formData": formData });
                            };

                            asyncCall();
                            break;
                        case 'cancel':
                            this.fireDataEvent('actionResponse',{action: 'cancel'});
                            break;
                        case 'popup':
                            if (! btCfg.noValidation) { // backward incompatibility work around
                                var formData = getParentFormData();
                                if (formData === false){
                                    callbackery.ui.MsgBox.getInstance().error(
                                        this.tr("Validation Error"),
                                        this.tr("The form can only be submitted when all data fields have valid content.")
                                    );
                                    return;
                                }
                            }
                            var popup = new callbackery.ui.Popup(btCfg,getParentFormData, this);
                            var appRoot = that.getApplicationRoot();
                            popup.addListenerOnce('close',function(){
                                // wait for stuff to happen before we rush into
                                // disposing the popup
                                qx.event.Timer.once(function(){
                                    appRoot.remove(popup);
                                    popup.dispose();
                                    this.fireEvent('popupClosed');
                                },that,100);
                            },that);
                            popup.open();
                            break;
                        case 'logout':
                            that.fireDataEvent('actionResponse',{action: 'logout'});
                            break;

                        default:
                            this.debug('Invalid execute action:' + btCfg.action);
                    }
                }; // var action = function() { ... };

lib/CallBackery/qooxdoo/callbackery/source/class/callbackery/ui/plugin/CardList.js  view on Meta::CPAN

                        }
                        else {
                            that.setInfo(null);
                        }
                    }
                    if (that._hasTrigger) {
                        that._reconfForm();
                    }
                }
                else {
                    if (exc.code != 2){ /* 2 is for aborted calls, this happens when the popup is closed */
                        callbackery.ui.MsgBox.getInstance().exc(exc);
                    }
                }
                busy.vanish();
                that._loading--;
            }, 'getPluginData', this._cfg.name, 'getAllCardData', parentFormData, { currentFormData: this._form.getData()});
        },

        // now special handling here
        _loadDataReadOnly: function(){

lib/CallBackery/qooxdoo/callbackery/source/class/callbackery/ui/plugin/Form.js  view on Meta::CPAN

                                delete data[key];
                            }
                        }
                        that._form.setData(data,true);
                        if (that._hasTrigger) {
                            that._reconfForm();
                        }
                    }
                }
                else {
                    if (exc.code != 2){ /* 2 is for aborted calls, this happens when the popup is closed */
                        callbackery.ui.MsgBox.getInstance().exc(exc);
                    }
                }
                busy.vanish();
                that._loading--;
                // see _loadDataReadOnly: release reconfigurations parked
                // while the form was loading (covers the error path too;
                // on success _reconfForm above picks them up itself).
                if (that._loading === 0) {
                    that._executeReconfPending();

lib/CallBackery/qooxdoo/callbackery/source/class/callbackery/ui/plugin/Html.js  view on Meta::CPAN

                parentFormData = this._getParentFormData();
            }
            var busy = callbackery.ui.Busy.getInstance();
            busy.manifest(this.tr('Loading HTML Data'));
            var that = this;
            rpc.callAsync(function(data,exc){
                if (!exc){
                    html.setHtml(data);
                }
                else {
                    if (exc.code != 2){ /* 2 is for aborted calls, this happens when the popup is closed */
                        callbackery.ui.MsgBox.getInstance().exc(exc);
                    }
                }
                busy.vanish();
            },'getPluginData',cfg.name,parentFormData);
        }
    }
});

t/session_expiry.t  view on Meta::CPAN

    like($@->message, qr/session/i, 'code 7 message mentions session');
}

# unauthenticated + NOT expired, level-2 method -> returns 0 (dispatcher -> code 6)
{
    my $c = mk_ctrl(authed => 0, expired => 0);
    is($c->allow_rpc_access('getSessionCookie'), 0, 'not-expired level-2 -> 0 (code 6)');
}

# unauthenticated + expired, level-3 method whose plugin instantiation dies ->
# code 7 (regression: must NOT escape as a generic code-9999 popup)
{
    my $c = mk_ctrl(authed => 0, expired => 1, params => ['NoSuchPlugin']);
    my $ok = eval { $c->allow_rpc_access('getPluginData'); 1 };
    ok(!$ok, 'expired level-3 dies despite plugin-instantiation failure');
    is($@->code, 7, 'expired level-3 -> code 7, not 9999');
}

# unauthenticated + NOT expired, level-3 non-anonymous plugin -> returns 0 (code 6)
{
    my $c = mk_ctrl(authed => 0, expired => 0, params => ['NoSuchPlugin']);



( run in 1.497 second using v1.01-cache-2.11-cpan-364913b4093 )