diff --git a/.gitignore b/.gitignore
index 791b4ee4..73fef35e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,4 +4,5 @@ bin/setup.conf
.DS_Store
update.sh
.*
+site/
/nbproject
diff --git a/CRM/Volunteer/APIWrapper/CustomField.php b/CRM/Volunteer/APIWrapper/CustomField.php
new file mode 100644
index 00000000..2b024691
--- /dev/null
+++ b/CRM/Volunteer/APIWrapper/CustomField.php
@@ -0,0 +1,63 @@
+ $customFieldValue) {
+ $key = 'custom_' . $customFieldId;
+ // If custom field have set value.
+ if($customFieldValue) {
+ // Explode with seperator.
+ $seperator = CRM_CORE_DAO::VALUE_SEPARATOR;
+ $newCustomFieldValue = explode($seperator, $customFieldValue);
+ // If multiple value then prepare associative array for that custom field.
+ // Set value under key.
+ if(count($newCustomFieldValue) > 1) {
+ $customFieldValueArray = array();
+ foreach ($newCustomFieldValue as $new_key => $value) {
+ if($value) {
+ $customFieldValueArray[$value] = $value;
+ }
+ }
+ $customFieldValue = $customFieldValueArray;
+ }
+ }
+ $item[$key] = $customFieldValue;
+ }
+ }
+ }
+
+ return $result;
+ }
+
+}
diff --git a/CRM/Volunteer/Angular.php b/CRM/Volunteer/Angular.php
index d4910393..463f98be 100644
--- a/CRM/Volunteer/Angular.php
+++ b/CRM/Volunteer/Angular.php
@@ -25,7 +25,22 @@ public static function load($defaultRoute) {
CRM_Core_Resources::singleton()->addScriptFile('civicrm', 'packages/jquery/plugins/jquery.notify.min.js', 10, 'html-header');
$loader = new \Civi\Angular\AngularLoader();
- $loader->setModules(array('volunteer'));
+
+
+ // Check if fieldmeta extension is installed or not.
+ // If installed then add crmFieldMetadata module.
+ $result = civicrm_api3('Extension', 'get', [
+ 'sequential' => 1,
+ 'full_name' => "org.civicrm.fieldmetadata",
+ 'status' => "installed",
+ ]);
+
+ if($result['count']) {
+ $loader->setModules(array('volunteer', 'crmFieldMetadata'));
+ } else {
+ $loader->setModules(array('volunteer'));
+ }
+
$loader->setPageName('civicrm/vol');
$loader->load();
\Civi::resources()->addSetting(array(
diff --git a/CRM/Volunteer/Angular/Manager.php b/CRM/Volunteer/Angular/Manager.php
new file mode 100644
index 00000000..384bb41f
--- /dev/null
+++ b/CRM/Volunteer/Angular/Manager.php
@@ -0,0 +1,107 @@
+modules === NULL) {
+ $config = \CRM_Core_Config::singleton();
+
+ $angularModules = array();
+ //$angularModules['angularFileUpload'] = array(
+ // 'ext' => 'civicrm',
+ // 'js' => array('bower_components/angular-file-upload/angular-file-upload.min.js'),
+ //);
+ $angularModules['crmApp'] = array(
+ 'ext' => 'civicrm',
+ 'js' => array('ang/crmApp.js'),
+ );
+ //$angularModules['crmAttachment'] = array(
+ // 'ext' => 'civicrm',
+ // 'js' => array('ang/crmAttachment.js'),
+ // 'css' => array('ang/crmAttachment.css'),
+ // 'partials' => array('ang/crmAttachment'),
+ // 'settings' => array(
+ // 'token' => \CRM_Core_Page_AJAX_Attachment::createToken(),
+ // ),
+ //);
+ $angularModules['crmAutosave'] = array(
+ 'ext' => 'civicrm',
+ 'js' => array('ang/crmAutosave.js'),
+ );
+ $angularModules['crmCxn'] = array(
+ 'ext' => 'civicrm',
+ 'js' => array('ang/crmCxn.js', 'ang/crmCxn/*.js'),
+ 'css' => array('ang/crmCxn.css'),
+ 'partials' => array('ang/crmCxn'),
+ );
+ $angularModules['crmResource'] = array(
+ 'ext' => 'civicrm',
+ // 'js' => array('js/angular-crmResource/byModule.js'), // One HTTP request per module.
+ 'js' => array('js/angular-crmResource/all.js'), // One HTTP request for all modules.
+ );
+ $angularModules['crmUi'] = array(
+ 'ext' => 'civicrm',
+ 'js' => array('ang/crmUi.js'),
+ 'partials' => array('ang/crmUi'),
+ 'settings' => array(
+ 'browseUrl' => $config->userFrameworkResourceURL . 'packages/kcfinder/browse.php',
+ 'uploadUrl' => $config->userFrameworkResourceURL . 'packages/kcfinder/upload.php',
+ ),
+ );
+ $angularModules['crmUtil'] = array(
+ 'ext' => 'civicrm',
+ 'js' => array('ang/crmUtil.js'),
+ );
+ // https://github.com/jwstadler/angular-jquery-dialog-service
+ $angularModules['dialogService'] = array(
+ 'ext' => 'civicrm',
+ 'js' => array('bower_components/angular-jquery-dialog-service/dialog-service.js'),
+ );
+ $angularModules['ngRoute'] = array(
+ 'ext' => 'civicrm',
+ 'js' => array('bower_components/angular-route/angular-route.min.js'),
+ );
+ $angularModules['ngSanitize'] = array(
+ 'ext' => 'civicrm',
+ 'js' => array('bower_components/angular-sanitize/angular-sanitize.min.js'),
+ );
+ $angularModules['ui.utils'] = array(
+ 'ext' => 'civicrm',
+ 'js' => array('bower_components/angular-ui-utils/ui-utils.min.js'),
+ );
+ $angularModules['ui.sortable'] = array(
+ 'ext' => 'civicrm',
+ 'js' => array('bower_components/angular-ui-sortable/sortable.min.js'),
+ );
+ $angularModules['unsavedChanges'] = array(
+ 'ext' => 'civicrm',
+ 'js' => array('bower_components/angular-unsavedChanges/dist/unsavedChanges.min.js'),
+ );
+
+ \CRM_Utils_Hook::angularModules($angularModules);
+
+ // Filter out modules which should not be loaded on Volunteer's base page
+ foreach ($angularModules as $name => $module) {
+ // Angular modules can register to be loaded by supplying a truthy
+ // property 'volunteer' as a sibling to 'ext' and 'js'
+ $moduleSelfRegisters = !empty($module['volunteer']);
+
+ // These extensions are always allowed. (Note: the modules associated
+ // with the civicrm "extension" are already filtered above.)
+ $whitelist = array('civicrm', 'org.civicrm.angularprofiles', 'org.civicrm.fieldmetadata',);
+
+ if (!$moduleSelfRegisters && !in_array($module['ext'], $whitelist)) {
+ unset($angularModules[$name]);
+ }
+ }
+
+ $this->modules = $this->resolvePatterns($angularModules);
+ }
+
+ return $this->modules;
+ }
+
+}
\ No newline at end of file
diff --git a/CRM/Volunteer/BAO/NeedSearch.php b/CRM/Volunteer/BAO/NeedSearch.php
index 33e28ac4..7d6684ee 100644
--- a/CRM/Volunteer/BAO/NeedSearch.php
+++ b/CRM/Volunteer/BAO/NeedSearch.php
@@ -66,35 +66,170 @@ private function getDefaultSearchParams() {
* @return array $this->searchResults
*/
public function search() {
- $projects = CRM_Volunteer_BAO_Project::retrieve($this->searchParams['project']);
- foreach ($projects as $project) {
- $results = array();
-
- $flexibleNeed = civicrm_api3('VolunteerNeed', 'getsingle', array(
- 'id' => $project->flexible_need_id,
- ));
- if ($flexibleNeed['visibility_id'] === CRM_Core_OptionGroup::getValue('visibility', 'public', 'name')) {
- $needId = $flexibleNeed['id'];
- $results[$needId] = $flexibleNeed;
+ // Get volunteer_role_option_group_id of volunteer_role".
+ $result = civicrm_api3('OptionGroup', 'get', [
+ 'sequential' => 1,
+ 'name' => "volunteer_role",
+ ]);
+ $volunteer_role_option_group_id = $result['id'];
+
+ // Prepare select query for preparing fetch opportunity.
+ // Join relevant table of need.
+ $select = " SELECT project.id,project.title, project.description, project.is_active, project.loc_block_id, project.campaign_id, need.id as need_id, need.start_time, need.end_time, need.is_flexible, need.visibility_id, need.is_active as need_active,need.created as need_created,need.last_updated as need_last_updated,need.role_id as role_id, addr.street_address, addr.city, addr.postal_code, country.name as country, state.name as state_province, opt.label as role_lable, opt.description as role_description, campaign.title as campaign_title ";
+ $from = " FROM civicrm_volunteer_project AS project";
+ $join = " LEFT JOIN civicrm_volunteer_need AS need ON (need.project_id = project.id) ";
+ $join .= " LEFT JOIN civicrm_loc_block AS loc ON (loc.id = project.loc_block_id) ";
+ $join .= " LEFT JOIN civicrm_address AS addr ON (addr.id = loc.address_id) ";
+ $join .= " LEFT JOIN civicrm_country AS country ON (country.id = addr.country_id) ";
+ $join .= " LEFT JOIN civicrm_state_province AS state ON (state.id = addr.state_province_id) ";
+ $join .= " LEFT JOIN civicrm_campaign AS campaign ON (campaign.id = project.campaign_id) ";
+ // Get beneficiary_rel_no for volunteer_project_relationship type.
+ $beneficiary_rel_no = CRM_Core_PseudoConstant::getKey("CRM_Volunteer_BAO_ProjectContact", 'relationship_type_id', 'volunteer_beneficiary');
+
+ // Join Project Contact table for benificiary for specific $beneficiary_rel_no.
+ $join .= " LEFT JOIN civicrm_volunteer_project_contact AS pc ON (pc.project_id = project.id And pc.relationship_type_id='".$beneficiary_rel_no."') ";
+ // Join civicrm_option_value table for role details of need.
+ $join .= " LEFT JOIN civicrm_option_value AS opt ON (opt.value = need.role_id And opt.option_group_id='".$volunteer_role_option_group_id."') ";
+ // Join civicrm_contact table for contact details.
+ $join .= " LEFT JOIN civicrm_contact AS cc ON (cc.id = pc.contact_id) ";
+ $select .= ", GROUP_CONCAT( cc.id ) as beneficiary_id , GROUP_CONCAT( cc.display_name ) as beneficiary_display_name";
+
+ $visibility_id = CRM_Volunteer_BAO_Project::getVisibilityId('name', "public");
+ $where = " Where project.is_active = 1 AND need.visibility_id = ".$visibility_id;
+ // Default Filter parameter of date start and date end field of need table.
+ if(empty($this->searchParams['need']['date_start']) && empty($this->searchParams['need']['date_end'])) {
+ $where .= " AND (
+ (DATE_FORMAT(need.start_time,'%Y-%m-%d') <= CURDATE() AND DATE_FORMAT(need.end_time,'%Y-%m-%d') >= CURDATE()) OR
+ (DATE_FORMAT(need.start_time,'%Y-%m-%d') >= CURDATE()) OR (DATE_FORMAT(need.end_time,'%Y-%m-%d') >= CURDATE()) OR
+ (need.start_time Is NOT NULL && need.end_time IS NULL) OR
+ (need.start_time Is NULL && need.end_time IS NULL)
+ )";
+ }
+ // Add date start and date end filter if passed in UI.
+ if($this->searchParams['need']['date_start'] && $this->searchParams['need']['date_end']) {
+ $start_time = date("Y-m-d", $this->searchParams['need']['date_start']);
+ $end_time = date("Y-m-d", $this->searchParams['need']['date_end']);
+ $where .= " AND (
+ ( need.end_time IS NOT NULL AND need.start_time IS NOT NULL
+ AND (
+ DATE_FORMAT(need.start_time,'%Y-%m-%d')<='".$end_time."' AND DATE_FORMAT(need.start_time,'%Y-%m-%d')>='".$start_time."'
+ OR
+ DATE_FORMAT(need.end_time,'%Y-%m-%d') >= '".$start_time."' AND DATE_FORMAT(need.end_time,'%Y-%m-%d') <= '".$end_time."'
+ )
+ ) OR (
+ need.end_time IS NULL AND DATE_FORMAT(need.start_time,'%Y-%m-%d')>='".$start_time."' AND DATE_FORMAT(need.start_time,'%Y-%m-%d')<='".$end_time."'
+ )
+ )";
+ } else { // one but not the other supplied:
+ if($this->searchParams['need']['date_start']) {
+ $start_time = date("Y-m-d", $this->searchParams['need']['date_start']);
+ $where .= " And (DATE_FORMAT(need.start_time,'%Y-%m-%d')>='".$start_time."')";
}
-
- $openNeeds = $project->open_needs;
- foreach ($openNeeds as $key => $need) {
- if ($this->needFitsSearchCriteria($need)) {
- $results[$key] = $need;
+ if($this->searchParams['need']['date_end']) {
+ $end_time = date("Y-m-d", $this->searchParams['need']['date_end']);
+ $where .= " And (DATE_FORMAT(need.end_time,'%Y-%m-%d')<='".$end_time."')";
+ }
+ }
+ // Add role filter if passed in UI.
+ if($this->searchParams['need']['role_id'] && is_array($this->searchParams['need']['role_id'])) {
+ $role_id_string = implode(",", $this->searchParams['need']['role_id']);
+ $where .= " And need.role_id IN (".$role_id_string.")";
+ }
+ // Add with(benificiary) filter if passed in UI.
+ if($this->searchParams['project']['project_contacts']['volunteer_beneficiary']) {
+ $beneficiary_id_string = implode(",", $this->searchParams['project']['project_contacts']['volunteer_beneficiary']);
+ $where .= " And pc.contact_id IN (".$beneficiary_id_string.")";
+ }
+ // Add Location filter if passed in UI.
+ if(isset($this->searchParams['project']["proximity"]) && !empty($this->searchParams['project']["proximity"])) {
+ $proximityquery = CRM_Volunteer_BAO_Project::buildProximityWhere($this->searchParams['project']["proximity"]);
+ $proximityquery = str_replace("civicrm_address", "addr", $proximityquery);
+ $where .= " And ".$proximityquery;
+ }
+ // If Project Id is passed from URL- Query String.
+ if(isset($this->searchParams['project']) && !empty($this->searchParams['project'])) {
+ if(isset($this->searchParams['project']['is_active']) && isset($this->searchParams['project']['id'])) {
+ $where .= " And project.id=".$this->searchParams['project']['id'];
+ }
+ }
+ // Order by Logic.
+ $orderByColumn = "project.id";
+ $order = "ASC";
+ $orderby = " group by need.id ORDER BY " . $orderByColumn . " " . $order;
+
+ // Pagination Logic.
+ $no_of_records_per_page = 10;
+ if(isset($params['page_no']) && !empty($params['page_no'])) {
+ $page_no = $params['page_no'];
+ } else {
+ $page_no = 1;
+ }
+ $offset = ($page_no-1) * $no_of_records_per_page;
+ $limit = " LIMIT ".$offset.", ".$no_of_records_per_page;
+ // Prepare whole sql query dynamic.
+ //$sql = $select . $from . $join . $where . $orderby . $limit;
+ $sql = $select . $from . $join . $where . $orderby;
+ $dao = new CRM_Core_DAO();
+ $dao->query($sql);
+ $project_opportunities = [];
+ $i=0;
+ $config = CRM_Core_Config::singleton();
+ $timeFormat = $config->dateformatDatetime;
+ // Prepare array for need of projects.
+ while ($dao->fetch()) {
+ $project_opportunities[$i]['id'] = $dao->need_id;
+ $project_opportunities[$i]['project_id'] = $dao->id;
+ $project_opportunities[$i]['is_flexible'] = $dao->is_flexible;
+ $project_opportunities[$i]['visibility_id'] = $dao->visibility_id;
+ $project_opportunities[$i]['is_active'] = $dao->need_active;
+ $project_opportunities[$i]['created'] = $dao->need_created;
+ $project_opportunities[$i]['last_updated'] = $dao->need_last_updated;
+ if(isset($dao->start_time) && !empty($dao->start_time)) {
+ $start_time = CRM_Utils_Date::customFormat($dao->start_time, $timeFormat);
+ if(isset($dao->end_time) && !empty($dao->end_time)) {
+ $end_time = CRM_Utils_Date::customFormat($dao->end_time, $timeFormat);
+ $project_opportunities[$i]['display_time'] = $start_time ." - ". $end_time;
+ } else {
+ $project_opportunities[$i]['display_time'] = $start_time;
}
+ } else {
+ $project_opportunities[$i]['display_time'] = "Any";
}
-
- if (!empty($results)) {
- $this->projects[$project->id] = array();
+ $project_opportunities[$i]['role_id'] = $dao->role_id;
+ if(empty($dao->role_lable)) {
+ $project_opportunities[$i]['role_label'] = "Any";
+ } else {
+ $project_opportunities[$i]['role_label'] = $dao->role_lable;
}
-
- $this->searchResults += $results;
+ $project_opportunities[$i]['role_description'] = $dao->role_description;
+ $project_opportunities[$i]['project']['description'] = $dao->description;
+ $project_opportunities[$i]['project']['id'] = $dao->id;
+ $project_opportunities[$i]['project']['title'] = $dao->title;
+ $project_opportunities[$i]['project']['campaign_title'] = $dao->campaign_title;
+ $project_opportunities[$i]['project']['location'] = array(
+ "city" => $dao->city,
+ "country" => $dao->country,
+ "postal_code" => $dao->postal_code,
+ "state_province" => $dao->state_province,
+ "street_address" => $dao->street_address
+ );
+ $beneficiary_display_name = explode(',', $dao->beneficiary_display_name);
+ if(isset($beneficiary_display_name) && !empty($beneficiary_display_name) && is_array($beneficiary_display_name)) {
+ $beneficiary_id_array = explode(',', $dao->beneficiary_id);
+ foreach ($beneficiary_display_name as $key => $display_name) {
+ $project_opportunities[$i]['project']['beneficiaries'][$key] = array(
+ "id" => $beneficiary_id_array[$key],
+ "display_name" => $display_name
+ );
+ }
+ } else {
+ $project_opportunities[$i]['project']['beneficiaries'] = $dao->beneficiary_display_name;
+ $project_opportunities[$i]['project']['beneficiary_id'] = $dao->beneficiary_id;
+ }
+ $i++;
}
- $this->getSearchResultsProjectData();
- usort($this->searchResults, array($this, "usortDateAscending"));
- return $this->searchResults;
+ return $project_opportunities;
}
/**
@@ -305,4 +440,4 @@ private static function usortDateAscending($a, $b) {
return ($startTimeA < $startTimeB) ? -1 : 1;
}
-}
+}
\ No newline at end of file
diff --git a/CRM/Volunteer/BAO/Project.php b/CRM/Volunteer/BAO/Project.php
index 000215de..5425ef46 100644
--- a/CRM/Volunteer/BAO/Project.php
+++ b/CRM/Volunteer/BAO/Project.php
@@ -463,9 +463,28 @@ public static function retrieve(array $params) {
foreach ($project->fields() as $field) {
$fieldName = $field['name'];
-
+ // default sqlExpr: see CRM_Utils_SQL_BaseParamQuery::interpolate()
+ $comparator = "=";
+ $sqlExpr = '!column '.$comparator.' @value';
+ // Check any field parameter set with array or not.
+ // If array then use comparator from key. Otheriwse use "=" comparator.
if (!empty($project->$fieldName)) {
- $query->where('!column = @value', array(
+ if(isset($project->$fieldName) && !empty($project->$fieldName) && is_array($project->$fieldName)) {
+ // Key contains comparator value. eg. "Like, Not Like etc"
+ $comparator = key($project->$fieldName);
+ if ($comparator == "IN") {
+ if (is_array($project->$fieldName)) {
+ $project->$fieldName = '('. implode(",",current($project->$fieldName )) .')';
+ }
+ // disable escaping: "!value"
+ $sqlExpr = '!column '.$comparator.' !value';
+ } else {
+ $sqlExpr = '!column '.$comparator.' @value';
+ }
+ }
+
+ // Use dynamic comparator based on passed parameter.
+ $query->where($sqlExpr, array(
'column' => $fieldName,
'value' => $project->$fieldName,
));
@@ -539,7 +558,7 @@ private static function buildContactJoin(array $projectContacts) {
* SQL fragment (partial where clause)
* @throws Exception
*/
- private static function buildProximityWhere(array $params) {
+ public static function buildProximityWhere(array $params) {
$country = $lat = $lon = $radius = $unit = NULL;
extract($params, EXTR_IF_EXISTS);
@@ -547,44 +566,44 @@ private static function buildProximityWhere(array $params) {
if (!CRM_Utils_Rule::numeric($radius)) {
throw new Exception(ts('Radius should exist and be numeric'));
}
+ if(!isset($lat) && !isset($lon)) {
+ if (!CRM_Utils_Rule::numeric($lat) || !CRM_Utils_Rule::numeric($lon)) {
+ // try to supply a default country if none provided
+ if (empty($country)) {
+ $settings = civicrm_api3('Setting', 'get', array(
+ "return" => array("defaultContactCountry"),
+ "sequential" => 1,
+ ));
+ $country = $settings['values'][0]['defaultContactCountry'];
+ }
+
+ if (empty($country)) {
+ throw new Exception(ts('Either Country or both Latitude and Longitude are required'));
+ }
- if (!CRM_Utils_Rule::numeric($lat) || !CRM_Utils_Rule::numeric($lon)) {
- // try to supply a default country if none provided
- if (empty($country)) {
- $settings = civicrm_api3('Setting', 'get', array(
- "return" => array("defaultContactCountry"),
- "sequential" => 1,
- ));
- $country = $settings['values'][0]['defaultContactCountry'];
- }
-
- if (empty($country)) {
- throw new Exception(ts('Either Country or both Latitude and Longitude are required'));
- }
-
- // TODO: I think CRM_Utils_Geocode_*::format should be responsible for this
- // If/when CRM-17245 is closed, this if-block can be removed.
- if (CRM_Utils_Type::validate($country, 'Positive', FALSE)) {
- $params['country'] = civicrm_api3('Country', 'getvalue', array(
- 'id' => $country,
- 'return' => 'name',
- ));
- }
+ // TODO: I think CRM_Utils_Geocode_*::format should be responsible for this
+ // If/when CRM-17245 is closed, this if-block can be removed.
+ if (CRM_Utils_Type::validate($country, 'Positive', FALSE)) {
+ $params['country'] = civicrm_api3('Country', 'getvalue', array(
+ 'id' => $country,
+ 'return' => 'name',
+ ));
+ }
- // TODO: support other geocoders
- $geocodeSuccess = CRM_Utils_Geocode_Google::format($params);
- if (!$geocodeSuccess) {
- // this is intentionally a string; a query like "SELECT * FROM foo WHERE FALSE"
- // will return an empty set, which is what we should do if the provided address
- // can't be geocoded
- return 'FALSE';
+ // TODO: support other geocoders
+ $geocodeSuccess = CRM_Utils_Geocode_Google::format($params);
+ if (!$geocodeSuccess) {
+ // this is intentionally a string; a query like "SELECT * FROM foo WHERE FALSE"
+ // will return an empty set, which is what we should do if the provided address
+ // can't be geocoded
+ return 'FALSE';
+ }
+ // $params is passed to the geocoder by reference; on success, these values
+ // will be available
+ $lat = $params['geo_code_1'];
+ $lon = $params['geo_code_2'];
}
- // $params is passed to the geocoder by reference; on success, these values
- // will be available
- $lat = $params['geo_code_1'];
- $lon = $params['geo_code_2'];
}
-
$conversionFactor = ($unit == "mile") ? 1609.344 : 1000;
//radius in meters
$radius = $radius * $conversionFactor;
@@ -910,7 +929,7 @@ private function _get_needs() {
$result = civicrm_api3('VolunteerNeed', 'get', array(
'is_active' => '1',
'project_id' => $this->id,
- 'visibility_id' => CRM_Core_OptionGroup::getValue('visibility', 'public', 'name'),
+ 'visibility_id' => CRM_Volunteer_BAO_Project::getVisibilityId('name', "public"),
'options' => array(
'sort' => 'start_time',
'limit' => 0,
@@ -1004,4 +1023,16 @@ private function _get_flexible_need_id() {
return self::getFlexibleNeedID($this->id);
}
+ /*
+ * Implement getVisibilityId() function.
+ * Based on column and name it return visibility id.
+ */
+ public static function getVisibilityId($column, $name) {
+ $visibility = CRM_Core_PseudoConstant::visibility($column);
+ $visibility_id = array_search ($name, $visibility);
+
+ return $visibility_id;
+ }
+
+
}
diff --git a/CRM/Volunteer/BAO/VolunteerAppeal.php b/CRM/Volunteer/BAO/VolunteerAppeal.php
new file mode 100644
index 00000000..48790ca9
--- /dev/null
+++ b/CRM/Volunteer/BAO/VolunteerAppeal.php
@@ -0,0 +1,596 @@
+imageUploadDir.'appeal/';
+ $upload_appeal_main_directory = $config->imageUploadDir.'appeal/main/';
+ $upload_appeal_thumb_directory = $config->imageUploadDir.'appeal/thumb/';
+ $upload_appeal_medium_directory = $config->imageUploadDir.'appeal/medium/';
+ // If appeal folder not exist, create appeal folder on civicrm.files folder.
+ if (!file_exists($upload_appeal_directory)) {
+ mkdir($upload_appeal_directory, 0777, TRUE);
+ }
+ // If main image folder not exist, create main folder under appeal folder on civicrm.files folder.
+ if (!file_exists($upload_appeal_main_directory)) {
+ mkdir($upload_appeal_main_directory, 0777, TRUE);
+ }
+ // If thumb image folder not exist, create thumb folder under appeal folder on civicrm.files folder.
+ if (!file_exists($upload_appeal_thumb_directory)) {
+ mkdir($upload_appeal_thumb_directory, 0777, TRUE);
+ }
+ // If medium image folder not exist, create medium folder under appeal folder on civicrm.files folder.
+ if (!file_exists($upload_appeal_medium_directory)) {
+ mkdir($upload_appeal_medium_directory, 0777, TRUE);
+ }
+ // If new image is updated then resize that image and move that into folder.
+ if(isset($params['image_data'])) {
+ $image_parts = explode(";base64,", $params['image_data']);
+ $image_base64 = base64_decode($image_parts[1]);
+ $current_time = time();
+ $file = $upload_appeal_main_directory . $current_time."_".$params['image'];
+ file_put_contents($file, $image_base64);
+
+ // Resize Image with 150*150 and save into destination folder.
+ $source_path = $upload_appeal_main_directory . $current_time."_".$params['image'];
+ $destination_path = $upload_appeal_thumb_directory . $current_time."_".$params['image'];
+ $destination_path_for_detail_image = $upload_appeal_medium_directory . $current_time."_".$params['image'];
+
+ if (class_exists('Imagick')) { // Imagick resizing if available
+
+ $imgSmall = new Imagick($source_path);
+ $imgProps = $imgSmall->getImageGeometry();
+ $width = $imgProps['width'];
+ $height = $imgProps['height'];
+ $imgSmallDim = 150;
+ if ($width > $height) {
+ $newHeight = $imgSmallDim;
+ $newWidth = ($imgSmallDim / $height) * $width;
+ } else {
+ $newWidth = $imgSmallDim ;
+ $newHeight = ($imgSmallDim / $width) * $height;
+ }
+ $imgSmall->resizeImage($newWidth, $newHeight, Imagick::FILTER_CATROM, 1, true);
+ $imgSmall->cropImage($imgSmallDim, $imgSmallDim, floor(abs($newWidth-$imgSmallDim) / 2), floor(abs($newHeight-$imgSmallDim) / 2));
+ $imgSmall->writeImage($destination_path);
+
+ $imgMedium = new Imagick($source_path);
+ $imgProps = $imgMedium->getImageGeometry();
+ $width = $imgProps['width'];
+ $height = $imgProps['height'];
+ $imgMediumDim = 300;
+ if ($width > $height) {
+ $newHeight = $imgMediumDim;
+ $newWidth = ($imgMediumDim / $height) * $width;
+ } else {
+ $newWidth = $imgMediumDim ;
+ $newHeight = ($imgMediumDim / $width) * $height;
+ }
+ $imgMedium->resizeImage($newWidth, $newHeight, Imagick::FILTER_CATROM, 1, true);
+ $imgMedium->cropImage($imgMediumDim, $imgMediumDim, floor(abs($newWidth-$imgMediumDim) / 2), floor(abs($newHeight-$imgMediumDim) / 2));
+ $imgMedium->writeImage($destination_path_for_detail_image);
+
+ } else if (function_exists('image_load')) { // native Drupal resizing
+ $imgSmall = image_load($source_path);
+ image_resize($imgSmall, 150, 150);
+ image_save($imgSmall, $destination_path);
+ image_resize($imgSmall, 300, 300);
+ image_save($imgSmall, $destination_path_for_detail_image);
+ } else { // resizing not supported
+ CRM_Core_Error::debug_log_message('Image resizing not supported for Volunteer Appeal images', FALSE, 'org.civicrm.volunteer');
+ }
+ }
+ // If image is not updated on edit page, save old image name in database.
+ if($params['image'] == $params['old_image']) {
+ $params['image'] = $params['old_image'];
+ } else {
+ $params['image'] = $current_time."_".$params['image'];
+ }
+
+ $appeal = new CRM_Volunteer_BAO_VolunteerAppeal();
+ $appeal->copyValues($params);
+ $appeal->save();
+
+ // Custom data saved in database for appeal if user has set any.
+ $customData = CRM_Core_BAO_CustomField::postProcess($params, $appeal->id, 'VolunteerAppeal');
+ if (!empty($customData)) {
+ CRM_Core_BAO_CustomValueTable::store($customData, 'civicrm_volunteer_appeal', $appeal->id);
+ }
+
+ return $appeal;
+ }
+
+ /**
+ * Strips invalid params, throws exception in case of unusable params.
+ *
+ * @param array $params
+ * Params for self::create().
+ * @return array
+ * Filtered params.
+ *
+ * @throws Exception
+ * Via delegate.
+ */
+ private static function validateCreateParams(array $params) {
+ if (empty($params['id']) && empty($params['title'])) {
+ CRM_Core_Error::fatal(ts('Title field is required for Appeal creation.'));
+ }
+ if (empty($params['id']) && empty($params['appeal_description'])) {
+ CRM_Core_Error::fatal(ts('Appeal Description field is required for Appeal creation.'));
+ }
+
+ return $params;
+ }
+
+ /**
+ * Get a list of Project Appeal matching the params.
+ *
+ * This function is invoked from within the web form layer and also from the
+ * API layer. Special params include:
+ *
+ *
+ * NOTE: This method does not return data related to the special params
+ * outlined above; however, these parameters can be used to filter the list
+ * of Projects appeal that is returned.
+ *
+ * @param array $params
+ * @return array of CRM_Volunteer_BAO_VolunteerAppeal objects
+ */
+ public static function retrieve(array $params) {
+ $result = array();
+
+ $query = CRM_Utils_SQL_Select::from('`civicrm_volunteer_appeal` vp')->select('*');
+ $appeal = new CRM_Volunteer_BAO_VolunteerAppeal();
+
+ $appeal->copyValues($params);
+
+ foreach ($appeal->fields() as $field) {
+ $fieldName = $field['name'];
+
+ if (!empty($appeal->$fieldName)) {
+ if(isset($appeal->$fieldName) && !empty($appeal->$fieldName) && is_array($appeal->$fieldName)) {
+ // Key contains comparator value. eg. "Like, Not Like etc"
+ $comparator = key($appeal->$fieldName);
+ } else {
+ $comparator = "=";
+ }
+ // Use dynamic comparator based on passed parameter.
+ $query->where('!column '.$comparator.' @value', array(
+ 'column' => $fieldName,
+ 'value' => $appeal->$fieldName,
+ ));
+ }
+ }
+
+ // Get the global configuration.
+ $config = CRM_Core_Config::singleton();
+ $upload_appeal_main_directory = $config->imageUploadDir.'appeal/main/';
+ $upload_appeal_medium_directory = $config->imageUploadDir.'appeal/medium/';
+ $upload_appeal_thumb_directory = $config->imageUploadDir.'appeal/thumb/';
+ $default_image_name = "appeal-default-logo-sq.png";
+
+ $dao = self::executeQuery($query->toSQL());
+ while ($dao->fetch()) {
+ $fetchedAppeal = new CRM_Volunteer_BAO_VolunteerAppeal();
+ $daoClone = clone $dao;
+ $fetchedAppeal->copyValues($daoClone);
+ if($fetchedAppeal->image == "null" || !$fetchedAppeal->image) {
+ // check if the default image exists before we set the image property to it
+ if (file_exists($upload_appeal_main_directory . $default_image_name)
+ && file_exists($upload_appeal_medium_directory . $default_image_name)
+ && file_exists($upload_appeal_thumb_directory . $default_image_name)
+ ) {
+ $fetchedAppeal->image = $default_image_name;
+ } else {
+ $fetchedAppeal->image = null;
+ }
+ }
+ $result[(int) $dao->id] = $fetchedAppeal;
+ }
+
+
+ $dao->free();
+
+ return $result;
+ }
+
+ /**
+ * Wrapper method for retrieve
+ *
+ * @param mixed $id Int or int-like string representing Appeal ID
+ * @return CRM_Volunteer_BAO_VolunteerAppeal
+ */
+ public static function retrieveByID($id) {
+ $id = (int) CRM_Utils_Type::validate($id, 'Integer');
+ // Get Appeal with location and location address based on appeal ID.
+ $api = civicrm_api3('VolunteerAppeal', 'getsingle', array(
+ 'id' => $id,
+ 'api.LocBlock.getsingle' => array(
+ 'api.Address.getsingle' => array(),
+ ),
+ ));
+ if (empty($api['loc_block_id']) || empty($api['api.LocBlock.getsingle']['address_id'])) {
+ $api['location'] = "";
+ } else {
+ $address = "";
+ if ($api['api.LocBlock.getsingle']['api.Address.getsingle']['street_address']) {
+ $address .= " ".$api['api.LocBlock.getsingle']['api.Address.getsingle']['street_address'];
+ }
+ if ($api['api.LocBlock.getsingle']['api.Address.getsingle']['street_address'] && ($api['api.LocBlock.getsingle']['api.Address.getsingle']['city'] || $api['api.LocBlock.getsingle']['api.Address.getsingle']['postal_code'])) {
+ $address .= '
';
+ }
+ if ($api['api.LocBlock.getsingle']['api.Address.getsingle']['city']) {
+ $address .= " ".$api['api.LocBlock.getsingle']['api.Address.getsingle']['city'];
+ }
+ if ($api['api.LocBlock.getsingle']['api.Address.getsingle']['city'] && $api['api.LocBlock.getsingle']['api.Address.getsingle']['postal_code']) {
+ $address .= ', '.$api['api.LocBlock.getsingle']['api.Address.getsingle']['postal_code'];
+ } else if ($api['api.LocBlock.getsingle']['api.Address.getsingle']['postal_code']) {
+ $address .= $api['api.LocBlock.getsingle']['api.Address.getsingle']['postal_code'];
+ }
+ $api['location'] = $address;
+ }
+ // Get Project Details.
+ $api2 = civicrm_api3('VolunteerProject', 'getsingle', array(
+ 'id' => $api['project_id'],
+ 'api.LocBlock.getsingle' => array(
+ 'api.Address.getsingle' => array(),
+ ),
+ 'api.VolunteerProjectContact.get' => array(
+ 'options' => array('limit' => 0),
+ 'relationship_type_id' => 'volunteer_beneficiary',
+ 'api.Contact.get' => array(
+ 'options' => array('limit' => 0),
+ ),
+ ),
+ ));
+ $flexibleNeed = civicrm_api('volunteer_need', 'getvalue', array(
+ 'is_active' => 1,
+ 'is_flexible' => 1,
+ 'project_id' => $api['project_id'],
+ 'return' => 'id',
+ 'version' => 3,
+ ));
+ if (CRM_Utils_Array::value('is_error', $flexibleNeed) == 1) {
+ $flexibleNeed = NULL;
+ } else {
+ $flexibleNeed = (int) $flexibleNeed;
+ }
+ $project = CRM_Volunteer_BAO_Project::retrieveByID($api['project_id']);
+ $openNeeds = $project->open_needs;
+ $project = $project->toArray();
+ foreach ($openNeeds as $key => $need) {
+ $project['available_shifts'][] = $need['display_time'];
+ }
+ if (empty($api2['loc_block_id']) || empty($api2['api.LocBlock.getsingle']['address_id'])) {
+ $api2['location'] = "";
+ } else {
+ $address = "";
+ if ($api2['api.LocBlock.getsingle']['api.Address.getsingle']['street_address']) {
+ $address .= " ".$api2['api.LocBlock.getsingle']['api.Address.getsingle']['street_address'];
+ }
+ if ($api2['api.LocBlock.getsingle']['api.Address.getsingle']['street_address'] && ($api2['api.LocBlock.getsingle']['api.Address.getsingle']['city'] || $api2['api.LocBlock.getsingle']['api.Address.getsingle']['postal_code'])) {
+ $address .= '
';
+ }
+ if ($api2['api.LocBlock.getsingle']['api.Address.getsingle']['city']) {
+ $address .= " ".$api2['api.LocBlock.getsingle']['api.Address.getsingle']['city'];
+ }
+ if ($api2['api.LocBlock.getsingle']['api.Address.getsingle']['city'] && $api2['api.LocBlock.getsingle']['api.Address.getsingle']['postal_code']) {
+ $address .= ', '.$api2['api.LocBlock.getsingle']['api.Address.getsingle']['postal_code'];
+ } else if ($api2['api.LocBlock.getsingle']['api.Address.getsingle']['postal_code']) {
+ $address .= $api2['api.LocBlock.getsingle']['api.Address.getsingle']['postal_code'];
+ }
+ $project['project_location'] = $address;
+ }
+ foreach ($api2['api.VolunteerProjectContact.get']['values'] as $projectContact) {
+ if (!array_key_exists('beneficiaries', $project)) {
+ $project['beneficiaries'] = array();
+ }
+ $project['beneficiaries'][] = array(
+ 'id' => $projectContact['contact_id'],
+ 'display_name' => $projectContact['api.Contact.get']['values'][0]['display_name'],
+ 'image_URL' => $projectContact['api.Contact.get']['values'][0]['image_URL'],
+ 'email' => $projectContact['api.Contact.get']['values'][0]['email'],
+ );
+ }
+ $api['project'] = $project;
+ $api['project']['flexibleNeed'] = $flexibleNeed;
+
+ return $api;
+ }
+
+
+ /**
+ * @inheritDoc This override adds a little data massaging prior to calling its
+ * parent.
+ *
+ * @deprecated since version 4.7.21-2.3.0
+ * Internal core methods should not be extended by third-party code.
+ */
+ public function copyValues(&$params, $serializeArrays = FALSE) {
+ if (is_a($params, 'CRM_Core_DAO')) {
+ $params = get_object_vars($params);
+ }
+
+ if (array_key_exists('is_active', $params)) {
+ /*
+ * don't force is_active to have a value if none was set, to allow searches
+ * where the is_active state of appeal is irrelevant
+ */
+ $params['is_active'] = CRM_Volunteer_BAO_VolunteerAppeal::isOff($params['is_active']) ? 0 : 1;
+ }
+ return parent::copyValues($params, $serializeArrays);
+ }
+
+ /**
+ * Invoked from the API layer.
+ *
+ * Fetch appeal based on search parameter.
+ * @param array $params
+ * @return array $appeals
+ */
+ public static function doSearch($params) {
+
+ $show_beneficiary_at_front = 1;
+ $seperator = CRM_CORE_DAO::VALUE_SEPARATOR;
+
+ $select = " SELECT (select id from civicrm_volunteer_need where civicrm_volunteer_need.is_flexible = 1 and civicrm_volunteer_need.project_id=p.id) as need_flexi_id, appeal.*, addr.street_address, addr.city, addr.postal_code";
+ $select .= " , GROUP_CONCAT(DISTINCT need.id ) as need_id";//,mdt.need_start_time
+ $from = " FROM civicrm_volunteer_appeal AS appeal";
+ $join = " LEFT JOIN civicrm_volunteer_project AS p ON (p.id = appeal.project_id) ";
+ $join .= " LEFT JOIN civicrm_loc_block AS loc ON (loc.id = appeal.loc_block_id) ";
+ $join .= " LEFT JOIN civicrm_address AS addr ON (addr.id = loc.address_id) ";
+ $join .= " LEFT JOIN civicrm_volunteer_need AS need ON (need.project_id = p.id) And need.is_active = 1 And need.is_flexible = 1 And need.visibility_id = 1";
+ if($show_beneficiary_at_front == 1) {
+ $beneficiary_rel_no = CRM_Core_PseudoConstant::getKey("CRM_Volunteer_BAO_ProjectContact", 'relationship_type_id', 'volunteer_beneficiary');
+ $join .= " LEFT JOIN civicrm_volunteer_project_contact AS pc ON (pc.project_id = p.id And pc.relationship_type_id='".$beneficiary_rel_no."') ";
+ $join .= " LEFT JOIN civicrm_contact AS cc ON (cc.id = pc.contact_id) ";
+ $select .= " , GROUP_CONCAT(DISTINCT cc.display_name ) as beneficiary_display_name, GROUP_CONCAT(DISTINCT cc.id ) as beneficiary_id";
+ }
+ // Appeal should be active, Current Date between appeal date and related project should be active.
+ $where = " Where p.is_active = 1 And appeal.is_appeal_active = 1 And CURDATE() between appeal.active_fromdate and appeal.active_todate ";
+
+ if(isset($params['search_appeal'])) {
+ $search_appeal = $params['search_appeal'];
+ $search_appeal = trim($search_appeal);
+ $where .= " And (appeal.title Like '%".$search_appeal."%' OR appeal.appeal_description Like '%".$search_appeal."%' OR cc.display_name LIKE '%".$search_appeal."%')";
+ }
+ $having = "";
+ // Handle beneficiary filter.
+ if($params['beneficiary']) {
+ $params['beneficiary'] = rtrim($params['beneficiary'], ',');
+ $beneficiary = explode(',',$params['beneficiary']);
+ if (sizeof($beneficiary) > 1) {
+ $lastElement = end($beneficiary);
+ $having = " HAVING (";
+ foreach ($beneficiary as $key => $benificiery_id) {
+ if($benificiery_id) {
+ if($benificiery_id == $lastElement) {
+ $having .= " FIND_IN_SET(".$benificiery_id.", beneficiary_id)";
+ } else {
+ $having .= " FIND_IN_SET(".$benificiery_id.", beneficiary_id) OR";
+ }
+ }
+ }
+ $having .= ")";
+ } else {
+ $having = " HAVING FIND_IN_SET(".$beneficiary[0].", beneficiary_id)";
+ }
+ }
+ //Advance search parameter.
+ if(isset($params["advanced_search"])) {
+ // If start date and end date filter passed on advance search.
+ if($params["advanced_search"]["fromdate"] && $params["advanced_search"]["todate"]) {
+ $select .= " , GROUP_CONCAT(DISTINCT advance_need.id ) as need_shift_id";
+ $join .= " LEFT JOIN civicrm_volunteer_need as advance_need ON (advance_need.project_id = p.id) And advance_need.is_active = 1 And advance_need.visibility_id = 1 and advance_need.is_flexible=0";
+
+ $start_time = $params["advanced_search"]["fromdate"];
+ $end_time = $params["advanced_search"]["todate"];
+ $where .= " AND (
+ (
+ (advance_need.end_time IS NULL AND DATE_FORMAT(advance_need.start_time,'%Y-%m-%d')>='".$start_time."') OR (DATE_FORMAT(advance_need.start_time,'%Y-%m-%d')>='".$start_time."' and DATE_FORMAT(advance_need.end_time,'%Y-%m-%d')<='".$end_time."')
+ )
+ )";
+ } else { // one but not the other supplied:
+ $select .= " , GROUP_CONCAT(DISTINCT advance_need.id ) as need_shift_id";
+ $join .= " LEFT JOIN civicrm_volunteer_need as advance_need ON (advance_need.project_id = p.id) And advance_need.is_active = 1 And advance_need.visibility_id = 1 and advance_need.is_flexible=0";
+ if($params["advanced_search"]["fromdate"]) {
+ $where .= " And (DATE_FORMAT(advance_need.start_time,'%Y-%m-%d')>='".$params["advanced_search"]["fromdate"]."')";
+ }
+ if($params["advanced_search"]["todate"]) {
+ $where .= " And (DATE_FORMAT(advance_need.end_time,'%Y-%m-%d')<='".$params["advanced_search"]["todate"]."')";
+ }
+ }
+
+ // If show appeals done anywhere passed on advance search.
+ if(isset($params["advanced_search"]["show_appeals_done_anywhere"]) && $params["advanced_search"]["show_appeals_done_anywhere"] == true ) {
+ $where .= " And appeal.location_done_anywhere = 1 ";
+ } else {
+ // If show appeal is not set then check postal code, radius and proximity.
+ if(isset($params["advanced_search"]["proximity"]['postal_code']) || (isset($params["advanced_search"]["proximity"]['lat']) && isset($params["advanced_search"]["proximity"]['lon']))) {
+ $proximityquery = CRM_Volunteer_BAO_Project::buildProximityWhere($params["advanced_search"]["proximity"]);
+ $proximityquery = str_replace("civicrm_address", "addr", $proximityquery);
+ $where .= " And ".$proximityquery;
+ }
+ }
+ // If custom field pass from advance search filter.
+ if(isset($params["advanced_search"]["appealCustomFieldData"]) && !empty($params["advanced_search"]["appealCustomFieldData"])) {
+ // Get all custom field database tables which are assoicated with Volunteer Appeal.
+ $sql_query = "SELECT cg.table_name, cg.id as groupID, cg.is_multiple, cf.column_name, cf.id as fieldID, cf.data_type as fieldDataType FROM civicrm_custom_group cg, civicrm_custom_field cf WHERE cf.custom_group_id = cg.id AND cg.is_active = 1 AND cf.is_active = 1 AND cg.extends IN ( 'VolunteerAppeal' )";
+ $dao10 = CRM_Core_DAO::executeQuery($sql_query);
+ // Join all custom field tables with appeal data which are assoicated with VolunteerAppeal.
+ while ($dao10->fetch()) {
+ $table_name = $dao10->table_name;
+ $column_name = $dao10->column_name;
+ $fieldID = $dao10->fieldID;
+ $table_alias = "table_".$fieldID;
+ // Join all custom field tables.
+ $join .= " LEFT JOIN $table_name $table_alias ON appeal.id = $table_alias.entity_id";
+ $select .= ", ".$table_alias.".".$column_name;
+ foreach ($params["advanced_search"]["appealCustomFieldData"] as $key => $field_data) {
+ if(isset($field_data) && !empty($field_data)) {
+ $custom_field_array = explode("_", $key);
+ if(isset($custom_field_array) && isset($custom_field_array[1])) {
+ $custom_field_id = $custom_field_array[1];
+ if($custom_field_id == $fieldID) {
+ // If value is in array then implode with Pipe first and then add in where condition.
+ if(is_array($field_data)) {
+ $field_data_string = implode("|", $field_data);
+ $where .= " AND CONCAT(',', $table_alias.$column_name, ',') REGEXP '$seperator($field_data_string)$seperator'";
+ } else {
+ // Otherwise add with like query.
+ $where .= " AND $table_alias.$column_name Like'%$field_data%'";
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ // Order by Logic.
+ $orderByColumn = "appeal.id";
+ $order = "ASC";
+ if(empty($params["orderby"])) {
+ $params["orderby"] = "upcoming_appeal";
+ $params["order"] = "DESC";
+ }
+ if(!empty($params["orderby"])) {
+ if($params["orderby"] == "project_beneficiary") {
+ $orderByColumn = "cc.display_name";
+ } elseif($params["orderby"] == "upcoming_appeal") {
+ $select .= ", mdt.need_start_time";
+ $join .= " LEFT JOIN (SELECT MIN(start_time) as need_start_time, id, project_id as need_project_id FROM civicrm_volunteer_need as need_sort Where id IS NOT NULL GROUP BY project_id) AS mdt ON (mdt.need_project_id = p.id)";
+ $orderByColumn = "mdt.need_start_time";
+ } else {
+ $orderByColumn = $params["orderby"];
+ }
+ }
+ if(!empty($params["order"])) {
+ $order = $params["order"];
+ }
+ // prepare orderby query.
+ $orderby = " GROUP By appeal.id ".$having." ORDER BY " . $orderByColumn . " " . $order;
+
+ // Pagination Logic.
+ $no_of_records_per_page = 10;//2;
+ if(isset($params['page_no']) && !empty($params['page_no'])) {
+ $page_no = $params['page_no'];
+ } else {
+ $page_no = 1;
+ }
+ $offset = ($page_no-1) * $no_of_records_per_page;
+ $limit = " LIMIT ".$offset.", ".$no_of_records_per_page;
+ $sql = $select . $from . $join . $where . $orderby . $limit;
+ $dao = new CRM_Core_DAO();
+ $dao->query($sql);
+
+ $sql2 = $select . $from . $join . $where . $orderby;
+ $dao2 = new CRM_Core_DAO();
+ $dao2->query($sql2);
+ $total_appeals = count($dao2->fetchAll());
+ $appeals = array();
+ $appeals['appeal'] = array();
+ $appeal = [];
+
+ // Get the global configuration.
+ $config = CRM_Core_Config::singleton();
+ $upload_appeal_main_directory = $config->imageUploadDir.'appeal/main/';
+ $upload_appeal_medium_directory = $config->imageUploadDir.'appeal/medium/';
+ $upload_appeal_thumb_directory = $config->imageUploadDir.'appeal/thumb/';
+ $default_image_name = "appeal-default-logo-sq.png";
+
+ // Prepare appeal details array with proper format.
+ while ($dao->fetch()) {
+ $appeal['id'] = $dao->id;
+ $appeal['project_id'] = $dao->project_id;
+ $appeal['title'] = $dao->title;
+ if($dao->image == "null" || !$dao->image) {
+ // check if the default image exists before we set the image property to it
+ if (file_exists($upload_appeal_main_directory . $default_image_name)
+ && file_exists($upload_appeal_medium_directory . $default_image_name)
+ && file_exists($upload_appeal_thumb_directory . $default_image_name)
+ ) {
+ $fetchedAppeal->image = $default_image_name;
+ } else {
+ $fetchedAppeal->image = null;
+ }
+ }
+ $appeal['image'] = $dao->image;
+ $appeal['appeal_teaser'] = $dao->appeal_teaser;
+ $appeal['appeal_description'] = htmlspecialchars_decode($dao->appeal_description);
+ $appeal['location_done_anywhere'] = $dao->location_done_anywhere;
+ $appeal['is_appeal_active'] = $dao->is_appeal_active;
+ $appeal['active_fromdate'] = $dao->active_fromdate;
+ $appeal['active_todate'] = $dao->active_todate;
+ $appeal['display_volunteer_shift'] = $dao->display_volunteer_shift;
+ $appeal['hide_appeal_volunteer_button'] = $dao->hide_appeal_volunteer_button;
+ $appeal['show_project_information'] = $dao->show_project_information;
+ $appeal['beneficiary_display_name'] = $dao->beneficiary_display_name;
+ $appeal['need_id'] = $dao->need_id;
+ $appeal['need_shift_id'] = $dao->need_shift_id;
+ $appeal['need_flexi_id'] = $dao->need_flexi_id;
+ if($params["orderby"] == "upcoming_appeal") {
+ $appeal['need_start_time'] = $dao->need_start_time;
+ }
+ // Prepare whole address of appeal in array.
+ $address = "";
+ if ($dao->street_address) {
+ $address .= " ".$dao->street_address;
+ }
+ if ($dao->street_address && ($dao->city || $dao->postal_code)) {
+ $address .= '
';
+ }
+ if ($dao->city) {
+ $address .= " ".$dao->city;
+ }
+ if ($dao->city && $dao->postal_code) {
+ $address .= ', '.$dao->postal_code;
+ } else if ($dao->postal_code) {
+ $address .= $dao->postal_code;
+ }
+ $appeal['location'] = $address;
+ $appeals['appeal'][] = $appeal;
+ }
+ $appeals['total_appeal'] = $total_appeals;
+
+ return $appeals;
+ }
+
+}
\ No newline at end of file
diff --git a/CRM/Volunteer/DAO/VolunteerAppeal.php b/CRM/Volunteer/DAO/VolunteerAppeal.php
new file mode 100644
index 00000000..42da815c
--- /dev/null
+++ b/CRM/Volunteer/DAO/VolunteerAppeal.php
@@ -0,0 +1,389 @@
+__table = 'civicrm_volunteer_appeal';
+ parent::__construct();
+ }
+
+ /**
+ * Returns foreign keys and entity references.
+ *
+ * @return array
+ * [CRM_Core_Reference_Interface]
+ */
+ public static function getReferenceColumns() {
+ if (!isset(Civi::$statics[__CLASS__]['links'])) {
+ Civi::$statics[__CLASS__]['links'] = static ::createReferenceColumns(__CLASS__);
+ Civi::$statics[__CLASS__]['links'][] = new CRM_Core_Reference_Basic(self::getTableName(), 'project_id', 'civicrm_volunteer_project', 'id');
+ Civi::$statics[__CLASS__]['links'][] = new CRM_Core_Reference_Basic(self::getTableName() , 'loc_block_id', 'civicrm_loc_block', 'id');
+ CRM_Core_DAO_AllCoreTables::invoke(__CLASS__, 'links_callback', Civi::$statics[__CLASS__]['links']);
+ }
+ return Civi::$statics[__CLASS__]['links'];
+ }
+
+ /**
+ * Returns all the column names of this table
+ *
+ * @return array
+ */
+ public static function &fields() {
+ if (!isset(Civi::$statics[__CLASS__]['fields'])) {
+ Civi::$statics[__CLASS__]['fields'] = [
+ 'id' => [
+ 'name' => 'id',
+ 'type' => CRM_Utils_Type::T_INT,
+ 'title' => ts('CiviVolunteer Appeal ID', array('domain' => 'org.civicrm.volunteer')) ,
+ 'description' => CRM_Volunteer_ExtensionUtil::ts('Unique Volunteer Appeal ID'),
+ 'required' => TRUE,
+ 'table_name' => 'civicrm_volunteer_appeal',
+ 'entity' => 'VolunteerAppeal',
+ 'bao' => 'CRM_Volunteer_DAO_VolunteerAppeal',
+ 'localizable' => 0,
+ ],
+ 'project_id' => [
+ 'name' => 'project_id',
+ 'type' => CRM_Utils_Type::T_INT,
+ 'title' => ts('CiviVolunteer Project ID') ,
+ 'description' => CRM_Volunteer_ExtensionUtil::ts('Foreign key to the Volunteer Project for this record'),
+ 'required' => true,
+ 'table_name' => 'civicrm_volunteer_appeal',
+ 'entity' => 'VolunteerAppeal',
+ 'bao' => 'CRM_Volunteer_DAO_VolunteerAppeal',
+ 'FKClassName' => 'CRM_Volunteer_DAO_Project',
+ 'localizable' => 0,
+ ],
+ 'title' => [
+ 'name' => 'title',
+ 'type' => CRM_Utils_Type::T_STRING,
+ 'title' => CRM_Volunteer_ExtensionUtil::ts('Opportunity Title'),
+ 'description' => CRM_Volunteer_ExtensionUtil::ts('The title of the Volunteer Opportunity'),
+ 'required' => true,
+ 'maxlength' => 255,
+ 'size' => CRM_Utils_Type::HUGE,
+ 'table_name' => 'civicrm_volunteer_appeal',
+ 'entity' => 'VolunteerAppeal',
+ 'bao' => 'CRM_Volunteer_DAO_VolunteerAppeal',
+ 'localizable' => 0,
+ ],
+ 'image' => [
+ 'name' => 'image',
+ 'type' => CRM_Utils_Type::T_STRING,
+ 'title' => CRM_Volunteer_ExtensionUtil::ts('Opportunity Image'),
+ 'description' => CRM_Volunteer_ExtensionUtil::ts('The Image of the Volunteer Opportunity.'),
+ 'maxlength' => 255,
+ 'size' => CRM_Utils_Type::HUGE,
+ 'table_name' => 'civicrm_volunteer_appeal',
+ 'entity' => 'VolunteerAppeal',
+ 'bao' => 'CRM_Volunteer_DAO_VolunteerAppeal',
+ 'localizable' => 0,
+ ],
+ 'appeal_teaser' => [
+ 'name' => 'appeal_teaser',
+ 'type' => CRM_Utils_Type::T_TEXT,
+ 'title' => CRM_Volunteer_ExtensionUtil::ts('Opportunity Teaser'),
+ 'description' => CRM_Volunteer_ExtensionUtil::ts('Opportunity Teaser'),
+ 'required' => false,
+ 'table_name' => 'civicrm_volunteer_appeal',
+ 'entity' => 'VolunteerAppeal',
+ 'bao' => 'CRM_Volunteer_DAO_VolunteerAppeal',
+ 'localizable' => 0,
+ ],
+ 'appeal_description' => [
+ 'name' => 'appeal_description',
+ 'type' => CRM_Utils_Type::T_TEXT,
+ 'title' => CRM_Volunteer_ExtensionUtil::ts('Opportunity Description'),
+ 'description' => CRM_Volunteer_ExtensionUtil::ts('Full description of the Volunteer Appeal. Text and HTML allowed.'),
+ 'required' => false,
+ 'rows' => 8,
+ 'cols' => 60,
+ 'table_name' => 'civicrm_volunteer_appeal',
+ 'entity' => 'VolunteerAppeal',
+ 'bao' => 'CRM_Volunteer_DAO_VolunteerAppeal',
+ 'html' => array(
+ 'type' => 'RichTextEditor',
+ ),
+ 'localizable' => 0,
+ ],
+ 'loc_block_id' => array(
+ 'name' => 'loc_block_id',
+ 'type' => CRM_Utils_Type::T_INT,
+ 'title' => ts('Location Block ID') ,
+ 'description' => 'FK to Location Block ID',
+ 'table_name' => 'civicrm_volunteer_appeal',
+ 'entity' => 'VolunteerAppeal',
+ 'bao' => 'CRM_Volunteer_DAO_VolunteerAppeal',
+ 'FKClassName' => 'CRM_Core_DAO_LocBlock',
+ ),
+ 'location_done_anywhere' => [
+ 'name' => 'location_done_anywhere',
+ 'type' => CRM_Utils_Type::T_INT,
+ 'title' => CRM_Volunteer_ExtensionUtil::ts('Set Location done anywhere parameter for Volunteer Appeal.'),
+ 'description' => CRM_Volunteer_ExtensionUtil::ts('Location Done Anywhere "1" Means Location Done Anywhere True and "0" Means not true.'),
+ 'table_name' => 'civicrm_volunteer_appeal',
+ 'entity' => 'VolunteerAppeal',
+ 'bao' => 'CRM_Volunteer_DAO_VolunteerAppeal',
+ 'localizable' => 0,
+ ],
+ 'is_appeal_active' => [
+ 'name' => 'is_appeal_active',
+ 'type' => CRM_Utils_Type::T_INT,
+ 'title' => CRM_Volunteer_ExtensionUtil::ts('Volunteer Opportunity Active Or Not'),
+ 'description' => CRM_Volunteer_ExtensionUtil::ts('Volunteer Opportunity is Active or not. '),
+ 'table_name' => 'civicrm_volunteer_appeal',
+ 'entity' => 'VolunteerAppeal',
+ 'bao' => 'CRM_Volunteer_DAO_VolunteerAppeal',
+ 'localizable' => 0,
+ ],
+ 'active_fromdate' => [
+ 'name' => 'active_fromdate',
+ 'type' => CRM_Utils_Type::T_DATE,
+ 'title' => CRM_Volunteer_ExtensionUtil::ts('Active From Date for Opportunity'),
+ 'description' => CRM_Volunteer_ExtensionUtil::ts('Active From Date for Opportunity'),
+ 'table_name' => 'civicrm_volunteer_appeal',
+ 'entity' => 'VolunteerAppeal',
+ 'bao' => 'CRM_Volunteer_DAO_VolunteerAppeal',
+ 'localizable' => 0,
+ ],
+ 'active_todate' => [
+ 'name' => 'active_todate',
+ 'type' => CRM_Utils_Type::T_DATE,
+ 'title' => CRM_Volunteer_ExtensionUtil::ts('Active To Date for Opportunity'),
+ 'description' => CRM_Volunteer_ExtensionUtil::ts('Active To Date for Opportunity'),
+ 'table_name' => 'civicrm_volunteer_appeal',
+ 'entity' => 'VolunteerAppeal',
+ 'bao' => 'CRM_Volunteer_DAO_VolunteerAppeal',
+ 'localizable' => 0,
+ ],
+ 'display_volunteer_shift' => [
+ 'name' => 'display_volunteer_shift',
+ 'type' => CRM_Utils_Type::T_INT,
+ 'title' => CRM_Volunteer_ExtensionUtil::ts('Display Volunteer Shift or not.'),
+ 'description' => CRM_Volunteer_ExtensionUtil::ts('Display Volunteer Shift or not.'),
+ 'table_name' => 'civicrm_volunteer_appeal',
+ 'entity' => 'VolunteerAppeal',
+ 'bao' => 'CRM_Volunteer_DAO_VolunteerAppeal',
+ 'localizable' => 0,
+ ],
+ 'hide_appeal_volunteer_button' => [
+ 'name' => 'hide_appeal_volunteer_button',
+ 'type' => CRM_Utils_Type::T_INT,
+ 'title' => CRM_Volunteer_ExtensionUtil::ts('Hide Volunteer Button or not.'),
+ 'description' => CRM_Volunteer_ExtensionUtil::ts('Hide Volunteer Button or not.'),
+ 'table_name' => 'civicrm_volunteer_appeal',
+ 'entity' => 'VolunteerAppeal',
+ 'bao' => 'CRM_Volunteer_DAO_VolunteerAppeal',
+ 'localizable' => 0,
+ ],
+ 'show_project_information' => [
+ 'name' => 'show_project_information',
+ 'type' => CRM_Utils_Type::T_INT,
+ 'title' => CRM_Volunteer_ExtensionUtil::ts('Show Project Information.'),
+ 'description' => CRM_Volunteer_ExtensionUtil::ts('Show Project Information on Opportunity Detail Page.'),
+ 'table_name' => 'civicrm_volunteer_appeal',
+ 'entity' => 'VolunteerAppeal',
+ 'bao' => 'CRM_Volunteer_DAO_VolunteerAppeal',
+ 'localizable' => 0,
+ ],
+ ];
+ CRM_Core_DAO_AllCoreTables::invoke(__CLASS__, 'fields_callback', Civi::$statics[__CLASS__]['fields']);
+ }
+ return Civi::$statics[__CLASS__]['fields'];
+ }
+
+ /**
+ * Return a mapping from field-name to the corresponding key (as used in fields()).
+ *
+ * @return array
+ * Array(string $name => string $uniqueName).
+ */
+ public static function &fieldKeys() {
+ if (!isset(Civi::$statics[__CLASS__]['fieldKeys'])) {
+ Civi::$statics[__CLASS__]['fieldKeys'] = array_flip(CRM_Utils_Array::collect('name', self::fields()));
+ }
+ return Civi::$statics[__CLASS__]['fieldKeys'];
+ }
+
+ /**
+ * Returns the names of this table
+ *
+ * @return string
+ */
+ public static function getTableName() {
+ return self::$_tableName;
+ }
+
+ /**
+ * Returns if this table needs to be logged
+ *
+ * @return bool
+ */
+ public function getLog() {
+ return self::$_log;
+ }
+
+ /**
+ * Returns the list of fields that can be imported
+ *
+ * @param bool $prefix
+ *
+ * @return array
+ */
+ public static function &import($prefix = FALSE) {
+ $r = CRM_Core_DAO_AllCoreTables::getImports(__CLASS__, 'volunteer_appeal', $prefix, []);
+ return $r;
+ }
+
+ /**
+ * Returns the list of fields that can be exported
+ *
+ * @param bool $prefix
+ *
+ * @return array
+ */
+ public static function &export($prefix = FALSE) {
+ $r = CRM_Core_DAO_AllCoreTables::getExports(__CLASS__, 'volunteer_appeal', $prefix, []);
+ return $r;
+ }
+
+ /**
+ * Returns the list of indices
+ *
+ * @param bool $localize
+ *
+ * @return array
+ */
+ public static function indices($localize = TRUE) {
+ $indices = [];
+ return ($localize && !empty($indices)) ? CRM_Core_DAO_AllCoreTables::multilingualize(__CLASS__, $indices) : $indices;
+ }
+
+}
diff --git a/CRM/Volunteer/Permission.php b/CRM/Volunteer/Permission.php
index d216dac6..915fe6c7 100644
--- a/CRM/Volunteer/Permission.php
+++ b/CRM/Volunteer/Permission.php
@@ -1,5 +1,6 @@
installNeedMetaDateFields();
+ // Volunteer Appeal table and relevant DB changes.
+ $this->schemaUpgradeVolunteerAppeal();
+
// uncomment the next line to insert sample data
// $this->executeSqlFile('sql/volunteer_sample.mysql');
}
@@ -885,4 +888,25 @@ public static function checkExtensionDependencies() {
}
return $unmet;
}
-}
+
+ /**
+ * CiviVolunteer 2302 update introduces Volunteer Appeal Functionality.
+ *
+ * @return boolean TRUE on success
+ */
+ public function upgrade_2302() {
+ $this->ctx->log->info('Applying update 2302 - CiviVolunteer Volunteer Appeal Enhancement');
+ $this->schemaUpgradeVolunteerAppeal();
+
+ return TRUE;
+ }
+
+ /**
+ * Volunteer Appeal Functionality Integrated.
+ * Execute sql queries for relevant volunteer appeal functionality.
+ */
+ public function schemaUpgradeVolunteerAppeal() {
+ $this->executeSqlFile('sql/volunteer_upgrade_with_appeal_2.1.sql');
+ }
+
+}
\ No newline at end of file
diff --git a/CRM/Volunteer/Upgrader/Base.php b/CRM/Volunteer/Upgrader/Base.php
index 7aba3c9c..5338d823 100644
--- a/CRM/Volunteer/Upgrader/Base.php
+++ b/CRM/Volunteer/Upgrader/Base.php
@@ -1,6 +1,7 @@
run($xml_file);
return TRUE;
@@ -281,7 +281,7 @@ private function deleteDeprecatedRevision() {
// ******** Hook delegates ********
/**
- * @see https://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_install
+ * @see https://docs.civicrm.org/dev/en/latest/hooks/hook_civicrm_install
*/
public function onInstall() {
$files = glob($this->extensionDir . '/sql/*_install.sql');
@@ -308,7 +308,7 @@ public function onInstall() {
}
/**
- * @see https://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_postInstall
+ * @see https://docs.civicrm.org/dev/en/latest/hooks/hook_civicrm_postInstall
*/
public function onPostInstall() {
$revisions = $this->getRevisions();
@@ -321,7 +321,7 @@ public function onPostInstall() {
}
/**
- * @see https://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_uninstall
+ * @see https://docs.civicrm.org/dev/en/latest/hooks/hook_civicrm_uninstall
*/
public function onUninstall() {
$files = glob($this->extensionDir . '/sql/*_uninstall.mysql.tpl');
@@ -342,7 +342,7 @@ public function onUninstall() {
}
/**
- * @see https://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_enable
+ * @see https://docs.civicrm.org/dev/en/latest/hooks/hook_civicrm_enable
*/
public function onEnable() {
// stub for possible future use
@@ -352,7 +352,7 @@ public function onEnable() {
}
/**
- * @see https://wiki.civicrm.org/confluence/display/CRMDOC/hook_civicrm_disable
+ * @see https://docs.civicrm.org/dev/en/latest/hooks/hook_civicrm_disable
*/
public function onDisable() {
// stub for possible future use
diff --git a/Makefile b/Makefile
new file mode 100644
index 00000000..4b4e2023
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,7 @@
+
+push:
+ gsync -ruvz ./ lce:/var/www/sandbox-volunteer.leadercenter.org/htdocs/sites/default/files/civicrm/ext/org.civicrm.volunteer/
+
+push-utils:
+ gsync -ruvz ./create-custom-fields.php lce:/var/www/sandbox-volunteer.leadercenter.org/htdocs/
+ gsync -ruvz ./volunteer_appeal_seed.php lce:/var/www/sandbox-volunteer.leadercenter.org/htdocs/
diff --git a/ang/volunteer.css b/ang/volunteer.css
index c447ffae..e69609db 100644
--- a/ang/volunteer.css
+++ b/ang/volunteer.css
@@ -151,3 +151,350 @@ span.crm-button-text {
#crm-vol-form-textarea-wrapper {
clear: left;
}
+
+.grid .grid2x2 {
+ min-height: 100%;
+ display: flex;
+ flex-wrap: wrap;
+ flex-direction: row;
+}
+.grid .grid2x2 > div {
+ display: flex;
+ flex-basis: calc(50% - 40px);
+ justify-content: center;
+ flex-direction: column;
+}
+/*.grid .grid2x2 > div > div {
+ display: flex;
+ justify-content: center;
+ flex-direction: row;
+}*/
+
+.grid .box { margin: 20px; }
+
+.grid .w-30{
+ width: 30%;
+}
+.grid .w-70{
+ width: 70%;
+}
+.text-right{
+ text-align: right;
+}
+.text-center{
+ text-align: center;
+}
+.detail-btn {
+ margin-right: 15px;
+ height: 37px;
+ width: 132px;
+}
+.p-l-15{
+ padding-left: 15px;
+}
+.loc{
+ padding-left: 15px;
+ padding-top: 15px;
+}
+.m-t-0{
+ margin-top:0;
+}
+.clearfix{
+ clear: both
+}
+.m-5{
+ margin: 5px;
+}
+.text-limit {
+ width: 400px;
+ overflow: hidden;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+}
+.detail{
+ flex-basis: auto!important;
+}
+
+.beneficiary-details {
+ display: flex;
+ flex-direction: coloumn;
+
+}
+
+.beneficiary-details__image {
+ width: 120px;
+ margin-right: 20px;
+}
+
+.appeal-details__image img,
+.beneficiary-details__image img {
+ max-width: 100%;
+ height: auto;
+}
+
+.beneficiary-details__info-detail {
+ margin-bottom: 20px;
+}
+
+.search-box{position: relative;}
+.search-box i{
+position: absolute;
+top: 50%;
+margin-top: -8px;
+right: 10px;
+opacity: 0.3;
+}
+
+.modalDialog {
+ position: fixed;
+ font-family: Arial, Helvetica, sans-serif;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ background: rgba(82, 79, 79, 0.8);/*rgba(0,0,0,0.8);*/
+ z-index: 99999;
+ opacity:1;
+ -webkit-transition: opacity 400ms ease-in;
+ -moz-transition: opacity 400ms ease-in;
+ transition: opacity 400ms ease-in;
+ pointer-events: auto;
+}
+.modalDialog:target {
+ opacity:1;
+ pointer-events: auto;
+}
+
+.modalDialog > div {
+ max-width: 720px;
+ position: relative;
+ margin: 10% auto;
+ padding: 0px 0px 10px 0px;
+ /*border-radius: 10px;*/
+ border: black solid 1px;
+ background: #fff;
+ overflow: hidden;
+ overflow: auto;
+}
+
+.modal-header {
+ border-bottom: 1px solid #9e9e9e;
+ padding: 0px 20px;
+}
+
+.modal-header button{
+ float: right;
+ margin-top: 5px;
+ margin-right: 3px;
+}
+.modal-header h2{
+ margin-bottom: 10px !important;
+ margin-top: 5px;
+}
+.modalDialog > div input{
+ height: 20px !important;
+}
+
+.modalDialog > div input[type="text"]
+{
+ height: 20px !important;
+ width: 128px;/*pr*/
+}
+
+.filter-model{
+ padding: 15px;
+}
+
+.close {
+ background: #606061;
+ color: #FFFFFF;
+ line-height: 25px;
+ position: absolute;
+ right: -12px;
+ text-align: center;
+ top: -10px;
+ width: 24px;
+ text-decoration: none;
+ font-weight: bold;
+ -webkit-border-radius: 12px;
+ -moz-border-radius: 12px;
+ border-radius: 12px;
+ -moz-box-shadow: 1px 1px 3px #000;
+ -webkit-box-shadow: 1px 1px 3px #000;
+ box-shadow: 1px 1px 3px #000;
+}
+
+.close:hover { background: #00d9ff; }
+
+
+/*For tab*/
+* {box-sizing: border-box}
+body {font-family: "Lato", sans-serif;}
+
+/* Style the tab */
+.tab {
+ float: left;
+ border: 1px solid #ccc;
+ background-color: #f1f1f1;
+ width: 30%;
+ height: 300px;
+ padding: 15px 10px;
+ overflow: auto;
+}
+
+/* Style the buttons inside the tab */
+.tab button {
+ display: block;
+ background-color: inherit;
+ color: black;
+ padding: 14px 14px;
+ width: 100%;
+ border: #989393 solid 1px;/*border: none;*/
+ outline: none;
+ text-align: left;
+ cursor: pointer;
+ transition: 0.3s;
+ font-size: 12px;
+ font-weight: normal;
+ /*font-size: 17px;*/
+}
+
+/* Change background color of buttons on hover */
+.tab button:hover {
+ background-color: #ddd;
+}
+
+/* Create an active/current "tab button" class */
+.tab button.active {
+ background-color: #ccc;
+}
+
+/* Style the tab content */
+.tabcontent {
+ float: left;
+ padding: 15px;
+ border: 1px solid #989393;/*#ccc;*/
+ width: 70%;
+ border-left: none;
+ height: 300px;
+}
+.postal-code-input{
+ width: 124px;
+}
+.posta-code-wrapper select{
+ height: 27px;
+ padding: 0px !important;
+ font-size: 13px !important;
+}
+.posta-code-wrapper {
+ margin-top: 15px;
+}
+.show-opp input[type="checkbox"]{
+ height: unset !important;
+}
+.modal-footer button{
+ float: right;
+ margin-top: 10px;
+}
+.volunteer_appeal_result_count_message {
+ margin-right: 10px;
+ margin-left: 14px;
+ display: inline-block;
+}
+.manage_appeal_form .display_volunteer_note {
+ margin-left: 10px;
+ font-size: 0.8em;
+ font-weight: normal;
+ white-space: normal;
+ color: #696969;
+}
+.manage_appeal_form .location_done_anywhere {
+ margin-left: 30px;
+}
+.custom_fieldset_link .custom-fieldset-text {
+ color: #fff;
+ text-decoration: none;
+ margin-left: 5px;
+}
+.custom_fieldset_link {
+ display: inline-block;
+ width: 15%;
+ text-align: center;
+ margin-left: 10px !important;
+}
+.custom_fieldgroup_dropdown {
+ display: inline-block;
+ height: 30px;
+ margin-left: 14px;
+ font-size: 14px !important;
+ padding: 2px !important;
+ cursor: pointer;
+}
+.crm-button-remove-custom-group {
+ float: right;
+ margin-right: 20px;
+}
+
+.sortorder:after {
+ content: '\25b2'; /* BLACK UP-POINTING TRIANGLE */
+}
+.sortorder.reverse:after {
+ content: '\25bc'; /* BLACK DOWN-POINTING TRIANGLE */
+}
+
+.sortorder.reverseExpiredTable:after {
+ content: '\25bc'; /* BLACK DOWN-POINTING TRIANGLE */
+}
+.delete_appeal, .edit_appeal {
+ cursor: pointer;
+}
+.custom_fieldset_selector .custom_hr {
+ border: 1px lightgrey;
+ margin: 20px;
+}
+.grid_active {
+ background: #878484;
+ border: 1px solid #878484;
+}
+.advance_filter_wrapper {
+ display: inline-block;
+}
+
+.advance_filter_footer {
+ position: absolute;
+ bottom: 0;
+ right: 0;
+ background: #fff;
+ left: 0;
+ box-shadow: 4px -1px 6px 0px rgba(0, 0, 0, 0.3);
+ padding: 5px 15px 15px 10px;
+}
+.advance_filter_body {
+ height: 420px;
+}
+.custom_fied_content {
+ overflow: auto;
+}
+.reset_filter {
+ display: inline-block;
+}
+#select2-drop {
+ z-index: 99999;
+}
+.active_filters {
+ font-size: 16px;
+ margin-bottom: 10px;
+ border: 1px solid #d3d3d3;
+ padding: 5px;
+ border-radius: 4px;
+}
+.active_filter_content {
+ margin-top: 10px;
+}
+.active_filter_heading {
+ text-decoration: underline;
+ font-size: 18px;
+}
+.filter_data {
+ margin-bottom: 4px;
+}
\ No newline at end of file
diff --git a/ang/volunteer.js b/ang/volunteer.js
index 8f8ff5be..9b8ef168 100644
--- a/ang/volunteer.js
+++ b/ang/volunteer.js
@@ -28,6 +28,21 @@
CRM.$('#crm-main-content-wrapper').block();
})
+ .filter('plainText', function() {
+ return function(textish) {
+ return angular.element(textish).text();
+ };
+ })
+ .filter('textShortenerFilter', function() {
+ return function(text, length) {
+ if (text.length > length) {
+ text = text ? String(text).replace(/<[^>]+>/gm, '') : '';
+ return text.substr(0, length) + "...";
+ }
+ return text;
+ }
+ })
+
.factory('volOppSearch', ['crmApi', '$location', '$route', function(crmApi, $location, $route) {
//Search params and results are stored here and assigned by reference to the form
var volOppSearch = {};
@@ -165,6 +180,100 @@
})
+ // Example:
{{beneficiary.email}}
+{{ appeal.appeal_teaser }}
+ +{{ts("Image")}} | +{{ts("Title")}} | +{{ts("Beneficiaries")}} | +{{ts("Description")}} | +{{ts("Location")}} | +{{ts("SignUp")}} | +
---|---|---|---|---|---|
+ + | ++ {{ appeal.title }} + | ++ {{appeal.beneficiary_display_name}} + | +
+ {{ appeal.appeal_teaser }} + + |
+ + + | ++ + + | +
{{ts("Title")}} + + | +{{ts("Start")}} + + | +{{ts("End")}} + + | +{{ts("Enabled")}} | +{{ts("Action")}} | +
---|---|---|---|---|
+ {{ appeal.title }} + | ++ {{ appeal.active_fromdate }} + | ++ {{ appeal.active_todate }} + | ++ + | ++ View + Edit + Delete + | +
Thank you.
+ + + +