persistent user prefs for UI pages, #41397
authorMark Wells <mark@freeside.biz>
Tue, 5 Apr 2016 19:51:49 +0000 (12:51 -0700)
committerMark Wells <mark@freeside.biz>
Tue, 5 Apr 2016 20:06:08 +0000 (13:06 -0700)
FS/FS/Mason.pm
FS/FS/Schema.pm
FS/FS/UI/Web.pm
FS/FS/access_user.pm
FS/FS/access_user_page_pref.pm [new file with mode: 0644]
FS/MANIFEST
FS/t/access_user_page_pref.t [new file with mode: 0644]
httemplate/elements/header.html
httemplate/elements/page_pref.js [new file with mode: 0644]
httemplate/misc/process/set_page_pref.html [new file with mode: 0644]

index 3a00f42..aa9d3be 100644 (file)
@@ -131,7 +131,8 @@ if ( -e $addl_handler_use_file ) {
   use FS::Conf;
   use FS::CGI qw(header menubar table itable ntable idiot
                  eidiot myexit http_header);
-  use FS::UI::Web qw(svc_url random_id);
+  use FS::UI::Web qw(svc_url random_id
+                  get_page_pref  set_page_pref);
   use FS::UI::Web::small_custview qw(small_custview);
   use FS::UI::bytecount;
   use FS::UI::REST qw( rest_auth rest_uri_remain encode_rest );
@@ -409,6 +410,7 @@ if ( -e $addl_handler_use_file ) {
   use FS::svc_fiber;
   use FS::fiber_olt;
   use FS::olt_site;
+  use FS::access_user_page_pref;
   # Sammath Naur
 
   if ( $FS::Mason::addl_handler_use ) {
index c27b727..2cb9425 100644 (file)
@@ -5812,6 +5812,26 @@ sub tables_hashref {
       'index'        => [ ['usernum'], ['path'], ['_date'] ],
     },
 
+    'access_user_page_pref' => {
+      'columns'     => [
+        'prefnum'     =>  'serial',     '',      '', '', '',
+        'usernum'     =>     'int',     '',      '', '', '',
+        'path'        =>    'text',     '',      '', '', '',
+        'tablenum'    =>     'int', 'NULL',      '', '', '',
+        '_date'       =>    @date_type,              '', '',
+        'prefname'    =>    'varchar',  '', $char_d, '', '',
+        'prefvalue'   =>    'text',     '',      '', '', '',
+      ],
+      'primary_key' => 'prefnum',
+      'unique'      => [ [ 'usernum', 'path', 'tablenum', 'prefname' ] ],
+      'index'       => [],
+      'foreign_keys' => [
+                          { columns   => [ 'usernum' ],
+                            table     => 'access_user'
+                          },
+                        ],
+    },
+
     'sched_item' => {
       'columns' => [
         'itemnum',   'serial',      '', '', '', '', 
index 136c8e6..8f10011 100644 (file)
@@ -15,7 +15,7 @@ use FS::cust_main;  # are sql_balance and sql_date_balance in the right module?
 #@ISA = qw( FS::UI );
 @ISA = qw( Exporter );
 
-@EXPORT_OK = qw( svc_url random_id );
+@EXPORT_OK = qw( get_page_pref set_page_pref svc_url random_id );
 
 $DEBUG = 0;
 $me = '[FS::UID::Web]';
@@ -23,9 +23,79 @@ $me = '[FS::UID::Web]';
 our $NO_RANDOM_IDS;
 
 ###
+# user prefs
+###
+
+=item get_page_pref NAME, TABLENUM
+
+Returns the user's page preference named NAME for the current page. If the
+page is a view or edit page or otherwise shows a single record at a time,
+it should use TABLENUM to link the preference to that record.
+
+=cut
+
+sub get_page_pref {
+  my ($prefname, $tablenum) = @_;
+
+  my $m = $HTML::Mason::Commands::m
+    or die "can't get page pref when running outside the UI";
+  # what's more useful: to tie prefs to the base_comp (usually where
+  # code is executing right now), or to the request_comp (approximately the
+  # one in the URL)? not sure.
+  $FS::CurrentUser::CurrentUser->get_page_pref( $m->request_comp->path,
+                                                $prefname,
+                                                $tablenum
+                                              );
+}
+
+=item set_page_pref NAME, TABLENUM, VALUE
+
+Sets the user's page preference named NAME for the current page. Use TABLENUM
+as for get_page_pref.
+
+If VALUE is an empty string, the preference will be deleted (and
+C<get_page_pref> will return an empty string).
+
+  my $mypref = set_page_pref('mypref', '', 100);
+
+=cut
+
+sub set_page_pref {
+  my ($prefname, $tablenum, $prefvalue) = @_;
+
+  my $m = $HTML::Mason::Commands::m
+    or die "can't set page pref when running outside the UI";
+  $FS::CurrentUser::CurrentUser->set_page_pref( $m->request_comp->path,
+                                                $prefname,
+                                                $tablenum,
+                                                $prefvalue );
+}
+
+###
 # date parsing
 ###
 
+=item parse_beginning_ending CGI [, PREFIX ]
+
+Parses a beginning/ending date range, as used on many reports. This function
+recognizes two sets of CGI params: "begin" and "end", the integer timestamp
+values, and "beginning" and "ending", the user-readable date fields.
+
+If "begin" contains an integer, that's passed through as the beginning date.
+Otherwise, "beginning" is passed to L<DateTime::Format::Natural> and turned
+into an integer. If this fails or it doesn't have a value, zero is used as the
+beginning date.
+
+The same happens for "end" and "ending", except that if "ending" contains a
+date without a time, it gets moved to the end of that day, and if there's no
+value, the value returned is the highest unsigned 32-bit time value (some time
+in 2037).
+
+PREFIX is optionally a string to prepend (with '_' as a delimiter) to the form
+field names.
+
+=cut
+
 use Date::Parse;
 sub parse_beginning_ending {
   my($cgi, $prefix) = @_;
index 3b36e46..a9fdf5b 100644 (file)
@@ -742,6 +742,78 @@ sub locale {
   $self->{_locale} = $self->option('locale');
 }
 
+=item get_page_pref PATH, NAME, TABLENUM
+
+Returns the user's page preference named NAME for the page at PATH. If the
+page is a view or edit page or otherwise shows a single record at a time,
+it should use TABLENUM to tell which record the preference is for.
+
+=cut
+
+sub get_page_pref {
+  my $self = shift;
+  my ($path, $prefname, $tablenum) = @_;
+  $tablenum ||= '';
+  
+  my $access_user_page_pref = qsearchs('access_user_page_pref', {
+      path      => $path,
+      usernum   => $self->usernum,
+      tablenum  => $tablenum,
+      prefname  => $prefname,
+  }); 
+  $access_user_page_pref ? $access_user_page_pref->prefvalue : '';
+} 
+
+=item set_page_pref PATH, NAME, TABLENUM, VALUE
+
+Sets the user's page preference named NAME for the page at PATH. Use TABLENUM
+as for get_page_pref.
+
+=cut
+
+sub set_page_pref {
+  my $self = shift;
+  my ($path, $prefname, $tablenum, $prefvalue) = @_;
+  $tablenum ||= '';
+  
+  my $error;
+  my $access_user_page_pref = qsearchs('access_user_page_pref', {
+      path      => $path,
+      usernum   => $self->usernum,
+      tablenum  => $tablenum,
+      prefname  => $prefname,
+  });
+  if ( $access_user_page_pref ) { 
+    if ( $prefvalue eq $access_user_page_pref->get('prefvalue') ) {
+      return '';
+    }
+    if ( length($prefvalue) > 0 ) {
+      $access_user_page_pref->set('prefvalue', $prefvalue);
+      $error = $access_user_page_pref->replace;
+      $error .= " (updating $prefname)" if $error;
+    } else { 
+      $error = $access_user_page_pref->delete;
+      $error .= " (removing $prefname)" if $error;
+    }
+  } else {
+    if ( length($prefvalue) > 0 ) {
+      $access_user_page_pref = FS::access_user_page_pref->new({
+          path      => $path,
+          usernum   => $self->usernum,
+          tablenum  => $tablenum,
+          prefname  => $prefname,
+          prefvalue => $prefvalue,
+      });
+      $error = $access_user_page_pref->insert;
+      $error .= " (creating $prefname)" if $error;
+    } else { 
+      return '';
+    }
+  }
+
+  return $error;
+}
+
 =back
 
 =head1 BUGS
diff --git a/FS/FS/access_user_page_pref.pm b/FS/FS/access_user_page_pref.pm
new file mode 100644 (file)
index 0000000..890d29f
--- /dev/null
@@ -0,0 +1,128 @@
+package FS::access_user_page_pref;
+use base qw( FS::Record );
+
+use strict;
+use FS::Record qw( qsearch qsearchs );
+
+sub table { 'access_user_page_pref'; }
+
+=head1 NAME
+
+FS::access_user_page_pref - Object methods for access_user_page_pref records
+
+=head1 SYNOPSIS
+
+  use FS::access_user_page_pref;
+
+  $record = new FS::access_user_page_pref \%hash;
+  $record = new FS::access_user_page_pref { 'column' => 'value' };
+
+  $error = $record->insert;
+
+  $error = $new_record->replace($old_record);
+
+  $error = $record->delete;
+
+  $error = $record->check;
+
+=head1 DESCRIPTION
+
+An FS::access_user_page_pref object represents a per-page user interface
+preference.  FS::access_user_page_pref inherits from FS::Record.  The
+following fields are currently supported:
+
+=over 4
+
+=item prefnum
+
+primary key
+
+=item usernum
+
+The user who has this preference, a L<FS::access_user> foreign key.
+
+=item path
+
+The path of the page where the preference is set, relative to the Mason
+document root.
+
+=item tablenum
+
+For view and edit pages (which show one record at a time), the record primary
+key that the preference applies to.
+
+=item _date
+
+The date the preference was created.
+
+=item prefname
+
+The name of the preference, as defined by the page.
+
+=item prefvalue
+
+The value (a free-text field).
+
+=back
+
+=head1 METHODS
+
+=over 4
+
+=item new HASHREF
+
+Creates a new preference.  To add the preference to the database, see
+L<"insert">.
+
+=item insert
+
+Adds this record to the database.  If there is an error, returns the error,
+otherwise returns false.
+
+=item delete
+
+Delete this record from the database.
+
+=item replace OLD_RECORD
+
+Replaces the OLD_RECORD with this one in the database.  If there is an error,
+returns the error, otherwise returns false.
+
+=item check
+
+Checks all fields to make sure this is a valid preference.  If there is
+an error, returns the error, otherwise returns false.  Called by the insert
+and replace methods.
+
+=cut
+
+sub check {
+  my $self = shift;
+
+  $self->set('_date', time) unless $self->get('_date');
+
+  my $error = 
+    $self->ut_numbern('prefnum')
+    || $self->ut_number('usernum')
+    || $self->ut_foreign_key('usernum', 'access_user', 'usernum')
+    || $self->ut_text('path')
+    || $self->ut_numbern('tablenum')
+    || $self->ut_numbern('_date')
+    || $self->ut_text('prefname')
+    || $self->ut_text('prefvalue')
+  ;
+  return $error if $error;
+
+  $self->SUPER::check;
+}
+
+=back
+
+=head1 SEE ALSO
+
+L<FS::Record>
+
+=cut
+
+1;
+
index 80ff917..d0bf99b 100644 (file)
@@ -866,3 +866,5 @@ FS/olt_site.pm
 t/olt_site.t
 FS/webservice_log.pm
 t/webservice_log.t
+FS/access_user_page_pref.pm
+t/access_user_page_pref.t
diff --git a/FS/t/access_user_page_pref.t b/FS/t/access_user_page_pref.t
new file mode 100644 (file)
index 0000000..4a45b4d
--- /dev/null
@@ -0,0 +1,5 @@
+BEGIN { $| = 1; print "1..1\n" }
+END {print "not ok 1\n" unless $loaded;}
+use FS::access_user_page_pref;
+$loaded=1;
+print "ok 1\n";
index c8a83ca..699f82c 100644 (file)
@@ -53,6 +53,12 @@ Example:
 
     <% $head |n %>
 
+%# announce our base path, and the Mason comp path of this page
+  <script type="text/javascript">
+  window.fsurl = <% $fsurl |js_string %>;
+  window.request_comp_path = <% $m->request_comp->path |js_string %>;
+  </script>
+
   </HEAD>
   <BODY BGCOLOR="#f8f8f8" <% $etc |n %> STYLE="margin-top:0; margin-bottom:0; margin-left:0px; margin-right:0px">
     <table width="100%" CELLPADDING=0 CELLSPACING=0 STYLE="padding-left:0px; padding-right:4px" CLASS="fshead">
@@ -178,6 +184,7 @@ Example:
 % }
 
           <% $menubar !~ /^\s*$/ ? "$menubar<BR><BR>" : '' %>
+
 <%init>
 
 my( $title, $title_noescape, $menubar, $etc, $head ) = ( '', '', '', '', '' );
@@ -225,4 +232,5 @@ if ( scalar(@agentnums) == 1 ) {
   $company_name = $conf->config('company_name');
   $company_url  = $conf->config('company_url');
 }
+
 </%init>
diff --git a/httemplate/elements/page_pref.js b/httemplate/elements/page_pref.js
new file mode 100644 (file)
index 0000000..253c6da
--- /dev/null
@@ -0,0 +1,10 @@
+function set_page_pref(prefname, tablenum, prefvalue, success) {
+  jQuery.post( window.fsurl + 'misc/process/set_page_pref.html',
+      { path: window.request_comp_path,
+        name: prefname,
+        num: tablenum,
+        value: prefvalue
+      },
+      success
+  );
+}
diff --git a/httemplate/misc/process/set_page_pref.html b/httemplate/misc/process/set_page_pref.html
new file mode 100644 (file)
index 0000000..a7f1231
--- /dev/null
@@ -0,0 +1,12 @@
+<%init>
+my $path = $cgi->param('path');
+my $name = $cgi->param('name');
+my $tablenum = $cgi->param('num') || '';
+my $value = $cgi->param('value');
+
+my $error = $FS::CurrentUser::CurrentUser->set_page_pref($path, $name, $tablenum, $value);
+my $result = { 'error' => $error }; # in case someone cares
+
+http_header('Content-Type', 'application/json');
+</%init>
+<% encode_json($result) %>