<commit_before>package GADS;

use DateTime;
use GADS::Alert;
use GADS::Audit;
use GADS::Column;
use GADS::Column::Calc;
use GADS::Column::Date;
use GADS::Column::Daterange;
use GADS::Column::Enum;
use GADS::Column::File;
use GADS::Column::Intgr;
use GADS::Column::Person;
use GADS::Column::Rag;
use GADS::Column::String;
use GADS::Column::Tree;
use GADS::Config;
use GADS::DB;
use GADS::Email;
use GADS::Graph;
use GADS::Graph::Data;
use GADS::Graphs;
use GADS::Layout;
use GADS::Record;
use GADS::Records;
use GADS::User;
use GADS::Util         qw(:all);
use GADS::View;
use GADS::Views;
use HTML::Entities;
use JSON qw(decode_json encode_json);
use Log::Report mode => 'DEBUG';
use String::CamelCase qw(camelize);
use Text::CSV;

use Dancer2; # Last to stop Moo generating conflicting namespace
use Dancer2::Plugin::Auth::Complete;
use Dancer2::Plugin::DBIC qw(schema resultset rset);

schema->storage->debug(1);

our $VERSION = '0.1';

# set serializer => 'JSON';
set behind_proxy => config->{behind_proxy}; # XXX Why doesn't this work in config file

# Callback dispatcher to send error messages to the web browser
dispatcher CALLBACK => 'error_handler'
   , callback => \&error_handler
   , mode => 'DEBUG';

# And a syslog dispatcher
dispatcher SYSLOG => 'gads'
  , identity => 'infosaas'
  , facility => 'local0'
  , flags    => "pid ndelay nowait",
  , mode     => 'DEBUG';

Dancer2::Plugin::Auth::Complete->user_callback( sub {
    my ($retuser, $user) = @_;
    $retuser->{lastrecord} = $user->lastrecord ? $user->lastrecord->id : undef;
    $retuser;
});

hook init_error => sub {
    my $error = shift;
    # Catch other exceptions. This is hook is called for all errors
    # not just exceptions (including for example 404s), so check first.
    # If it's an exception then panic it to get Log::Report
    # to handle it nicely. If it's another error such as a 404
    # then exception will not be set.
    panic $error->{exception} if $error->{exception};
};

hook before => sub {

    # Static content
    return if request->uri =~ m!^/(error|js|css|login|images|fonts|resetpw|ping)!;
    return if param 'error';

    # Redirect on no session
    redirect '/login' unless user;

    # Dynamically generate "virtual" columns for each row of data, based on the
    # configured layout
    GADS::DB->setup(schema);

};

hook before_template => sub {
    my $tokens = shift;

    # Log to audit
    my $user = user;
    my $method = request->method;
    my $path   = request->path;
    my $audit  = GADS::Audit->new(schema => schema, user => $user);
    $audit->user_action(qq(User $user->{username} made $method request to $path))
        if $user;

    my $base = request->base;
    $tokens->{url}->{css}  = "${base}css";
    $tokens->{url}->{js}   = "${base}js";
    $tokens->{url}->{page} = $base;
    $tokens->{url}->{page} =~ s!.*/!!; # Remove trailing slash
    $tokens->{hostlocal}   = config->{gads}->{hostlocal};

    $tokens->{header} = config->{gads}->{header};

    if (permission 'approver')
    {
        $tokens->{approve_waiting} = GADS::Records->approval_count(schema);
    }
    $tokens->{messages} = session('messages');
    $tokens->{user}     = $user;
    $tokens->{config}   = config;
    session 'messages' => [];

};

get '/' => sub {

    my $config = GADS::Config->new(schema => schema);
    template 'index' => {
        instance => $config,
        page     => 'index'
    };
};

get '/ping' => sub {
    content_type 'text/plain';
    'alive';
};

