function printView() { if ($this->_group) { ?> <h3>Group Details</h3> <table class="table-full-width"> <tr> <th class="narrow" style="padding-bottom: 10px">Category</th> <td><?php $this->_group->printFieldValue('categoryid'); ?> </td> <th class="narrow hidden-phone">Record Attendance?</th> <td class="hidden-phone"><?php $this->_group->printFieldValue('attendance_recording_days'); ?> </td> <td class="align-right"> <a class="link-collapse" href="?view=_edit_group&groupid=<?php echo $this->_group->id; ?> "><i class="icon-wrench"></i>Edit group details</a> </td> </tr> <tr> <th class="narrow">Status</th> <td><?php $this->_group->printFieldValue('is_archived'); ?> </td> <th class="narrow hidden-phone">Share Member Details?</th> <td class="hidden-phone"><?php $this->_group->printFieldValue('share_member_details'); ?> </td> <td class="align-right"> <form class="min" method="post" action="?view=_edit_group&groupid=<?php echo $this->_group->id; ?> "> <input type="hidden" name="action" value="delete" /> <button class="btn-link double-confirm-title link-collapse" type="submit" title="Delete this group"> <i class="icon-trash"></i>Delete group </button> </form> </td> </tr> </table> <div class="modal hide fade" id="action-plan-modal" role="dialog" aria-hidden="true"> <form method="post" action="?view=_edit_group&action=add_member&groupid=<?php echo $this->_group->id; ?> "> <div class="modal-header"> <h4>Add Members by Name Search</h4> </div> <div class="modal-body"> <table> <tr> <td>Select persons:</td> <td> <?php $GLOBALS['system']->includeDBClass('person'); Person::printMultipleFinder('personid'); ?> </td> </tr> <tr> <td>Membership status:</td> <td> <?php $GLOBALS['system']->includeDBClass('person_group'); Person_Group::printMembershipStatusChooser('membership_status'); ?> </td> </tr> </table> </div> <div class="modal-footer"> <input class="btn" type="submit" value="Add Members" id="add-member-button" /> <input class="btn" type="button" value="Cancel" data-dismiss="modal" aria-hidden="true" /> </div> </form> </div> <div class="modal hide fade autosize" id="email-modal" role="dialog" aria-hidden="true"> <div class="modal-header"> <h4>Email members of <?php echo ents($this->_group->getValue('name')); ?> </h4> </div> <div class="modal-body"> <!-- to be populated with ajax --> </div> <div class="modal-footer"> <input class="btn" type="button" value="Cancel" data-dismiss="modal" aria-hidden="true" /> </div> </div> <?php $persons = $this->_group->getMembers(!empty($_SESSION['show_archived_group_members'])); list($status_options, $default_status) = Person_Group::getMembershipStatusOptionsAndDefault(); ?> <h3>Group Members (<?php echo count($persons); ?> )</h3> <?php if (empty($_REQUEST['edit_statuses'])) { ?> <div class="group-members-links"> <div class="archived-link"> <?php if (empty($_SESSION['show_archived_group_members'])) { ?> <a class="hidden-phone" href="<?php echo build_url(array('show_archived' => 1)); ?> "><i class="icon-eye-open"></i>Show archived members</a> <?php } else { ?> <a class="hidden-phone" href="<?php echo build_url(array('show_archived' => 0)); ?> "><i class="icon-eye-close"></i>Hide archived members</a> <?php } ?> </div> <?php if (!empty($persons)) { ?> <div class="email-link"> <a href="<?php echo build_url(array('view' => NULL, 'call' => 'email', 'groupid' => $this->_group->id, 'show_modal' => 1)); ?> " data-target="#email-modal" data-toggle="modal"><i class="icon-email">@</i>Email members</a> </div> <?php } if (!empty($persons) && $GLOBALS['user_system']->havePerm(PERM_EDITPERSON)) { if (count($status_options) > 1) { ?> <div class="edit-status-link"> <a href="<?php echo build_url(array('edit_statuses' => 1)); ?> "><i class="icon-wrench"></i>Edit membership statuses</a> </div> <?php } } ?> <div class="add-link"> <a href="#action-plan-modal" data-toggle="modal"><i class="icon-plus-sign"></i>Add members</a> </div> </div> <?php } if (!empty($persons)) { $special_fields = array('joined_group', 'congregation'); if (count($status_options) > 1) { array_unshift($special_fields, 'membership_status'); } if (!empty($_REQUEST['edit_statuses'])) { ?> <form method="post" action="<?php echo build_url(array('edit_statuses' => NULL)); ?> "> <?php $callbacks = array('membership_status' => array($this, 'printMembershipStatusChooser')); $show_actions = FALSE; // This is a bit ugly, but the 'membership status' column needs to show the membership status chooser, // which needs the ID rather than the label foreach ($persons as &$person) { $person['membership_status'] = $person['membership_status_id']; } } include_once 'templates/person_list.template.php'; if (!empty($_REQUEST['edit_statuses'])) { ?> <div class="align-right"> <input type="submit" class="btn" value="Save membership statuses" /> <a class="btn" href="<?php echo build_url(array('edit_statuses' => NULL)); ?> ">Cancel</a> </div> </form> <?php } } else { ?> <p><em>This group does not currently have any members</em></p> <?php } } }
/** * Get the options for filtering people by (person or group-membership) status * @return array */ public static function getStatusOptions() { $statusOptions = array(); foreach (Person::getStatusOptions() as $id => $val) { $statusOptions['p-' . $id] = $val; } list($gOptions, $default) = Person_Group::getMembershipStatusOptionsAndDefault(); foreach ($gOptions as $id => $val) { $statusOptions['g-' . $id] = $val; } return $statusOptions; }
public function printView() { ?> <p>Some of the following settings can be edited on this page. Other settings are read only on this page, but can be adjusted by getting your <?php if (defined('SYSADMIN_HREF')) { echo '<a href="' . SYSADMIN_HREF . '">'; } ?> system administrator <?php if (defined('SYSADMIN_HREF')) { echo '</a>'; } ?> to edit the Jethro configuration file.</p> <table class="table no-autofocus system-config"> <tr> <td colspan="2"><h3>Overall system settings</h3></td> </tr> <tr> <th>System Name</th> <td><?php echo SYSTEM_NAME; ?> </td> </tr> <tr> <th>Base URL</th> <td><?php echo BASE_URL; ?> </td> </tr> <tr> <th>Require HTTPS</th> <td><?php echo REQUIRE_HTTPS ? 'Yes' : 'No'; ?> </td> </tr> <tr> <td colspan="2"><h3>Jethro behaviour settings</h3></td> </tr> <tr> <th>Enabled Features</th> <td> <?php $enabled = explode(',', ENABLED_FEATURES); foreach (explode(',', 'NOTES,PHOTOS,DATES,ATTENDANCE,ROSTERS&SERVICES,SERVICEDETAILS,DOCUMENTS,SERVICEDOCUMENTS') as $feature) { echo '<i class="icon-' . (in_array($feature, $enabled) ? 'ok-sign' : 'ban-circle') . '"></i>' . $feature . '<br />'; } ?> </td> </tr> <tr> <th>Require note when adding new family?</th> <td><?php echo REQUIRE_INITIAL_NOTE ? 'Yes' : 'No'; ?> </td> </tr> <tr> <th>Attendance list order</th> <td><?php echo ATTENDANCE_LIST_ORDER; ?> <br /><small>When recording attendance, persons will be listed in this order</small> </td> </tr> <tr> <th>Chunk size for listings</th> <td> <?php echo CHUNK_SIZE; ?> <br /><small>When listing all persons or families, Jethro will paginate the results and aim for this number per page (up to a maximum of 26 pages).</small> </td> </tr> <tr> <th>Lock length for editing objects</th> <td><?php echo LOCK_LENGTH; ?> <br /><small>When you open an object for editing, Jethro will prevent other users from editing the object for this long. You will need to save your changes within this timeframe.</small> </td> </tr> <tr> <td colspan="2"><h3>Security settings</h3></td> </tr> <tr> <th>Default Permissions</th> <td> <?php $GLOBALS['system']->includeDBClass('staff_member'); $sm = new Staff_Member(); $sm->printFieldValue('permissions', DEFAULT_PERMISSIONS); ?> </td> </tr> <tr> <th>Session Inactivity Timeout</th> <td> <?php echo defined('SESSION_TIMEOUT_MINS') && SESSION_TIMEOUT_MINS > 0 ? SESSION_TIMEOUT_MINS : 90; ?> mins <br /><small>Users will be asked to log in again if they haven't done anything for this length of time. This is important for security, especially on mobile devices.</small> </td> </tr> <tr> <th>Maximum Session Length</th> <td> <?php $val = defined('SESSION_MAXLENGTH_MINS') && SESSION_MAXLENGTH_MINS > 0 ? SESSION_MAXLENGTH_MINS : 8 * 60; if ($val % 60 == 0 && $val > 60) { echo $val / 60 . ' hours'; } else { echo $val . ' mins'; } ?> <br /><small>Active users will be asked to log in again after this length of time. This is important for security, especially on mobile devices.</small> </td> </tr> <tr> <td colspan="2"><h3>Jethro data structure settings</h3></td> </tr> <tr> <th>Person Status Options</th> <td><?php echo PERSON_STATUS_OPTIONS; ?> (Default <?php echo PERSON_STATUS_DEFAULT; ?> )</td> </tr> <tr> <th>Age Bracket Options</th> <td> <?php echo AGE_BRACKET_OPTIONS; ?> <br /><small>This list must always begin with 'adult'</small> </td> </tr> <tr> <th>Group Membership Status Options</th> <td> <form method="post"> <input type="hidden" name="group_membership_statuses_submitted" value="1" /> <table class="table-condensed expandable table-bordered table-auto-width"> <thead> <tr> <th>ID</th> <th>Label</th> <th>Default?</th> <th>Re-order</th> <th>Delete?</th> </tr> </thead> <tbody> <?php $GLOBALS['system']->includeDBClass('person_group'); list($options, $default) = Person_Group::getMembershipStatusOptionsAndDefault(); $options[null] = ''; $i = 0; foreach ($options as $id => $label) { ?> <tr> <td> <?php if ($id) { echo $id; echo '<input type="hidden" name="membership_status_' . $i . '_id" value="' . $id . '" />'; } echo '<input type="hidden" name="membership_status_ranking[]" value="' . $i . '" />'; ?> </td> <td><input type="text" name="membership_status_<?php echo $i; ?> _label" value="<?php echo ents($label); ?> " /></td> <td><input type="radio" name="membership_status_default_rank" value="<?php echo $i; ?> " <?php if ($id == $default) { echo 'checked="checked"'; } ?> /></td> <td> <img src="<?php echo BASE_URL; ?> /resources/img/arrow_up_thin_black.png" class="icon move-row-up" title="Move this role up" /> <img src="<?php echo BASE_URL; ?> /resources/img/arrow_down_thin_black.png" class="icon move-row-down" title="Move this role down" /> </td> <td> <?php if ($id) { ?> <input type="checkbox" name="membership_status_delete[]" data-toggle="strikethrough" data-target="row" value="<?php echo $id; ?> " /> <?php } ?> </td> </tr> <?php $i++; } ?> </table> <input type="submit" value="Save" class="btn" /> </form> </td> </tr> <tr> <td colspan="2"><h3>Rosters and Services</h3></td> </tr> <tr> <th>Roster Weeks Default</th> <td> <?php echo ROSTER_WEEKS_DEFAULT; ?> <br /><small>By default, rosters will display this number of weeks in the future.</small> </td> </tr> <tr> <th>Roster repeat date threshold</th> <td> <?php echo REPEAT_DATE_THRESHOLD; ?> <br /><small>If a roster has more than this number of columns, the date column will be repeated on the right hand side</small> </td> </tr> <tr> <th>Service Documents: Folders to populate</th> <td> <?php if (SERVICE_DOCS_TO_POPULATE_DIRS) { echo implode('<br />', explode('|', SERVICE_DOCS_TO_POPULATE_DIRS)); } ?> </td> </tr> <tr> <th>Service Documents: Folders to expand</th> <td> <?php if (SERVICE_DOCS_TO_EXPAND_DIRS) { echo implode('<br />', explode('|', SERVICE_DOCS_TO_POPULATE_DIRS)); } ?> </td> </tr> <tr> <td colspan="2"><h3>External tools</h3></td> </tr> <tr> <th>Bible reference URL</th> <td> <?php echo BIBLE_URL; ?> <br /><small>Bible references in rosters will be linked using this URL template</small> </td> </tr> <tr> <th>Maps URL</th> <td> <?php echo MAP_LOOKUP_URL; ?> <br /><small>The "map" link displayed next to a family's address uses this URL template</small> </td> </tr> <tr> <th>Email chunk size</th> <td> <?php echo EMAIL_CHUNK_SIZE; ?> <br /><small>Email servers can only handle a limited number of recipients per email. When constructing email links to multiple persons, Jethro will divide the list into several links if there are more than this number of recipients.</small> </td> </tr> <tr> <th>SMS Gateway</th> <td> <?php echo SMS_HTTP_URL; ?> <br /> <?php echo SMS_HTTP_POST_TEMPLATE && SMS_HTTP_RESPONSE_OK_REGEX ? 'See details in config file' : '<b>Not fully configured<b>'; ?> </tr> <tr> <th>Max length for SMS messages</th> <td> <?php echo SMS_MAX_LENGTH; ?> <br /><small>160 characters is generally a one-part SMS. Longer messages will be sent in several parts and will cost more.</small> </td> </tr> <tr> <th>Logging of SMS sending</th> <td> <?php echo SMS_SEND_LOGFILE ? 'Configured' : 'Not configured'; ?> <br /><small>This allows you to track how many SMSes each user is sending via Jethro.</small> </td> </tr> <tr> <td colspan="2"><h3>Locale settings</h3></td> </tr> <tr> <th>Timezone</th> <td><?php echo defined('TIMEZONE') ? TIMEZONE : '(Server default)'; ?> </td> </tr> <tr> <th>Label for the Address 'suburb' field</th> <td><?php echo defined('ADDRESS_SUBURB_LABEL') ? ADDRESS_SUBURB_LABEL : 'Suburb'; ?> </td> </tr> <tr> <th>Label for the address 'state' field</th> <td> <?php if (!defined('ADDRESS_STATE_LABEL')) { echo 'State'; } else { if (ADDRESS_STATE_LABEL) { echo ADDRESS_STATE_LABEL; } else { echo '(State field disabled)'; } } echo '<br /><small>The state field can be hidden altogether by setting this to blank</small>'; ?> </td> </tr> <tr> <th>Options for the Address 'state' field</th> <td><?php echo ADDRESS_STATE_OPTIONS; ?> (Default: <?php echo ADDRESS_STATE_DEFAULT; ?> )</td> </tr> <tr> <th>Label for the address 'postcode' field</th> <td><?php echo defined('ADDRESS_POSTCODE_LABEL') ? ADDRESS_POSTCODE_LABEL : 'Postcode'; ?> </td> </tr> <tr> <th>Valid formats for the address 'postcode' field</th> <td><?php echo ADDRESS_POSTCODE_WIDTH . ' characters matching the expression ' . ADDRESS_POSTCODE_REGEX; ?> </td> </tr> <tr> <th>Postcode lookup URL</th> <td> <?php echo POSTCODE_LOOKUP_URL; ?> <br /><small>When editing an address, the "look up <?php echo defined('ADDRESS_POSTCODE_LABEL') ? ADDRESS_POSTCODE_LABEL : 'postcode'; ?> " link uses this URL</small> </td> </tr> <tr> <th>Envelope Size</th> <td><?php echo ENVELOPE_WIDTH_MM . 'mm x ' . ENVELOPE_HEIGHT_MM . 'mm'; ?> </td> </tr> <tr> <th>Formats for the home phone field</th> <td> <?php echo nl2br(HOME_TEL_FORMATS); ?> <br /><small>When a phone number is displayed, it is laid out using these formats. When a phone number is entered, Jethro makes sure it has the right number of digits to match one of these formats.</small> </td> </tr> <tr> <th>Formats for the work phone field</th> <td><?php echo nl2br(HOME_TEL_FORMATS); ?> </td> </tr> <tr> <th>Formats for the mobile phone field</th> <td><?php echo nl2br(MOBILE_TEL_FORMATS); ?> </td> </tr> </table> <?php }
private function printSet($cohortid, $cohortname) { $stats = Attendance_Record_Set::getStatsForPeriod($this->_start_date, $this->_end_date, $cohortid); if (empty($stats) || $stats[NULL]['rate'] == 0) { return FALSE; } ?> <div class="span4"> <table class="table table-bordered attendance-stats"> <thead> <tr> <th colspan="4"><?php echo ents($cohortname); ?> </th> </tr> <tr> <th><?php echo _('Segment'); ?> </th> <th title=<?php echo _('"Percentage of dates marked present rather than absent"'); ?> ><?php echo _('Rate'); ?> </th> <th class="present" title=<?php echo _('"Average number marked present per date"'); ?> ><?php echo _('Avg P'); ?> </th> <th class="absent" title="<?php echo _('Average number marked absent per date"'); ?> ><?php echo _('Avg A'); ?> </th> </thead> <tbody> <?php $map['age_bracket'] = explode(',', AGE_BRACKET_OPTIONS); if ($cohortid[0] == 'g') { list($map['status'], $default) = Person_Group::getMembershipStatusOptionsAndDefault(); } else { $map['status'] = $this->status_map; } foreach (array('status', 'age_bracket') as $grouping) { foreach ($map[$grouping] as $k => $v) { if (!isset($stats[$grouping][$k])) { continue; } ?> <tr <?php if ($k == 0 && $grouping == 'age_bracket') { echo 'class="thick-top-border"'; } ?> > <th><?php echo ents($v); ?> </th> <?php if (isset($stats[$grouping][$k])) { ?> <td><?php echo $stats[$grouping][$k]['rate']; ?> %</td> <td><?php echo number_format($stats[$grouping][$k]['avg_present'], 1); ?> </td> <td><?php echo number_format($stats[$grouping][$k]['avg_absent'], 1); ?> </td> <?php } else { ?> <td>-</td> <td>-</td> <td>-</td> <?php } ?> </tr> <?php } } ?> <tr class="thick-top-border"> <th><?php echo _('Overall'); ?> </th> <td><?php echo $stats[NULL]['rate']; ?> %</td> <td><?php echo number_format($stats[NULL]['avg_present'], 1); ?> </td> <td><?php echo number_format($stats[NULL]['avg_absent'], 1); ?> </td> </tr> <tr class="headcount"> <th colspan="2"> <?php echo _('Avg Headcount'); ?> </th> <td class="right"> <?php $bits = explode('-', $cohortid); $hc = Headcount::fetchAverage($bits[0], $bits[1], $this->_start_date, $this->_end_date); if ($hc) { echo number_format($hc, 1); } else { echo 'N/A'; } ?> </td> <td colspan="2"></td> </tr> </tbody> </table> </div> <?php return TRUE; }
function _processObjectEditing() { $mod_count = 0; $processed = FALSE; switch (array_get($_REQUEST, 'action')) { case 'add_member': case 'add_members': $personids = array_get($_POST, 'personid', array()); list($status_options, $default_status) = Person_Group::getMembershipStatusOptionsAndDefault(); $mstatus = array_get($_POST, 'membership_status', $default_status); // When moving from an old group to this one, the magic membership status _PRESERVE_ // means we should look up their status in the old group and use that status in the new group. if (!empty($_POST['remove_from_groupid'])) { $old_group = $GLOBALS['system']->getDBObject('person_group', (int) $_POST['remove_from_groupid']); if ($mstatus == '_PRESERVE_') { $old_memberships = $old_group->getMembers(); } } // overwrite_membership means if they are already in the group with a different status, // their membership status will be updated. Used for single-person actions but not bulk. $overwrite = array_get($_POST, 'overwrite_membership'); if (!empty($personids)) { if (!is_array($personids)) { $personids = array($personids); } foreach ($personids as $personid) { $new_member =& $GLOBALS['system']->getDBObject('person', (int) $personid); $newstatus = $mstatus == '_PRESERVE_' ? $old_memberships[$personid]['membership_status_id'] : $mstatus; if ($new_member->id) { if ($this->_edited_object->addMember((int) $personid, $newstatus, $overwrite)) { $mod_count++; } } } $verb = !empty($_POST['remove_from_groupid']) ? 'moved' : 'added'; if (count($personids) > 1) { add_message($mod_count . ' persons ' . $verb . ' to group'); } else { add_message('Person ' . $verb . ' to group'); } } if (!empty($_POST['remove_from_groupid']) && !empty($old_group)) { $old_group->removeMembers($_POST['personid']); } $processed = TRUE; break; case 'remove_member': case 'remove_members': $personids = $_POST['personid']; if (!empty($personids)) { if (!is_array($personids)) { $personids = array($personids); } foreach ($personids as $personid) { if ($this->_edited_object->removeMember((int) $personid)) { $mod_count++; } } if (count($personids) > 1) { add_message($mod_count . ' persons removed from group'); } else { add_message('Person removed from group'); } } $processed = TRUE; break; case 'delete': if ($_POST['action'] == 'delete') { // must be POSTed $GLOBALS['user_system']->checkPerm(PERM_EDITGROUP); $name = $this->_edited_object->toString(); $this->_edited_object->delete(); add_message('Group "' . $name . '" deleted'); redirect('groups__list_all', array('groupid' => NULL, 'action' => NULL)); // exits } break; } if (!$processed) { // normal group edit $GLOBALS['user_system']->checkPerm(PERM_EDITGROUP); $processed = parent::_processObjectEditing(); } if ($processed) { switch (array_get($_REQUEST, 'back_to')) { case 'persons': redirect('persons', array('personid' => (int) reset($personids)), 'groups'); case 'groups__list_all': redirect('groups__list_all', array('groupid' => NULL, 'action' => NULL)); // exits // exits case 'groups': default: redirect('groups', array('groupid' => $this->_edited_object->id)); // exits } } }
private function printSet($cohortid, $cohortname) { $stats = Attendance_Record_Set::getStatsForPeriod($this->_start_date, $this->_end_date, $cohortid); if (empty($stats)) { return FALSE; } ?> <div class="span4"> <table class="table table-bordered attendance-stats"> <thead> <tr> <th colspan="4"><?php echo ents($cohortname); ?> </th> </tr> <tr> <th>Status</th> <th title="Percentage of dates marked present rather than absent">Rate</th> <th class="present" title="Average number marked present per date">Avg P</th> <th class="absent" title="Average number marked absent per date">Avg A</th> </thead> <tbody> <?php if ($cohortid[0] == 'g') { list($map, $default) = Person_Group::getMembershipStatusOptionsAndDefault(); } else { $map = $this->status_map; } foreach ($map as $k => $v) { if (isset($stats[$k])) { ?> <tr> <th><?php echo ents($v); ?> </th> <td style="width: 6ex; text-align: right"><?php echo $stats[$k]['rate']; ?> %</td> <td style="width: 6ex; text-align: right"><?php echo number_format($stats[$k]['avg_present'], 1); ?> </td> <td style="width: 6ex; text-align: right"><?php echo number_format($stats[$k]['avg_absent'], 1); ?> </td> </tr> <?php } } ?> <tr class="thick-top-border"> <th>Overall</th> <td style="width: 6ex; text-align: right"><?php echo $stats[NULL]['rate']; ?> %</td> <td style="width: 6ex; text-align: right"><?php echo number_format($stats[NULL]['avg_present'], 1); ?> </td> <td style="width: 6ex; text-align: right"><?php echo number_format($stats[NULL]['avg_absent'], 1); ?> </td> </tr> <tr class="headcount"> <th colspan="2"> Avg Headcount </th> <td class="right"> <?php $bits = explode('-', $cohortid); $hc = Headcount::fetchAverage($bits[0], $bits[1], $this->_start_date, $this->_end_date); if ($hc) { echo number_format($hc, 1); } else { echo 'N/A'; } ?> </td> <td colspan="2"></td> </tr> </tbody> </table> </div> <?php return TRUE; }