get '/data_calendar/:time' => sub {

    # Time variable is used to prevent caching by browser

    my $view_id = session 'view_id';

    my $fromdt  = DateTime->from_epoch( epoch => ( param('from') / 1000 ) )->truncate( to => 'day'); 
    my $todt    = DateTime->from_epoch( epoch => ( param('to') / 1000 ) ); 

    my $diff     = $todt->subtract_datetime($fromdt);
    my $dt_view  = $diff->years
                 ? 'year'
                 : $diff->weeks
                 ? 'week'
                 : $diff->days
                 ? 'day'
                 : 'month'; # Default to month

    # Remember previous day and view. Day is difficult, due to the
    # timezone issues described above. XXX How to fix?
    session 'calendar' => {
        day  => $todt->clone->subtract(days => 1),
        view => $dt_view,
    };

    # Epochs received from the calendar module are based on the timezone of the local
    # browser. So in BST, 24th August is requested as 23rd August 23:00. Rather than
    # trying to convert timezones, we keep things simple and round down any "from"
    # times and round up any "to" times.
    if ($todt->hms('') ne '000000')
    {
        # If time is after midnight, round down to midnight and add day
        $todt->set(hour => 0, minute => 0, second => 0);
        $todt->add(days => 1);
    }

    if ($fromdt->hms('') ne '000000')
    {
        # If time is after midnight, round down to midnight
        $fromdt->set(hour => 0, minute => 0, second => 0);
    }

    my $user    = user;
    my $layout  = GADS::Layout->new(user => $user, schema => schema);
    my $views   = GADS::Views->new(user => $user, schema => schema, layout => $layout);
    my $view    = $views->view(session 'view_id') || $views->default_view; # Can still be undef
    my $records = GADS::Records->new(user => $user, layout => $layout, schema => schema);
    $records->search(<commit_msg>Fix retrieval of default view<commit_after>package GADS;

use DateTime;
use GADS::Alert;
use GADS::Audit;
use GADS::Column;
use GADS::Column::Calc;
use GADS::Column::Date;
use GADS::Column::Daterange;
use GADS::Column::Enum;
use GADS::Column::File;
use GADS::Column::Intgr;
use GADS::Column::Person;
use GADS::Column::Rag;
use GADS::Column::String;
use GADS::Column::Tree;
use GADS::Config;
use GADS::DB;
use GADS::Email;
use GADS::Graph;
use GADS::Graph::Data;
use GADS::Graphs;
use GADS::Layout;
use GADS::Record;
use GADS::Records;
use GADS::User;
use GADS::Util         qw(:all);
use GADS::View;
use GADS::Views;
use HTML::Entities;
use JSON qw(decode_json encode_json);
use Log::Report mode => 'DEBUG';
use String::CamelCase qw(camelize);
use Text::CSV;

use Dancer2; # Last to stop Moo generating conflicting namespace
use Dancer2::Plugin::Auth::Complete;
use Dancer2::Plugin::DBIC qw(schema resultset rset);

schema->storage->debug(1);

our $VERSION = '0.1';

# set serializer => 'JSON';
set behind_proxy => config->{behind_proxy}; # XXX Why doesn't this work in config file

# Callback dispatcher to send error messages to the web browser
dispatcher CALLBACK => 'error_handler'
   , callback => \&error_handler
   , mode => 'DEBUG';

# And a syslog dispatcher
dispatcher SYSLOG => 'gads'
  , identity => 'infosaas'
  , facility => 'local0'
  , flags    => "pid ndelay nowait",
  , mode     => 'DEBUG';

Dancer2::Plugin::Auth::Complete->user_callback( sub {
    my ($retuser, $user) = @_;
    $retuser->{lastrecord} = $user->lastrecord ? $user->lastrecord->id : undef;
    $retuser;
});

hook init_error => sub {
    my $error = shift;
    # Catch other exceptions. This is hook is called for all errors
    # not just exceptions (including for example 404s), so check first.
    # If it's an exception then panic it to get Log::Report
    # to handle it nicely. If it's another error such as a 404
    # then exception will not be set.
    panic $error->{exception} if $error->{exception};
};

hook before => sub {

    # Static content
    return if request->uri =~ m!^/(error|js|css|login|images|fonts|resetpw|ping)!;
    return if param 'error';

    # Redirect on no session
    redirect '/login' unless user;

    # Dynamically generate "virtual" columns for each row of data, based on the
    # configured layout
    GADS::DB->setup(schema);

};

hook before_template => sub {
    my $tokens = shift;

    # Log to audit
    my $user = user;
    my $method = request->method;
    my $path   = request->path;
    my $audit  = GADS::Audit->new(schema => schema, user => $user);
    $audit->user_action(qq(User $user->{username} made $method request to $path))
        if $user;

    my $base = request->base;
    $tokens->{url}->{css}  = "${base}css";
    $tokens->{url}->{js}   = "${base}js";
    $tokens->{url}->{page} = $base;
    $tokens->{url}->{page} =~ s!.*/!!; # Remove trailing slash
    $tokens->{hostlocal}   = config->{gads}->{hostlocal};

    $tokens->{header} = config->{gads}->{header};

    if (permission 'approver')
    {
        $tokens->{approve_waiting} = GADS::Records->approval_count(schema);
    }
    $tokens->{messages} = session('messages');
    $tokens->{user}     = $user;
    $tokens->{config}   = config;
    session 'messages' => [];

};

get '/' => sub {

    my $config = GADS::Config->new(schema => schema);
    template 'index' => {
        instance => $config,
        page     => 'index'
    };
};

get '/ping' => sub {
    content_type 'text/plain';
    'alive';
};

get '/data_calendar/:time' => sub {

    # Time variable is used to prevent caching by browser

    my $view_id = session 'view_id';

    my $fromdt  = DateTime->from_epoch( epoch => ( param('from') / 1000 ) )->truncate( to => 'day'); 
    my $todt    = DateTime->from_epoch( epoch => ( param('to') / 1000 ) ); 

    my $diff     = $todt->subtract_datetime($fromdt);
    my $dt_view  = $diff->years
                 ? 'year'
                 : $diff->weeks
                 ? 'week'
                 : $diff->days
                 ? 'day'
                 : 'month'; # Default to month

    # Remember previous day and view. Day is difficult, due to the
    # timezone issues described above. XXX How to fix?
    session 'calendar' => {
        day  => $todt->clone->subtract(days => 1),
        view => $dt_view,
    };

    # Epochs received from the calendar module are based on the timezone of the local
    # browser. So in BST, 24th August is requested as 23rd August 23:00. Rather than
    # trying to convert timezones, we keep things simple and round down any "from"
    # times and round up any "to" times.
    if ($todt->hms('') ne '000000')
    {
        # If time is after midnight, round down to midnight and add day
        $todt->set(hour => 0, minute => 0, second => 0);
        $todt->add(days => 1);
    }

    if ($fromdt->hms('') ne '000000')
    {
        # If time is after midnight, round down to midnight
        $fromdt->set(hour => 0, minute => 0, second => 0);
    }

    my $user    = user;
    my $layout  = GADS::Layout->new(user => $user, schema => schema);
    my $views   = GADS::Views->new(user => $user, schema => schema, layout => $layout);
    my $view    = $views->view(session 'view_id') || $views->default; # Can still be undef
    my $records = GADS::Records->new(user => $user, layout => $layout, schema => schema);
    $records->search(
{'fraction_non_alphanumeric': 0.1598516458043579, 'fraction_numerical': 0.00927213722763097, 'mean_word_length': 3.056412185031967, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 211, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7604541', 'n_tokens_mistral': 3728, 'n_tokens_neox': 3515, 'n_words': 1053}