From 9b4c33c3913c75ee424262a077c4bc2e445381a9 Mon Sep 17 00:00:00 2001 From: praneettekdi Date: Fri, 15 Jan 2021 16:09:39 +0530 Subject: [PATCH 01/25] Merge Release 1.0.3 into Master (#87) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Task #165254 chore: Native Add to linkedin Button - Linkdin Education Profile certificate upload/share (#69) * Bug #164674 fix: search box for cert-xxxx is showing error (#48) * Bug #164625 fix: title is showing blank data, it should display course name (#49) * Bug #164705 fix: click on the social media post the back button on the certificate is of no use (#52) * Bug #164705 fix: click on the social media post :: the back button on the certificate is of no use * Bug #164705 fix: Resolve comment * Bug #164707 fix: user able to download others certificate as well (#53) * Bug #164707 fix: user able to download others certificate as well * Bug #164707 fix: Resolve comments * Bug #164707 fix: Resolve comments * Bug #164707 fix: Resolve comment * Task #164910 chore: Button to copy shareble certificate link (#51) * Task #164910 chore: Button to copy shareble certificate link * Task #164910 chore: Button to copy shareble certificate link * Task #164910 chore: Button to copy shareble certificate link * Task #164910 chore: Resolve comment * Task #164910 chore: Resolve comments * Task #164910 chore: Resolve comments * Task #164910 chore: Resolve comments * Task #164910 chore: Resolve comments * Task #163318 fix: Fixed image cut issue while image generation (#54) * Issue #164867 style: desing changes update (#50) Co-authored-by: “Mangesh <“mangesh_m@tekditechonologies.com”> * Task #163318 fix: Added fixed width height for certificate container (#58) * Bug165031 : Backend > Attendees > Error '0 Call to a member function getDownloadUrl() on string' occurs on checkin the attendee (#62) Co-authored-by: Snehal Patil * Task #165230 Chore: Back end>>Issued Certificate >> Search should also be done by username. (#59) * Task #165122 Chore: Backend certificate view changes- Adding Course co… (#55) * Task #165122 Chore: Backend certificate view changes- Adding Curse column at Issued certificate View * Changing title of column * Resolving conflicts * Task #165122 Chore: Backend Issued certificate view changes- Adding attendee… (#56) * Task #165122 Chore: Backend certificate view changes- Adding attendee name to the user column * Changing title of column User * Resolving phpcs issue * Resolving conflicts * Task #165166 Chore: Add Certificate Url column under Issued Certificate View (#57) * Task #165166 Chore: Add Copy Url column under Issued Cetificate VIew * Resolving conflicts * Resolving comments * Resolving comments * Resolving comments * Task #165166 Feat: Adding (#63) * Bug165031 : Backend > Attendees > Error '0 Call to a member function … (#64) * Bug165031 : Backend > Attendees > Error '0 Call to a member function … * Bug165031 : Backend > Attendees > Error '0 Call to a member function … Co-authored-by: Snehal Patil * Task #165259 Chore: Adding proper names to the client filter and column in Issue… (#66) * Task #165259 Chore: Adding proper names to the client filter in Issued Certificate view * Adding names to client column * Task #165259 Chore: Renaming Unique Certificate Id column name to Certificate Id at both end (#67) * Task #165259 Chore: Reordering columns of Issues Certificate View (#68) * Task #165254 chore: Native Add to linkedin Button - Linkdin Education Profile certificate upload/share * Task #165254 chore: Native Add to linkedin Button - Linkdin Education Profile certificate upload/share * Task #165254 chore: Resolve comments * Task #165254 chore: update download permission code * Task #165254 chore: Resolve comments * Task #165254 chore: Remove images Co-authored-by: praneettekdi Co-authored-by: Mangesh Mane Co-authored-by: “Mangesh <“mangesh_m@tekditechonologies.com”> Co-authored-by: snehal patil Co-authored-by: Snehal Patil Co-authored-by: divyachaudhari <58217051+divyachaudhari@users.noreply.github.com> * Bug #164674 fix: search box for cert-xxxx is showing error (#73) * Bug #164674 fix: search box for cert-xxxx is showing error * Bug #164674 fix: Resolve comments * Bug #164674 fix: Resolve commenys * Task #165166 Chore: Adding SEF url to the certificate copy Url functi… (#72) * Bug #164674 fix: search box for cert-xxxx is showing error (#48) * Bug #164625 fix: title is showing blank data, it should display course name (#49) * Bug #164705 fix: click on the social media post the back button on the certificate is of no use (#52) * Bug #164705 fix: click on the social media post :: the back button on the certificate is of no use * Bug #164705 fix: Resolve comment * Bug #164707 fix: user able to download others certificate as well (#53) * Bug #164707 fix: user able to download others certificate as well * Bug #164707 fix: Resolve comments * Bug #164707 fix: Resolve comments * Bug #164707 fix: Resolve comment * Task #164910 chore: Button to copy shareble certificate link (#51) * Task #164910 chore: Button to copy shareble certificate link * Task #164910 chore: Button to copy shareble certificate link * Task #164910 chore: Button to copy shareble certificate link * Task #164910 chore: Resolve comment * Task #164910 chore: Resolve comments * Task #164910 chore: Resolve comments * Task #164910 chore: Resolve comments * Task #164910 chore: Resolve comments * Task #163318 fix: Fixed image cut issue while image generation (#54) * Issue #164867 style: desing changes update (#50) Co-authored-by: “Mangesh <“mangesh_m@tekditechonologies.com”> * Task #163318 fix: Added fixed width height for certificate container (#58) * Bug165031 : Backend > Attendees > Error '0 Call to a member function getDownloadUrl() on string' occurs on checkin the attendee (#62) Co-authored-by: Snehal Patil * Task #165230 Chore: Back end>>Issued Certificate >> Search should also be done by username. (#59) * Task #165122 Chore: Backend certificate view changes- Adding Course co… (#55) * Task #165122 Chore: Backend certificate view changes- Adding Curse column at Issued certificate View * Changing title of column * Resolving conflicts * Task #165122 Chore: Backend Issued certificate view changes- Adding attendee… (#56) * Task #165122 Chore: Backend certificate view changes- Adding attendee name to the user column * Changing title of column User * Resolving phpcs issue * Resolving conflicts * Task #165166 Chore: Add Certificate Url column under Issued Certificate View (#57) * Task #165166 Chore: Add Copy Url column under Issued Cetificate VIew * Resolving conflicts * Resolving comments * Resolving comments * Resolving comments * Task #165166 Feat: Adding (#63) * Bug165031 : Backend > Attendees > Error '0 Call to a member function … (#64) * Bug165031 : Backend > Attendees > Error '0 Call to a member function … * Bug165031 : Backend > Attendees > Error '0 Call to a member function … Co-authored-by: Snehal Patil * Task #165259 Chore: Adding proper names to the client filter and column in Issue… (#66) * Task #165259 Chore: Adding proper names to the client filter in Issued Certificate view * Adding names to client column * Task #165259 Chore: Renaming Unique Certificate Id column name to Certificate Id at both end (#67) * Task #165166 Chore: Adding SEF url to the certificate copy Url functioning * Changing the routing of getUrl() * Changing the routing of getUrl() * Changing the routing of getUrl() Co-authored-by: Tushar Shekokar Co-authored-by: praneettekdi Co-authored-by: Mangesh Mane Co-authored-by: “Mangesh <“mangesh_m@tekditechonologies.com”> Co-authored-by: snehal patil Co-authored-by: Snehal Patil * Task #165166 Chore: Adding SEF url to the certificate copy Url functioning (#74) * Bug #163318 fix: Fixed image generation issue in smaller devices (#75) * Issue #166260 fix: Render default template issue when a different editor is used other than tinyMCE & CodeMirror (#78) * Merge Release 1.0.4 into Release 1.0.3 (#79) * Task #165032 chore: Changes in TjCertificate Issued Certificate list view to allow admin to edit Issued Certificates (#76) * Task #165032 chore: Changes in TjCertificate Issued Certificate list view to allow admin to edit Issued Certificate * Task #165032 chore: Changes in TjCertificate Issued Certificate list view to allow admin to edit Issued Certificates * Task #165032 chore: Backend list view changes * Task #165032 chore: Resolve comments * Task #165032 chore: Resolve comments * Task #165032 chore: Resolve comments * Task #165032 chore: Resolve comments * Feature #165030 chore: Changes for certificate re-generate feature (#77) * Feature #165030 chore: Changes for certificate re-generate feature * Feature #165030 chore: Resolve comments * Task #166208 chore: Tj certificate list view changes * Feature #165030 chore: Delete certificate image * Feature #165030 chore: Changes for certificate re-generate feature * Update view.html.php Co-authored-by: Tushar Shekokar * Task #165032 chore: Resolve conflicts and update folder in xml (#80) * Task #165032 chore: Changes in TjCertificate Issued Certificate list view to allow admin to edit Issued Certificates (#76) * Task #165032 chore: Changes in TjCertificate Issued Certificate list view to allow admin to edit Issued Certificate * Task #165032 chore: Changes in TjCertificate Issued Certificate list view to allow admin to edit Issued Certificates * Task #165032 chore: Backend list view changes * Task #165032 chore: Resolve comments * Task #165032 chore: Resolve comments * Task #165032 chore: Resolve comments * Task #165032 chore: Resolve comments * Feature #165030 chore: Changes for certificate re-generate feature (#77) * Feature #165030 chore: Changes for certificate re-generate feature * Feature #165030 chore: Resolve comments * Task #166208 chore: Tj certificate list view changes * Feature #165030 chore: Delete certificate image * Feature #165030 chore: Changes for certificate re-generate feature * Update view.html.php * Task #165032 chore: Resolve conflicts * Task #165032 chore: Add version in XML * Task #165032 chore: Resolve comments * Task #165032 chore: Resolve scrutinizer issue Co-authored-by: praneettekdi * Issue #166434 task: Server side certificate image generation using Imagick (#81) * Issue #166434 task: Server side certificate image generation using Imagick * Issue #166434 task: Server side certificate image generation using Imagick * Issue #166434 task: Server side certificate image generation using Imagick * Issue #166434 task: Server side certificate image generation using Imagick * Issue #166434 task: Server side certificate image generation using Imagick * Issue #166434 task: Server side certificate image generation using Imagick * Issue #166434 task: Server side certificate image generation using Imagick * Update default.php Make sure Canvas image generation works even if the global config values are not saved * Feature #166428 chore: Add external record and integrate tjnotification (#82) * Feature #166428 chore: Add external record and integrate tjnotification * Feature #166428 chore: Resolve comments * Feature #166428 chore: Resolve comments * Feature #166428 chore: Resolve comments * Feature #166428 chore: Resolve comments * Feature #166428 chore: Resolve comments * Feature #166428 chore: Resolve comments * Feature #166428 chore: Resolve comments * Feature #166428 chore: Resolve comments * Feature #166428 chore: Resolve comments * Feature #166428 chore: Resolve comments * Feature #166428 chore: Update file and class name * Feature #166428 chore: Resolve comments * Feature #166428 chore: Resolve comments * Feature #166428 chore: Backend functionality for add training records * Feature #166428 chore: Backend functionality for add training records * Feature #166428 chore: Backend functionality for add training records * Feature #166428 chore: Backend functionality for add training records * Feature #166428 chore: Resolve comments * Feature #166428 chore: Resolve comments * Feature #166428 chore: Update sql file version * Feature #166428 chore: Update js * Feature #166428 chore: Update js * Feature #166428 chore: Update changes after UT (#83) * Feature #166428 chore: Add external record and integrate tjnotification * Feature #166428 chore: Resolve comments * Feature #166428 chore: Resolve comments * Feature #166428 chore: Resolve comments * Feature #166428 chore: Resolve comments * Feature #166428 chore: Resolve comments * Feature #166428 chore: Resolve comments * Feature #166428 chore: Resolve comments * Feature #166428 chore: Resolve comments * Feature #166428 chore: Resolve comments * Feature #166428 chore: Resolve comments * Feature #166428 chore: Update file and class name * Feature #166428 chore: Resolve comments * Feature #166428 chore: Resolve comments * Feature #166428 chore: Backend functionality for add training records * Feature #166428 chore: Backend functionality for add training records * Feature #166428 chore: Backend functionality for add training records * Feature #166428 chore: Backend functionality for add training records * Feature #166428 chore: Resolve comments * Feature #166428 chore: Resolve comments * Feature #166428 chore: Update sql file version * Feature #166428 chore: Update js * Feature #166428 chore: Update js * Feature #166428 chore: Update changes after UT * Feature #166428 chore: Load fontawesome css on init * Feature #166428 chore :Fix Bug #167401 and Bug #167402 (#84) * Bug #167400 fix: Redirect on list view on after action 'Save & Close' in backend (#85) * Feature #166428 chore :Fix Bug #167401 and Bug #167402 * Bug #167400 fix: Redirect on list view on after action 'Save & Close' in backend * Bug #167400 fix: Resolve comment Co-authored-by: Tushar Shekokar Co-authored-by: Mangesh Mane Co-authored-by: “Mangesh <“mangesh_m@tekditechonologies.com”> Co-authored-by: snehal patil Co-authored-by: Snehal Patil Co-authored-by: divyachaudhari <58217051+divyachaudhari@users.noreply.github.com> --- .../administrator/access.xml | 3 + .../administrator/config.xml | 39 ++- .../administrator/controllers/certificate.php | 104 ++++++- .../controllers/certificates.php | 45 +++ .../controllers/template.json.php | 32 ++ .../controllers/trainingrecord.json.php | 154 ++++++++++ .../controllers/trainingrecord.php | 242 +++++++++++++++ .../administrator/includes/tjcertificate.php | 48 +++ .../en-GB/en-GB.com_tjcertificate.ini | 96 +++++- .../en-GB/en-GB.com_tjcertificate.sys.ini | 3 + .../administrator/layouts/preview.php | 39 +++ .../administrator/libraries/certificate.php | 262 ++++++++++++++-- .../administrator/libraries/language.php | 38 +++ .../administrator/libraries/mails.php | 175 +++++++++++ .../administrator/models/certificate.php | 131 ++++++++ .../administrator/models/certificates.php | 7 +- .../models/fields/certificatetemplates.php | 11 +- .../models/forms/certificate.xml | 8 +- .../models/forms/filter_certificates.xml | 15 +- .../models/forms/filter_templates.xml | 9 +- .../models/forms/trainingrecord.xml | 131 ++++++++ .../administrator/models/trainingrecord.php | 290 ++++++++++++++++++ .../administrator/sql/install.mysql.utf8.sql | 42 +++ .../administrator/sql/updates/mysql/1.0.3.sql | 42 +++ .../administrator/tjcertificate.php | 1 + .../administrator/tjcertificateTemplate.json | 158 ++++++++++ .../views/certificate/tmpl/edit.php | 43 ++- .../views/certificate/view.html.php | 29 +- .../views/certificates/tmpl/default.php | 76 +++-- .../views/certificates/view.html.php | 8 +- .../views/template/tmpl/edit.php | 32 +- .../views/templates/tmpl/default.php | 10 +- .../views/trainingrecord/index.html | 0 .../views/trainingrecord/tmpl/edit.php | 111 +++++++ .../views/trainingrecord/tmpl/index.html | 0 .../views/trainingrecord/tmpl/preview.php | 95 ++++++ .../views/trainingrecord/view.html.php | 182 +++++++++++ .../media/images/buttons/en_US.png | Bin 0 -> 139290 bytes .../com_tjcertificate/media/js/certificate.js | 165 ++++++++++ .../media/js/certificate.min.js | 1 + .../media/js/certificateImage.js | 14 + .../media/js/certificateImage.min.js | 2 +- .../com_tjcertificate/media/js/template.js | 60 ++-- .../media/js/template.min.js | 2 +- .../media/js/tjCertificateService.js | 22 +- .../media/js/tjCertificateService.min.js | 2 +- .../script.tjcertificate.php | 33 ++ .../site/controllers/certificates.php | 106 +++++++ .../site/controllers/trainingrecord.json.php | 15 + .../site/controllers/trainingrecord.php | 14 + .../com_tjcertificate/site/events/record.php | 89 ++++++ .../en-GB/en-GB.com_tjcertificate.ini | 53 ++++ .../site/models/fields/createdby.php | 57 ++++ .../site/models/fields/getclientlist.php | 17 +- .../site/models/fields/users.php | 73 +++++ .../site/models/forms/filter_certificates.xml | 24 ++ .../site/models/forms/trainingrecord.xml | 136 ++++++++ .../site/models/trainingrecord.php | 14 + .../com_tjcertificate/site/tjcertificate.php | 1 + .../site/views/certificate/tmpl/default.php | 44 +-- .../tmpl/default_social_sharing.php | 7 + .../site/views/certificate/view.html.php | 59 ++-- .../site/views/certificates/tmpl/my.php | 108 ++++++- .../site/views/certificates/view.html.php | 28 +- .../site/views/trainingrecord/index.html | 0 .../views/trainingrecord/tmpl/default.php | 102 ++++++ .../site/views/trainingrecord/tmpl/edit.php | 117 +++++++ .../site/views/trainingrecord/tmpl/edit.xml | 8 + .../site/views/trainingrecord/view.html.php | 93 ++++++ .../com_tjcertificate/tjcertificate.xml | 8 +- 70 files changed, 3993 insertions(+), 192 deletions(-) create mode 100644 src/components/com_tjcertificate/administrator/controllers/trainingrecord.json.php create mode 100644 src/components/com_tjcertificate/administrator/controllers/trainingrecord.php create mode 100644 src/components/com_tjcertificate/administrator/layouts/preview.php create mode 100644 src/components/com_tjcertificate/administrator/libraries/language.php create mode 100644 src/components/com_tjcertificate/administrator/libraries/mails.php create mode 100644 src/components/com_tjcertificate/administrator/models/forms/trainingrecord.xml create mode 100644 src/components/com_tjcertificate/administrator/models/trainingrecord.php create mode 100644 src/components/com_tjcertificate/administrator/sql/updates/mysql/1.0.3.sql create mode 100644 src/components/com_tjcertificate/administrator/tjcertificateTemplate.json create mode 100644 src/components/com_tjcertificate/administrator/views/trainingrecord/index.html create mode 100644 src/components/com_tjcertificate/administrator/views/trainingrecord/tmpl/edit.php create mode 100644 src/components/com_tjcertificate/administrator/views/trainingrecord/tmpl/index.html create mode 100644 src/components/com_tjcertificate/administrator/views/trainingrecord/tmpl/preview.php create mode 100644 src/components/com_tjcertificate/administrator/views/trainingrecord/view.html.php create mode 100644 src/components/com_tjcertificate/media/images/buttons/en_US.png create mode 100644 src/components/com_tjcertificate/media/js/certificate.js create mode 100644 src/components/com_tjcertificate/media/js/certificate.min.js create mode 100644 src/components/com_tjcertificate/site/controllers/certificates.php create mode 100644 src/components/com_tjcertificate/site/controllers/trainingrecord.json.php create mode 100644 src/components/com_tjcertificate/site/controllers/trainingrecord.php create mode 100644 src/components/com_tjcertificate/site/events/record.php create mode 100644 src/components/com_tjcertificate/site/models/fields/createdby.php create mode 100644 src/components/com_tjcertificate/site/models/fields/users.php create mode 100644 src/components/com_tjcertificate/site/models/forms/trainingrecord.xml create mode 100644 src/components/com_tjcertificate/site/models/trainingrecord.php create mode 100644 src/components/com_tjcertificate/site/views/trainingrecord/index.html create mode 100644 src/components/com_tjcertificate/site/views/trainingrecord/tmpl/default.php create mode 100644 src/components/com_tjcertificate/site/views/trainingrecord/tmpl/edit.php create mode 100644 src/components/com_tjcertificate/site/views/trainingrecord/tmpl/edit.xml create mode 100644 src/components/com_tjcertificate/site/views/trainingrecord/view.html.php diff --git a/src/components/com_tjcertificate/administrator/access.xml b/src/components/com_tjcertificate/administrator/access.xml index 944f9715..d6adfd02 100644 --- a/src/components/com_tjcertificate/administrator/access.xml +++ b/src/components/com_tjcertificate/administrator/access.xml @@ -12,5 +12,8 @@ + + + diff --git a/src/components/com_tjcertificate/administrator/config.xml b/src/components/com_tjcertificate/administrator/config.xml index fafde553..028b934d 100644 --- a/src/components/com_tjcertificate/administrator/config.xml +++ b/src/components/com_tjcertificate/administrator/config.xml @@ -37,7 +37,19 @@ - + + + + + + + + + + + +
@@ -50,7 +62,15 @@ - + + + + + + + + +
+ +
+ + +
+ +
+ + + + + + +
+
diff --git a/src/components/com_tjcertificate/administrator/controllers/certificate.php b/src/components/com_tjcertificate/administrator/controllers/certificate.php index 337faeb7..8c2414ba 100644 --- a/src/components/com_tjcertificate/administrator/controllers/certificate.php +++ b/src/components/com_tjcertificate/administrator/controllers/certificate.php @@ -24,6 +24,48 @@ */ class TjCertificateControllerCertificate extends FormController { + /** + * The client for which the templates are being created. + * + * @var string + * @since __DEPLOY_VERSION__ + */ + protected $client; + + /** + * The extension for which the templates are being created. + * + * @var string + * @since __DEPLOY_VERSION__ + */ + protected $extension; + + /** + * Constructor. + * + * @param array $config An optional associative array of configuration settings. + * + * @since __DEPLOY_VERSION__ + * @see JControllerLegacy + */ + public function __construct($config = array()) + { + parent::__construct($config); + + $app = Factory::getApplication(); + $jinput = $app->input; + + if (empty($this->extension)) + { + $this->extension = $jinput->get('extension', ''); + } + + if (empty($this->client)) + { + $this->client = $jinput->get('client', ''); + } + } + /** * Method to download issued certificate. * @@ -48,15 +90,22 @@ public function download() $certificate = TJCERT::Certificate(); + $certificateObj = $certificate::validateCertificate($uniqueCertificateId); + + // If $uniqueCertificateId is not valid then object is empty so need to handle error (CALL TO A MEMBER FUNCTION CANDOWNLOAD() ON BOOLEAN) + if (!$certificateObj->id) + { + $app->enqueueMessage(Text::_('JERROR_AN_ERROR_HAS_OCCURRED'), 'error'); + $app->redirect('index.php'); + } + // Check user having permission to download - if (!$certificate::canDownload($uniqueCertificateId)) + if (!$certificateObj->canDownload()) { $app->enqueueMessage(Text::_('JERROR_ALERTNOAUTHOR')); $app->redirect('index.php'); } - $certificateObj = $certificate::validateCertificate($uniqueCertificateId); - if (!$certificateObj->id) { $app->enqueueMessage(Text::_('COM_TJCERTIFICATE_ERROR_CERTIFICATE_EXPIRED'), 'error'); @@ -101,4 +150,53 @@ public function uploadCertificate() jexit(); } + + /** + * Gets the URL arguments to append to an item redirect. + * + * @param integer $recordId The primary key id for the item. + * @param string $urlVar The name of the URL variable for the id. + * + * @return string The arguments to append to the redirect URL. + * + * @since __DEPLOY_VERSION__ + */ + protected function getRedirectToItemAppend($recordId = null, $urlVar = 'id') + { + $append = parent::getRedirectToItemAppend($recordId); + + if (!empty ($this->extension)) + { + $append .= '&extension=' . $this->extension; + } + elseif (!empty ($this->client)) + { + $append .= '&client=' . $this->client; + } + + return $append; + } + + /** + * Gets the URL arguments to append to a list redirect. + * + * @return string The arguments to append to the redirect URL. + * + * @since __DEPLOY_VERSION__ + */ + protected function getRedirectToListAppend() + { + $append = parent::getRedirectToListAppend(); + + if (!empty ($this->extension)) + { + $append .= '&extension=' . $this->extension; + } + elseif (!empty ($this->client)) + { + $append .= '&client=' . $this->client; + } + + return $append; + } } diff --git a/src/components/com_tjcertificate/administrator/controllers/certificates.php b/src/components/com_tjcertificate/administrator/controllers/certificates.php index 6fc7e820..72fea524 100644 --- a/src/components/com_tjcertificate/administrator/controllers/certificates.php +++ b/src/components/com_tjcertificate/administrator/controllers/certificates.php @@ -12,6 +12,9 @@ defined('_JEXEC') or die('Restricted access'); use Joomla\CMS\MVC\Controller\AdminController; +use Joomla\Utilities\ArrayHelper; +use Joomla\CMS\Language\Text; +use Joomla\CMS\Router\Route; /** * Certificate list controller class. @@ -34,4 +37,46 @@ public function getModel($name = 'Certificate', $prefix = 'TjCertificateModel') { return parent::getModel($name, $prefix, array('ignore_request' => true)); } + + /** + * Method to remove a record. + * + * @return void + * + * @since __DEPLOY_VERSION__ + */ + public function delete() + { + $this->checkToken(); + + // Get items to remove from the request. + $cid = $this->input->get('cid', array(), 'array'); + + $extension = $this->input->getCmd('extension', null); + + if (!is_array($cid) || count($cid) < 1) + { + JError::raiseWarning(500, Text::_($this->text_prefix . '_NO_ITEM_SELECTED')); + } + else + { + // Get the model. + $model = $this->getModel(); + + // Make sure the item ids are integers + $cid = ArrayHelper::toInteger($cid); + + // Remove the items. + if ($model->delete($cid)) + { + $this->setMessage(Text::plural($this->text_prefix . '_N_ITEMS_DELETED', count($cid))); + } + else + { + $this->setMessage($model->getError()); + } + } + + $this->setRedirect(Route::_('index.php?option=com_tjcertificate&view=certificates', false)); + } } diff --git a/src/components/com_tjcertificate/administrator/controllers/template.json.php b/src/components/com_tjcertificate/administrator/controllers/template.json.php index 35ba7285..ff9c66d5 100644 --- a/src/components/com_tjcertificate/administrator/controllers/template.json.php +++ b/src/components/com_tjcertificate/administrator/controllers/template.json.php @@ -14,6 +14,8 @@ use Joomla\CMS\MVC\Controller\FormController; use Joomla\CMS\Factory; use Joomla\CMS\Language\Text; +use Joomla\CMS\Response\JsonResponse; +use Joomla\CMS\Session\Session; jimport('joomla.filesystem.folder'); @@ -84,4 +86,34 @@ public function loadDefaultTemplate() echo new JResponseJson($templateData); } } + + /** + * Function to load custom template + * + * @return object|void object + */ + public function loadCustomTemplate() + { + if (!Session::checkToken('get')) + { + echo new JsonResponse(null, Text::_('JINVALID_TOKEN'), true); + } + else + { + $app = Factory::getApplication(); + $input = $app->input; + $templateId = $input->get('templateId'); + + if (empty($templateId)) + { + echo new JsonResponse(null, Text::_('COM_TJCERTIFICATE_ERROR_SOMETHING_WENT_WRONG'), true); + + return; + } + + $tjCertificateTemplate = TJCERT::Template($templateId); + + echo new JsonResponse($tjCertificateTemplate->body); + } + } } diff --git a/src/components/com_tjcertificate/administrator/controllers/trainingrecord.json.php b/src/components/com_tjcertificate/administrator/controllers/trainingrecord.json.php new file mode 100644 index 00000000..23d4353c --- /dev/null +++ b/src/components/com_tjcertificate/administrator/controllers/trainingrecord.json.php @@ -0,0 +1,154 @@ + + * @copyright Copyright (C) 2009 - 2020 Techjoomla. All rights reserved. + * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL + */ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\Factory; +use Joomla\CMS\Language\Text; +use Joomla\Registry\Registry; +use Joomla\Utilities\ArrayHelper; +use Joomla\CMS\MVC\Controller\FormController; +use Joomla\CMS\Filesystem\Folder; +use Joomla\CMS\Filesystem\File; +use Joomla\CMS\Component\ComponentHelper; +use Joomla\CMS\Session\Session; +use Joomla\CMS\Router\Route; +use Joomla\CMS\Response\JsonResponse; +use Joomla\CMS\Table\Table; + +JLoader::import("/techjoomla/media/storage/local", JPATH_LIBRARIES); + +/** + * The Tj Certificate Training Record controller + * + * @since __DEPLOY_VERSION__ + */ +class TjCertificateControllerTrainingRecord extends FormController +{ + /** + * Function to delete the record attachment + * + * @return void + * + * @since __DEPLOY_VERSION__ + */ + public function deleteAttachment() + { + $app = Factory::getApplication(); + + if (!Session::checkToken()) + { + $app->enqueueMessage(Text::_('JINVALID_TOKEN'), 'error'); + echo new JsonResponse(null, null, true); + $app->close(); + } + + // Get the current user id + $user = Factory::getuser(); + + if (!$user->id) + { + return false; + } + + $clientId = $app->input->get('certificateId', 0, 'INT'); + $mediaId = $app->input->get('mediaId', 0, 'INT'); + + if (!$mediaId && !$clientId) + { + echo new JsonResponse(null, Text::_("JERROR_ALERTNOAUTHOR"), true); + $app->close(); + } + + $model = $this->getModel(); + $mediaPath = TJCERT::getMediaPath(); + $client = TJCERT::getClient(); + $result = $model->deleteMedia($mediaId, $mediaPath, $client, $clientId); + + if ($result) + { + echo new JResponseJson($result, Text::_('COM_TJCERTIFICATE_ATTACHMENT_DELETED_SUCCESSFULLY'), false); + $app->close(); + } + else + { + echo new JResponseJson(null, Text::_('COM_TJCERTIFICATE_ATTACHMENT_DELETED_FAILED'), true); + $app->close(); + } + } + + /** + * Method to delete the record from frontend. + * + * @return void|boolean + * + * @since __DEPLOY_VERSION__ + */ + public function delete() + { + $app = Factory::getApplication(); + + if (!Session::checkToken()) + { + $app->enqueueMessage(Text::_('JINVALID_TOKEN'), 'error'); + echo new JsonResponse(null, null, true); + $app->close(); + } + + $user = Factory::getUser(); + $mediaPath = TJCERT::getMediaPath(); + $client = TJCERT::getClient(); + $certificateId = $app->input->getInt('certificateId'); + $manageOwn = $user->authorise('certificate.external.manageown', $client); + $manage = $user->authorise('certificate.external.manage', $client); + + // If manageOwn permission then check record owner can only deleting own record + if ($manageOwn && !$manage) + { + $table = TJCERT::table("certificates"); + $table->load(array('id' => (int) $certificateId, 'user_id' => $user->id)); + + if (!$table->id) + { + echo new JsonResponse(null, Text::_('COM_TJCERTIFICATE_ERROR_SOMETHING_WENT_WRONG'), true); + $app->close(); + } + } + + $model = TJCERT::model('Certificate', array('ignore_request' => true)); + + if ($manageOwn || $manage) + { + // Remove the item + if ($model->delete($certificateId)) + { + // Delete media + $model = $this->getModel(); + JLoader::import("/techjoomla/media/tables/xref", JPATH_LIBRARIES); + $tableXref = Table::getInstance('Xref', 'TJMediaTable'); + $tableXref->load(array('client_id' => $certificateId)); + + if ($tableXref->media_id) + { + $model->deleteMedia($tableXref->media_id, $mediaPath, $client, $certificateId); + } + + echo new JResponseJson($result, Text::_('COM_TJCERTIFICATE_CERTIFICATE_DELETED_SUCCESSFULLY'), false); + $app->close(); + } + else + { + echo new JResponseJson(null, Text::_('COM_TJCERTIFICATE_CERTIFICATE_DELETED_FAILED'), true); + $app->close(); + } + } + } +} diff --git a/src/components/com_tjcertificate/administrator/controllers/trainingrecord.php b/src/components/com_tjcertificate/administrator/controllers/trainingrecord.php new file mode 100644 index 00000000..00a6e35b --- /dev/null +++ b/src/components/com_tjcertificate/administrator/controllers/trainingrecord.php @@ -0,0 +1,242 @@ + + * @copyright Copyright (C) 2009 - 2020 Techjoomla. All rights reserved. + * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL + */ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\Factory; +use Joomla\CMS\Language\Text; +use Joomla\Registry\Registry; +use Joomla\Utilities\ArrayHelper; +use Joomla\CMS\MVC\Controller\FormController; +use Joomla\CMS\Filesystem\Folder; +use Joomla\CMS\Filesystem\File; +use Joomla\CMS\Component\ComponentHelper; +use Joomla\CMS\Session\Session; +use Joomla\CMS\Router\Route; + +JLoader::import("/techjoomla/media/storage/local", JPATH_LIBRARIES); + +/** + * The Tj Certificate Training Record controller + * + * @since __DEPLOY_VERSION__ + */ +class TjCertificateControllerTrainingRecord extends FormController +{ + /** + * Method to save a training record data. + * + * @param string $key The name of the primary key of the URL variable. + * @param string $urlVar The name of the URL variable if different from the primary key (sometimes required to avoid router collisions). + * + * @return boolean|void Incase of error boolean and in case of success void + * + * @since __DEPLOY_VERSION__ + */ + public function save($key = null, $urlVar = null) + { + // Check for request forgeries. + $this->checkToken(); + $app = Factory::getApplication(); + $user = Factory::getUser(); + $recordId = $app->input->getInt('id'); + $params = ComponentHelper::getParams('com_tjcertificate'); + + if (!$user->id) + { + throw new Exception(Text::_('JERROR_ALERTNOAUTHOR'), 403); + } + + $data = $app->input->get('jform', array(), 'array'); + + $model = $this->getModel(); + + // Validate the posted data. + $form = $model->getForm($data, false); + + if (!$form) + { + throw new \Exception($model->getError(), 500); + } + + $validData = $model->validate($form, $data); + + // Check for validation errors. + if ($validData === false) + { + // Get the validation messages. + $errors = $model->getErrors(); + + if (!empty($errors)) + { + // Push up to three validation messages out to the user. + for ($i = 0, $n = count($errors); $i < $n && $i < 3; $i++) + { + if ($errors[$i] instanceof Exception) + { + $app->enqueueMessage($errors[$i]->getMessage(), 'warning'); + } + else + { + $app->enqueueMessage($errors[$i], 'warning'); + } + } + } + + // Save the data in the session. + $app->setUserState('com_tjcertificate.edit.trainingrecord.data', $data); + + // Redirect back to the edit screen. + $this->setRedirect(Route::_('index.php?option=com_tjcertificate&view=trainingrecord&layout=edit&id=' . $recordId, false)); + + return false; + } + + if ($validData['assigned_user_id']) + { + $validData['user_id'] = $validData['assigned_user_id']; + } + else + { + $validData['user_id'] = $user->id; + } + + $validData['client'] = "external"; + $validData['state'] = $validData['state'] ? $validData['state'] : "-1"; + $validData['is_external'] = 1; + + $file = $app->input->files->get('jform', array(), 'array'); + + if (!empty($file['cert_file'])) + { + $validData['old_media_ids'] = $app->input->get('oldFiles', 0, 'INT'); + $uploadData = $model->uploadMedia($file, $validData); + $validData['cert_file'] = $uploadData['source']; + } + + $certificateModel = TJCERT::model('Certificate', array('ignore_request' => true)); + + $certificateModel->save($validData); + + $modelMediaXref = TJMediaXref::getInstance(); + + if ($uploadData['id']) + { + $mediaData['id'] = ''; + $mediaData['client_id'] = $certificateModel->getState('certificate.id'); + $mediaData['media_id'] = $uploadData['id']; + $mediaData['client'] = TJCERT::getClient(); + $modelMediaXref->bind($mediaData); + $modelMediaXref->save(); + } + + $this->setMessage(Text::_('COM_TJCERTIFICATE_TRAINING_RECORD_SAVE_SUCCESSFULLY')); + + if ($task === "apply") + { + // Redirect back to the edit screen. + $this->setRedirect( + Route::_('index.php?option=com_tjcertificate&view=trainingrecord&layout=edit&id=' . $certificateModel->getState('certificate.id'), false) + ); + } + + // Save task using to "Save & Close" action which is used only in backend + if ($task === "save") + { + // Redirect to the list screen. + $this->setRedirect( + Route::_('index.php?option=com_tjcertificate&view=certificates', false) + ); + } + + // Flush the data from the session. + $app->setUserState('com_tjcertificate.edit.trainingrecord.data', null); + } + + /** + * Cancel operation + * + * @return void + * + * @since __DEPLOY_VERSION__ + */ + public function cancel() + { + // Check for request forgeries. + $this->checkToken('request'); + + // Clear data from session. + \JFactory::getApplication()->setUserState('com_tjcertificate.edit.trainingrecord.data', null); + + $this->setRedirect(Route::_('index.php?option=com_tjcertificate&view=certificates&layout=my', false)); + } + + /** + * Downloads the file requested by user + * + * @return boolean|void + * + * @since __DEPLOY_VERSION__ + */ + public function downloadAttachment() + { + $app = Factory::getApplication(); + $user = Factory::getUser(); + + if (!$user->id) + { + throw new Exception(Text::_('JERROR_ALERTNOAUTHOR'), 403); + + return false; + } + + $clientId = $app->input->get('recordId', '', 'INT'); + $mediaId = $app->input->get('id', '', 'INT'); + + $manageOwn = $user->authorise('certificate.external.manageown', 'com_tjcertificate'); + $manage = $user->authorise('certificate.external.manage', 'com_tjcertificate'); + + // If manageOwn permission then check record owner can only download own record + if ($manageOwn && !$manage) + { + $table = TJCERT::table("certificates"); + $table->load(array('id' => (int) $clientId, 'user_id' => $user->id)); + + if (!$table->id) + { + throw new Exception(Text::_('JERROR_ALERTNOAUTHOR'), 403); + } + } + + $params = ComponentHelper::getParams('com_tjcertificate'); + + if (!$mediaId && !$clientId) + { + return false; + } + + $config = array(); + $config['mediaId'] = $mediaId; + + // Assign client id as Record Id + $config['client_id'] = $clientId; + $config['client'] = TJCERT::getClient(); + $mediaPath = TJCERT::getMediaPath(); + $mediaAttachmentData = TJMediaXref::getInstance($config); + $folderName = explode('.', $mediaAttachmentData->media->type); + + $downloadPath = JPATH_SITE . '/' . $mediaPath; + $downloadPath = $downloadPath . '/' . $folderName[0] . '/' . $mediaAttachmentData->media->source; + + $media = TJMediaStorageLocal::getInstance(); + $media->downloadMedia($downloadPath); + } +} diff --git a/src/components/com_tjcertificate/administrator/includes/tjcertificate.php b/src/components/com_tjcertificate/administrator/includes/tjcertificate.php index 70404a7d..3fc1b78c 100644 --- a/src/components/com_tjcertificate/administrator/includes/tjcertificate.php +++ b/src/components/com_tjcertificate/administrator/includes/tjcertificate.php @@ -15,6 +15,7 @@ use Joomla\CMS\Table\Table; use Joomla\String\StringHelper; use Joomla\CMS\Component\ComponentHelper; +use Joomla\CMS\HTML\HTMLHelper; $language = JFactory::getLanguage(); $language->load('com_tjcertificate'); @@ -44,6 +45,10 @@ class TJCERT */ private static $config = null; + public static $client = "com_tjcertificate"; + + public static $mediaPath = "media/com_tjcertificate/external"; + /** * Retrieves a table from the table folder * @@ -130,4 +135,47 @@ public static function loadClass($className) return self::$loadedClass[$className]; } + + /** + * Initializes js lang constant dependencies + * + * @param string $location The location where the assets needs to load + * + * @return void + * + * @since __DEPLOY_VERSION__ + */ + public static function init($location = 'site') + { + self::Language()->JsLanguageConstant(); + + if ($location == 'site') + { + HTMLHelper::stylesheet('media/com_tjcertificate/vendors/font-awesome-4.1.0/css/font-awesome.min.css'); + } + } + + /** + * Method to get client + * + * @return void + * + * @since __DEPLOY_VERSION__ + */ + public function getClient() + { + return self::$client; + } + + /** + * Method to get external media path + * + * @return void + * + * @since __DEPLOY_VERSION__ + */ + public function getMediaPath() + { + return self::$mediaPath; + } } diff --git a/src/components/com_tjcertificate/administrator/languages/en-GB/en-GB.com_tjcertificate.ini b/src/components/com_tjcertificate/administrator/languages/en-GB/en-GB.com_tjcertificate.ini index b52714cd..dd31d865 100644 --- a/src/components/com_tjcertificate/administrator/languages/en-GB/en-GB.com_tjcertificate.ini +++ b/src/components/com_tjcertificate/administrator/languages/en-GB/en-GB.com_tjcertificate.ini @@ -9,7 +9,7 @@ COM_TJCERTIFICATE_CONFIGURATION="TJ Certificate Configuration" COM_TJCERTIFICATE_GENEARAL_SETINGS="General" COM_TJCERTIFICATE_CERTIFICATE_PREFIX_LABEL="Certificate Prefix" COM_TJCERTIFICATE_CERTIFICATE_PREFIX_DESC="Unique Certificate Id Prefix" -COM_TJCERTIFICATE_CERTIFICATE_RANDOM_STRING_LENTGH_LABEL="Certificate random string length" +COM_TJCERTIFICATE_CERTIFICATE_RANDOM_STRING_LENTGH_LABEL="Certificate Random String Length" COM_TJCERTIFICATE_CERTIFICATE_RANDOM_STRING_LENTGH_DESC="Each generated certificate as a code. The format of the code is [Certificate Prefix]-[Random number]. This option sets the length of the random number. " @@ -233,7 +233,7 @@ COM_TJCERTIFICATE_BLOCKED_USER="Unknown / Deleted User" ; Certificate access COM_TJCERTIFICATE_SHOW_PUBLIC_PRIVATE="Set Certificate Privacy" COM_TJCERTIFICATE_SHOW_PUBLIC_PRIVATE_DESC="If 'Private' option is selected then only the owner is authorised to view the certificate" -COM_TJCERTIFICATE_SHOW_SEARCH_BOX="Show search box on certificate view" +COM_TJCERTIFICATE_SHOW_SEARCH_BOX="Show Search Box On Certificate View" COM_TJCERTIFICATE_SHOW_SEARCH_BOX_DESC="Select option 'Yes' to show search box" COM_TJCERTIFICATE_OPTION_PUBLIC="Public" COM_TJCERTIFICATE_OPTION_PRIVATE="Private" @@ -246,6 +246,14 @@ COM_TJCERTIFICATE_SOCIAL_SHARING_FACEBOOK="Facebook share" COM_TJCERTIFICATE_SOCIAL_SHARING_LINKEDIN="LinkedIn share" COM_TJCERTIFICATE_SOCIAL_SHARING_TWITTER="Twitter share" COM_TJCERTIFICATE_SOCIAL_SHARING_OPTIONS="Select social sharing options" +COM_TJCERTIFICATE_LINKEDIN_PROFILE_BTN="Enable Linkedin 'Add to profile' button" +COM_TJCERTIFICATE_LINKEDIN_PROFILE_BTN_DESC="Enable 'Add to profile' button to add the certificate in profile" +COM_TJCERTIFICATE_LINKEDIN_ORGANIZATION_INFO="Select Organisation name or Organisation Id to pass in Url" +COM_TJCERTIFICATE_LINKEDIN_ORGANIZATION_INFO_DESC="on option selection, link parameter will change accordingly" +COM_TJCERTIFICATE_LINKEDIN_ORGANIZATION_NAME="Organization Name" +COM_TJCERTIFICATE_LINKEDIN_ORGANIZATION_ID="Organization Id" +COM_TJCERTIFICATE_LINKEDIN_ORGANIZATION_ID_NAME="Add linkedIn organization name or Id" +COM_TJCERTIFICATE_LINKEDIN_ORGANIZATION_ID_NAME_DESC="Your organization ID (if your organization has an existing page on LinkedIn) or Your organization name (if your organization doesn’t have an existing page on LinkedIn)" ;Certificate Menu option COM_TJCERTIFICATE_CERTIFICATE_TEXT_FILTER="Show Free Text Filter" @@ -268,3 +276,87 @@ COM_TJCERTIFICATE_CERTIFICATE_FILTER_CERTIFICATE_TYPE_SELECT="- Select Type -" COM_TJCERTIFICATE_CLIENT_COM_TJLMS_COURSE="Course" COM_TJCERTIFICATE_CLIENT_COM_JTICKETING_EVENT="Event" COM_TJCERTIFICATE_CERTIFICATE_LIST_VIEW_TYPE="Type" + +;__DEPLOY_VERSION__ +;Global config - Certificate Image Generation +COM_TJCERTIFICATE_IMAGE_GENERATION="Certificate Image" +COM_TJCERTIFICATE_IMAGE_GENERATION_SETTINGS="Certificate Image Generation Settings" +COM_TJCERTIFICATE_IMAGE_GENERATION_TYPE="Image Generation Type" +COM_TJCERTIFICATE_IMAGE_GENERATION_TYPE_DESC="There are two ways certificate image can be generated.
1) By using JavaScript Canvas librabry
2) Using PHP ImageMagick library" +COM_TJCERTIFICATE_IMAGE_GENERATION_TYPE_CANVAS="HTML2Canvas Library" +COM_TJCERTIFICATE_IMAGE_GENERATION_TYPE_IMAGICK="PHP ImageMagick Library" +COM_TJCERTIFICATE_IMAGE_GENERATION_SETTINGS_NOTE="Please note:

" + +;__DEPLOY_VERSION__ +;Permission for external record +COM_TJCERTIFICATE_CLIENT_EXTERNAL="External" +COM_TJCERTIFICATE_PERMISSION_CREATE_EXTERNAL_CERTIFICATE="Create training records" +COM_TJCERTIFICATE_PERMISSION_CREATE_EXTERNAL_CERTIFICATE_DESC="Allow users to create training records" +COM_TJCERTIFICATE_PERMISSION_MANAGE_EXTERNAL_CERTIFICATE="Manage training records" +COM_TJCERTIFICATE_PERMISSION_MANAGE_EXTERNAL_CERTIFICATE_DESC="Allow users to manage training records" +COM_TJCERTIFICATE_PERMISSION_MANAGEOWN_EXTERNAL_CERTIFICATE="Manage own training records" +COM_TJCERTIFICATE_PERMISSION_MANAGEOWN_EXTERNAL_CERTIFICATE_DESC="Allow users to manage own training records" + +;__DEPLOY_VERSION__ +;params email, media +COM_TJCERTIFICATE_EMAIL_SETTINGS="Email Notifications" +COM_TJCERTIFICATE_ADMIN_EMAIL="Admin email address" +COM_TJCERTIFICATE_ADMIN_EMAIL_DESC="Add comma separated admin email address" +COM_TJCERTIFICATE_MEDIA_SETS="Media" +COM_TJCERTIFICATE_UPLOAD_MAX_SIZE="Maximum Size (in MB)" +COM_TJCERTIFICATE_UPLOAD_MAX_SIZE_DESC="The maximum size for an upload (in megabytes). Use zero for no limit. Note: your server has a maximum limit." +COM_TJCERTIFICATE_LEGAL_EXTENSION="Allowed Extensions (File Types)" +COM_TJCERTIFICATE_LEGAL_EXTENSION_DESC="Extensions (file types) you are allowed to upload (comma separated)." +COM_TJCERTIFICATE_N_RECORD_PUBLISHED="%d record(s) successfully published" +COM_TJCERTIFICATE_N_RECORD_UNPUBLISHED="%d record(s) successfully unpublished" + +;Date format +COM_TJCERTIFICATE_DATE_FORMAT_TO_SHOW="Date format" +COM_TJCERTIFICATE_DATE_FORMAT_TO_SHOW_DESC="Date format to show on site except filters having date format" +COM_TJCERTIFICATE_DATE_FORMAT_1="2012-01-02 01:30:00" +COM_TJCERTIFICATE_DATE_FORMAT_2="Mon, Jan 02 01:30 AM" +COM_TJCERTIFICATE_DATE_FORMAT_3="January 2, 2012, 1:30 am" +COM_TJCERTIFICATE_DATE_FORMAT_4="01.02.12" +COM_TJCERTIFICATE_DATE_FORMAT_5="2, 1, 2012" +COM_TJCERTIFICATE_DATE_FORMAT_6="01-30-00, 2-01-12" +COM_TJCERTIFICATE_DATE_FORMAT_7="01:30:00" +COM_TJCERTIFICATE_DATE_FORMAT_CUSTOM="Custom" +COM_TJCERTIFICATE_CUSTOM_DATE_FORMAT="Custom Date Format" +COM_TJCERTIFICATE_CUSTOM_DATE_FORMAT_DESC="This option will used to set custom php date format" + +;Training record form +COM_TJCERTIFICATE_FORM_LBL_CERTIFICATE_NAME="Name" +COM_TJCERTIFICATE_FORM_LBL_CERTIFICATE_NAME_DESC="Training record name" +COM_TJCERTIFICATE_CERTIFICATE_FORM_LBL_CERTIFICATE_ID="Record Id" +COM_TJCERTIFICATE_CERTIFICATE_FORM_LBL_CERTIFICATE_ID_DESC="Record Id" +COM_TJCERTIFICATE_FORM_LBL_CERTIFICATE_URL="Url
(start url with http/https)" +COM_TJCERTIFICATE_FORM_LBL_CERTIFICATE_URL_DESC="Add training record certificate Url" +COM_TJCERTIFICATE_FORM_LBL_ISSUE_ORG="Issuing Organization" +COM_TJCERTIFICATE_FORM_LBL_ISSUE_ORG_DESC="Organization Name" +COM_TJCERTIFICATE_CERTIFICATE_FORM_LBL_CERTIFICATE_ISSUED_DATE="Issue Date" +COM_TJCERTIFICATE_CERTIFICATE_FORM_LBL_CERTIFICATE_ISSUED_DATE_DESC="Add training record completion or certificate issue date" +COM_TJCERTIFICATE_CERTIFICATE_FORM_LBL_CERTIFICATE_EXPIRY_DATE="Expiration Date" +COM_TJCERTIFICATE_CERTIFICATE_FORM_LBL_CERTIFICATE_EXPIRY_DATE_DESC="Certificate expiry date" +COM_TJCERTIFICATE_CERTIFICATE_FORM_LBL_CERTIFICATE_STATUS="Record Status" +COM_TJCERTIFICATE_CERTIFICATE_FORM_LBL_CERTIFICATE_STATUS_DESC="Select record status" +COM_TJCERTIFICATE_CERTIFICATE_FORM_STATUS_ATTENDED="Attended" +COM_TJCERTIFICATE_CERTIFICATE_FORM_STATUS_COMPLETED="Completed" +COM_TJCERTIFICATE_CERTIFICATE_FORM_STATUS_PASSED="Passed" +COM_TJCERTIFICATE_CERTIFICATE_FORM_STATUS_FAILED="Failed" +COM_TJCERTIFICATE_FORM_LBL_CERTIFICATE_FILE="Certificate File
pdf/image" +COM_TJCERTIFICATE_FORM_LBL_CERTIFICATE_FILE_DESC="Upload certificate pdf/image" +COM_TJCERTIFICATE_EXTERNAL_CERTIFICATE_DETAIL_VIEW_HEAD="Training Record" +COM_TJCERTIFICATE_MEDIA_UPLOAD_ERROR="Uploaded media exceeds the allowed file size or it is an unsupported file." +COM_TJCERTIFICATE_MEDIA_INVALID_FILE_TYPE="Invalid file type. Please enter the allowed file types." +COM_TJCERTIFICATE_CONFIRM_DELETE_ATTACHMENT="Are you sure you want to delete this attachement?" +COM_TJCERTIFICATE_ATTACHMENT_DELETE="Delete attachment" +COM_TJCERTIFICATE_ATTACHMENT_DELETED_SUCCESSFULLY="Attachment deleted successfully" +COM_TJCERTIFICATE_ATTACHMENT_DELETED_FAILED="Failed to delete attachment. Please try again after some time." +COM_TJCERTIFICATE_ADD_EXTERNAL_CERTIFICATE="New Training Record" +COM_TJCERTIFICATE_PAGE_ADD_TRAINING_RECORD="Training Record: New" +COM_TJCERTIFICATE_PAGE_EDIT_TRAINING_RECORD="Training Record: Edit" +COM_TJCERTIFICATE_CERTIFICATE_FRONTEND_PREVIEW="Frontend Preview" +COM_TJCERTIFICATE_TRAINING_RECORD_SAVE_SUCCESSFULLY="Training record saved successfully" +COM_TJCERTIFICATE_STATUS_PENDING="Pending" +COM_TJCERTIFICATE_EXPIRY_DATE_VALIDATION_MESSAGE="Expiration date should be greater than issue date" +COM_TJCERTIFICATE_LBL_CERTIFICATE_URL="Url" diff --git a/src/components/com_tjcertificate/administrator/languages/en-GB/en-GB.com_tjcertificate.sys.ini b/src/components/com_tjcertificate/administrator/languages/en-GB/en-GB.com_tjcertificate.sys.ini index b53b1258..061c19f1 100644 --- a/src/components/com_tjcertificate/administrator/languages/en-GB/en-GB.com_tjcertificate.sys.ini +++ b/src/components/com_tjcertificate/administrator/languages/en-GB/en-GB.com_tjcertificate.sys.ini @@ -29,3 +29,6 @@ COM_TJCERTIFICATE_CERTIFICATE_LIST_DEFAULT_TITLE="Certificates" COM_TJCERTIFICATE_CERTIFICATE_LIST_DEFAULT_DESC="List of certificates" COM_TJCERTIFICATE_CERTIFICATE_FIELDSET_CLIENT_SELECT_LABEL="Client" COM_TJCERTIFICATE_CERTIFICATE_FIELDSET_CLIENT_SELECT_DESC="Client" + +;Add record menu +COM_TJCERTIFICATE_ADD_EXTERNAL_CERTIFICATE="Add training record" diff --git a/src/components/com_tjcertificate/administrator/layouts/preview.php b/src/components/com_tjcertificate/administrator/layouts/preview.php new file mode 100644 index 00000000..b88239d0 --- /dev/null +++ b/src/components/com_tjcertificate/administrator/layouts/preview.php @@ -0,0 +1,39 @@ + + * @copyright Copyright (C) 2009 - 2020 Techjoomla. All rights reserved. + * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL + */ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\Language\Text; + +?> + + + diff --git a/src/components/com_tjcertificate/administrator/libraries/certificate.php b/src/components/com_tjcertificate/administrator/libraries/certificate.php index 503b063a..910f8b9e 100644 --- a/src/components/com_tjcertificate/administrator/libraries/certificate.php +++ b/src/components/com_tjcertificate/administrator/libraries/certificate.php @@ -21,6 +21,9 @@ use Joomla\Registry\Registry; use Dompdf\Dompdf; use Dompdf\Options; +use Joomla\CMS\Plugin\PluginHelper; +use Joomla\CMS\HTML\HTMLHelper; +use Joomla\CMS\Uri\Uri; /** * Certificate class. Handles all application interaction with a Certificate @@ -57,8 +60,26 @@ class TjCertificateCertificate extends CMSObject public $defaultCertPrefix = "CERT"; + public $certImageDir = JPATH_SITE . '/media/com_tjcertificate/certificates/'; + + public $certTmpDir = JPATH_SITE . '/media/com_tjcertificate/tmp/'; + protected static $certificateObj = array(); + public $is_external = 0; + + public $name = null; + + public $cert_url = ""; + + public $cert_file = ""; + + public $issuing_org = ""; + + public $status = ""; + + public $created_by = ""; + /** * Constructor activating the default information of the Certificate * @@ -282,6 +303,32 @@ public function getComment() return $this->comment; } + /** + * Set certificate issue date + * + * @param string $value comment. + * + * @return void. + * + * @since __DEPLOY_VERSION__ + */ + public function setIssuedDate($value = null) + { + $this->issued_on = $value; + } + + /** + * Get certificate issue date + * + * @return string comment + * + * @since __DEPLOY_VERSION__ + */ + public function getIssuedDate() + { + return $this->issued_on; + } + /** * Returns the global Certificate object * @@ -428,6 +475,13 @@ public function save() $table->issued_on = Factory::getDate()->toSql(); } + // If certificate id is not added from the form then add + if (empty($this->unique_certificate_id)) + { + $options = new Registry; + $table->unique_certificate_id = $this->generateUniqueCertId($options); + } + // Store the user data in the database if (!($table->store())) { @@ -438,9 +492,19 @@ public function save() $this->id = $table->id; - // Fire the onTjCertificateAfterSave event. $dispatcher = \JEventDispatcher::getInstance(); + if ($table->is_external && $isNew) + { + /* Send mail on record creation */ + JLoader::import('components.com_tjcertificate.events.record', JPATH_SITE); + $tjCertificateTriggerRecord = new TjCertificateTriggerRecord; + $tjCertificateTriggerRecord->onAfterRecordSave($this, true); + $dispatcher->trigger('onTrainingRecordAfterAdded', array($isNew, $this)); + } + + // Fire the onTjCertificateAfterSave event. + $dispatcher->trigger('onTjCertificateAfterSave', array($isNew, $this)); } catch (\Exception $e) @@ -471,14 +535,33 @@ public function bind(&$array) return false; } - // Bind the array - if (!$this->setProperties($array)) + $getPrivateProperties = $this->_getPrivateProperties(); + + $getPublicProperties = $this->_getPublicProperties(); + + $publicProperties = array(); + + foreach ($getPublicProperties as $key => $value) + { + $publicProperties[$value->name] = ''; + } + + $setPublicProperties = array_intersect_key($array, $publicProperties); + + // Set public properties + if (!$this->setProperties($setPublicProperties)) { $this->setError(Text::_('COM_TJCERTIFICATE_BINDING_ERROR')); return false; } + // Set private properties + foreach ($getPrivateProperties as $key => $value) + { + $this->{$value->name} = $array[$value->name]; + } + // Make sure its an integer $this->id = (int) $this->id; @@ -544,13 +627,22 @@ public static function getIssued($client, $clientId, $userId = 0, $expired = fal * * @param boolean $showSearchBox Show search box * + * @param boolean $isExternal Check record is external + * * @return string Certificate url. * * @since 1.0 */ - public function getUrl($options, $showSearchBox = true) + public function getUrl($options, $showSearchBox = true, $isExternal = false) { - $url = 'index.php?option=com_tjcertificate&view=certificate&certificate=' . $this->unique_certificate_id; + if ($isExternal) + { + $url = 'index.php?option=com_tjcertificate&view=trainingrecord&id=' . $this->id; + } + else + { + $url = 'index.php?option=com_tjcertificate&view=certificate&certificate=' . $this->unique_certificate_id; + } // If search box is true then only show search box param in URL if ($showSearchBox) @@ -565,7 +657,7 @@ public function getUrl($options, $showSearchBox = true) if (isset($options['absolute'])) { - return JUri::root() . substr(Route::_($url), strlen(JUri::base(true)) + 1); + return Route::link('site', $url, false, 0, true); } return Route::_($url); @@ -605,7 +697,7 @@ public function getDownloadUrl($options = array()) /** * Method to get certificate download url. * - * @param boolean $store Store as attachment for emails + * @param integer $store Store as attachment for emails * * @return boolean|string Certificate pdf url. * @@ -697,6 +789,10 @@ public function pdfDownload($store = 0) readfile($certificatePdfName); jexit(); } + elseif ($store == 2) + { + return $domPDF->output(); + } $domPDF->stream($certificatePdfName, array("Attachment" => 1)); @@ -769,8 +865,11 @@ public function issueCertificate($replacements, $options) throw new Exception(Text::_('COM_TJCERTIFICATE_TEMPLATE_INVALID')); } - // Generate unique certificate id - $this->unique_certificate_id = $this->generateUniqueCertId($options); + if (empty($this->unique_certificate_id)) + { + // Generate unique certificate id + $this->unique_certificate_id = $this->generateUniqueCertId($options); + } // Generate unique certificate id replacement $replacements->certificate->cert_id = $this->unique_certificate_id; @@ -808,9 +907,28 @@ public function issueCertificate($replacements, $options) } // Save certificate - $this->save(); + if ($this->save()) + { + // Remove old certificate image after re-generating the certificate + $path = JPATH_SITE . '/media/com_tjcertificate/certificates/'; + $fileName = $this->unique_certificate_id . '.png'; + + if (JFile::exists($path . $fileName)) + { + JFile::delete($path . $fileName); + } + + // Generate Certificate Image + $params = ComponentHelper::getParams('com_tjcertificate'); + + if ($params->get('cert_image_gen_type') == 'imagick') + { + // Generate image from PDF + $this->generateImageFromPDF($this->pdfDownload(2)); + } - return self::getInstance($this->id); + return self::getInstance($this->id); + } } catch (\Exception $e) { @@ -943,15 +1061,13 @@ protected function generateUniqueCertId($options) } /** - * This function checks the certificate download permission - * - * @param STRING $uniqueCertificateId certificate Id + * This function checks the certificate download permission * * @return boolean * * @since __DEPLOY_VERSION__ */ - public static function canDownload($uniqueCertificateId) + public function canDownload() { $user = Factory::getUser(); @@ -962,10 +1078,7 @@ public static function canDownload($uniqueCertificateId) if ($user->authorise('certificate.download.own', 'com_tjcertificate')) { - $table = TJCERT::table("certificates"); - $table->load(array('unique_certificate_id' => $uniqueCertificateId)); - - if ($user->get('id') == $table->user_id) + if ($user->get('id') == $this->user_id) { return true; } @@ -973,4 +1086,115 @@ public static function canDownload($uniqueCertificateId) return false; } + + /** + * Method to get linkedIn add to profile url. + * + * @return STRING + * + * @since __DEPLOY_VERSION__ + */ + public function getAddToLinkedInProfileUrl() + { + $params = ComponentHelper::getParams('com_tjcertificate'); + $config = Factory::getConfig(); + $siteName = $config->get('sitename'); + + $issuedMonth = HTMLHelper::_('date', $this->issued_on, 'm'); + $issuedYear = HTMLHelper::_('date', $this->issued_on, 'Y'); + + $expirationDetails = null; + + if ($this->expired_on != '0000-00-00 00:00:00') + { + $expirationMonth = HTMLHelper::_('date', $this->expired_on, 'm'); + $expirationYear = HTMLHelper::_('date', $this->expired_on, 'Y'); + $expirationDetails = '&expirationYear=' . $expirationYear . '&expirationMonth=' . $expirationMonth; + } + + $orgParam = '&' . $params->get('organization_info') . '=' . $params->get('organization_id_name'); + + // Get client data + $dispatcher = JDispatcher::getInstance(); + PluginHelper::importPlugin('content'); + $result = $dispatcher->trigger('getCertificateClientData', array($this->client_id, $this->client)); + $clientData = $result[0]; + + $urlOptions = array(); + $urlOptions['absolute'] = true; + $certificateUrl = $this->getURL($urlOptions, false); + + $certificateTitle = $clientData->title ? $clientData->title : $siteName . ' ' . Text::_('COM_TJCERTIFICATE_CERTIFICATE_DETAIL_VIEW_HEAD'); + $linkedInprofileUrl = 'https://www.linkedin.com/profile/add?startTask=CERTIFICATION_NAME&name=' . $certificateTitle . $orgParam + . '&issueYear=' . $issuedYear . '&issueMonth=' . $issuedMonth . $expirationDetails + . '&certUrl=' . urlencode($certificateUrl) . '&certId=' . $this->unique_certificate_id; + + return $linkedInprofileUrl; + } + + /** + * Method to generate certificate image from PDF. + * + * @param string $domPDFOutput DomPDF output. + * + * @return void + * + * @since __DEPLOY_VERSION__ + */ + public function generateImageFromPDF($domPDFOutput) + { + if (extension_loaded('imagick')) + { + if (!JFolder::exists($this->certImageDir)) + { + JFolder::create($this->certImageDir); + } + + if (!JFolder::exists($this->certTmpDir)) + { + JFolder::create($this->certTmpDir); + } + + $tmpPDF = $this->certTmpDir . $this->unique_certificate_id . '.pdf'; + + file_put_contents($tmpPDF, $domPDFOutput); + + $im = new Imagick; + $im->setResolution(72, 72); + $im->readimage($tmpPDF); + $im->setImageBackgroundColor('white'); + $im->setImageAlphaChannel(imagick::ALPHACHANNEL_REMOVE); + $im->mergeImageLayers(imagick::LAYERMETHOD_FLATTEN); + $im->writeImage($this->certImageDir . $this->unique_certificate_id . '.png'); + $im->clear(); + $im->destroy(); + + if (JFile::exists($tmpPDF)) + { + JFile::delete($tmpPDF); + } + } + } + + /** + * Get formated date + * + * @param string $datetime The current offset + * + * @return string formatted datetime + * + * @since __DEPLOY_VERSION__ + **/ + public function getFormatedDate($datetime) + { + $params = ComponentHelper::getParams('com_tjcertificate'); + $dateFormat = $params->get('date_format_show'); + + if ($dateFormat == "custom") + { + $dateFormat = $params->get('custom_format'); + } + + return HTMLHelper::_('date', $datetime, $dateFormat, true); + } } diff --git a/src/components/com_tjcertificate/administrator/libraries/language.php b/src/components/com_tjcertificate/administrator/libraries/language.php new file mode 100644 index 00000000..02298065 --- /dev/null +++ b/src/components/com_tjcertificate/administrator/libraries/language.php @@ -0,0 +1,38 @@ + + * @copyright Copyright (C) 2009 - 2020 Techjoomla. All rights reserved. + * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL + */ + +defined('_JEXEC') or die(); + +use Joomla\CMS\Language\Text; + +/** + * TJCertificate language constant class for common methods + * + * @since _DEPLOY_VERSION_ + */ +class TJCertificateLanguage +{ + /** + * Language constants to be used in js + * + * @return void + * + * @since _DEPLOY_VERSION_ + */ + public function JsLanguageConstant() + { + // Tjmedia js + Text::script('COM_TJCERTIFICATE_CONFIRM_DELETE_ATTACHMENT'); + Text::script('COM_TJCERTIFICATE_MEDIA_INVALID_FILE_TYPE'); + Text::script('COM_TJCERTIFICATE_MEDIA_UPLOAD_ERROR'); + Text::script('COM_TJCERTIFICATE_DELETE_CERTIFICATE_MESSAGE'); + Text::script('COM_TJCERTIFICATE_EXPIRY_DATE_VALIDATION_MESSAGE'); + } +} diff --git a/src/components/com_tjcertificate/administrator/libraries/mails.php b/src/components/com_tjcertificate/administrator/libraries/mails.php new file mode 100644 index 00000000..e34435f3 --- /dev/null +++ b/src/components/com_tjcertificate/administrator/libraries/mails.php @@ -0,0 +1,175 @@ + + * @copyright Copyright (C) 2009 - 2020 Techjoomla. All rights reserved. + * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL + */ + +defined('_JEXEC') or die; +jimport('techjoomla.tjnotifications.tjnotifications'); + +use Joomla\CMS\Factory; +use Joomla\CMS\User\User; +use Joomla\CMS\Language\Text; +use Joomla\CMS\Component\ComponentHelper; +use Joomla\Registry\Registry; + +/** + * Class TjCertificateMails + * + * @since __DEPLOY_VERSION__ + */ +class TjCertificateMails +{ + protected $params; + + protected $siteConfig; + + protected $sitename; + + protected $siteadminname; + + protected $user; + + protected $client; + + protected $tjnotifications; + + protected $siteinfo; + + /** + * Method acts as a consturctor + * + * @since __DEPLOY_VERSION__ + */ + public function __construct() + { + $this->params = ComponentHelper::getParams('com_tjcertificate'); + $this->siteConfig = Factory::getConfig(); + $this->sitename = $this->siteConfig->get('sitename'); + $this->siteadminname = $this->siteConfig->get('fromname'); + $this->user = Factory::getUser(); + $this->client = TJCERT::getClient(); + $this->tjnotifications = new Tjnotifications; + + $this->siteinfo = new stdClass; + $this->siteinfo->sitename = $this->sitename; + } + + /** + * Send mails when record is created + * + * @param OBJECT $recordDetails Record Detail + * + * @return void + * + * @since __DEPLOY_VERSION__ + */ + public function onAfterCreateRecord($recordDetails) + { + $adminRecipients = array(); + $db = Factory::getDBO(); + + // Get all admin users + $query = $db->getQuery(true); + + $query->select('id'); + $query->from($db->quoteName('#__users')); + $query->where($db->quoteName('sendEmail') . '= 1'); + $db->setQuery($query); + $adminUsers = $db->loadObjectList(); + + foreach ($adminUsers as $adminUser) + { + $adminRecipients[] = Factory::getUser($adminUser->id); + $adminRecipients['email']['to'][] = Factory::getUser($adminUser->id)->email; + } + + $userEmailArray = array(); + + if ($recordDetails->getUserId()) + { + $user = Factory::getUser($recordDetails->getUserId()); + $userEmailArray[] = $user->email; + } + + $recipients = array('email' => array('to' => $userEmailArray)); + + $adminkey = "createRecordMailToAdmin"; + $userkey = "createRecordMailToUser"; + + $siteInfo = new stdClass; + $siteInfo->sitename = $this->sitename; + + $replacements = new stdClass; + $replacements->info = $this->siteinfo; + $replacements->record = $recordDetails; + $replacements->user = $user; + + $options = new Registry; + $options->set('record', $recordDetails); + + // Mail to User after record added on behalf + + if ($recordDetails->getUserId() != $recordDetails->created_by) + { + $assignUserkey = "assignRecordMailToUser"; + $replacements->assigner = Factory::getUser($recordDetails->created_by); + + $this->tjnotifications->send($this->client, $assignUserkey, $recipients, $replacements, $options); + } + else + { + // Mail to site admin + $this->tjnotifications->send($this->client, $adminkey, $adminRecipients, $replacements, $options); + + // Mail to User + $this->tjnotifications->send($this->client, $userkey, $recipients, $replacements, $options); + } + + return; + } + + /** + * Send mail when record is edited + * + * @param OBJECT $recordDetails Record Detail + * + * @param int $isPublished Record state + * + * @return void + * + * @since __DEPLOY_VERSION__ + */ + public function onAfterRecordStateChange($recordDetails, $isPublished) + { + $userEmailArray = array(); + + if ($recordDetails->user_id) + { + $recordOwner = Factory::getUser($recordDetails->user_id); + $userEmailArray[] = $recordOwner->email; + } + + $recipients = array('email' => array('to' => $userEmailArray)); + + $replacements = new stdClass; + $replacements->info = $this->siteinfo; + $replacements->record = $recordDetails; + $replacements->user = $recordOwner; + + $siteinfo = new stdClass; + $siteinfo->sitename = $this->sitename; + + $options = new Registry; + $options->set('record', $recordDetails); + + // Mail to record owner + $this->tjnotifications->send($this->client, "recordApprovedMailToUser", $recipients, $replacements, $options); + + return; + } +} diff --git a/src/components/com_tjcertificate/administrator/models/certificate.php b/src/components/com_tjcertificate/administrator/models/certificate.php index 0b8e3bf3..8ef13993 100644 --- a/src/components/com_tjcertificate/administrator/models/certificate.php +++ b/src/components/com_tjcertificate/administrator/models/certificate.php @@ -15,6 +15,7 @@ use \Joomla\CMS\MVC\Model\AdminModel; use Joomla\CMS\Table\Table; use Joomla\CMS\Plugin\PluginHelper; +use Joomla\Registry\Registry; /** * Item Model for an Certificate. @@ -23,6 +24,29 @@ */ class TjCertificateModelCertificate extends AdminModel { + /** + * Method to get a certificate. + * + * @param integer $pk An optional id of the object to get, otherwise the id from the model state is used. + * + * @return mixed certificate data object on success, false on failure. + * + * @since __DEPLOY_VERSION__ + */ + public function getItem($pk = null) + { + if ($result = parent::getItem($pk)) + { + // Prime required properties. + if (empty($result->id)) + { + $result->client = $this->getState('certificate.client'); + } + } + + return $result; + } + /** * Method to get the record form. * @@ -130,6 +154,18 @@ protected function populateState() $jinput = Factory::getApplication()->input; $id = ($jinput->get('id'))?$jinput->get('id'):$jinput->get('id'); $this->setState('certificate.id', $id); + + $client = $jinput->get('client', ''); + $extension = $jinput->get('extension', ''); + + if (!empty($extension)) + { + $this->setState('certificate.client', $extension); + } + else + { + $this->setState('certificate.client', $client); + } } /** @@ -152,4 +188,99 @@ public function getCertificateProviderInfo($contentId, $client) return trim(implode("\n", $html)); } + + /** + * Method to delete record + * + * @param array $certificateIds post data + * + * @return boolean True on success. + * + * @since __DEPLOY_VERSION__ + */ + public function delete($certificateIds) + { + $certificateIds = (array) $certificateIds; + $table = $this->getTable('Certificates'); + + foreach ($certificateIds as $certificateId) + { + $table->load(array('id' => (int) $certificateId)); + + if ($table->delete($table->id)) + { + if ($table->is_external) + { + $dispatcher = \JEventDispatcher::getInstance(); + $dispatcher->trigger('onTrainingRecordAfterDelete', array($table)); + } + + // Delete media + $model = TJCERT::model('TrainingRecord', array('ignore_request' => true)); + JLoader::import("/techjoomla/media/tables/xref", JPATH_LIBRARIES); + $tableXref = Table::getInstance('Xref', 'TJMediaTable'); + $tableXref->load(array('client_id' => $table->id)); + $mediaPath = TJCERT::getMediaPath(); + $client = TJCERT::getClient(); + + if ($tableXref->media_id) + { + $model->deleteMedia($tableXref->media_id, $mediaPath, $client, $table->id); + } + } + } + + return true; + } + + /** + * Publish the element + * + * @param array $ids Item id + * + * @param int $state Publish state + * + * @return boolean + * + * @since __DEPLOY_VERSION__ + */ + public function publish($ids, $state = 1) + { + $table = $this->getTable(); + + foreach ($ids as $id) + { + $table->load($id); + $oldState = $table->state; + $table->state = $state; + + if ($table->store()) + { + if ($table->is_external) + { + JLoader::import('components.com_tjcertificate.events.record', JPATH_SITE); + $tjCertificateTriggerRecord = new TjCertificateTriggerRecord; + + // If record state is pending then only send the approval email + if ($oldState == -1) + { + $tjCertificateTriggerRecord->onRecordStateChange($table, $table->state); + } + + $dispatcher = \JEventDispatcher::getInstance(); + + if ($table->state == 1) + { + $dispatcher->trigger('onTrainingRecordAfterPublished', array($table)); + } + elseif ($table->state == 0) + { + $dispatcher->trigger('onTrainingRecordAfterUnpublished', array($table)); + } + } + } + } + + return true; + } } diff --git a/src/components/com_tjcertificate/administrator/models/certificates.php b/src/components/com_tjcertificate/administrator/models/certificates.php index 78ce5435..a5074d46 100644 --- a/src/components/com_tjcertificate/administrator/models/certificates.php +++ b/src/components/com_tjcertificate/administrator/models/certificates.php @@ -81,6 +81,7 @@ protected function getListQuery() // Initialize variables. $db = $this->getDbo(); $query = $db->getQuery(true); + $app = Factory::getApplication(); $extension = Factory::getApplication()->input->get('extension', '', 'CMD'); @@ -172,7 +173,11 @@ protected function getListQuery() } elseif ($state === '') { - $query->where('(ci.state = 0 OR ci.state = 1)'); + // Publish, Unpublish and Pending records available in frontend + if ($app->isSite()) + { + $query->where('(ci.state IN (0,1,-1))'); + } } // Filter by Expired certificates diff --git a/src/components/com_tjcertificate/administrator/models/fields/certificatetemplates.php b/src/components/com_tjcertificate/administrator/models/fields/certificatetemplates.php index a738626f..8b03b2b7 100644 --- a/src/components/com_tjcertificate/administrator/models/fields/certificatetemplates.php +++ b/src/components/com_tjcertificate/administrator/models/fields/certificatetemplates.php @@ -10,6 +10,7 @@ JFormHelper::loadFieldClass('list'); use Joomla\CMS\Language\Text; +use Joomla\CMS\Factory; JLoader::import('components.com_tjcertificate.includes.tjcertificate', JPATH_ADMINISTRATOR); @@ -31,11 +32,17 @@ protected function getOptions() { $options = array(); - $user = JFactory::getUser(); - $db = JFactory::getDbo(); + $app = Factory::getApplication()->input; + $user = Factory::getUser(); + $db = Factory::getDbo(); $client = $this->getAttribute('client'); + if (empty($client)) + { + $client = $app->get('extension', ''); + } + $options[] = JHtml::_('select.option', '', Text::_('COM_TJCERTIFICATE_CERTIFICATE_TEMPLATE_FIELD_SELECT')); // Get Private/Created by logged-in user's templates diff --git a/src/components/com_tjcertificate/administrator/models/forms/certificate.xml b/src/components/com_tjcertificate/administrator/models/forms/certificate.xml index d1fafc51..6b4b23da 100644 --- a/src/components/com_tjcertificate/administrator/models/forms/certificate.xml +++ b/src/components/com_tjcertificate/administrator/models/forms/certificate.xml @@ -13,12 +13,7 @@ @@ -51,6 +46,7 @@ diff --git a/src/components/com_tjcertificate/administrator/models/forms/filter_certificates.xml b/src/components/com_tjcertificate/administrator/models/forms/filter_certificates.xml index f5b6dcbd..0017c2dc 100644 --- a/src/components/com_tjcertificate/administrator/models/forms/filter_certificates.xml +++ b/src/components/com_tjcertificate/administrator/models/forms/filter_certificates.xml @@ -41,14 +41,27 @@ --> + + + + + + + diff --git a/src/components/com_tjcertificate/administrator/models/forms/filter_templates.xml b/src/components/com_tjcertificate/administrator/models/forms/filter_templates.xml index 4a45dbc2..76d7b813 100644 --- a/src/components/com_tjcertificate/administrator/models/forms/filter_templates.xml +++ b/src/components/com_tjcertificate/administrator/models/forms/filter_templates.xml @@ -11,14 +11,13 @@ /> - - + addfieldpath="/components/com_tjcertificate/models/fields" + clientByUser="1" + onchange="this.form.submit();" /> +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
diff --git a/src/components/com_tjcertificate/administrator/models/trainingrecord.php b/src/components/com_tjcertificate/administrator/models/trainingrecord.php new file mode 100644 index 00000000..9fa80adf --- /dev/null +++ b/src/components/com_tjcertificate/administrator/models/trainingrecord.php @@ -0,0 +1,290 @@ + + * @copyright Copyright (C) 2009 - 2019 Techjoomla. All rights reserved. + * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL + */ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\Model\AdminModel; +use Joomla\CMS\Table\Table; +use Joomla\CMS\Component\ComponentHelper; +use Joomla\CMS\Factory; +use Joomla\CMS\MVC\Model\BaseDatabaseModel; +use Joomla\CMS\Language\Text; + +JLoader::import("/techjoomla/media/storage/local", JPATH_LIBRARIES); + +/** + * TjCertificate Training Record Model. + * + * @since __DEPLOY_VERSION__ + */ +class TjCertificateModelTrainingRecord extends AdminModel +{ + /** + * @var null Item data + * @since __DEPLOY_VERSION__ + */ + protected $item = null; + + /** + * Method to get a certificate. + * + * @param integer $pk An optional id of the object to get, otherwise the id from the model state is used. + * + * @return mixed certificate data object on success, false on failure. + * + * @since __DEPLOY_VERSION__ + */ + public function getItem($pk = null) + { + if ($item = parent::getItem($pk)) + { + if (!empty($item->id)) + { + // Do any procesing on fields here if needed + BaseDatabaseModel::addIncludePath(JPATH_SITE . '/libraries/techjoomla/media/models'); + + // Create TJMediaXref class object + $modelMediaXref = BaseDatabaseModel::getInstance('Xref', 'TJMediaModel', array('ignore_request' => true)); + $modelMediaXref->setState('filter.clientId', $item->id); + $modelMediaXref->setState('filter.client', 'com_tjcertificate'); + $mediaData = $modelMediaXref->getItems(); + + $item->mediaData = $mediaData; + } + } + + return $item; + } + + /** + * Method to get the record form. + * + * @param array $data Data for the form. + * @param boolean $loadData True if the form is to load its own data (default case), false if not. + * + * @return JForm|boolean A JForm object on success, false on failure + * + * @since __DEPLOY_VERSION__ + */ + public function getForm($data = array(), $loadData = true) + { + // Get the form. + $form = $this->loadForm('com_tjcertificate.trainingrecord', 'trainingrecord', array('control' => 'jform', 'load_data' => $loadData)); + + return empty($form) ? false : $form; + } + + /** + * Returns a Table object, always creating it. + * + * @param string $type The table type to instantiate + * @param string $prefix A prefix for the table class name. Optional. + * @param array $config Configuration array for model. Optional. + * + * @return JTable A database object + */ + public function getTable($type = 'Certificates', $prefix = 'TjCertificateTable', $config = array()) + { + Table::addIncludePath(JPATH_ADMINISTRATOR . '/components/com_tjcertificate/tables'); + + return Table::getInstance($type, $prefix, $config); + } + + /** + * Method to get the data that should be injected in the form. + * + * @return mixed The data for the form. + * + * @since __DEPLOY_VERSION__ + */ + protected function loadFormData() + { + // Check the session for previously entered form data. + $data = Factory::getApplication()->getUserState('com_tjcertificate.edit.trainingrecord.data', array()); + + if (empty($data)) + { + $data = $this->getItem(); + $data->assigned_user_id = $data->user_id; + } + + return $data; + } + + /** + * Method to upload file for timelog activity + * + * @param Array $file File field array + * + * @param array $data The form data + * + * @return array + * + * @since __DEPLOY_VERSION__ + */ + public function uploadMedia($file, $data) + { + $user = Factory::getUser(); + + $params = ComponentHelper::getParams('com_tjcertificate'); + + if (!empty($file['cert_file'])) + { + $filePath = TJCERT::getMediaPath(); + $uploadedFileExtension = strtolower($params->get('upload_extensions', '', 'STRING')); + $fileExtensionType = explode(',', $uploadedFileExtension); + + $config = array(); + $config['type'] = $fileExtensionType; + $config['size'] = $params->get('upload_maxsize', '10'); + $config['auth'] = true; + + if (!empty($file['cert_file']['name'])) + { + $fileType = explode("/", $file['cert_file']['type']); + $config['title'] = $file['cert_file']['name']; + $config['uploadPath'] = JPATH_SITE . '/' . $filePath . '/' . strtolower($fileType[0]); + + $media = TJMediaStorageLocal::getInstance($config); + $mediaData = $media->upload(array($file['cert_file'])); + + if (!empty($media->getError())) + { + $errorFiles[] = $media->getError() . ' (' . $attachments['media_file']['name'] . ')'; + } + elseif ($mediaData[0]['id']) + { + $uploadedMediaId = $mediaData[0]; + + if (!empty($data['old_media_ids'])) + { + if ($data['old_media_ids'] != $mediaId) + { + $this->deleteMedia($data['old_media_ids'], $filePath, 'com_tjcertificate', $data['id']); + } + } + } + } + + // Check error exist in file + if (!empty($errorFiles)) + { + $this->setError($errorFiles); + } + } + + return $uploadedMediaId; + } + + /** + * Method to delete media record + * + * @param Integer $mediaId media Id of files table + * @param STRING $deletePath file path from params in config + * @param STRING $client client(example -'com_timelog.activity') + * @param Integer $clientId clientId(example - Timelog activity id) + * + * @return boolean True if successful, false if an error occurs. + * + * @since __DEPLOY_VERSION__ + */ + public function deleteMedia($mediaId, $deletePath, $client, $clientId) + { + JLoader::import("/techjoomla/media/tables/xref", JPATH_LIBRARIES); + JLoader::import("/techjoomla/media/tables/files", JPATH_LIBRARIES); + $tableXref = Table::getInstance('Xref', 'TJMediaTable'); + $filetable = Table::getInstance('Files', 'TJMediaTable'); + + // CheckMediaDataExist will return 1 when media is present clientId is Report Id + $checkMediaDataExist = $tableXref->load(array('media_id' => $mediaId, 'client_id' => $clientId)); + + // Making file delete path + $mediaPresent = $filetable->load($mediaId); + + $mediaType = explode(".", $filetable->type); + $deletePath = $deletePath . '/' . $mediaType[0]; + + // If Media is present + if ($checkMediaDataExist) + { + // Get Object which include Media xref + Media File data of provided Media xref id + $mediaXrefLib = TJMediaXref::getInstance(array('id' => $tableXref->id)); + + // If media is not deleted it will return false here + if ($mediaXrefLib->delete()) + { + // If media xref delete then delete main entry from media_files + $mediaLib = TJMediaStorageLocal::getInstance(array('id' => $mediaId, 'uploadPath' => $deletePath)); + + // Checking Media is present or not + if ($mediaLib->id) + { + // If Media is not deleted + if (!$mediaLib->delete()) + { + return false; + } + } + + return true; + } + else + { + return false; + } + } + elseif ($mediaPresent) + { + $mediaLib = TJMediaStorageLocal::getInstance(array('id' => $mediaId, 'uploadPath' => $deletePath)); + + if ($mediaLib->id) + { + if ($mediaLib->delete()) + { + return true; + } + else + { + return false; + } + } + } + + return true; + } + + /** + * Method to validate the form data. + * + * @param \JForm $form The form to validate against. + * @param Array $data The data to validate. + * + * @return array|boolean Array of filtered data if valid, false otherwise. + * + * @since __DEPLOY_VERSION__ + */ + public function validate($form, $data) + { + $return = true; + $return = parent::validate($form, $data); + + if (!empty($data['expired_on']) && $data['expired_on'] != '0000-00-00 00:00:00') + { + if ($data['issued_on'] > $data['expired_on']) + { + $this->setError(Text::_('COM_TJCERTIFICATE_EXPIRY_DATE_VALIDATION_MESSAGE')); + $return = false; + } + } + + return $return; + } +} diff --git a/src/components/com_tjcertificate/administrator/sql/install.mysql.utf8.sql b/src/components/com_tjcertificate/administrator/sql/install.mysql.utf8.sql index d5b51fee..e50305b3 100644 --- a/src/components/com_tjcertificate/administrator/sql/install.mysql.utf8.sql +++ b/src/components/com_tjcertificate/administrator/sql/install.mysql.utf8.sql @@ -33,6 +33,48 @@ CREATE TABLE IF NOT EXISTS `#__tj_certificate_issue` ( `state` tinyint(3) NOT NULL, `issued_on` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', `expired_on` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', + `is_external` tinyint(1) NOT NULL DEFAULT '0', + `name` varchar(255) NOT NULL, + `issuing_org` varchar(255) NOT NULL, + `cert_url` text NULL, + `cert_file` varchar(255) NOT NULL, + `created_by` int(11) NOT NULL, + `access` tinyint(1) NOT NULL DEFAULT '0', + `status` varchar(64) NULL, PRIMARY KEY (`id`), UNIQUE KEY unqk_certificate_id (`unique_certificate_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_unicode_ci; + +-- +-- Table structure for table `#__tj_media_files` +-- + +CREATE TABLE IF NOT EXISTS `#__tj_media_files` ( + `id` int(11) unsigned NOT NULL AUTO_INCREMENT, + `title` varchar(250) NOT NULL, + `type` varchar(250) NOT NULL, + `path` varchar(250) COLLATE utf8mb4_bin NOT NULL, + `state` tinyint(1) NOT NULL, + `source` varchar(250) NOT NULL, + `original_filename` varchar(250) COLLATE utf8mb4_bin NOT NULL, + `size` int(11) NOT NULL, + `storage` varchar(250) NOT NULL, + `created_by` int(11) NOT NULL, + `access` tinyint(1) NOT NULL, + `created_date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', + `params` varchar(500) NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_unicode_ci AUTO_INCREMENT=1; + +-- +-- Table structure for table `#__tj_media_files_xref` +-- + +CREATE TABLE IF NOT EXISTS `#__tj_media_files_xref` ( + `id` int(11) unsigned NOT NULL AUTO_INCREMENT, + `media_id` int(11) NOT NULL, + `client_id` int(11) NOT NULL, + `client` varchar(250) NOT NULL, + `is_gallery` tinyint(1) NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_unicode_ci AUTO_INCREMENT=1; diff --git a/src/components/com_tjcertificate/administrator/sql/updates/mysql/1.0.3.sql b/src/components/com_tjcertificate/administrator/sql/updates/mysql/1.0.3.sql new file mode 100644 index 00000000..de1b71f4 --- /dev/null +++ b/src/components/com_tjcertificate/administrator/sql/updates/mysql/1.0.3.sql @@ -0,0 +1,42 @@ +ALTER TABLE `#__tj_certificate_issue` ADD COLUMN `is_external` tinyint(1) NOT NULL DEFAULT '0' AFTER `expired_on`; +ALTER TABLE `#__tj_certificate_issue` ADD COLUMN `name` varchar(255) NOT NULL AFTER `is_external`; +ALTER TABLE `#__tj_certificate_issue` ADD COLUMN `issuing_org` varchar(255) NOT NULL AFTER `name`; +ALTER TABLE `#__tj_certificate_issue` ADD COLUMN `cert_url` text NULL AFTER `issuing_org`; +ALTER TABLE `#__tj_certificate_issue` ADD COLUMN `cert_file` varchar(255) NOT NULL AFTER `cert_url`; +ALTER TABLE `#__tj_certificate_issue` ADD COLUMN `access` tinyint(1) NOT NULL DEFAULT '0' AFTER `cert_file`; +ALTER TABLE `#__tj_certificate_issue` ADD COLUMN `created_by` int(11) NOT NULL AFTER `access`; +ALTER TABLE `#__tj_certificate_issue` ADD COLUMN `status` varchar(64) NULL AFTER `created_by`; + +-- +-- Table structure for table `#__tj_media_files` +-- + +CREATE TABLE IF NOT EXISTS `#__tj_media_files` ( + `id` int(11) unsigned NOT NULL AUTO_INCREMENT, + `title` varchar(250) NOT NULL, + `type` varchar(250) NOT NULL, + `path` varchar(250) COLLATE utf8mb4_bin NOT NULL, + `state` tinyint(1) NOT NULL, + `source` varchar(250) NOT NULL, + `original_filename` varchar(250) COLLATE utf8mb4_bin NOT NULL, + `size` int(11) NOT NULL, + `storage` varchar(250) NOT NULL, + `created_by` int(11) NOT NULL, + `access` tinyint(1) NOT NULL, + `created_date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', + `params` varchar(500) NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_unicode_ci AUTO_INCREMENT=1; + +-- +-- Table structure for table `#__tj_media_files_xref` +-- + +CREATE TABLE IF NOT EXISTS `#__tj_media_files_xref` ( + `id` int(11) unsigned NOT NULL AUTO_INCREMENT, + `media_id` int(11) NOT NULL, + `client_id` int(11) NOT NULL, + `client` varchar(250) NOT NULL, + `is_gallery` tinyint(1) NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_unicode_ci AUTO_INCREMENT=1; diff --git a/src/components/com_tjcertificate/administrator/tjcertificate.php b/src/components/com_tjcertificate/administrator/tjcertificate.php index 202eae8c..781effbd 100644 --- a/src/components/com_tjcertificate/administrator/tjcertificate.php +++ b/src/components/com_tjcertificate/administrator/tjcertificate.php @@ -15,6 +15,7 @@ use Joomla\CMS\MVC\Controller\BaseController; JLoader::import('components.com_tjcertificate.includes.tjcertificate', JPATH_ADMINISTRATOR); +TJCERT::init('admin'); JLoader::registerPrefix('TjCertificate', JPATH_ADMINISTRATOR); JLoader::register('TjCertificateController', JPATH_ADMINISTRATOR . '/controller.php'); diff --git a/src/components/com_tjcertificate/administrator/tjcertificateTemplate.json b/src/components/com_tjcertificate/administrator/tjcertificateTemplate.json new file mode 100644 index 00000000..dce916ef --- /dev/null +++ b/src/components/com_tjcertificate/administrator/tjcertificateTemplate.json @@ -0,0 +1,158 @@ +{ + "template1": { + "id": "", + "client": "com_tjcertificate", + "key": "assignRecordMailToUser", + "title": "Learning Record Added by Admin", + "user_control": 1, + "state": 1, + "core": 1, + "email":{ + "state": 1, + "cc": "", + "bcc": "", + "from_name": "", + "from_email": "", + "emailfields": { + "emailfields0": { + "id": "", + "language": "*", + "subject": "A New Learning Record \"{{record.name}}\" has been added against you", + "body": "

Dear {{user.name}},

A new record {{record.name}} added by {{assigner.name}}.

" + } + } + }, + "replacement_tags":[ + { + "name": "user.name", + "description": "Name of record owner" + }, + { + "name": "info.sitename", + "description": "Sitename" + }, + { + "name": "assigner.name", + "description": "Record assigner name" + }, + { + "name": "record.name", + "description": "Name of record" + } + ] + }, + "template2": { + "id": "", + "client": "com_tjcertificate", + "key": "createRecordMailTouser", + "title": "User has Submitted a Learning Record", + "user_control": 1, + "state": 1, + "core": 1, + "email":{ + "state": 1, + "cc": "", + "bcc": "", + "from_name": "", + "from_email": "", + "emailfields": { + "emailfields0": { + "id": "", + "language": "*", + "subject": "Record {{record.name}} added by you", + "body": "

Dear {{user.name}},

You have added record {{record.name}}.

" + } + } + }, + "replacement_tags":[ + { + "name": "user.name", + "description": "Name of record owner" + }, + { + "name": "info.sitename", + "description": "Sitename" + }, + { + "name": "record.name", + "description": "Name of record" + } + ] + }, + "template3": { + "id": "", + "client": "com_tjcertificate", + "key": "createRecordMailToAdmin", + "title": "Admin Notification when user Submits a Learning Record", + "user_control": 1, + "state": 1, + "core": 1, + "email":{ + "state": 1, + "cc": "", + "bcc": "", + "from_name": "", + "from_email": "", + "emailfields": { + "emailfields0": { + "id": "", + "language": "*", + "subject": "A new record {{record.name}} added", + "body": "

Hello Admin,

A new Record : {{record.name}} was added by {{user.name}} on {{info.sitename}}.

" + } + } + }, + "replacement_tags":[ + { + "name": "user.name", + "description": "Name of record owner" + }, + { + "name": "info.sitename", + "description": "Sitename" + }, + { + "name": "record.name", + "description": "Name of record" + } + ] + }, + "template4": { + "id": "", + "client": "com_tjcertificate", + "key": "recordPublishMailToUser", + "title": "Learning Record Approval Email Sent to user", + "user_control": 1, + "state": 1, + "core": 1, + "email":{ + "state": 1, + "cc": "", + "bcc": "", + "from_name": "", + "from_email": "", + "emailfields": { + "emailfields0": { + "id": "", + "language": "*", + "subject": "Record {{record.name}} is approved", + "body": "

Dear {{user.name}},

Your record {{record.name}} is approved.

" + } + } + }, + "replacement_tags":[ + { + "name": "user.name", + "description": "Name of record owner" + }, + { + "name": "info.sitename", + "description": "Sitename" + }, + { + "name": "record.name", + "description": "Name of record" + } + ] + } +} diff --git a/src/components/com_tjcertificate/administrator/views/certificate/tmpl/edit.php b/src/components/com_tjcertificate/administrator/views/certificate/tmpl/edit.php index 8dd9eeb3..69ae886a 100644 --- a/src/components/com_tjcertificate/administrator/views/certificate/tmpl/edit.php +++ b/src/components/com_tjcertificate/administrator/views/certificate/tmpl/edit.php @@ -15,16 +15,41 @@ use Joomla\CMS\Language\Text; use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\Router\Route; +use Joomla\CMS\Layout\LayoutHelper; HTMLHelper::addIncludePath(JPATH_COMPONENT . '/helpers/html'); +HTMLHelper::_('jquery.token'); +HTMLHelper::_('behavior.framework'); HTMLHelper::_('behavior.formvalidator'); HTMLHelper::_('behavior.keepalive'); HTMLHelper::_('formbehavior.chosen', 'select'); + +$options['relative'] = true; +HTMLHelper::_('script', 'com_tjcertificate/tjCertificateService.min.js', $options); +HTMLHelper::_('script', 'com_tjcertificate/template.min.js', $options); + +$app = Factory::getApplication(); +$input = $app->input; + +$client = $input->getCmd('client', ''); +$extension = $input->getCmd('extension', ''); + +$clientUrlAppend = ''; + +if (!empty($extension)) +{ + $clientUrlAppend = '&extension=' . $extension; +} +elseif (!empty($client)) +{ + $clientUrlAppend = '&client=' . $client; +} + ?>
-
sidebar)) { @@ -63,3 +88,19 @@
+ + + diff --git a/src/components/com_tjcertificate/administrator/views/certificate/view.html.php b/src/components/com_tjcertificate/administrator/views/certificate/view.html.php index 887236cd..fc3a93f9 100644 --- a/src/components/com_tjcertificate/administrator/views/certificate/view.html.php +++ b/src/components/com_tjcertificate/administrator/views/certificate/view.html.php @@ -14,6 +14,7 @@ use Joomla\CMS\Factory; use Joomla\CMS\Language\Text; use Joomla\CMS\MVC\View\HtmlView; +use Joomla\CMS\Router\Route; /** * View to edit @@ -68,21 +69,24 @@ class TjCertificateViewCertificate extends HtmlView */ public function display($tpl = null) { + $app = Factory::getApplication(); $this->state = $this->get('State'); $this->item = $this->get('Item'); + + // If training record then redirect to training record form + if ($this->item->is_external) + { + $app->redirect( + Route::_('index.php?option=com_tjcertificate&view=trainingrecord&layout=edit&id=' . $this->item->id, false) + ); + } + $this->form = $this->get('Form'); $this->input = Factory::getApplication()->input; $this->canDo = JHelperContent::getActions('com_tjcertificate', 'certificate', $this->item->id); $layout = $this->input->get('layout', 'edit'); - if ($layout == 'edit') - { - JError::raiseNotice(403, Text::_('COM_TJCERTIFICATE_ERROR_CERTIFICATE_EDIT_NOT_PERMITTED')); - - return false; - } - // Check for errors. if (count($errors = $this->get('Errors'))) { @@ -143,7 +147,6 @@ protected function addToolbar() JToolbarHelper::apply('certificate.apply'); JToolbarHelper::save('certificate.save'); JToolbarHelper::save2new('certificate.save2new'); - JToolbarHelper::cancel('certificate.cancel'); } else { @@ -151,6 +154,16 @@ protected function addToolbar() // Can't save the record if it's checked out and editable $this->canSave($itemEditable); + } + + JToolbarHelper::modal('templatePreview', 'icon-eye', 'COM_TJCERTIFICATE_CERTIFICATE_TEMPLATE_TOOLBAR_PREVIEW'); + + if (empty($this->item->id)) + { + JToolbarHelper::cancel('certificate.cancel'); + } + else + { JToolbarHelper::cancel('certificate.cancel', 'JTOOLBAR_CLOSE'); } } diff --git a/src/components/com_tjcertificate/administrator/views/certificates/tmpl/default.php b/src/components/com_tjcertificate/administrator/views/certificates/tmpl/default.php index 4113aa13..3fabe596 100644 --- a/src/components/com_tjcertificate/administrator/views/certificates/tmpl/default.php +++ b/src/components/com_tjcertificate/administrator/views/certificates/tmpl/default.php @@ -30,15 +30,8 @@ $listOrder = $this->escape($this->state->get('list.ordering')); $listDirn = $this->escape($this->state->get('list.direction')); -$saveOrder = $listOrder == 'ci.id'; $dispatcher = JDispatcher::getInstance(); PluginHelper::importPlugin('content'); - -if ( $saveOrder ) -{ - $saveOrderingUrl = 'index.php?option=com_tjcertificate&task=certificates.saveOrderAjax'; - HTMLHelper::_('sortablelist.sortable', 'certificateList', 'adminForm', strtolower($listDirn), $saveOrderingUrl); -} ?>
@@ -87,7 +80,6 @@ - @@ -107,13 +99,12 @@ - + - + - @@ -131,6 +122,7 @@ items as $i => $item) { + $certificateObj = TJCERT::Certificate($item->id); $data = $dispatcher->trigger('getCertificateClientData', array($item->client_id, $item->client)); $item->max_ordering = 0; @@ -153,16 +145,15 @@
- + ?> + escape($item->unique_certificate_id); ?> + } + else + { + ?> escape($item->unique_certificate_id); ?> title)) ? $data[0]->title : '-'; + if ($item->is_external) + { + echo $item->name; + } + else + { + echo ($data[0]->title ? $data[0]->title : "-"); + } ?> - issued_on, Text::_('DATE_FORMAT_LC')); ?> + getFormatedDate($item->issued_on); ?> expired_on) && $item->expired_on != '0000-00-00 00:00:00') { - echo HTMLHelper::date($item->expired_on, Text::_('DATE_FORMAT_LC')); + echo $certificateObj->getFormatedDate($item->expired_on); } else { @@ -210,16 +208,23 @@ echo TEXT::_($client); ?> - escape($item->title); ?> toSql(); - + $link = ""; if ($item->expired_on > $utcNow || $item->expired_on == '0000-00-00 00:00:00') { // Get TJcertificate url for display certificate - $urlOpts = array ('absolute' => ''); - $link = TJCERT::Certificate($item->id)->getUrl($urlOpts, false); + $urlOpts = array ('absolute' => true); + + if ($item->is_external) + { + $link = $certificateObj->getUrl($urlOpts, false, true); + } + else + { + $link = $certificateObj->getUrl($urlOpts, false); + } ?>
- escape($item->comment); ?> + + + + + + + + id; ?> canDo; - /*if ($canDo->get('core.create')) + if ($canDo->get('core.create')) { JToolbarHelper::addNew('certificate.add'); } + if ($canDo->get('certificate.external.create')) + { + JToolbarHelper::addNew('trainingrecord.add', 'COM_TJCERTIFICATE_ADD_EXTERNAL_CERTIFICATE'); + } + if ($canDo->get('core.edit')) { JToolbarHelper::editList('certificate.edit'); @@ -156,7 +161,6 @@ protected function addToolbar() JToolbarHelper::deleteList('JGLOBAL_CONFIRM_DELETE', 'certificates.delete', 'JTOOLBAR_DELETE'); JToolbarHelper::divider(); } - */ if ($canDo->get('core.admin') || $canDo->get('core.options')) { diff --git a/src/components/com_tjcertificate/administrator/views/template/tmpl/edit.php b/src/components/com_tjcertificate/administrator/views/template/tmpl/edit.php index 8de3209f..fee116ad 100644 --- a/src/components/com_tjcertificate/administrator/views/template/tmpl/edit.php +++ b/src/components/com_tjcertificate/administrator/views/template/tmpl/edit.php @@ -141,39 +141,19 @@
- - - - + diff --git a/src/components/com_tjcertificate/administrator/views/templates/tmpl/default.php b/src/components/com_tjcertificate/administrator/views/templates/tmpl/default.php index 4d26991d..1a1b6525 100644 --- a/src/components/com_tjcertificate/administrator/views/templates/tmpl/default.php +++ b/src/components/com_tjcertificate/administrator/views/templates/tmpl/default.php @@ -100,7 +100,7 @@ - + @@ -201,7 +201,13 @@
- escape($item->client); ?> + + client); + $client = strtoupper("COM_TJCERTIFICATE_CLIENT_" . $client); + echo TEXT::_($client); + ?> + is_public); ?> escape($item->uname); ?> id; ?> diff --git a/src/components/com_tjcertificate/administrator/views/trainingrecord/index.html b/src/components/com_tjcertificate/administrator/views/trainingrecord/index.html new file mode 100644 index 00000000..e69de29b diff --git a/src/components/com_tjcertificate/administrator/views/trainingrecord/tmpl/edit.php b/src/components/com_tjcertificate/administrator/views/trainingrecord/tmpl/edit.php new file mode 100644 index 00000000..0ffc182f --- /dev/null +++ b/src/components/com_tjcertificate/administrator/views/trainingrecord/tmpl/edit.php @@ -0,0 +1,111 @@ + + * @copyright Copyright (C) 2009 - 2020 Techjoomla. All rights reserved. + * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL + */ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\Factory; +use Joomla\CMS\Language\Text; +use Joomla\CMS\HTML\HTMLHelper; +use Joomla\CMS\Router\Route; +use Joomla\CMS\Layout\LayoutHelper; +use Joomla\CMS\Uri\Uri; + +HTMLHelper::addIncludePath(JPATH_COMPONENT . '/helpers/html'); + +HTMLHelper::_('jquery.token'); +HTMLHelper::_('behavior.framework'); +HTMLHelper::_('behavior.formvalidator'); +HTMLHelper::_('behavior.keepalive'); +HTMLHelper::_('formbehavior.chosen', 'select'); + +$options['relative'] = true; +HTMLHelper::_('script', 'com_tjcertificate/tjCertificateService.min.js', $options); +HTMLHelper::_('script', 'com_tjcertificate/certificate.min.js', $options); +?> +
+
+
+ sidebar)) + { + ?> +
+ sidebar; ?> +
+
+ +
+ +
+ + +
+ form->renderField('id'); ?> + form->renderField('assigned_user_id'); ?> + form->renderField('name'); ?> + form->renderField('unique_certificate_id'); ?> + form->renderField('cert_url'); ?> + form->renderField('issuing_org'); ?> + form->renderField('issued_on'); ?> + form->renderField('expired_on'); ?> + form->renderField('status'); ?> +
+
form->getLabel('cert_file'); ?>
+
+ form->getInput('cert_file'); ?> + item->mediaData[0]) + { + $downloadAttachmentLink = Uri::root() . 'index.php?option=com_tjcertificate&task=trainingrecord.downloadAttachment&id=' . $this->item->mediaData[0]->media_id . '&recordId=' . $this->item->id; + echo ''; + ?> + + item->mediaData[0]->title;?> + + + + + + +
+
+ form->renderField('state'); ?> + form->renderField('comment'); ?> + +
+ + + +
+ +
+
+ + diff --git a/src/components/com_tjcertificate/administrator/views/trainingrecord/tmpl/index.html b/src/components/com_tjcertificate/administrator/views/trainingrecord/tmpl/index.html new file mode 100644 index 00000000..e69de29b diff --git a/src/components/com_tjcertificate/administrator/views/trainingrecord/tmpl/preview.php b/src/components/com_tjcertificate/administrator/views/trainingrecord/tmpl/preview.php new file mode 100644 index 00000000..52d5fe3c --- /dev/null +++ b/src/components/com_tjcertificate/administrator/views/trainingrecord/tmpl/preview.php @@ -0,0 +1,95 @@ + + * @copyright Copyright (C) 2009 - 2020 Techjoomla. All rights reserved. + * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL + */ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); +use Joomla\CMS\Language\Text; +use Joomla\CMS\Uri\Uri; +?> +
+ + + +
+
+ +
+
+ escape($this->item->name); ?> +
+ item->cert_url) { ?> +
+ +
+
+ escape($this->item->cert_url); ?> +
+ +
+ +
+
+ escape($this->item->issuing_org); ?> +
+
+ +
+
+ escape($this->item->status)); ?> +
+
+ +
+
+ certificate->getFormatedDate($this->item->issued_on);?> +
+ item->expired_on != "0000-00-00 00:00:00") { ?> +
+ +
+
+ certificate->getFormatedDate($this->item->expired_on);?> +
+ + item->cert_file) { ?> +
+
+
+ item->mediaData[0]) + { + if ($this->item->mediaData[0]->type === "image") + { + ?> + + + + item->mediaData[0]->title;?> + + + +
+ + item->comment) { ?> +
+ +
+
+ escape($this->item->comment); ?> +
+ +
+
diff --git a/src/components/com_tjcertificate/administrator/views/trainingrecord/view.html.php b/src/components/com_tjcertificate/administrator/views/trainingrecord/view.html.php new file mode 100644 index 00000000..b9bba39a --- /dev/null +++ b/src/components/com_tjcertificate/administrator/views/trainingrecord/view.html.php @@ -0,0 +1,182 @@ + + * @copyright Copyright (C) 2009 - 2020 Techjoomla. All rights reserved. + * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL + */ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\Factory; +use Joomla\CMS\Language\Text; +use Joomla\CMS\MVC\View\HtmlView; +use Joomla\CMS\Component\ComponentHelper; + +/** + * View to edit + * + * @since __DEPLOY_VERSION__ + */ +class TjCertificateViewTrainingRecord extends HtmlView +{ + /** + * The JForm object + * + * @var JForm + */ + protected $form; + + /** + * The active item + * + * @var object + */ + protected $item; + + /** + * The model state + * + * @var object + */ + protected $state; + + /** + * The actions the user is authorised to perform + * + * @var JObject + */ + protected $canDo; + + /** + * Display the view + * + * @param string $tpl Template name + * + * @return void + * + * @throws Exception + */ + public function display($tpl = null) + { + $this->state = $this->get('State'); + $this->item = $this->get('Item'); + $this->form = $this->get('Form'); + $this->input = Factory::getApplication()->input; + $this->canDo = JHelperContent::getActions('com_tjcertificate', 'certificate', $this->item->id); + $this->params = ComponentHelper::getParams('com_tjcertificate'); + $this->allowedFileExtensions = $this->params->get('upload_extensions'); + $this->uploadLimit = $this->params->get('upload_maxsize', '1024'); + $this->certificate = TJCERT::Certificate(); + + $layout = $this->input->get('layout', 'edit'); + + // Check for errors. + if (count($errors = $this->get('Errors'))) + { + throw new Exception(implode("\n", $errors), 500); + } + + $this->addToolbar(); + + parent::display($tpl); + } + + /** + * Add the page title and toolbar. + * + * @return void + * + * @since __DEPLOY_VERSION__ + */ + protected function addToolbar() + { + $user = Factory::getUser(); + $userId = $user->id; + $isNew = empty($this->item->id); + + // Built the actions for new and existing records. + $canDo = $this->canDo; + $layout = Factory::getApplication()->input->get("layout"); + + $app = Factory::getApplication(); + + JLoader::import('administrator.components.com_tjcertificate.helpers.tjcertificate', JPATH_SITE); + TjCertificateHelper::addSubmenu('certificates'); + + if ($app->isAdmin()) + { + $this->sidebar = JHtmlSidebar::render(); + } + + // For new records, check the create permission. + if ($layout != "default") + { + Factory::getApplication()->input->set('hidemainmenu', true); + + JToolbarHelper::title( + Text::_('COM_TJCERTIFICATE_PAGE_' . ($isNew ? 'ADD_TRAINING_RECORD' : 'EDIT_TRAINING_RECORD')), + 'pencil-2 certificate-add' + ); + + if ($isNew) + { + JToolbarHelper::apply('trainingrecord.apply'); + JToolbarHelper::save('trainingrecord.save'); + JToolbarHelper::save2new('trainingrecord.save2new'); + } + else + { + $itemEditable = $this->isEditable($canDo, $userId); + + // Can't save the record if it's checked out and editable + $this->canSave($itemEditable); + } + + if (empty($this->item->id)) + { + JToolbarHelper::cancel('certificate.cancel'); + } + else + { + JToolbarHelper::cancel('certificate.cancel', 'JTOOLBAR_CLOSE'); + } + } + + JToolbarHelper::divider(); + } + + /** + * Can't save the record if it's checked out and editable + * + * @param boolean $itemEditable Item editable + * + * @return void + */ + protected function canSave($itemEditable) + { + if ($itemEditable) + { + JToolbarHelper::apply('trainingrecord.apply'); + JToolbarHelper::save('trainingrecord.save'); + } + } + + /** + * Is editable + * + * @param Object $canDo Checked Out + * + * @param integer $userId User ID + * + * @return boolean + */ + protected function isEditable($canDo, $userId) + { + // Since it's an existing record, check the edit permission, or fall back to edit own if the owner. + return $canDo->get('core.edit') || ($canDo->get('core.edit.own') && $this->item->created_by == $userId); + } +} diff --git a/src/components/com_tjcertificate/media/images/buttons/en_US.png b/src/components/com_tjcertificate/media/images/buttons/en_US.png new file mode 100644 index 0000000000000000000000000000000000000000..22fdb3a4f72c782963fea6e03f999db5bf06d83f GIT binary patch literal 139290 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 Qo~^s8*n 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 + * @copyright Copyright (C) 2009 - 2020 Techjoomla. All rights reserved. + * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL + */ + +var certificate = { + validateFile: function(thisFile) { + /** Validation is for file field only */ + if (jQuery(thisFile).attr('type') != 'file') { + return false; + } + + /** Clear error message */ + jQuery('#system-message-container').empty(); + + var uploadedfile = jQuery(thisFile)[0].files[0]; + var fileType = uploadedfile.type; + var fileExtension = uploadedfile.name.split("."); + + /** global: allowedAttachments */ + var allowedExtensionsArray = allowedAttachments.split(","); + + var invalid = 0; + var errorMsg = new Array(); + + if ((fileExtension[fileExtension.length - 1] !== '' || fileExtension[fileExtension.length - 1] !== null) && (jQuery.inArray(fileType, allowedExtensionsArray) == -1)) { + invalid = "1"; + errorMsg.push(Joomla.JText._('COM_TJCERTIFICATE_MEDIA_INVALID_FILE_TYPE')); + } + + var uploadedFileSize = uploadedfile.size; + + + /** global: attachmentMaxSize */ + if (uploadedFileSize > attachmentMaxSize * 1024 * 1024) { + + invalid = "1"; + errorMsg.push(Joomla.JText._('COM_TJCERTIFICATE_MEDIA_UPLOAD_ERROR')); + console.log("COM_TIMELOG_FILE_SIZE_ERROR"); + } + + if (invalid) { + Joomla.renderMessages({ + 'error': errorMsg + }); + + jQuery("html, body").animate({ + scrollTop: 0 + }, 500); + + return false; + } + }, + deleteAttachment: function(currentElement) { + if (confirm(Joomla.JText._('COM_TJCERTIFICATE_CONFIRM_DELETE_ATTACHMENT')) == true) { + var formData = {}; + + if (currentElement == '' || currentElement === undefined) { + return false; + } + + formData['certificateId'] = jQuery(currentElement).attr('data-aid'); + formData['mediaId'] = jQuery(currentElement).attr('data-mid'); + + var promise = tjCertificateService.deleteAttachment(formData); + + promise.fail( + function(response) { + var messages = { + "error": [response.responseText] + }; + certificate.renderMessage(messages); + } + ).done(function(response) { + + if (!response.success && response.message) { + var messages = { + "error": [response.message] + }; + certificate.renderMessage(messages); + } + + if (response.messages) { + certificate.renderMessage(response.messages); + } + + if (response.success) { + certificate.renderMessage(response.message); + } + + jQuery(currentElement).closest("span.fileupload").remove(); + }); + } + }, + deleteItem: function(certificateId, obj) { + if (confirm(Joomla.JText._('COM_TJCERTIFICATE_DELETE_CERTIFICATE_MESSAGE')) == true) { + var formData = {}; + + if (certificateId == '' || certificateId === undefined) { + return false; + } + + formData['certificateId'] = certificateId; + + var promise = tjCertificateService.deleteItem(formData); + + promise.fail( + function(response) { + var messages = { + "error": [response.responseText] + }; + certificate.renderMessage(messages); + } + ).done(function(response) { + + if (!response.success && response.message) { + var messages = { + "error": [response.message] + }; + certificate.renderMessage(messages); + } + + if (response.messages) { + certificate.renderMessage(response.messages); + } + + if (response.success) { + certificate.renderMessage(response.message); + } + + jQuery(obj).closest("tr").remove(); + }); + } + }, + renderMessage: function(msg) { + Joomla.renderMessages({ + 'alert alert-success': [msg] + }); + jQuery("html, body").animate({ + scrollTop: 0 + }, 2000); + }, + validationEndDate: function(expDateObj) { + var expDate = jQuery(expDateObj).val(); + var issueDate = jQuery('#jform_issued_on').val(); + + jQuery(document).ready(function(){ + document.formvalidator.setHandler('expdate', function (value) { + if (issueDate > expDate) { + certificate.renderMessage(Joomla.JText._('COM_TJCERTIFICATE_EXPIRY_DATE_VALIDATION_MESSAGE')); + jQuery('#jform_expired_on').val(""); + + return false; + } + + return true; + + }); + }); + } +}; diff --git a/src/components/com_tjcertificate/media/js/certificate.min.js b/src/components/com_tjcertificate/media/js/certificate.min.js new file mode 100644 index 00000000..1a871180 --- /dev/null +++ b/src/components/com_tjcertificate/media/js/certificate.min.js @@ -0,0 +1 @@ +var certificate={validateFile:function(e){if("file"!=jQuery(e).attr("type"))return!1;jQuery("#system-message-container").empty();var r=jQuery(e)[0].files[0],t=r.type,a=r.name.split("."),s=allowedAttachments.split(","),i=0,n=new Array;return""===a[a.length-1]&&null===a[a.length-1]||-1!=jQuery.inArray(t,s)||(i="1",n.push(Joomla.JText._("COM_TJCERTIFICATE_MEDIA_INVALID_FILE_TYPE"))),r.size>1024*attachmentMaxSize*1024&&(i="1",n.push(Joomla.JText._("COM_TJCERTIFICATE_MEDIA_UPLOAD_ERROR")),console.log("COM_TIMELOG_FILE_SIZE_ERROR")),i?(Joomla.renderMessages({error:n}),jQuery("html, body").animate({scrollTop:0},500),!1):void 0},deleteAttachment:function(e){if(1==confirm(Joomla.JText._("COM_TJCERTIFICATE_CONFIRM_DELETE_ATTACHMENT"))){var r={};if(""==e||void 0===e)return!1;r.certificateId=jQuery(e).attr("data-aid"),r.mediaId=jQuery(e).attr("data-mid"),tjCertificateService.deleteAttachment(r).fail(function(e){var r={error:[e.responseText]};certificate.renderMessage(r)}).done(function(r){if(!r.success&&r.message){var t={error:[r.message]};certificate.renderMessage(t)}r.messages&&certificate.renderMessage(r.messages),r.success&&certificate.renderMessage(r.message),jQuery(e).closest("span.fileupload").remove()})}},deleteItem:function(e,r){if(1==confirm(Joomla.JText._("COM_TJCERTIFICATE_DELETE_CERTIFICATE_MESSAGE"))){var t={};if(""==e||void 0===e)return!1;t.certificateId=e,tjCertificateService.deleteItem(t).fail(function(e){var r={error:[e.responseText]};certificate.renderMessage(r)}).done(function(e){if(!e.success&&e.message){var t={error:[e.message]};certificate.renderMessage(t)}e.messages&&certificate.renderMessage(e.messages),e.success&&certificate.renderMessage(e.message),jQuery(r).closest("tr").remove()})}},renderMessage:function(e){Joomla.renderMessages({"alert alert-success":[e]}),jQuery("html, body").animate({scrollTop:0},2e3)},validationEndDate:function(e){var r=jQuery(e).val(),t=jQuery("#jform_issued_on").val();jQuery(document).ready(function(){document.formvalidator.setHandler("expdate",function(e){return!(t>r)||(certificate.renderMessage(Joomla.JText._("COM_TJCERTIFICATE_EXPIRY_DATE_VALIDATION_MESSAGE")),jQuery("#jform_expired_on").val(""),!1)})})}}; diff --git a/src/components/com_tjcertificate/media/js/certificateImage.js b/src/components/com_tjcertificate/media/js/certificateImage.js index ce2977d9..71d10e80 100644 --- a/src/components/com_tjcertificate/media/js/certificateImage.js +++ b/src/components/com_tjcertificate/media/js/certificateImage.js @@ -47,6 +47,13 @@ var certificateImage = { img.src = imagePath + certificateId + ".png"; jQuery("#previewImage").append(img); setTimeout(function(){ + + if (screen.width < 1200) + { + viewport = document.querySelector("meta[name=viewport]"); + viewport.setAttribute("content", "width=device-width"); + } + Joomla.loadingLayer('hide'); }, 1000); } @@ -57,6 +64,13 @@ var certificateImage = { generateImage: function(element) { // jQuery('#certificateContent').width(element.offsetWidth).height(element.offsetHeight); + + if (screen.width < 1200) + { + viewport = document.querySelector("meta[name=viewport]"); + viewport.setAttribute("content", "width=1200px"); + } + Joomla.loadingLayer('show'); html2canvas(element, { diff --git a/src/components/com_tjcertificate/media/js/certificateImage.min.js b/src/components/com_tjcertificate/media/js/certificateImage.min.js index de5e7ab6..d677faa5 100644 --- a/src/components/com_tjcertificate/media/js/certificateImage.min.js +++ b/src/components/com_tjcertificate/media/js/certificateImage.min.js @@ -1 +1 @@ -var certificateImage={printCertificate:function(e){var t=document.getElementById(e).innerHTML,o=document.body.innerHTML;document.body.innerHTML=t,window.print(),document.body.innerHTML=o,certificateImage.enableDownloadShareBtns()},enableDownloadShareBtns:function(){jQuery("#download-popover").popover({trigger:"focus",html:!0,content:jQuery("#download-popover-content").html()}),jQuery("#sharing-popover").popover({trigger:"focus",html:!0,content:jQuery("#sharing-popover-content").html()}),jQuery("#copyurl").popover()},uploadImage:function(e){var t=!1,o=jQuery("#certificateId").val();return jQuery.ajax({url:certRootUrl+"index.php?option=com_tjcertificate&task=certificate.uploadCertificate",type:"POST",data:{image:e,certificateId:o},success:function(e){t=e;var o=jQuery("#certificateId").val(),n=certRootUrl+"media/com_tjcertificate/certificates/",r=document.createElement("img");jQuery("#certificateContent").hide(),r.src=n+o+".png",jQuery("#previewImage").append(r),setTimeout(function(){Joomla.loadingLayer("hide")},1e3)}}),t},generateImage:function(e){Joomla.loadingLayer("show"),html2canvas(e,{scrollX:0,scrollY:-window.scrollY,allowTaint:!0}).then(function(e){certificateImage.enableDownloadShareBtns(),certificateImage.uploadImage(e.toDataURL("image/png"))})},copyUrl:function(e){e="#"+e;var t=document.createElement("input"),o=jQuery(e).attr("data-alt-url");jQuery(e).popover("show"),document.body.appendChild(t),t.value=o,t.select(),document.execCommand("copy"),document.body.removeChild(t),setTimeout(function(){jQuery(e).popover("hide")},1e3)}}; \ No newline at end of file +var certificateImage={printCertificate:function(e){var t=document.getElementById(e).innerHTML,o=document.body.innerHTML;document.body.innerHTML=t,window.print(),document.body.innerHTML=o,certificateImage.enableDownloadShareBtns()},enableDownloadShareBtns:function(){jQuery("#download-popover").popover({trigger:"focus",html:!0,content:jQuery("#download-popover-content").html()}),jQuery("#sharing-popover").popover({trigger:"focus",html:!0,content:jQuery("#sharing-popover-content").html()}),jQuery("#copyurl").popover()},uploadImage:function(e){var t=!1,o=jQuery("#certificateId").val();return jQuery.ajax({url:certRootUrl+"index.php?option=com_tjcertificate&task=certificate.uploadCertificate",type:"POST",data:{image:e,certificateId:o},success:function(e){t=e;var o=jQuery("#certificateId").val(),r=certRootUrl+"media/com_tjcertificate/certificates/",n=document.createElement("img");jQuery("#certificateContent").hide(),n.src=r+o+".png",jQuery("#previewImage").append(n),setTimeout(function(){screen.width<1200&&(viewport=document.querySelector("meta[name=viewport]"),viewport.setAttribute("content","width=device-width")),Joomla.loadingLayer("hide")},1e3)}}),t},generateImage:function(e){screen.width<1200&&(viewport=document.querySelector("meta[name=viewport]"),viewport.setAttribute("content","width=1200px")),Joomla.loadingLayer("show"),html2canvas(e,{scrollX:0,scrollY:-window.scrollY,allowTaint:!0}).then(function(e){certificateImage.enableDownloadShareBtns(),certificateImage.uploadImage(e.toDataURL("image/png"))})},copyUrl:function(e){e="#"+e;var t=document.createElement("input"),o=jQuery(e).attr("data-alt-url");jQuery(e).popover("show"),document.body.appendChild(t),t.value=o,t.select(),document.execCommand("copy"),document.body.removeChild(t),setTimeout(function(){jQuery(e).popover("hide")},1e3)}}; \ No newline at end of file diff --git a/src/components/com_tjcertificate/media/js/template.js b/src/components/com_tjcertificate/media/js/template.js index ab980df2..60756439 100644 --- a/src/components/com_tjcertificate/media/js/template.js +++ b/src/components/com_tjcertificate/media/js/template.js @@ -9,19 +9,20 @@ var template = { - previewTemplate: function () { + previewTemplate: function (id) { jQuery(document).on('click', 'button[data-target="#templatePreview"]', function () { - + jQuery('#show-info').hide(); + var editorId = jQuery('#'+id); if (typeof tinyMCE != "undefined") { - tinyMCE.execCommand('mceToggleEditor', false, 'jform_body'); + tinyMCE.execCommand('mceToggleEditor', false, id); } else if (typeof CodeMirror != "undefined") { var editor = document.querySelector('.CodeMirror').CodeMirror; - jQuery('#jform_body').html(editor.getValue()); + editorId.html(editor.getValue()); } else { @@ -30,14 +31,14 @@ var template = { jQuery('#previewTempl').empty(); jQuery('"].join(" "))})}); diff --git a/src/components/com_tjcertificate/site/languages/en-GB/en-GB.com_tjcertificate.ini b/src/components/com_tjcertificate/site/languages/en-GB/en-GB.com_tjcertificate.ini index fb40598b..984e0f9a 100644 --- a/src/components/com_tjcertificate/site/languages/en-GB/en-GB.com_tjcertificate.ini +++ b/src/components/com_tjcertificate/site/languages/en-GB/en-GB.com_tjcertificate.ini @@ -125,3 +125,6 @@ COM_TJCERTIFICATE_TRAINING_RECORD_SAVE_SUCCESSFULLY="Training record saved succe COM_TJCERTIFICATE_STATUS_PENDING="Pending" COM_TJCERTIFICATE_EXPIRY_DATE_VALIDATION_MESSAGE="Expiration date should be greater than issue date" COM_TJCERTIFICATE_LBL_CERTIFICATE_URL="Url" +COM_TJCERTIFICATE_CERTIFICATE_DETAIL_VIEW_CERTIFICATE="This certificate (ID: %s ) verifies that %s has successfully completed the %s on %s." +COM_TJCERTIFICATE_CERTIFICATE_DETAIL_VIEW_AWARDED="This certificate (ID: %s ) has been awarded to %s on %s." +COM_TJCERTIFICATE_CERTIFICATE_DETAIL_VIEW_CERTIFICATE_EXPIRES=" This Certificate expires on %s" diff --git a/src/components/com_tjcertificate/site/views/certificate/tmpl/default.php b/src/components/com_tjcertificate/site/views/certificate/tmpl/default.php index 95201de4..d65ccb61 100644 --- a/src/components/com_tjcertificate/site/views/certificate/tmpl/default.php +++ b/src/components/com_tjcertificate/site/views/certificate/tmpl/default.php @@ -25,6 +25,7 @@ HTMLHelper::StyleSheet('media/com_tjcertificate/css/tjCertificate.css'); HTMLHelper::StyleSheet('media/com_tjlms/vendors/artificiers/artficier.css'); HTMLHelper::script('media/com_tjcertificate/vendors/html2canvas/js/html2canvas.js'); +HTMLHelper::script('media/com_tjcertificate/vendors/loader/js/loadingoverlay.min.js'); HTMLHelper::script('com_tjcertificate/certificateImage.min.js', $options); $imageUrl = ""; @@ -171,22 +172,17 @@

item->title) - { ?> - This certificate (ID: certificate->unique_certificate_id;?>) verifies that certificate->getUserId())->name; ?> has successfully completed the item->title; ?> on certificate->issued_on, Text::_('COM_TJCERTIFICATE_CERTIFICATE_DETAIL_VIEW_DATE_FORMAT'));?>. - certificate->unique_certificate_id, Factory::getUser($this->certificate->getUserId())->name, $this->item->title, HTMLHelper::_('date', $this->certificate->issued_on, Text::_('COM_TJCERTIFICATE_CERTIFICATE_DETAIL_VIEW_DATE_FORMAT'))); } else - { ?> - This certificate (ID: certificate->unique_certificate_id;?>) has been awarded to certificate->getUserId())->name; ?> on certificate->issued_on, Text::_('COM_TJCERTIFICATE_CERTIFICATE_DETAIL_VIEW_DATE_FORMAT'));?>. - certificate->unique_certificate_id, Factory::getUser($this->certificate->getUserId())->name, HTMLHelper::_('date', $this->certificate->issued_on, Text::_('COM_TJCERTIFICATE_CERTIFICATE_DETAIL_VIEW_DATE_FORMAT'))); } - ?> - certificate->getExpiry() != '0000-00-00 00:00:00') { - ?> - This Certificate expires on certificate->getExpiry(), Text::_('COM_TJCERTIFICATE_CERTIFICATE_DETAIL_VIEW_DATE_FORMAT'));?>. - certificate->getExpiry(), Text::_('COM_TJCERTIFICATE_CERTIFICATE_DETAIL_VIEW_DATE_FORMAT'))); } ?>
diff --git a/src/components/com_tjcertificate/tjcertificate.xml b/src/components/com_tjcertificate/tjcertificate.xml index b81efb91..ab275f43 100644 --- a/src/components/com_tjcertificate/tjcertificate.xml +++ b/src/components/com_tjcertificate/tjcertificate.xml @@ -8,7 +8,7 @@ extensions@techjoomla.com http://techjoomla.com - 1.0.4 + 1.0.5 From a97585b40f3234a7a02de4b81ddebe60b9d10d98 Mon Sep 17 00:00:00 2001 From: Tushar Shekokar Date: Wed, 24 Mar 2021 11:57:19 +0530 Subject: [PATCH 04/25] Feature #168713 feat: Make Tj-certificate multi-agency aware (#96) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update tjcertificate.xml * Bug #168296 Fix: Certificate view - Text is not coming from language constant. (#92) * Bug #168296 Fix: Certificate view - Text is not coming from language constant. * Bug #168296 Fix: Certificate view - Text is not coming from language constant. * Task #168311 feat: Remove duplicates Language constant from language … (#93) * Task #168311 feat: Remove duplicates Language constant from language files. * Task #168311 feat: Remove duplicates Language constant from language files. * Task #168722 chore: Add jQuery LoadingOverlay (#95) * Feature #168713 feat: Make Tj-certificate multi-agency aware * Feature #168713 feat: Make Tj-certificate multi-agency aware * Feature #168713 feat: Make Tj-certificate multi-agency aware * Feature #168713 feat: Make Tj-certificate multi-agency aware * Feature #168713 feat: Make Tj-certificate multi-agency aware * Feature #168713 feat: Resolve scrutinizer issues * Feature #168713 feat: Resolve scrutinizer issues * Feature #168713 feat: Make Tj-certificate multi-agency aware * Feature #168713 feat: Make Tj-certificate multi-agency aware * Feature #168713 feat: Make Tj-certificate multi-agency aware * Feature #168713 feat: Resolve comments * Feature #168713 feat: Bug #169802 fix * Feature #168713 feat: Resolve comments * Feature #168713 feat: Resolve comments * Feature #168713 feat: Make Tj-certificate multi-agency aware * Feature #168713 feat: Functionality improvements * Feature #168713 feat: Functionality improvements * Feature #168713 feat: Resolve comment Co-authored-by: praneettekdi Co-authored-by: MeghaBiranje <58220237+MeghaBiranje@users.noreply.github.com> Co-authored-by: Rohan Shinde <37367348+shindebalu@users.noreply.github.com> --- .../administrator/config.xml | 4 + .../administrator/controllers/agency.json.php | 90 ++++++++++ .../en-GB/en-GB.com_tjcertificate.ini | 13 +- .../administrator/models/agency.php | 165 ++++++++++++++++++ .../administrator/models/certificates.php | 63 ++++++- .../administrator/models/fields/allusers.php | 86 +++++++++ .../models/forms/filter_certificates.xml | 10 +- .../models/forms/trainingrecord.xml | 17 +- .../administrator/models/trainingrecord.php | 75 +++++++- .../views/certificates/tmpl/default.php | 13 ++ .../views/certificates/view.html.php | 17 ++ .../views/trainingrecord/tmpl/edit.php | 11 ++ .../views/trainingrecord/view.html.php | 9 + .../com_tjcertificate/media/js/certificate.js | 46 ++++- .../media/js/certificate.min.js | 2 +- .../media/js/tjCertificateService.js | 4 + .../media/js/tjCertificateService.min.js | 2 +- .../site/controllers/agency.json.php | 15 ++ .../en-GB/en-GB.com_tjcertificate.ini | 12 ++ .../com_tjcertificate/site/models/agency.php | 14 ++ .../site/models/fields/agencies.php | 99 +++++++++++ .../site/models/forms/filter_certificates.xml | 10 +- .../site/models/forms/trainingrecord.xml | 18 +- .../site/views/certificates/tmpl/my.php | 22 ++- .../site/views/certificates/view.html.php | 21 ++- .../site/views/trainingrecord/tmpl/edit.php | 14 +- .../site/views/trainingrecord/view.html.php | 42 ++++- 27 files changed, 848 insertions(+), 46 deletions(-) create mode 100644 src/components/com_tjcertificate/administrator/controllers/agency.json.php create mode 100644 src/components/com_tjcertificate/administrator/models/agency.php create mode 100644 src/components/com_tjcertificate/administrator/models/fields/allusers.php create mode 100644 src/components/com_tjcertificate/site/controllers/agency.json.php create mode 100644 src/components/com_tjcertificate/site/models/agency.php create mode 100644 src/components/com_tjcertificate/site/models/fields/agencies.php diff --git a/src/components/com_tjcertificate/administrator/config.xml b/src/components/com_tjcertificate/administrator/config.xml index 028b934d..a5e2a904 100644 --- a/src/components/com_tjcertificate/administrator/config.xml +++ b/src/components/com_tjcertificate/administrator/config.xml @@ -49,6 +49,10 @@ + + + +
diff --git a/src/components/com_tjcertificate/administrator/controllers/agency.json.php b/src/components/com_tjcertificate/administrator/controllers/agency.json.php new file mode 100644 index 00000000..269d7258 --- /dev/null +++ b/src/components/com_tjcertificate/administrator/controllers/agency.json.php @@ -0,0 +1,90 @@ + + * @copyright Copyright (C) 2009 - 2021 Techjoomla. All rights reserved. + * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL + */ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\Factory; +use Joomla\CMS\Language\Text; +use Joomla\CMS\MVC\Controller\FormController; +use Joomla\CMS\Session\Session; +use Joomla\CMS\Response\JsonResponse; +use Joomla\CMS\HTML\HTMLHelper; + +/** + * The Tj Certificate Agency controller + * + * @since __DEPLOY_VERSION__ + */ +class TjCertificateControllerAgency extends FormController +{ + protected $comMultiAgency = 'com_multiagency'; + + /** + * Function to get agency users + * + * @return void|boolean + * + * @since __DEPLOY_VERSION__ + */ + public function getAgencyUsers() + { + $app = Factory::getApplication(); + + if (!Session::checkToken()) + { + $app->enqueueMessage(Text::_('JINVALID_TOKEN'), 'error'); + echo new JsonResponse(null, null, true); + $app->close(); + } + + // Get the current user id + $user = Factory::getuser(); + + if (!$user->id) + { + return false; + } + + if (!$user->authorise('core.manage.own.agency.user', $this->comMultiAgency)) + { + return false; + } + + $agencyId = $app->input->get('agency_id', 0, 'INT'); + + $model = $this->getModel(); + + if (!$model->validateUserAgency($agencyId)) + { + $app->enqueueMessage(Text::_('COM_TJCERTIFICATE_AGENCY_INVALID_USER'), 'error'); + echo new JsonResponse(null, null, true); + $app->close(); + } + + $userOptions = array(); + + // Initialize array to store dropdown options + $userOptions[] = HTMLHelper::_('select.option', "", Text::_('COM_TJCERTIFICATE_AGENCY_USER_SELECT')); + + $users = $model->getUsers($agencyId); + + if (!empty($users)) + { + foreach ($users as $user) + { + $userOptions[] = HTMLHelper::_('select.option', $user->id, trim($user->name)); + } + } + + echo new JsonResponse($userOptions); + $app->close(); + } +} diff --git a/src/components/com_tjcertificate/administrator/languages/en-GB/en-GB.com_tjcertificate.ini b/src/components/com_tjcertificate/administrator/languages/en-GB/en-GB.com_tjcertificate.ini index dd79f25c..67ce4e95 100644 --- a/src/components/com_tjcertificate/administrator/languages/en-GB/en-GB.com_tjcertificate.ini +++ b/src/components/com_tjcertificate/administrator/languages/en-GB/en-GB.com_tjcertificate.ini @@ -82,7 +82,7 @@ COM_TJCERTIFICATE_CERTIFICATE_FORM_DESC_CERTIFICATE_CLIENT_ID="Id of client reco COM_TJCERTIFICATE_CERTIFICATE_FORM_LBL_CERTIFICATE_ISSUED_USER="User" COM_TJCERTIFICATE_CERTIFICATE_FORM_DESC_CERTIFICATE_ISSUED_USER="User against whom the certificate is issued" COM_TJCERTIFICATE_CERTIFICATE_FORM_LBL_CERTIFICATE_COMMENT="Comment" -COM_TJCERTIFICATE_CERTIFICATE_FORM_DESC_CERTIFICATE_ISSUED_COMMENT="Comment" +COM_TJCERTIFICATE_CERTIFICATE_FORM_DESC_CERTIFICATE_ISSUED_COMMENT="Add Comment" COM_TJCERTIFICATE_CERTIFICATE_FORM_LBL_CERTIFICATE_ISSUED_DATE="Issue Date" COM_TJCERTIFICATE_CERTIFICATE_FORM_DESC_CERTIFICATE_ISSUED_DATE="Certificate issue date" COM_TJCERTIFICATE_CERTIFICATE_FORM_LBL_CERTIFICATE_EXPIRY_DATE="Expiration Date" @@ -354,3 +354,14 @@ COM_TJCERTIFICATE_TRAINING_RECORD_SAVE_SUCCESSFULLY="Training record saved succe COM_TJCERTIFICATE_STATUS_PENDING="Pending" COM_TJCERTIFICATE_EXPIRY_DATE_VALIDATION_MESSAGE="Expiration date should be greater than issue date" COM_TJCERTIFICATE_LBL_CERTIFICATE_URL="Url" + +;config +COM_TJCERTIFICATE_INTEGRATE_MULTIAGENCY="Enable Organization Support" +COM_TJCERTIFICATE_INTEGRATE_MULTIAGENCY_DESC="If you enable this then you can add certificate for organization users and also you can filter certificates by using orginzation filter (Note: To work this functionality you need com_multiagency and com_cluster)." + +;List view and form +COM_TJCERTIFICATE_CERTIFICATE_LIST_VIEW_USERNAME="User" +COM_TJCERTIFICATE_CERTIFICATE_LIST_VIEW_ORG_NAME="Organization" +COM_TJCERTIFICATE_ORG_SELECT="Select Organization" +COM_TJCERTIFICATE_FORM_CLUSTER_LBL="Select user for Organization" +COM_TJCERTIFICATE_AGENCY_USER_SELECT="Select User" diff --git a/src/components/com_tjcertificate/administrator/models/agency.php b/src/components/com_tjcertificate/administrator/models/agency.php new file mode 100644 index 00000000..1e385c7c --- /dev/null +++ b/src/components/com_tjcertificate/administrator/models/agency.php @@ -0,0 +1,165 @@ + + * @copyright Copyright (C) 2009 - 2021 Techjoomla. All rights reserved. + * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL + */ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\Factory; +use Joomla\CMS\MVC\Model\AdminModel; +use Joomla\CMS\Component\ComponentHelper; + +/** + * TjCertificate Agency Model. + * + * @since __DEPLOY_VERSION__ + */ +class TjCertificateModelAgency extends AdminModel +{ + protected $comMultiAgency = 'com_multiagency'; + + public $params; + + public $user; + + /** + * Constructor. + * + * @param array $config An optional associative array of configuration settings. + * + * @since __DEPLOY_VERSION__ + */ + public function __construct($config = array()) + { + $this->params = ComponentHelper::getParams('com_tjcertificate'); + $this->user = Factory::getuser(); + + parent::__construct($config); + } + + /** + * Abstract method for getting the form from the model. + * + * @param array $data Data for the form. + * @param boolean $loadData True if the form is to load its own data (default case), false if not. + * + * @return \JForm|boolean A \JForm object on success, false on failure + * + * @since __DEPLOY_VERSION__ + */ + public function getForm($data = array(), $loadData = true) + { + return; + } + + /** + * Function to get users + * + * @param integer $agencyId agency id + * + * @return Object Users object + * + * @since __DEPLOY_VERSION__ + */ + public function getUsers($agencyId = null) + { + $db = Factory::getDBO(); + $query = $db->getQuery(true); + $query->select('distinct(u.id), u.name'); + $query->from($db->quoteName('#__users', 'u')); + $query->where($db->qn('u.block') . ' = 0'); + + if (ComponentHelper::isEnabled($this->comMultiAgency) && $this->params->get('enable_multiagency')) + { + $query->join('INNER', '#__tj_cluster_nodes AS cn ON cn.user_id = u.id'); + $query->join('INNER', $db->qn('#__tj_clusters', 'clusters') . + ' ON (' . $db->qn('clusters.id') . ' = ' . $db->qn('cn.cluster_id') . + ' AND ' . $db->qn('clusters.client') . " = 'com_multiagency' ) "); + $query->join('INNER', $db->qn('#__tjmultiagency_multiagency', 'ml') . + ' ON (' . $db->qn('ml.id') . ' = ' . $db->qn('clusters.client_id') . ')'); + + $manageOwn = $this->user->authorise('core.manage.own.agency.user', $this->comMultiAgency); + $manage = $this->user->authorise('core.manage.all.agency.user', $this->comMultiAgency); + + // If user have only manage own permission and agency is not set then load own agency users + if ($manageOwn && empty($manage) && empty($agencyId)) + { + $loggedInUserAgencies = $this->getUserAgencies($this->user->id); + + foreach ($loggedInUserAgencies as $loggedInUserAgency) + { + $loggedInUserAgencyArr[] = $loggedInUserAgency->id; + } + + $query->where($db->quoteName('ml.id') . ' in (' . implode(',', $loggedInUserAgencyArr) . ')'); + } + elseif ($agencyId) + { + $query->where($db->qn('ml.id') . ' = ' . (int) $agencyId); + } + } + + $query->order($db->escape('u.name' . ' ' . 'asc')); + + $db->setQuery($query); + + return $db->loadObjectList(); + } + + /** + * Function to check user agency + * + * @param int $agencyId agency id + * + * @return integer The integer of the primary key + * + * @since __DEPLOY_VERSION__ + */ + public function validateUserAgency($agencyId) + { + $db = Factory::getDBO(); + $query = $db->getQuery(true); + $query->select($db->quoteName('u.id')); + $query->from($db->quoteName('#__users', 'u')); + $query->join('INNER', $db->quoteName('#__tj_cluster_nodes', 'cn') . ' ON ' . $db->quoteName('cn.user_id') . '=' . $db->quoteName('u.id')); + $query->join('INNER', $db->quoteName('#__tj_clusters', 'c') . ' ON ' . $db->quoteName('c.id') . '=' . $db->quoteName('cn.cluster_id')); + $query->join('INNER', $db->quoteName('#__tjmultiagency_multiagency', 'ml') . + ' ON ' . $db->quoteName('ml.id') . ' = ' . $db->quoteName('c.client_id') + ); + $query->where($db->qn('ml.id') . ' = ' . (int) $agencyId); + $query->where($db->qn('cn.user_id') . ' = ' . (int) $this->user->id); + $db->setQuery($query); + + return $db->loadResult(); + } + + /** + * Function to get user agency + * + * @param int $userId user id + * + * @return integer The integer of the primary key + * + * @since __DEPLOY_VERSION__ + */ + public function getUserAgencies($userId) + { + $db = Factory::getDBO(); + $query = $db->getQuery(true); + $query->select($db->quoteName('agency.id')); + $query->from($db->quoteName('#__tjmultiagency_multiagency', 'agency')); + $query->join('INNER', $db->quoteName('#__tj_clusters', 'c') . ' ON ' . $db->quoteName('c.client_id') . '=' . $db->quoteName('agency.id')); + $query->join('INNER', $db->quoteName('#__tj_cluster_nodes', 'cn') . ' ON ' . $db->quoteName('cn.cluster_id') . '=' . $db->quoteName('c.id')); + $query->Where($db->qn('agency.state') . '=' . 1); + $query->where($db->quoteName('cn.user_id') . ' = ' . (int) $userId); + $db->setQuery($query); + + return $db->loadObjectList(); + } +} diff --git a/src/components/com_tjcertificate/administrator/models/certificates.php b/src/components/com_tjcertificate/administrator/models/certificates.php index a5074d46..e3a792da 100644 --- a/src/components/com_tjcertificate/administrator/models/certificates.php +++ b/src/components/com_tjcertificate/administrator/models/certificates.php @@ -13,6 +13,8 @@ use Joomla\CMS\MVC\Model\ListModel; use Joomla\CMS\Factory; +use Joomla\CMS\Component\ComponentHelper; +use Joomla\CMS\MVC\Model\BaseDatabaseModel; /** * Methods supporting a list of records. @@ -21,6 +23,8 @@ */ class TjCertificateModelCertificates extends ListModel { + protected $comMultiAgency = 'com_multiagency'; + /** * Constructor. * @@ -40,10 +44,13 @@ public function __construct($config = array()) 'user_id', 'ci.user_id', 'state', 'ci.state', 'issued_on', 'ci.issued_on', - 'expired_on', 'ci.expired_on' + 'expired_on', 'ci.expired_on', + 'agency_id' ); } + $this->params = ComponentHelper::getParams('com_tjcertificate'); + parent::__construct($config); } @@ -81,18 +88,63 @@ protected function getListQuery() // Initialize variables. $db = $this->getDbo(); $query = $db->getQuery(true); - $app = Factory::getApplication(); + $app = Factory::getApplication(); + $user = Factory::getUser(); $extension = Factory::getApplication()->input->get('extension', '', 'CMD'); $this->setState('filter.component', $extension); + // Filter by client + $client = $this->getState('filter.client'); + // Create the base select statement. $query->select(array('ci.*', 'ct.title', 'users.name as uname')); $query->from($db->quoteName('#__tj_certificate_issue', 'ci')); + $query->join('LEFT', $db->quoteName('#__tj_certificate_templates', 'ct') . ' ON (' . $db->quoteName('ci.certificate_template_id') . ' = ' . $db->quoteName('ct.id') . ')'); - $query->join('LEFT', $db->quoteName('#__users', 'users') . ' ON (' . $db->quoteName('ci.user_id') . ' = ' . $db->quoteName('users.id') . ')'); + + $query->join('LEFT', $db->quoteName('#__users', 'users') . + ' ON (' . $db->quoteName('ci.user_id') . ' = ' . $db->quoteName('users.id') . ')'); + + if (ComponentHelper::isEnabled($this->comMultiAgency) && $this->params->get('enable_multiagency')) + { + $query->select('agency.title as title'); + + $query->join('INNER', $db->qn('#__tj_cluster_nodes', 'nodes') . + ' ON (' . $db->qn('users.id') . ' = ' . $db->qn('nodes.user_id') . ')'); + + $query->join('INNER', $db->qn('#__tj_clusters', 'clusters') . + ' ON (' . $db->qn('clusters.id') . ' = ' . $db->qn('nodes.cluster_id') . + ' AND ' . $db->qn('clusters.client') . " = " . $db->q($this->comMultiAgency) . ')'); + + $query->join('LEFT', $db->qn('#__tjmultiagency_multiagency', 'agency') . + ' ON (' . $db->qn('agency.id') . ' = ' . $db->qn('clusters.client_id') . ')'); + + $agencyId = $this->getState('filter.agency_id'); + + $canManageAllAgencyUser = $user->authorise('core.manage.all.agency.user', $this->comMultiAgency); + + // If don't have manage all user permission then get users of own agency + if (!$canManageAllAgencyUser && !$agencyId) + { + // Subquery to get agency users + $subquery = $db->getQuery(true); + $subquery->select($db->quoteName('ml.id')); + $subquery->from($db->quoteName('#__tjmultiagency_multiagency', 'ml')); + $subquery->join('INNER', $db->quoteName('#__tj_clusters', 'c') . ' ON ' . $db->quoteName('c.client_id') . '=' . $db->quoteName('ml.id')); + $subquery->join('INNER', $db->quoteName('#__tj_cluster_nodes', 'cn') . ' ON ' . $db->quoteName('cn.cluster_id') . '=' . $db->quoteName('c.id')); + $subquery->Where($db->qn('ml.state') . '=' . 1); + $subquery->where($db->quoteName('cn.user_id') . ' = ' . (int) $user->id); + + $query->where($db->quoteName('agency.id') . ' in (' . $subquery . ')'); + } + elseif ($agencyId) + { + $query->where($db->quoteName('agency.id') . ' = ' . (int) $agencyId); + } + } // Filter by certificate id $id = $this->getState('filter.id'); @@ -110,9 +162,6 @@ protected function getListQuery() $query->where($db->quoteName('ci.certificate_template_id') . ' = ' . (int) $certificateTemplateId); } - // Filter by client - $client = $this->getState('filter.client'); - if (!empty($client)) { $query->where($db->quoteName('ci.client') . ' = ' . $db->quote($client)); @@ -194,6 +243,8 @@ protected function getListQuery() $orderCol = $this->state->get('list.ordering', 'ci.id'); $orderDirn = $this->state->get('list.direction', 'desc'); + $query->group('ci.id'); + if ($orderCol && $orderDirn) { $query->order($db->escape($orderCol . ' ' . $orderDirn)); diff --git a/src/components/com_tjcertificate/administrator/models/fields/allusers.php b/src/components/com_tjcertificate/administrator/models/fields/allusers.php new file mode 100644 index 00000000..3020e8d6 --- /dev/null +++ b/src/components/com_tjcertificate/administrator/models/fields/allusers.php @@ -0,0 +1,86 @@ + + * @copyright Copyright (C) 2009 - 2021 Techjoomla. All rights reserved. + * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL + */ + +// No direct access. +defined('_JEXEC') or die(); + +use Joomla\CMS\Factory; +use Joomla\CMS\Language\Text; +use Joomla\CMS\HTML\HTMLHelper; +use Joomla\CMS\Component\ComponentHelper; +use Joomla\CMS\MVC\Model\BaseDatabaseModel; + +JFormHelper::loadFieldClass('list'); + +/** + * Supports an HTML select list of users + * + * @since __DEPLOY_VERSION__ + */ +class JFormFieldAllUsers extends JFormFieldList +{ + /** + * The form field type. + * + * @var string + * @since __DEPLOY_VERSION__ + */ + protected $type = 'allusers'; + + /** + * Fiedd to decide if options are being loaded externally and from xml + * + * @var integer + * @since __DEPLOY_VERSION__ + */ + protected $loadExternally = 0; + + /** + * Method to get a list of options for a list input. + * + * @return array An array of JHtml options. + * + * @since __DEPLOY_VERSION__ + */ + protected function getOptions() + { + $model = TJCERT::model('Agency', array('ignore_request' => true)); + $usersObject = $model->getUsers(); + + $options = array(); + + foreach ($usersObject as $user) + { + $options[] = HTMLHelper::_('select.option', $user->id, $user->name); + } + + if (!$this->loadExternally) + { + // Merge any additional options in the XML definition. + $options = array_merge(parent::getOptions(), $options); + } + + return $options; + } + + /** + * Method to get a list of options for a list input externally and not from xml. + * + * @return array An array of JHtml options. + * + * @since __DEPLOY_VERSION__ + */ + public function getOptionsExternally() + { + $this->loadExternally = 1; + + return $this->getOptions(); + } +} diff --git a/src/components/com_tjcertificate/administrator/models/forms/filter_certificates.xml b/src/components/com_tjcertificate/administrator/models/forms/filter_certificates.xml index 0017c2dc..25258277 100644 --- a/src/components/com_tjcertificate/administrator/models/forms/filter_certificates.xml +++ b/src/components/com_tjcertificate/administrator/models/forms/filter_certificates.xml @@ -41,9 +41,17 @@
--> + + + + + addfieldpath="administrator/components/com_tjcertificate/models/fields" + > + + params = ComponentHelper::getParams('com_tjcertificate'); + $this->user = Factory::getuser(); + + parent::__construct($config); + } + /** * Method to get a certificate. * @@ -77,7 +98,16 @@ public function getItem($pk = null) public function getForm($data = array(), $loadData = true) { // Get the form. - $form = $this->loadForm('com_tjcertificate.trainingrecord', 'trainingrecord', array('control' => 'jform', 'load_data' => $loadData)); + $form = $this->loadForm('com_tjcertificate.trainingrecord', 'trainingrecord', array('control' => 'jform', 'load_data' => $loadData)); + $loggedInuser = Factory::getUser(); + + $app = Factory::getApplication(); + $integrateMultiagency = $this->params->get('enable_multiagency'); + + if (!$loggedInuser->authorise('certificate.external.manage', 'com_tjcertificate')) + { + $form->setFieldAttribute('assigned_user_id', 'required', 'false'); + } return empty($form) ? false : $form; } @@ -134,17 +164,15 @@ public function uploadMedia($file, $data) { $user = Factory::getUser(); - $params = ComponentHelper::getParams('com_tjcertificate'); - if (!empty($file['cert_file'])) { $filePath = TJCERT::getMediaPath(); - $uploadedFileExtension = strtolower($params->get('upload_extensions', '', 'STRING')); + $uploadedFileExtension = strtolower($this->params->get('upload_extensions', '', 'STRING')); $fileExtensionType = explode(',', $uploadedFileExtension); $config = array(); $config['type'] = $fileExtensionType; - $config['size'] = $params->get('upload_maxsize', '10'); + $config['size'] = $this->params->get('upload_maxsize', '10'); $config['auth'] = true; if (!empty($file['cert_file']['name'])) @@ -264,17 +292,18 @@ public function deleteMedia($mediaId, $deletePath, $client, $clientId) /** * Method to validate the form data. * - * @param \JForm $form The form to validate against. - * @param Array $data The data to validate. + * @param \JForm $form The form to validate against. + * @param Array $data The data to validate. + * @param string $group The name of the field group to validate. * * @return array|boolean Array of filtered data if valid, false otherwise. * * @since __DEPLOY_VERSION__ */ - public function validate($form, $data) + public function validate($form, $data, $group = null) { $return = true; - $return = parent::validate($form, $data); + $return = parent::validate($form, $data, $group); if (!empty($data['expired_on']) && $data['expired_on'] != '0000-00-00 00:00:00') { @@ -285,6 +314,34 @@ public function validate($form, $data) } } + if (ComponentHelper::isEnabled($this->comMultiAgency) && $this->params->get('enable_multiagency')) + { + $manageOwn = $this->user->authorise('core.manage.own.agency.user', $this->comMultiAgency); + $manage = $this->user->authorise('core.manage.all.agency.user', $this->comMultiAgency); + + if ($manageOwn && empty($manage)) + { + $model = TJCERT::model('Agency', array('ignore_request' => true)); + + // Get agencies of logged-in user and assigned user + $assignedUserAgencies = $model->getUserAgencies($data['assigned_user_id']); + $loggedInUserAgencies = $model->getUserAgencies($this->user->id); + + // Convert object to array + $assignedUserAgencyArr = array_column($assignedUserAgencies, 'id'); + $loggedInUserAgencyArr = array_column($loggedInUserAgencies, 'id'); + + // Compare both users agencies + $result = array_intersect($loggedInUserAgencyArr, $assignedUserAgencyArr); + + if (empty($result)) + { + $this->setError(Text::_('COM_TJCERTIFICATE_ORGANIZATION_INVALID_USER')); + $return = false; + } + } + } + return $return; } } diff --git a/src/components/com_tjcertificate/administrator/views/certificates/tmpl/default.php b/src/components/com_tjcertificate/administrator/views/certificates/tmpl/default.php index 3fabe596..55001797 100644 --- a/src/components/com_tjcertificate/administrator/views/certificates/tmpl/default.php +++ b/src/components/com_tjcertificate/administrator/views/certificates/tmpl/default.php @@ -86,6 +86,13 @@ + + isAgencyEnabled) { ?> + + + + + @@ -177,6 +184,12 @@ echo $userName; ?> + isAgencyEnabled) + { ?> + title; ?> + is_external) diff --git a/src/components/com_tjcertificate/administrator/views/certificates/view.html.php b/src/components/com_tjcertificate/administrator/views/certificates/view.html.php index dba3cdbe..2923f6c8 100644 --- a/src/components/com_tjcertificate/administrator/views/certificates/view.html.php +++ b/src/components/com_tjcertificate/administrator/views/certificates/view.html.php @@ -15,6 +15,7 @@ use Joomla\CMS\Language\Text; use Joomla\CMS\MVC\View\HtmlView; use Joomla\CMS\Object\CMSObject; +use Joomla\CMS\Component\ComponentHelper; /** * Certificates view @@ -81,6 +82,11 @@ class TjCertificateViewCertificates extends HtmlView */ protected $canDo; + protected $params; + + public $isAgencyEnabled = false; + + protected $comMultiAgency = 'com_multiagency'; /** * Display the view * @@ -116,6 +122,17 @@ public function display($tpl = null) // Set sidebar $this->sidebar = JHtmlSidebar::render(); + $this->params = ComponentHelper::getParams('com_tjcertificate'); + + if (ComponentHelper::isEnabled($this->comMultiAgency) && $this->params->get('enable_multiagency')) + { + $this->isAgencyEnabled = true; + } + else + { + $this->filterForm->removeField('agency_id', 'filter'); + } + // Display the view parent::display($tpl); } diff --git a/src/components/com_tjcertificate/administrator/views/trainingrecord/tmpl/edit.php b/src/components/com_tjcertificate/administrator/views/trainingrecord/tmpl/edit.php index 0ffc182f..a3f9daf3 100644 --- a/src/components/com_tjcertificate/administrator/views/trainingrecord/tmpl/edit.php +++ b/src/components/com_tjcertificate/administrator/views/trainingrecord/tmpl/edit.php @@ -55,6 +55,15 @@
form->renderField('id'); ?> + + isAgencyEnabled) + { + + echo $this->form->renderField('agency_id'); + } + ?> + form->renderField('assigned_user_id'); ?> form->renderField('name'); ?> form->renderField('unique_certificate_id'); ?> @@ -95,6 +104,7 @@ class="p-5" form->renderField('comment'); ?>
+ @@ -108,4 +118,5 @@ class="p-5" diff --git a/src/components/com_tjcertificate/administrator/views/trainingrecord/view.html.php b/src/components/com_tjcertificate/administrator/views/trainingrecord/view.html.php index b9bba39a..ac0ec1f5 100644 --- a/src/components/com_tjcertificate/administrator/views/trainingrecord/view.html.php +++ b/src/components/com_tjcertificate/administrator/views/trainingrecord/view.html.php @@ -51,6 +51,10 @@ class TjCertificateViewTrainingRecord extends HtmlView */ protected $canDo; + public $isAgencyEnabled = false; + + protected $comMultiAgency = 'com_multiagency'; + /** * Display the view * @@ -72,6 +76,11 @@ public function display($tpl = null) $this->uploadLimit = $this->params->get('upload_maxsize', '1024'); $this->certificate = TJCERT::Certificate(); + if (ComponentHelper::isEnabled($this->comMultiAgency) && $this->params->get('enable_multiagency')) + { + $this->isAgencyEnabled = true; + } + $layout = $this->input->get('layout', 'edit'); // Check for errors. diff --git a/src/components/com_tjcertificate/media/js/certificate.js b/src/components/com_tjcertificate/media/js/certificate.js index ec2f9460..83e83773 100644 --- a/src/components/com_tjcertificate/media/js/certificate.js +++ b/src/components/com_tjcertificate/media/js/certificate.js @@ -161,5 +161,49 @@ var certificate = { }); }); - } + }, + getAgencyUsers: function(agencyObj) { + var formData = {}; + var clusterusers = jQuery('#jform_assigned_user_id'); + var assignedUser = jQuery('#assigned_user_id').val(); + formData['agency_id'] = jQuery(agencyObj).val(); + + var promise = tjCertificateService.getAgencyUsers(formData); + + promise.fail( + function(response) { + var messages = { + "error": [response.responseText] + }; + Joomla.renderMessage(messages); + } + ).done(function(response) { + + if (!response) + { + return false; + } + + if (response.success) { + clusterusers.empty(); + clusterusers.trigger("liszt:updated"); + + var data = response.data; + + for(var index = 0; index < data.length; ++index) + { + selectOption = ''; + if (assignedUser == data[index].value) + { + selectOption = ' selected="selected" '; + } + op="" ; + clusterusers.append(op); + } + + /* IMP : to update to chz-done selects*/ + clusterusers.trigger("liszt:updated"); + } + }); + } }; diff --git a/src/components/com_tjcertificate/media/js/certificate.min.js b/src/components/com_tjcertificate/media/js/certificate.min.js index 1a871180..0e9ee1f3 100644 --- a/src/components/com_tjcertificate/media/js/certificate.min.js +++ b/src/components/com_tjcertificate/media/js/certificate.min.js @@ -1 +1 @@ -var certificate={validateFile:function(e){if("file"!=jQuery(e).attr("type"))return!1;jQuery("#system-message-container").empty();var r=jQuery(e)[0].files[0],t=r.type,a=r.name.split("."),s=allowedAttachments.split(","),i=0,n=new Array;return""===a[a.length-1]&&null===a[a.length-1]||-1!=jQuery.inArray(t,s)||(i="1",n.push(Joomla.JText._("COM_TJCERTIFICATE_MEDIA_INVALID_FILE_TYPE"))),r.size>1024*attachmentMaxSize*1024&&(i="1",n.push(Joomla.JText._("COM_TJCERTIFICATE_MEDIA_UPLOAD_ERROR")),console.log("COM_TIMELOG_FILE_SIZE_ERROR")),i?(Joomla.renderMessages({error:n}),jQuery("html, body").animate({scrollTop:0},500),!1):void 0},deleteAttachment:function(e){if(1==confirm(Joomla.JText._("COM_TJCERTIFICATE_CONFIRM_DELETE_ATTACHMENT"))){var r={};if(""==e||void 0===e)return!1;r.certificateId=jQuery(e).attr("data-aid"),r.mediaId=jQuery(e).attr("data-mid"),tjCertificateService.deleteAttachment(r).fail(function(e){var r={error:[e.responseText]};certificate.renderMessage(r)}).done(function(r){if(!r.success&&r.message){var t={error:[r.message]};certificate.renderMessage(t)}r.messages&&certificate.renderMessage(r.messages),r.success&&certificate.renderMessage(r.message),jQuery(e).closest("span.fileupload").remove()})}},deleteItem:function(e,r){if(1==confirm(Joomla.JText._("COM_TJCERTIFICATE_DELETE_CERTIFICATE_MESSAGE"))){var t={};if(""==e||void 0===e)return!1;t.certificateId=e,tjCertificateService.deleteItem(t).fail(function(e){var r={error:[e.responseText]};certificate.renderMessage(r)}).done(function(e){if(!e.success&&e.message){var t={error:[e.message]};certificate.renderMessage(t)}e.messages&&certificate.renderMessage(e.messages),e.success&&certificate.renderMessage(e.message),jQuery(r).closest("tr").remove()})}},renderMessage:function(e){Joomla.renderMessages({"alert alert-success":[e]}),jQuery("html, body").animate({scrollTop:0},2e3)},validationEndDate:function(e){var r=jQuery(e).val(),t=jQuery("#jform_issued_on").val();jQuery(document).ready(function(){document.formvalidator.setHandler("expdate",function(e){return!(t>r)||(certificate.renderMessage(Joomla.JText._("COM_TJCERTIFICATE_EXPIRY_DATE_VALIDATION_MESSAGE")),jQuery("#jform_expired_on").val(""),!1)})})}}; +var certificate={validateFile:function(e){if("file"!=jQuery(e).attr("type"))return!1;jQuery("#system-message-container").empty();var r=jQuery(e)[0].files[0],t=r.type,a=r.name.split("."),s=allowedAttachments.split(","),i=0,n=new Array;return""===a[a.length-1]&&null===a[a.length-1]||-1!=jQuery.inArray(t,s)||(i="1",n.push(Joomla.JText._("COM_TJCERTIFICATE_MEDIA_INVALID_FILE_TYPE"))),r.size>1024*attachmentMaxSize*1024&&(i="1",n.push(Joomla.JText._("COM_TJCERTIFICATE_MEDIA_UPLOAD_ERROR")),console.log("COM_TIMELOG_FILE_SIZE_ERROR")),i?(Joomla.renderMessages({error:n}),jQuery("html, body").animate({scrollTop:0},500),!1):void 0},deleteAttachment:function(e){if(1==confirm(Joomla.JText._("COM_TJCERTIFICATE_CONFIRM_DELETE_ATTACHMENT"))){var r={};if(""==e||void 0===e)return!1;r.certificateId=jQuery(e).attr("data-aid"),r.mediaId=jQuery(e).attr("data-mid"),tjCertificateService.deleteAttachment(r).fail(function(e){var r={error:[e.responseText]};certificate.renderMessage(r)}).done(function(r){if(!r.success&&r.message){var t={error:[r.message]};certificate.renderMessage(t)}r.messages&&certificate.renderMessage(r.messages),r.success&&certificate.renderMessage(r.message),jQuery(e).closest("span.fileupload").remove()})}},deleteItem:function(e,r){if(1==confirm(Joomla.JText._("COM_TJCERTIFICATE_DELETE_CERTIFICATE_MESSAGE"))){var t={};if(""==e||void 0===e)return!1;t.certificateId=e,tjCertificateService.deleteItem(t).fail(function(e){var r={error:[e.responseText]};certificate.renderMessage(r)}).done(function(e){if(!e.success&&e.message){var t={error:[e.message]};certificate.renderMessage(t)}e.messages&&certificate.renderMessage(e.messages),e.success&&certificate.renderMessage(e.message),jQuery(r).closest("tr").remove()})}},renderMessage:function(e){Joomla.renderMessages({"alert alert-success":[e]}),jQuery("html, body").animate({scrollTop:0},2e3)},validationEndDate:function(e){var r=jQuery(e).val(),t=jQuery("#jform_issued_on").val();jQuery(document).ready(function(){document.formvalidator.setHandler("expdate",function(e){return!(t>r)||(certificate.renderMessage(Joomla.JText._("COM_TJCERTIFICATE_EXPIRY_DATE_VALIDATION_MESSAGE")),jQuery("#jform_expired_on").val(""),!1)})})},getAgencyUsers:function(e){var r={},t=jQuery("#jform_assigned_user_id"),a=jQuery("#assigned_user_id").val();r.agency_id=jQuery(e).val(),tjCertificateService.getAgencyUsers(r).fail(function(e){var r={error:[e.responseText]};Joomla.renderMessage(r)}).done(function(e){if(!e)return!1;if(e.success){t.empty(),t.trigger("liszt:updated");for(var r=e.data,s=0;s "+r[s].text+"",t.append(op);t.trigger("liszt:updated")}})}}; diff --git a/src/components/com_tjcertificate/media/js/tjCertificateService.js b/src/components/com_tjcertificate/media/js/tjCertificateService.js index 0854cba1..5d43f1ec 100644 --- a/src/components/com_tjcertificate/media/js/tjCertificateService.js +++ b/src/components/com_tjcertificate/media/js/tjCertificateService.js @@ -14,6 +14,7 @@ var tjCertificateService = { loadCustomTemplateUrl: '/index.php?option=com_tjcertificate&task=template.loadCustomTemplate&format=json', deleteAttachmentUrl: '/index.php?option=com_tjcertificate&task=trainingrecord.deleteAttachment&format=json', deleteItemUrl: '/index.php?option=com_tjcertificate&task=trainingrecord.delete&format=json', + getAgencyUsersUrl: '/index.php?option=com_tjcertificate&task=agency.getAgencyUsers&format=json', postData: function(url, formData, params) { if(!params){ @@ -42,5 +43,8 @@ var tjCertificateService = { }, deleteItem: function (formData, params) { return this.postData(this.deleteItemUrl, formData, params); + }, + getAgencyUsers: function (formData, params) { + return this.postData(this.getAgencyUsersUrl, formData, params); } } diff --git a/src/components/com_tjcertificate/media/js/tjCertificateService.min.js b/src/components/com_tjcertificate/media/js/tjCertificateService.min.js index 6beb6244..b8a26d7c 100644 --- a/src/components/com_tjcertificate/media/js/tjCertificateService.min.js +++ b/src/components/com_tjcertificate/media/js/tjCertificateService.min.js @@ -1 +1 @@ -var tjCertificateService={siteRoot:Joomla.getOptions("system.paths").base,loadDefaultTemplateUrl:"/index.php?option=com_tjcertificate&task=template.loadDefaultTemplate&format=json",loadCustomTemplateUrl:"/index.php?option=com_tjcertificate&task=template.loadCustomTemplate&format=json",deleteAttachmentUrl:"/index.php?option=com_tjcertificate&task=trainingrecord.deleteAttachment&format=json",deleteItemUrl:"/index.php?option=com_tjcertificate&task=trainingrecord.delete&format=json",postData:function(t,e,a){return a||(a={}),a.url=this.siteRoot+t,a.data=e,a.type=void 0!==a.type?a.type:"POST",a.async=void 0!==a.async&&a.async,a.dataType=void 0!==a.datatype?a.datatype:"json",a.contentType=void 0!==a.contentType?a.contentType:"application/x-www-form-urlencoded; charset=UTF-8",a.processData=void 0===a.processData||a.processData,jQuery.ajax(a)},loadDefaultTemplate:function(t,e){return this.postData(this.loadDefaultTemplateUrl,t,e)},loadCustomTemplate:function(t,e){return this.postData(this.loadCustomTemplateUrl,t,e)},deleteAttachment:function(t,e){return this.postData(this.deleteAttachmentUrl,t,e)},deleteItem:function(t,e){return this.postData(this.deleteItemUrl,t,e)}}; +var tjCertificateService={siteRoot:Joomla.getOptions("system.paths").base,loadDefaultTemplateUrl:"/index.php?option=com_tjcertificate&task=template.loadDefaultTemplate&format=json",loadCustomTemplateUrl:"/index.php?option=com_tjcertificate&task=template.loadCustomTemplate&format=json",deleteAttachmentUrl:"/index.php?option=com_tjcertificate&task=trainingrecord.deleteAttachment&format=json",deleteItemUrl:"/index.php?option=com_tjcertificate&task=trainingrecord.delete&format=json",getAgencyUsersUrl:"/index.php?option=com_tjcertificate&task=agency.getAgencyUsers&format=json",postData:function(t,e,a){return a||(a={}),a.url=this.siteRoot+t,a.data=e,a.type=void 0!==a.type?a.type:"POST",a.async=void 0!==a.async&&a.async,a.dataType=void 0!==a.datatype?a.datatype:"json",a.contentType=void 0!==a.contentType?a.contentType:"application/x-www-form-urlencoded; charset=UTF-8",a.processData=void 0===a.processData||a.processData,jQuery.ajax(a)},loadDefaultTemplate:function(t,e){return this.postData(this.loadDefaultTemplateUrl,t,e)},loadCustomTemplate:function(t,e){return this.postData(this.loadCustomTemplateUrl,t,e)},deleteAttachment:function(t,e){return this.postData(this.deleteAttachmentUrl,t,e)},deleteItem:function(t,e){return this.postData(this.deleteItemUrl,t,e)},getAgencyUsers:function(t,e){return this.postData(this.getAgencyUsersUrl,t,e)}}; diff --git a/src/components/com_tjcertificate/site/controllers/agency.json.php b/src/components/com_tjcertificate/site/controllers/agency.json.php new file mode 100644 index 00000000..9ee1c174 --- /dev/null +++ b/src/components/com_tjcertificate/site/controllers/agency.json.php @@ -0,0 +1,15 @@ + + * @copyright Copyright (C) 2009 - 2020 Techjoomla. All rights reserved. + * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL + */ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// Todo: Load with jimport +require_once JPATH_ADMINISTRATOR . '/components/com_tjcertificate/controllers/agency.json.php'; diff --git a/src/components/com_tjcertificate/site/languages/en-GB/en-GB.com_tjcertificate.ini b/src/components/com_tjcertificate/site/languages/en-GB/en-GB.com_tjcertificate.ini index 984e0f9a..68c73e4f 100644 --- a/src/components/com_tjcertificate/site/languages/en-GB/en-GB.com_tjcertificate.ini +++ b/src/components/com_tjcertificate/site/languages/en-GB/en-GB.com_tjcertificate.ini @@ -128,3 +128,15 @@ COM_TJCERTIFICATE_LBL_CERTIFICATE_URL="Url" COM_TJCERTIFICATE_CERTIFICATE_DETAIL_VIEW_CERTIFICATE="This certificate (ID: %s ) verifies that %s has successfully completed the %s on %s." COM_TJCERTIFICATE_CERTIFICATE_DETAIL_VIEW_AWARDED="This certificate (ID: %s ) has been awarded to %s on %s." COM_TJCERTIFICATE_CERTIFICATE_DETAIL_VIEW_CERTIFICATE_EXPIRES=" This Certificate expires on %s" + +;Certificate list view +COM_TJCERTIFICATE_CERTIFICATE_LIST_VIEW_USERNAME="User" +COM_TJCERTIFICATE_CERTIFICATE_LIST_VIEW_ORG_NAME="Organization" +COM_TJCERTIFICATE_ORG_SELECT="Select Organization" +COM_TJCERTIFICATE_FORM_CLUSTER_LBL="Select user for Organization" +COM_TJCERTIFICATE_AGENCY_USER_SELECT="Select User" + +;Record form +COM_TJCERTIFICATE_CERTIFICATE_FORM_LBL_CERTIFICATE_COMMENT_DESC="Add Comment" +COM_TJCERTIFICATE_ORGANIZATION_INVALID_USER="Invalid User" +COM_TJCERTIFICATE_AGENCY_INVALID_USER="Invalid Organization" diff --git a/src/components/com_tjcertificate/site/models/agency.php b/src/components/com_tjcertificate/site/models/agency.php new file mode 100644 index 00000000..c9a5cba8 --- /dev/null +++ b/src/components/com_tjcertificate/site/models/agency.php @@ -0,0 +1,14 @@ + + * @copyright Copyright (C) 2009 - 2021 Techjoomla. All rights reserved. + * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL + */ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +JLoader::import('components.com_tjcertificate.models.agency', JPATH_ADMINISTRATOR); diff --git a/src/components/com_tjcertificate/site/models/fields/agencies.php b/src/components/com_tjcertificate/site/models/fields/agencies.php new file mode 100644 index 00000000..066cd033 --- /dev/null +++ b/src/components/com_tjcertificate/site/models/fields/agencies.php @@ -0,0 +1,99 @@ + + * @copyright Copyright (C) 2009 - 2021 Techjoomla. All rights reserved. + * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL + */ + +defined('_JEXEC') or die(); + +use Joomla\CMS\Factory; +use Joomla\CMS\HTML\HTMLHelper; +use Joomla\CMS\Language\Text; + +JFormHelper::loadFieldClass('list'); + +/** + * Supports an HTML select list of agencies + * + * @since __DEPLOY_VERSION__ + */ +class JFormFieldAgencies extends JFormFieldList +{ + /** + * Fiedd to decide if options are being loaded externally and from xml + * + * @var integer + * @since __DEPLOY_VERSION__ + */ + protected $loadExternally = 0; + + protected $comMultiAgency = 'com_multiagency'; + + /** + * Method to get a list of options for a list input. + * + * @return array An array of HTMLHelper options. + * + * @since __DEPLOY_VERSION__ + */ + protected function getOptions() + { + $db = Factory::getDbo(); + $user = Factory::getUser(); + $query = $db->getQuery(true); + + $canManageAllAgencyUser = $user->authorise('core.manage.all.agency.user', $this->comMultiAgency); + + // Select the required fields from the table. + $query->select('DISTINCT ml.id, ml.title'); + $query->from('`#__tjmultiagency_multiagency` AS ml'); + $query->join('INNER', $db->quoteName('#__tj_clusters', 'c') . ' ON (' . $db->quoteName('c.client_id') . ' = ' . $db->qn('ml.id') . ')'); + $query->join('INNER', $db->quoteName('#__tj_cluster_nodes', 'cn') . ' ON ' . $db->quoteName('cn.cluster_id') . '=' . $db->quoteName('c.id')); + $query->Where($db->qn('c.state') . '=' . 1); + + if (!$canManageAllAgencyUser) + { + $query->Where($db->qn('cn.user_id') . '=' . (int) $user->id); + } + + $query->order($db->escape('ml.title ASC')); + $db->setQuery($query); + + // Get all agencies. + $agencies = $db->loadObjectList(); + + $options = array(); + $options[] = HTMLHelper::_('select.option', "", Text::_('COM_TJCERTIFICATE_ORG_SELECT')); + + foreach ($agencies as $agency) + { + $options[] = HTMLHelper::_('select.option', $agency->id, $agency->title); + } + + if (!$this->loadExternally) + { + // Merge any additional options in the XML definition. + $options = array_merge(parent::getOptions(), $options); + } + + return $options; + } + + /** + * Method to get a list of options for a list input externally and not from xml. + * + * @return array An array of HTMLHelper options. + * + * @since __DEPLOY_VERSION__ + */ + public function getOptionsExternally() + { + $this->loadExternally = 1; + + return $this->getOptions(); + } +} diff --git a/src/components/com_tjcertificate/site/models/forms/filter_certificates.xml b/src/components/com_tjcertificate/site/models/forms/filter_certificates.xml index 9ec5667e..fc16b86c 100644 --- a/src/components/com_tjcertificate/site/models/forms/filter_certificates.xml +++ b/src/components/com_tjcertificate/site/models/forms/filter_certificates.xml @@ -19,9 +19,17 @@ clientByUser="1" onchange="this.form.submit();" /> + + + + - + + + isAgencyEnabled) { ?> + manageOwn)) { ?> + + + + + + + + @@ -149,6 +160,15 @@ } ?> + isAgencyEnabled) + { ?> + manageOwn)) { ?> + uname; ?> + + title; ?> + getFormatedDate($item->issued_on); ?> manage && $item->is_external) { ?> - + state == -1 || $item->state == 0) { ?> diff --git a/src/components/com_tjcertificate/site/views/certificates/view.html.php b/src/components/com_tjcertificate/site/views/certificates/view.html.php index 5839968c..abf0f0f7 100644 --- a/src/components/com_tjcertificate/site/views/certificates/view.html.php +++ b/src/components/com_tjcertificate/site/views/certificates/view.html.php @@ -15,6 +15,7 @@ use Joomla\CMS\Factory; use Joomla\CMS\Language\Text; +use Joomla\CMS\Component\ComponentHelper; JLoader::import('components.com_tjcertificate.includes.tjcertificate', JPATH_ADMINISTRATOR); @@ -88,6 +89,11 @@ class TjCertificateViewCertificates extends JViewLegacy */ public $create; + protected $params; + + public $isAgencyEnabled = false; + + protected $comMultiAgency = 'com_multiagency'; /** * Display the view * @@ -97,8 +103,9 @@ class TjCertificateViewCertificates extends JViewLegacy */ public function display($tpl = null) { - $app = Factory::getApplication(); - $this->user = Factory::getUser(); + $app = Factory::getApplication(); + $this->user = Factory::getUser(); + $this->params = ComponentHelper::getParams('com_tjcertificate'); if (!$this->user->id) { @@ -133,6 +140,16 @@ public function display($tpl = null) $this->manageOwn = $this->user->authorise('certificate.external.manageown', 'com_tjcertificate'); $this->create = $this->user->authorise('certificate.external.create', 'com_tjcertificate'); + if (ComponentHelper::isEnabled($this->comMultiAgency) && $this->params->get('enable_multiagency')) + { + $this->isAgencyEnabled = true; + $this->filterForm->removeField('user_id', 'filter'); + } + else + { + $this->filterForm->removeField('agency_id', 'filter'); + } + // Check for errors. if (count($errors = $this->get('Errors'))) { diff --git a/src/components/com_tjcertificate/site/views/trainingrecord/tmpl/edit.php b/src/components/com_tjcertificate/site/views/trainingrecord/tmpl/edit.php index 0cecc175..4d8b43b2 100644 --- a/src/components/com_tjcertificate/site/views/trainingrecord/tmpl/edit.php +++ b/src/components/com_tjcertificate/site/views/trainingrecord/tmpl/edit.php @@ -12,9 +12,7 @@ defined('_JEXEC') or die('Restricted access'); use Joomla\CMS\HTML\HTMLHelper; -use Joomla\CMS\Router\Route; use Joomla\CMS\Language\Text; -use Joomla\CMS\Session\Session; use Joomla\CMS\Uri\Uri; HTMLHelper::_('behavior.formvalidation'); @@ -24,11 +22,11 @@ HTMLHelper::_('bootstrap.framework'); HTMLHelper::StyleSheet('media/com_tjcertificate/css/tjCertificate.css'); HTMLHelper::_('jquery.token'); +HTMLHelper::_('formbehavior.chosen', 'select'); $options['relative'] = true; HTMLHelper::_('script', 'com_tjcertificate/tjCertificateService.min.js', $options); HTMLHelper::_('script', 'com_tjcertificate/certificate.min.js', $options); - ?>
@@ -45,10 +43,17 @@
form->getInput('id'); ?>
isAgencyEnabled && $this->manage) + { + echo $this->form->renderField('agency_id'); + } + if ($this->manage) { echo $this->form->renderField('assigned_user_id'); } + echo $this->form->renderField('name'); echo $this->form->renderField('unique_certificate_id'); echo $this->form->renderField('cert_url'); @@ -102,6 +107,7 @@ class="p-5" + @@ -113,6 +119,4 @@ class="p-5" var allowedAttachments = 'allowedFileExtensions; ?>'; var attachmentMaxSize = 'uploadLimit; ?>'; - - diff --git a/src/components/com_tjcertificate/site/views/trainingrecord/view.html.php b/src/components/com_tjcertificate/site/views/trainingrecord/view.html.php index 3b8c2f1e..22f2c128 100644 --- a/src/components/com_tjcertificate/site/views/trainingrecord/view.html.php +++ b/src/components/com_tjcertificate/site/views/trainingrecord/view.html.php @@ -37,6 +37,24 @@ class TjCertificateViewTrainingRecord extends HtmlView public $certificate = null; + public $isAgencyEnabled = false; + + /** + * Manage own Permissions + * + * @var boolean + */ + public $manageOwn; + + /** + * Manage Permissions + * + * @var boolean + */ + public $manage; + + protected $comMultiAgency = 'com_multiagency'; + /** * Display the view * @@ -48,20 +66,26 @@ class TjCertificateViewTrainingRecord extends HtmlView */ public function display($tpl = null) { - $app = Factory::getApplication(); - $this->input = $app->input; - $this->user = Factory::getUser(); - $layout = $this->input->get('layout'); - $id = $this->input->getInt('id'); - $this->item = $this->get('Item'); + $app = Factory::getApplication(); + $this->input = $app->input; + $this->user = Factory::getUser(); + $layout = $this->input->get('layout'); + $id = $this->input->getInt('id'); + $this->item = $this->get('Item'); $this->certificate = TJCERT::Certificate(); - $params = ComponentHelper::getParams('com_tjcertificate'); - $this->manage = $this->user->authorise('certificate.external.manage', 'com_tjcertificate'); + $this->params = ComponentHelper::getParams('com_tjcertificate'); + $this->manage = $this->user->authorise('certificate.external.manage', 'com_tjcertificate'); + $this->manageOwn = $this->user->authorise('certificate.external.manageown', 'com_tjcertificate'); + + if (ComponentHelper::isEnabled($this->comMultiAgency) && $this->params->get('enable_multiagency')) + { + $this->isAgencyEnabled = true; + } if (!$this->manage) { // If certificate view is private then view is available only for record owner - if (!$params->get('certificate_scope') && Factory::getUser()->id != $this->item->user_id) + if (!$this->params->get('certificate_scope') && Factory::getUser()->id != $this->item->user_id) { JError::raiseWarning(500, Text::_('JERROR_ALERTNOAUTHOR')); From 06762bcbdadc507e0b3133c093cedbe9c1200c31 Mon Sep 17 00:00:00 2001 From: Rohan Shinde <37367348+shindebalu@users.noreply.github.com> Date: Wed, 24 Mar 2021 15:21:09 +0530 Subject: [PATCH 05/25] Feature #169747 feat: Generate QR code to validate certificate (#99) * chor : Feature #169747 : Generate QR code to validate certificate * chor : Feature #169747 : Generate QR code to validate certificate * chor : Feature #169747 : Generate QR code to validate certificate * chor : Feature #169747 : Generate QR code to validate certificate * chor : Feature #169747 : Generate QR code to validate certificate * chor : Feature #169747 : Generate QR code to validate certificate * chor : Feature #169747 : Generate QR code to validate certificate * chor : Feature #169747 : Generate QR code to validate certificate * chor : Feature #169747 : Generate QR code to validate certificate * chor : Feature #169747 : Generate QR code to validate certificate * chor : Feature #169747 : Generate QR code to validate certificate --- .../administrator/config.xml | 10 ++- .../en-GB/en-GB.com_tjcertificate.ini | 8 ++ .../administrator/libraries/certificate.php | 15 +++- .../com_tjcertificate/media/fields/legend.php | 78 +++++++++++++++++++ .../media/js/certificateImage.js | 3 +- .../media/js/certificateImage.min.js | 2 +- .../site/views/certificate/view.html.php | 2 +- .../com_tjcertificate/tjcertificate.xml | 26 +++++++ 8 files changed, 137 insertions(+), 7 deletions(-) create mode 100644 src/components/com_tjcertificate/media/fields/legend.php diff --git a/src/components/com_tjcertificate/administrator/config.xml b/src/components/com_tjcertificate/administrator/config.xml index a5e2a904..5a367b84 100644 --- a/src/components/com_tjcertificate/administrator/config.xml +++ b/src/components/com_tjcertificate/administrator/config.xml @@ -1,6 +1,6 @@ -
+
+ -
+ + + + + +
diff --git a/src/components/com_tjcertificate/administrator/languages/en-GB/en-GB.com_tjcertificate.ini b/src/components/com_tjcertificate/administrator/languages/en-GB/en-GB.com_tjcertificate.ini index 67ce4e95..09e919a3 100644 --- a/src/components/com_tjcertificate/administrator/languages/en-GB/en-GB.com_tjcertificate.ini +++ b/src/components/com_tjcertificate/administrator/languages/en-GB/en-GB.com_tjcertificate.ini @@ -365,3 +365,11 @@ COM_TJCERTIFICATE_CERTIFICATE_LIST_VIEW_ORG_NAME="Organization" COM_TJCERTIFICATE_ORG_SELECT="Select Organization" COM_TJCERTIFICATE_FORM_CLUSTER_LBL="Select user for Organization" COM_TJCERTIFICATE_AGENCY_USER_SELECT="Select User" + +;QR code config +COM_TJCERTIFICATE_QR_CODE_SETTING="QR-code configuration" +COM_TJCERTIFICATE_QR_CODE_WIDTH="QR code width" +COM_TJCERTIFICATE_QR_CODE_WIDTH_DESC="Enter QR code width" +COM_TJCERTIFICATE_QR_CODE_HEIGHT="QR code height" +COM_TJCERTIFICATE_QR_CODE_HEIGHT_DESC="Enter QR code height" +COM_TJCERTIFICATE_QR_CODE_SETTINGS_NOTE="Please note:

" diff --git a/src/components/com_tjcertificate/administrator/libraries/certificate.php b/src/components/com_tjcertificate/administrator/libraries/certificate.php index 910f8b9e..9cfb6876 100644 --- a/src/components/com_tjcertificate/administrator/libraries/certificate.php +++ b/src/components/com_tjcertificate/administrator/libraries/certificate.php @@ -874,6 +874,19 @@ public function issueCertificate($replacements, $options) // Generate unique certificate id replacement $replacements->certificate->cert_id = $this->unique_certificate_id; + $params = ComponentHelper::getParams('com_tjcertificate'); + + // Generate QR code of certificate. + $qrCodeWidth = $params->get('qr_code_width', 80); + $qrCodeHeight = $params->get('qr_code_height', 80); + + $qrString = 'index.php?option=com_tjcertificate&view=certificate&certificate=' . $this->unique_certificate_id; + $qrString = Uri::root() . substr(Route::_($qrString, false), strlen(Uri::base(true)) + 1); + $qrString = urlencode($qrString); + $qrUrl = "https://chart.apis.google.com/chart?cht=qr&chs="; + $qrImage = $qrUrl . $qrCodeWidth . "x" . $qrCodeHeight . "&chl=" . $qrString . "&chld=H|0"; + $replacements->certificate->qr_code = ''; + // Generate certificate body $this->generated_body = $this->generateCertificateBody($template->body, $replacements); @@ -919,8 +932,6 @@ public function issueCertificate($replacements, $options) } // Generate Certificate Image - $params = ComponentHelper::getParams('com_tjcertificate'); - if ($params->get('cert_image_gen_type') == 'imagick') { // Generate image from PDF diff --git a/src/components/com_tjcertificate/media/fields/legend.php b/src/components/com_tjcertificate/media/fields/legend.php new file mode 100644 index 00000000..ea299265 --- /dev/null +++ b/src/components/com_tjcertificate/media/fields/legend.php @@ -0,0 +1,78 @@ + + * @copyright Copyright (C) 2009 - 2021 Techjoomla. All rights reserved. + * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL + */ + +// No direct access. +defined('_JEXEC') or die; +use Joomla\CMS\Factory; +use Joomla\CMS\Language\Text; +use Joomla\CMS\Form\FormHelper; + +FormHelper::loadFieldClass('list'); + +/** + * Custom Legend field for component params. + * + * @package Com_Tjcertificate + * @since 1.0 + */ +class JFormFieldLegend extends \JFormFieldList +{ + /** + * The form field type. + * + * @var string + * @since 1.0 + */ + protected $type = 'Legend'; + + /** + * Method to get the field input markup. + * + * @return string The field input markup. + * + * @since 1.0 + */ + public function getInput() + { + $document = Factory::getDocument(); + + if (JVERSION < '3.0') + { + $element = (array) $this->element; + $hint = $element['@attributes']['hint']; + } + else + { + $hint = $this->hint; + + /*Let's remove controls class from parent + And, remove control-group class from grandparent*/ + $script = 'jQuery(document).ready(function(){ + jQuery("#' . $this->id . '").parent().removeClass("controls"); + jQuery("#' . $this->id . '").parent().parent().removeClass("control-group"); + });'; + + $document->addScriptDeclaration($script); + } + + // Show them a legend. + $return = '' . Text::_($this->value) . ''; + + // Show them a hint below the legend. + // Let them go - GaGa about the legend. + if (!empty($hint)) + { + $return .= '' . Text::_($hint) . ''; + $return .= '

'; + } + + return $return; + } +} diff --git a/src/components/com_tjcertificate/media/js/certificateImage.js b/src/components/com_tjcertificate/media/js/certificateImage.js index 9194672c..2ff98068 100644 --- a/src/components/com_tjcertificate/media/js/certificateImage.js +++ b/src/components/com_tjcertificate/media/js/certificateImage.js @@ -79,7 +79,8 @@ var certificateImage = { // scale: (2), scrollX: 0, scrollY: -window.scrollY, - allowTaint: true + allowTaint: true, + useCORS: true }).then(function(canvas) { certificateImage.enableDownloadShareBtns(); certificateImage.uploadImage(canvas.toDataURL('image/png')); diff --git a/src/components/com_tjcertificate/media/js/certificateImage.min.js b/src/components/com_tjcertificate/media/js/certificateImage.min.js index 7dbb7c94..ce9797cb 100644 --- a/src/components/com_tjcertificate/media/js/certificateImage.min.js +++ b/src/components/com_tjcertificate/media/js/certificateImage.min.js @@ -1 +1 @@ -var certificateImage={printCertificate:function(e){var t=document.getElementById(e).innerHTML,o=document.body.innerHTML;document.body.innerHTML=t,window.print(),document.body.innerHTML=o,certificateImage.enableDownloadShareBtns()},enableDownloadShareBtns:function(){jQuery("#download-popover").popover({trigger:"focus",html:!0,content:jQuery("#download-popover-content").html()}),jQuery("#sharing-popover").popover({trigger:"focus",html:!0,content:jQuery("#sharing-popover-content").html()}),jQuery("#copyurl").popover()},uploadImage:function(e){var t=!1,o=jQuery("#certificateId").val();return jQuery.ajax({url:certRootUrl+"index.php?option=com_tjcertificate&task=certificate.uploadCertificate",type:"POST",data:{image:e,certificateId:o},success:function(e){t=e;var o=jQuery("#certificateId").val(),r=certRootUrl+"media/com_tjcertificate/certificates/",n=document.createElement("img");jQuery("#certificateContent").hide(),n.src=r+o+".png",jQuery("#previewImage").append(n),setTimeout(function(){screen.width<1200&&(viewport=document.querySelector("meta[name=viewport]"),viewport.setAttribute("content","width=device-width")),jQuery.LoadingOverlay("hide")},1e3)}}),t},generateImage:function(e){screen.width<1200&&(viewport=document.querySelector("meta[name=viewport]"),viewport.setAttribute("content","width=1200px")),jQuery.LoadingOverlay("show",{image:"media/com_tjcertificate/images/loader/loader.gif"}),html2canvas(e,{scrollX:0,scrollY:-window.scrollY,allowTaint:!0}).then(function(e){certificateImage.enableDownloadShareBtns(),certificateImage.uploadImage(e.toDataURL("image/png"))})},copyUrl:function(e){e="#"+e;var t=document.createElement("input"),o=jQuery(e).attr("data-alt-url");jQuery(e).popover("show"),document.body.appendChild(t),t.value=o,t.select(),document.execCommand("copy"),document.body.removeChild(t),setTimeout(function(){jQuery(e).popover("hide")},1e3)}}; +var certificateImage={printCertificate:function(e){var t=document.getElementById(e).innerHTML,o=document.body.innerHTML;document.body.innerHTML=t,window.print(),document.body.innerHTML=o,certificateImage.enableDownloadShareBtns()},enableDownloadShareBtns:function(){jQuery("#download-popover").popover({trigger:"focus",html:!0,content:jQuery("#download-popover-content").html()}),jQuery("#sharing-popover").popover({trigger:"focus",html:!0,content:jQuery("#sharing-popover-content").html()}),jQuery("#copyurl").popover()},uploadImage:function(e){var t=!1,o=jQuery("#certificateId").val();return jQuery.ajax({url:certRootUrl+"index.php?option=com_tjcertificate&task=certificate.uploadCertificate",type:"POST",data:{image:e,certificateId:o},success:function(e){t=e;var o=jQuery("#certificateId").val(),r=certRootUrl+"media/com_tjcertificate/certificates/",n=document.createElement("img");jQuery("#certificateContent").hide(),n.src=r+o+".png",jQuery("#previewImage").append(n),setTimeout(function(){screen.width<1200&&(viewport=document.querySelector("meta[name=viewport]"),viewport.setAttribute("content","width=device-width")),jQuery.LoadingOverlay("hide")},1e3)}}),t},generateImage:function(e){screen.width<1200&&(viewport=document.querySelector("meta[name=viewport]"),viewport.setAttribute("content","width=1200px")),jQuery.LoadingOverlay("show",{image:"media/com_tjcertificate/images/loader/loader.gif"}),html2canvas(e,{scrollX:0,scrollY:-window.scrollY,allowTaint:!0,useCORS:!0}).then(function(e){certificateImage.enableDownloadShareBtns(),certificateImage.uploadImage(e.toDataURL("image/png"))})},copyUrl:function(e){e="#"+e;var t=document.createElement("input"),o=jQuery(e).attr("data-alt-url");jQuery(e).popover("show"),document.body.appendChild(t),t.value=o,t.select(),document.execCommand("copy"),document.body.removeChild(t),setTimeout(function(){jQuery(e).popover("hide")},1e3)}}; diff --git a/src/components/com_tjcertificate/site/views/certificate/view.html.php b/src/components/com_tjcertificate/site/views/certificate/view.html.php index 40034005..df29985e 100644 --- a/src/components/com_tjcertificate/site/views/certificate/view.html.php +++ b/src/components/com_tjcertificate/site/views/certificate/view.html.php @@ -83,7 +83,7 @@ public function display($tpl = null) elseif ($this->certificate->id) { // If certificate view is private then view is available only for certificate owner - if (!$this->params->get('certificate_scope') && Factory::getUser()->id != $this->certificate->getUserId()) + if (!$this->params->get('certificate_scope', '1') && Factory::getUser()->id != $this->certificate->getUserId()) { JError::raiseWarning(500, Text::_('JERROR_ALERTNOAUTHOR')); diff --git a/src/components/com_tjcertificate/tjcertificate.xml b/src/components/com_tjcertificate/tjcertificate.xml index ab275f43..0ff076d1 100644 --- a/src/components/com_tjcertificate/tjcertificate.xml +++ b/src/components/com_tjcertificate/tjcertificate.xml @@ -76,6 +76,32 @@ js images vendors + fields script.tjcertificate.php + + +
+ + + + + + + + + + + + + + + + + + + +
+
+
From 205654d257903df1bfda0530b7ef296d00a74549 Mon Sep 17 00:00:00 2001 From: Rohan Shinde <37367348+shindebalu@users.noreply.github.com> Date: Wed, 24 Mar 2021 16:20:18 +0530 Subject: [PATCH 06/25] Task #169750 feat: Set default value of qr code config (#100) * Task #169750 feat: Set default value of qr code config * Task #169750 feat: Set default value of qr code config --- .../com_tjcertificate/administrator/libraries/certificate.php | 4 ++-- src/components/com_tjcertificate/tjcertificate.xml | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/components/com_tjcertificate/administrator/libraries/certificate.php b/src/components/com_tjcertificate/administrator/libraries/certificate.php index 9cfb6876..08a045ee 100644 --- a/src/components/com_tjcertificate/administrator/libraries/certificate.php +++ b/src/components/com_tjcertificate/administrator/libraries/certificate.php @@ -877,8 +877,8 @@ public function issueCertificate($replacements, $options) $params = ComponentHelper::getParams('com_tjcertificate'); // Generate QR code of certificate. - $qrCodeWidth = $params->get('qr_code_width', 80); - $qrCodeHeight = $params->get('qr_code_height', 80); + $qrCodeWidth = $params->get('qr_code_width', 130); + $qrCodeHeight = $params->get('qr_code_height', 130); $qrString = 'index.php?option=com_tjcertificate&view=certificate&certificate=' . $this->unique_certificate_id; $qrString = Uri::root() . substr(Route::_($qrString, false), strlen(Uri::base(true)) + 1); diff --git a/src/components/com_tjcertificate/tjcertificate.xml b/src/components/com_tjcertificate/tjcertificate.xml index 0ff076d1..a1181d53 100644 --- a/src/components/com_tjcertificate/tjcertificate.xml +++ b/src/components/com_tjcertificate/tjcertificate.xml @@ -89,6 +89,8 @@ + + From 684ee5e0537ee3796ac350bb795087b8367be361 Mon Sep 17 00:00:00 2001 From: Rohan Shinde <37367348+shindebalu@users.noreply.github.com> Date: Wed, 24 Mar 2021 16:31:14 +0530 Subject: [PATCH 07/25] Task #169750 feat: Set default value of multy engancy (#101) --- src/components/com_tjcertificate/tjcertificate.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/com_tjcertificate/tjcertificate.xml b/src/components/com_tjcertificate/tjcertificate.xml index a1181d53..0fe41b16 100644 --- a/src/components/com_tjcertificate/tjcertificate.xml +++ b/src/components/com_tjcertificate/tjcertificate.xml @@ -89,6 +89,7 @@ + From cc57b9ee0d0f6abfedb6824555b207c502428e39 Mon Sep 17 00:00:00 2001 From: divyachaudhari <58217051+divyachaudhari@users.noreply.github.com> Date: Wed, 24 Mar 2021 18:35:58 +0530 Subject: [PATCH 08/25] Bug #169802 Fix: Backend > Issued Certificates > Add Training record > Warning and notices displayed on the page (#98) --- .../com_tjcertificate/site/views/trainingrecord/tmpl/edit.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/com_tjcertificate/site/views/trainingrecord/tmpl/edit.php b/src/components/com_tjcertificate/site/views/trainingrecord/tmpl/edit.php index 4d8b43b2..c5952bde 100644 --- a/src/components/com_tjcertificate/site/views/trainingrecord/tmpl/edit.php +++ b/src/components/com_tjcertificate/site/views/trainingrecord/tmpl/edit.php @@ -67,7 +67,7 @@
form->getInput('cert_file'); ?> item->mediaData[0]) + if (!empty($this->item->mediaData[0])) { $downloadAttachmentLink = Uri::root() . 'index.php?option=com_tjcertificate&task=trainingrecord.downloadAttachment&id=' . $this->item->mediaData[0]->media_id . '&recordId=' . $this->item->id; echo ''; From 81e7e5239d7693cdc43b36634d807445c02e2f66 Mon Sep 17 00:00:00 2001 From: Tushar Shekokar Date: Fri, 26 Mar 2021 10:14:24 +0530 Subject: [PATCH 09/25] Feature #168713 feat: Don't validate agency if manage all permission and show all site user if no org selected (#102) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update tjcertificate.xml * Bug #168296 Fix: Certificate view - Text is not coming from language constant. (#92) * Bug #168296 Fix: Certificate view - Text is not coming from language constant. * Bug #168296 Fix: Certificate view - Text is not coming from language constant. * Task #168311 feat: Remove duplicates Language constant from language … (#93) * Task #168311 feat: Remove duplicates Language constant from language files. * Task #168311 feat: Remove duplicates Language constant from language files. * Task #168722 chore: Add jQuery LoadingOverlay (#95) * Feature #168713 feat: Make Tj-certificate multi-agency aware * Feature #168713 feat: Make Tj-certificate multi-agency aware * Feature #168713 feat: Make Tj-certificate multi-agency aware * Feature #168713 feat: Make Tj-certificate multi-agency aware * Feature #168713 feat: Make Tj-certificate multi-agency aware * Feature #168713 feat: Resolve scrutinizer issues * Feature #168713 feat: Resolve scrutinizer issues * Feature #168713 feat: Make Tj-certificate multi-agency aware * Feature #168713 feat: Make Tj-certificate multi-agency aware * Feature #168713 feat: Make Tj-certificate multi-agency aware * Feature #168713 feat: Resolve comments * Feature #168713 feat: Bug #169802 fix * Feature #168713 feat: Resolve comments * Feature #168713 feat: Resolve comments * Feature #168713 feat: Make Tj-certificate multi-agency aware * Feature #168713 feat: Functionality improvements * Feature #168713 feat: Functionality improvements * Feature #168713 feat: Resolve comment * Feature #168713 feat: Don't validate agency if manage all permission and show all site user if no org selected * Feature #168713 feat: Resolve conflict * Feature #168713 feat: Resolve conflict Co-authored-by: praneettekdi Co-authored-by: MeghaBiranje <58220237+MeghaBiranje@users.noreply.github.com> Co-authored-by: Rohan Shinde <37367348+shindebalu@users.noreply.github.com> --- .../administrator/controllers/agency.json.php | 11 ++++--- .../en-GB/en-GB.com_tjcertificate.ini | 4 +++ .../administrator/models/agency.php | 33 ++++++++++++++----- .../en-GB/en-GB.com_tjcertificate.ini | 4 +-- 4 files changed, 37 insertions(+), 15 deletions(-) diff --git a/src/components/com_tjcertificate/administrator/controllers/agency.json.php b/src/components/com_tjcertificate/administrator/controllers/agency.json.php index 269d7258..eeb6c606 100644 --- a/src/components/com_tjcertificate/administrator/controllers/agency.json.php +++ b/src/components/com_tjcertificate/administrator/controllers/agency.json.php @@ -62,11 +62,14 @@ public function getAgencyUsers() $model = $this->getModel(); - if (!$model->validateUserAgency($agencyId)) + if ($agencyId) { - $app->enqueueMessage(Text::_('COM_TJCERTIFICATE_AGENCY_INVALID_USER'), 'error'); - echo new JsonResponse(null, null, true); - $app->close(); + if (!$model->validateUserAgency($agencyId)) + { + $app->enqueueMessage(Text::_('COM_TJCERTIFICATE_INVALID_ORGANIZATION'), 'error'); + echo new JsonResponse(null, null, true); + $app->close(); + } } $userOptions = array(); diff --git a/src/components/com_tjcertificate/administrator/languages/en-GB/en-GB.com_tjcertificate.ini b/src/components/com_tjcertificate/administrator/languages/en-GB/en-GB.com_tjcertificate.ini index 09e919a3..23369e81 100644 --- a/src/components/com_tjcertificate/administrator/languages/en-GB/en-GB.com_tjcertificate.ini +++ b/src/components/com_tjcertificate/administrator/languages/en-GB/en-GB.com_tjcertificate.ini @@ -373,3 +373,7 @@ COM_TJCERTIFICATE_QR_CODE_WIDTH_DESC="Enter QR code width" COM_TJCERTIFICATE_QR_CODE_HEIGHT="QR code height" COM_TJCERTIFICATE_QR_CODE_HEIGHT_DESC="Enter QR code height" COM_TJCERTIFICATE_QR_CODE_SETTINGS_NOTE="Please note:

" + +;Record form +COM_TJCERTIFICATE_ORGANIZATION_INVALID_USER="Invalid User" +COM_TJCERTIFICATE_INVALID_ORGANIZATION="Invalid Organization" diff --git a/src/components/com_tjcertificate/administrator/models/agency.php b/src/components/com_tjcertificate/administrator/models/agency.php index 1e385c7c..1335eda5 100644 --- a/src/components/com_tjcertificate/administrator/models/agency.php +++ b/src/components/com_tjcertificate/administrator/models/agency.php @@ -28,6 +28,10 @@ class TjCertificateModelAgency extends AdminModel public $user; + public $manageOwn; + + public $manage; + /** * Constructor. * @@ -37,8 +41,10 @@ class TjCertificateModelAgency extends AdminModel */ public function __construct($config = array()) { - $this->params = ComponentHelper::getParams('com_tjcertificate'); - $this->user = Factory::getuser(); + $this->params = ComponentHelper::getParams('com_tjcertificate'); + $this->user = Factory::getuser(); + $this->manageOwn = $this->user->authorise('core.manage.own.agency.user', $this->comMultiAgency); + $this->manage = $this->user->authorise('core.manage.all.agency.user', $this->comMultiAgency); parent::__construct($config); } @@ -84,12 +90,15 @@ public function getUsers($agencyId = null) $query->join('INNER', $db->qn('#__tjmultiagency_multiagency', 'ml') . ' ON (' . $db->qn('ml.id') . ' = ' . $db->qn('clusters.client_id') . ')'); - $manageOwn = $this->user->authorise('core.manage.own.agency.user', $this->comMultiAgency); - $manage = $this->user->authorise('core.manage.all.agency.user', $this->comMultiAgency); - - // If user have only manage own permission and agency is not set then load own agency users - if ($manageOwn && empty($manage) && empty($agencyId)) + // If user have manage all permission and no org selected then show all users + if ($this->manage && empty($agencyId)) + { + $query->clear('join'); + } + elseif ($this->manageOwn && empty($this->manage) && empty($agencyId)) { + // If user have only manage own permission and agency is not set then load own agency users + $loggedInUserAgencies = $this->getUserAgencies($this->user->id); foreach ($loggedInUserAgencies as $loggedInUserAgency) @@ -117,12 +126,18 @@ public function getUsers($agencyId = null) * * @param int $agencyId agency id * - * @return integer The integer of the primary key + * @return integer|boolean * * @since __DEPLOY_VERSION__ */ public function validateUserAgency($agencyId) { + // If user having multiagency manage all permission then return true + if ($this->manage) + { + return true; + } + $db = Factory::getDBO(); $query = $db->getQuery(true); $query->select($db->quoteName('u.id')); @@ -144,7 +159,7 @@ public function validateUserAgency($agencyId) * * @param int $userId user id * - * @return integer The integer of the primary key + * @return object * * @since __DEPLOY_VERSION__ */ diff --git a/src/components/com_tjcertificate/site/languages/en-GB/en-GB.com_tjcertificate.ini b/src/components/com_tjcertificate/site/languages/en-GB/en-GB.com_tjcertificate.ini index 68c73e4f..5c5c7e73 100644 --- a/src/components/com_tjcertificate/site/languages/en-GB/en-GB.com_tjcertificate.ini +++ b/src/components/com_tjcertificate/site/languages/en-GB/en-GB.com_tjcertificate.ini @@ -138,5 +138,5 @@ COM_TJCERTIFICATE_AGENCY_USER_SELECT="Select User" ;Record form COM_TJCERTIFICATE_CERTIFICATE_FORM_LBL_CERTIFICATE_COMMENT_DESC="Add Comment" -COM_TJCERTIFICATE_ORGANIZATION_INVALID_USER="Invalid User" -COM_TJCERTIFICATE_AGENCY_INVALID_USER="Invalid Organization" +COM_TJCERTIFICATE_INVALID_ORGANIZATION_USER="Invalid User" +COM_TJCERTIFICATE_INVALID_ORGANIZATION="Invalid Organization" From 4a93740122d418a1d22c4c91ed90148c740e0e71 Mon Sep 17 00:00:00 2001 From: Tushar Shekokar Date: Tue, 30 Mar 2021 16:35:50 +0530 Subject: [PATCH 10/25] Feature #168713 feat: Add external record delete permission (#103) * Feature #168713 feat: Add exteranal record delete permission * Feature #168713 feat: update external record delete permission * Feature #168713 feat: update external record delete permission * Feature #168713 feat: update external record delete permission * Feature #168713 feat: update external record delete permission * Feature #168713 feat: update external record delete permission * Feature #168713 feat: Show user name for all --- .../administrator/access.xml | 2 + .../controllers/trainingrecord.json.php | 35 ++++++++++------ .../en-GB/en-GB.com_tjcertificate.ini | 6 +++ .../site/views/certificates/tmpl/my.php | 40 ++++++++++++------- .../site/views/certificates/view.html.php | 17 ++++++-- 5 files changed, 69 insertions(+), 31 deletions(-) diff --git a/src/components/com_tjcertificate/administrator/access.xml b/src/components/com_tjcertificate/administrator/access.xml index d6adfd02..3b1ca7a2 100644 --- a/src/components/com_tjcertificate/administrator/access.xml +++ b/src/components/com_tjcertificate/administrator/access.xml @@ -14,6 +14,8 @@ + + diff --git a/src/components/com_tjcertificate/administrator/controllers/trainingrecord.json.php b/src/components/com_tjcertificate/administrator/controllers/trainingrecord.json.php index 23d4353c..047aa41c 100644 --- a/src/components/com_tjcertificate/administrator/controllers/trainingrecord.json.php +++ b/src/components/com_tjcertificate/administrator/controllers/trainingrecord.json.php @@ -109,24 +109,35 @@ public function delete() $certificateId = $app->input->getInt('certificateId'); $manageOwn = $user->authorise('certificate.external.manageown', $client); $manage = $user->authorise('certificate.external.manage', $client); + $deleteOwn = $user->authorise('certificate.external.deleteown', $client); + $delete = $user->authorise('certificate.external.delete', $client); + $allowDelete = false; - // If manageOwn permission then check record owner can only deleting own record + // If manageOwn and delete own permission then check own record and allow to delete record if ($manageOwn && !$manage) { - $table = TJCERT::table("certificates"); - $table->load(array('id' => (int) $certificateId, 'user_id' => $user->id)); - - if (!$table->id) + if ($deleteOwn) { - echo new JsonResponse(null, Text::_('COM_TJCERTIFICATE_ERROR_SOMETHING_WENT_WRONG'), true); - $app->close(); + $table = TJCERT::table("certificates"); + $table->load(array('id' => (int) $certificateId, 'user_id' => $user->id)); + + if ($table->id) + { + $allowDelete = true; + } + else + { + echo new JsonResponse(null, Text::_('COM_TJCERTIFICATE_ERROR_SOMETHING_WENT_WRONG'), true); + $app->close(); + } } } - $model = TJCERT::model('Certificate', array('ignore_request' => true)); - - if ($manageOwn || $manage) + // If user have manage all and delete all or allow to delete then delete the record + if (($manage && $delete) || $allowDelete) { + $model = TJCERT::model('Certificate', array('ignore_request' => true)); + // Remove the item if ($model->delete($certificateId)) { @@ -141,12 +152,12 @@ public function delete() $model->deleteMedia($tableXref->media_id, $mediaPath, $client, $certificateId); } - echo new JResponseJson($result, Text::_('COM_TJCERTIFICATE_CERTIFICATE_DELETED_SUCCESSFULLY'), false); + echo new JsonResponse($result, Text::_('COM_TJCERTIFICATE_CERTIFICATE_DELETED_SUCCESSFULLY'), false); $app->close(); } else { - echo new JResponseJson(null, Text::_('COM_TJCERTIFICATE_CERTIFICATE_DELETED_FAILED'), true); + echo new JsonResponse(null, Text::_('COM_TJCERTIFICATE_CERTIFICATE_DELETED_FAILED'), true); $app->close(); } } diff --git a/src/components/com_tjcertificate/administrator/languages/en-GB/en-GB.com_tjcertificate.ini b/src/components/com_tjcertificate/administrator/languages/en-GB/en-GB.com_tjcertificate.ini index 23369e81..9c2bd017 100644 --- a/src/components/com_tjcertificate/administrator/languages/en-GB/en-GB.com_tjcertificate.ini +++ b/src/components/com_tjcertificate/administrator/languages/en-GB/en-GB.com_tjcertificate.ini @@ -377,3 +377,9 @@ COM_TJCERTIFICATE_QR_CODE_SETTINGS_NOTE="Please note:

- - + + delete) + { + ?> + + @@ -204,9 +209,14 @@ { ?> - - - + deleteOwn && $item->user_id == $this->user->id) + { ?> + + + is_external || !$this->manageOwn) + if (!$item->is_external || !($this->manageOwn || $this->manage)) { echo "-"; } diff --git a/src/components/com_tjcertificate/site/views/certificates/view.html.php b/src/components/com_tjcertificate/site/views/certificates/view.html.php index abf0f0f7..05a969bb 100644 --- a/src/components/com_tjcertificate/site/views/certificates/view.html.php +++ b/src/components/com_tjcertificate/site/views/certificates/view.html.php @@ -94,6 +94,13 @@ class TjCertificateViewCertificates extends JViewLegacy public $isAgencyEnabled = false; protected $comMultiAgency = 'com_multiagency'; + + public $delete; + + public $deleteOwn; + + protected $comTjcertificate = 'com_tjcertificate'; + /** * Display the view * @@ -105,7 +112,7 @@ public function display($tpl = null) { $app = Factory::getApplication(); $this->user = Factory::getUser(); - $this->params = ComponentHelper::getParams('com_tjcertificate'); + $this->params = ComponentHelper::getParams($this->comTjcertificate); if (!$this->user->id) { @@ -121,7 +128,7 @@ public function display($tpl = null) $this->state = $this->get('State'); $layout = $app->input->get('layout', "my"); - $this->manage = $this->user->authorise('certificate.external.manage', 'com_tjcertificate'); + $this->manage = $this->user->authorise('certificate.external.manage', $this->comTjcertificate); if ($layout == 'my' && !$this->manage) { @@ -137,8 +144,10 @@ public function display($tpl = null) $this->filterForm = $this->get('FilterForm'); $this->activeFilters = $this->get('ActiveFilters'); - $this->manageOwn = $this->user->authorise('certificate.external.manageown', 'com_tjcertificate'); - $this->create = $this->user->authorise('certificate.external.create', 'com_tjcertificate'); + $this->manageOwn = $this->user->authorise('certificate.external.manageown', $this->comTjcertificate); + $this->create = $this->user->authorise('certificate.external.create', $this->comTjcertificate); + $this->delete = $this->user->authorise('certificate.external.delete', $this->comTjcertificate); + $this->deleteOwn = $this->user->authorise('certificate.external.deleteown', $this->comTjcertificate); if (ComponentHelper::isEnabled($this->comMultiAgency) && $this->params->get('enable_multiagency')) { From 89441635ff654cd4af1bcdec1f44aed4c24998ef Mon Sep 17 00:00:00 2001 From: divyachaudhari <58217051+divyachaudhari@users.noreply.github.com> Date: Thu, 1 Apr 2021 15:20:29 +0530 Subject: [PATCH 11/25] Bug #168131 Fix: Backend > Issued Certificates > Warning displayed on the certificate preview (#104) for delete() and publish() --- .../com_tjcertificate/administrator/models/certificate.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/com_tjcertificate/administrator/models/certificate.php b/src/components/com_tjcertificate/administrator/models/certificate.php index 8ef13993..863a3caf 100644 --- a/src/components/com_tjcertificate/administrator/models/certificate.php +++ b/src/components/com_tjcertificate/administrator/models/certificate.php @@ -198,7 +198,7 @@ public function getCertificateProviderInfo($contentId, $client) * * @since __DEPLOY_VERSION__ */ - public function delete($certificateIds) + public function delete(&$certificateIds) { $certificateIds = (array) $certificateIds; $table = $this->getTable('Certificates'); @@ -244,7 +244,7 @@ public function delete($certificateIds) * * @since __DEPLOY_VERSION__ */ - public function publish($ids, $state = 1) + public function publish(&$ids, $state = 1) { $table = $this->getTable(); From 7dd70772000b54e1ba4d840779ba25e3b01d8935 Mon Sep 17 00:00:00 2001 From: divyachaudhari <58217051+divyachaudhari@users.noreply.github.com> Date: Tue, 20 Apr 2021 14:40:28 +0530 Subject: [PATCH 12/25] Bug #170717 Fix: Frontend > My Certificate > Warnings and notices displayed on the certificate detail view (#107) --- .../administrator/views/certificate/tmpl/edit.php | 2 -- .../com_tjcertificate/site/views/certificate/tmpl/default.php | 3 ++- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/components/com_tjcertificate/administrator/views/certificate/tmpl/edit.php b/src/components/com_tjcertificate/administrator/views/certificate/tmpl/edit.php index 69ae886a..aedbb8ee 100644 --- a/src/components/com_tjcertificate/administrator/views/certificate/tmpl/edit.php +++ b/src/components/com_tjcertificate/administrator/views/certificate/tmpl/edit.php @@ -68,8 +68,6 @@ } ?>
- -
form->renderField('unique_certificate_id'); ?> form->renderField('certificate_template_id'); ?> diff --git a/src/components/com_tjcertificate/site/views/certificate/tmpl/default.php b/src/components/com_tjcertificate/site/views/certificate/tmpl/default.php index d65ccb61..837d29ac 100644 --- a/src/components/com_tjcertificate/site/views/certificate/tmpl/default.php +++ b/src/components/com_tjcertificate/site/views/certificate/tmpl/default.php @@ -57,7 +57,8 @@ if ($this->certificate) { $document = Factory::getDocument(); - $description = $this->item->description ? $this->item->description : $this->item->short_desc; + $description = !empty($this->item->description) ? $this->item->description : + (!empty($this->item->short_desc)? $this->item->short_desc: ''); $document->addScriptDeclaration("var certRootUrl = '" . JUri::root() . "'"); // For facebook and linkedin From 868f2638b88b4ca0a4370ead1cda7f37dde266b3 Mon Sep 17 00:00:00 2001 From: Tushar Shekokar Date: Mon, 26 Apr 2021 15:02:45 +0530 Subject: [PATCH 13/25] Feature #169954 chore: Add training records in bulk (#105) * Feature #169954 chore: Add training records in bulk * Feature #169954 chore: Add training records in bulk * Feature #169954 chore: Add training records in bulk * Feature #169954 chore: Add training records in bulk * Feature #169954 chore: Resolve comments * Feature #169954 chore: Resolve comments * Feature #169954 chore: Resolve comments * Feature #169954 chore: Resolve comments * Feature #169954 chore: Resolve comments * Feature #169954 chore: Resolve comments * Feature #169954 chore: Resolve comments * Feature #169954 chore: Resolve comments * Feature #169954 chore: Resolve comments * Feature #169954 chore: Add plugin install script --- .../administrator/config.xml | 16 ++ .../controllers/bulktrainingrecord.json.php | 156 ++++++++++++++++++ .../controllers/bulktrainingrecord.php | 23 +++ .../controllers/trainingrecord.php | 4 +- .../en-GB/en-GB.com_tjcertificate.ini | 21 +++ .../administrator/libraries/certificate.php | 2 + .../models/bulktrainingrecord.php | 138 ++++++++++++++++ .../models/fields/agencies.php | 0 .../models/forms/bulktrainingrecord.xml | 106 ++++++++++++ .../models/forms/trainingrecord.xml | 4 +- .../views/bulktrainingrecord/tmpl/edit.php | 94 +++++++++++ .../views/bulktrainingrecord/view.html.php | 103 ++++++++++++ .../views/certificates/view.html.php | 1 + .../com_tjcertificate/media/js/certificate.js | 32 ++++ .../media/js/certificate.min.js | 2 +- .../media/js/tjCertificateService.js | 6 +- .../media/js/tjCertificateService.min.js | 2 +- .../tjqueue/certificate/certificate.php | 38 +++++ .../tjqueue/certificate/certificate.xml | 23 +++ .../tjqueue/certificate/consumers/index.html | 1 + .../tjqueue/certificate/consumers/records.php | 43 +++++ .../plugins/tjqueue/certificate/index.html | 1 + .../en-GB/en-GB.plg_tjqueue_certificate.ini | 2 + .../en-GB.plg_tjqueue_certificate.sys.ini | 3 + .../script.tjcertificate.php | 84 ++++++++++ .../controllers/bulktrainingrecord.json.php | 14 ++ .../com_tjcertificate/site/events/record.php | 4 +- .../en-GB/en-GB.com_tjcertificate.ini | 12 +- .../site/models/bulktrainingrecord.php | 14 ++ .../site/models/forms/bulktrainingrecord.xml | 104 ++++++++++++ .../site/models/forms/trainingrecord.xml | 17 +- .../views/bulktrainingrecord/tmpl/edit.php | 93 +++++++++++ .../views/bulktrainingrecord/tmpl/edit.xml | 8 + .../views/bulktrainingrecord/view.html.php | 74 +++++++++ .../site/views/certificates/tmpl/my.php | 15 +- .../site/views/trainingrecord/tmpl/edit.php | 17 +- 36 files changed, 1257 insertions(+), 20 deletions(-) create mode 100644 src/components/com_tjcertificate/administrator/controllers/bulktrainingrecord.json.php create mode 100644 src/components/com_tjcertificate/administrator/controllers/bulktrainingrecord.php create mode 100644 src/components/com_tjcertificate/administrator/models/bulktrainingrecord.php rename src/components/com_tjcertificate/{site => administrator}/models/fields/agencies.php (100%) create mode 100644 src/components/com_tjcertificate/administrator/models/forms/bulktrainingrecord.xml create mode 100644 src/components/com_tjcertificate/administrator/views/bulktrainingrecord/tmpl/edit.php create mode 100644 src/components/com_tjcertificate/administrator/views/bulktrainingrecord/view.html.php create mode 100644 src/components/com_tjcertificate/plugins/tjqueue/certificate/certificate.php create mode 100644 src/components/com_tjcertificate/plugins/tjqueue/certificate/certificate.xml create mode 100644 src/components/com_tjcertificate/plugins/tjqueue/certificate/consumers/index.html create mode 100644 src/components/com_tjcertificate/plugins/tjqueue/certificate/consumers/records.php create mode 100644 src/components/com_tjcertificate/plugins/tjqueue/certificate/index.html create mode 100644 src/components/com_tjcertificate/plugins/tjqueue/certificate/languages/en-GB/en-GB.plg_tjqueue_certificate.ini create mode 100644 src/components/com_tjcertificate/plugins/tjqueue/certificate/languages/en-GB/en-GB.plg_tjqueue_certificate.sys.ini create mode 100644 src/components/com_tjcertificate/site/controllers/bulktrainingrecord.json.php create mode 100644 src/components/com_tjcertificate/site/models/bulktrainingrecord.php create mode 100644 src/components/com_tjcertificate/site/models/forms/bulktrainingrecord.xml create mode 100644 src/components/com_tjcertificate/site/views/bulktrainingrecord/tmpl/edit.php create mode 100644 src/components/com_tjcertificate/site/views/bulktrainingrecord/tmpl/edit.xml create mode 100644 src/components/com_tjcertificate/site/views/bulktrainingrecord/view.html.php diff --git a/src/components/com_tjcertificate/administrator/config.xml b/src/components/com_tjcertificate/administrator/config.xml index 5a367b84..74c9925c 100644 --- a/src/components/com_tjcertificate/administrator/config.xml +++ b/src/components/com_tjcertificate/administrator/config.xml @@ -106,6 +106,22 @@
+ +
+ + + + + + +
+
diff --git a/src/components/com_tjcertificate/administrator/controllers/bulktrainingrecord.json.php b/src/components/com_tjcertificate/administrator/controllers/bulktrainingrecord.json.php new file mode 100644 index 00000000..492ac0db --- /dev/null +++ b/src/components/com_tjcertificate/administrator/controllers/bulktrainingrecord.json.php @@ -0,0 +1,156 @@ + + * @copyright Copyright (C) 2009 - 2021 Techjoomla. All rights reserved. + * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL + */ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\Factory; +use Joomla\CMS\Language\Text; +use Joomla\CMS\MVC\Controller\FormController; +use Joomla\CMS\Session\Session; +use Joomla\CMS\Response\JsonResponse; +use Joomla\CMS\Component\ComponentHelper; + +/** + * The Tj Certificate Training Records controller + * + * @since __DEPLOY_VERSION__ + */ +class TjCertificateControllerBulkTrainingRecord extends FormController +{ + protected $comMultiAgency = 'com_multiagency'; + + /** + * Function to save multiple records + * + * @param string $key The name of the primary key of the URL variable. + * + * @param string $urlVar The name of the URL variable if different from the primary key (sometimes required to avoid router collisions). + * + * @return void + * + * @since __DEPLOY_VERSION__ + */ + public function save($key = null, $urlVar = null) + { + $app = Factory::getApplication(); + + if (!Session::checkToken()) + { + $app->enqueueMessage(Text::_('JINVALID_TOKEN'), 'error'); + echo new JsonResponse(null, null, true); + $app->close(); + } + + $user = Factory::getUser(); + $data = $app->input->post->get('jform', array(), 'array'); + + $model = $this->getModel(); + + // Validate the posted data. + $form = $model->getForm($data, false); + $data = $model->validate($form, $data); + + if ($data == false) + { + $errors = $model->getErrors(); + + if (!empty($errors)) + { + $msg = array(); + + // Push up to three validation messages out to the user. + for ($i = 0, $n = count($errors); $i < $n && $i < 3; $i++) + { + if ($errors[$i] instanceof Exception) + { + $msg[] = $errors[$i]->getMessage(); + } + else + { + $msg[] = $errors[$i]; + } + } + + $errormsg = implode("
", $msg); + echo new JsonResponse(0, $errormsg, true); + } + } + else + { + $params = ComponentHelper::getParams('com_tjcertificate'); + $userIds = $data['assigned_user_id']; + $data['client'] = "external"; + $data['is_external'] = 1; + + unset($data['assigned_user_id']); + + foreach ($userIds as $userId) + { + if (ComponentHelper::isEnabled($this->comMultiAgency) && $params->get('enable_multiagency')) + { + $manageOwn = $user->authorise('core.manage.own.agency.user', $this->comMultiAgency); + $manage = $user->authorise('core.manage.all.agency.user', $this->comMultiAgency); + + if ($manageOwn && empty($manage)) + { + $agencyModel = TJCERT::model('Agency', array('ignore_request' => true)); + + // Get agencies of logged-in user and assigned user + $assignedUserAgencies = $agencyModel->getUserAgencies($userId); + $loggedInUserAgencies = $agencyModel->getUserAgencies($user->id); + + $result = array(); + + if (!empty($assignedUserAgencies && $loggedInUserAgencies)) + { + // Convert object to array + $assignedUserAgencyArr = array_column($assignedUserAgencies, 'id'); + $loggedInUserAgencyArr = array_column($loggedInUserAgencies, 'id'); + + // Compare both users agencies + $result = array_intersect($loggedInUserAgencyArr, $assignedUserAgencyArr); + } + + if (empty($result)) + { + continue; + } + } + } + + $data['user_id'] = $userId; + $returnData = array(); + + if (ComponentHelper::isEnabled('com_tjqueue') && $params->get('tjqueue_records')) + { + $recordsModel = TJCERT::model('BulkTrainingRecord', array('ignore_request' => true)); + $response = $recordsModel->addToQueue($data); + $msg = $response ? Text::_("COM_TJCERTIFICATE_RECORDS_ADDED_TO_QUEUE_SUCCESSFULLY") : Text::_("COM_TJCERTIFICATE_RECORDS_FAILED"); + $returnData['msg'] = $msg; + } + else + { + $certificateModel = TJCERT::model('Certificate', array('ignore_request' => true)); + $certificateModel->save($data); + $certificateIds[] = $certificateModel->getState('certificate.id'); + + if ($certificateIds) + { + $returnData['msg'] = Text::sprintf('COM_TJCERTIFICATE_TOTAL_RECORDS_ADDED', count($certificateIds)); + } + } + } + + echo new JsonResponse($returnData); + $app->close(); + } + } +} diff --git a/src/components/com_tjcertificate/administrator/controllers/bulktrainingrecord.php b/src/components/com_tjcertificate/administrator/controllers/bulktrainingrecord.php new file mode 100644 index 00000000..8a6fe68c --- /dev/null +++ b/src/components/com_tjcertificate/administrator/controllers/bulktrainingrecord.php @@ -0,0 +1,23 @@ + + * @copyright Copyright (C) 2009 - 2021 Techjoomla. All rights reserved. + * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL + */ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\Controller\FormController; + +/** + * The Tj Certificate Training Records controller + * + * @since __DEPLOY_VERSION__ + */ +class TjCertificateControllerBulkTrainingRecord extends FormController +{ +} diff --git a/src/components/com_tjcertificate/administrator/controllers/trainingrecord.php b/src/components/com_tjcertificate/administrator/controllers/trainingrecord.php index b4892cb4..c8290f81 100644 --- a/src/components/com_tjcertificate/administrator/controllers/trainingrecord.php +++ b/src/components/com_tjcertificate/administrator/controllers/trainingrecord.php @@ -110,8 +110,8 @@ public function save($key = null, $urlVar = null) $validData['user_id'] = $user->id; } - $validData['client'] = "external"; - $validData['state'] = $validData['state'] ? $validData['state'] : "-1"; + $validData['client'] = "external"; + $validData['state'] = isset($validData['state']) ? $validData['state'] : "-1"; $validData['is_external'] = 1; $file = $app->input->files->get('jform', array(), 'array'); diff --git a/src/components/com_tjcertificate/administrator/languages/en-GB/en-GB.com_tjcertificate.ini b/src/components/com_tjcertificate/administrator/languages/en-GB/en-GB.com_tjcertificate.ini index 9c2bd017..3812514d 100644 --- a/src/components/com_tjcertificate/administrator/languages/en-GB/en-GB.com_tjcertificate.ini +++ b/src/components/com_tjcertificate/administrator/languages/en-GB/en-GB.com_tjcertificate.ini @@ -383,3 +383,24 @@ COM_TJCERTIFICATE_PERMISSION_DELETE_EXTERNAL_CERTIFICATE="Delete training record COM_TJCERTIFICATE_PERMISSION_DELETE_EXTERNAL_CERTIFICATE_DESC="Allow users to delete training records" COM_TJCERTIFICATE_PERMISSION_DELETEOWN_EXTERNAL_CERTIFICATE="Delete own records" COM_TJCERTIFICATE_PERMISSION_DELETEOWN_EXTERNAL_CERTIFICATE_DESC="Allow users to delete own training records" + +;Bulk Record Config +COM_TJCERTIFICATE_TJQUEUE_SETTING="Use TjQueue while adding bulk records" +COM_TJCERTIFICATE_TJQUEUE_SETTING_DESC="Set to 'Yes' if you want to use TjQueue while adding bulk records (Note: To make it work, you need com_tjqueue component, and also you need to enable certificate queue plugin)" +COM_TJCERTIFICATE_RECORDS_USER_SELECT_LIMIT="User limit for adding bulk records" +COM_TJCERTIFICATE_RECORDS_USER_SELECT_LIMIT_DESC="If the limit is set above 40 may result in a timeout." +COM_TJCERTIFICATE_USER_LIMIT_MESSAGE="You cannot add more than the %s records." +COM_TJCERTIFICATE_BULK_RECORD_SETTINGS="Bulk Training Record" +COM_TJCERTIFICATE_BULK_RECORD_SETTINGS_NOTE="Please note:

Cron Setup +

Example:
*/1 * * * * /usr/bin/php7.3 JOOMLA_SITE/cli/tjqueue.php -t tjqueue -n 5 +" + +;Bulk Record form +COM_TJCERTIFICATE_ADD_EXTERNAL_CERTIFICATES="Bulk Training Records" +COM_TJCERTIFICATE_BULK_ADD_FORM_LBL_ASSIGNED_USERS="Select Users" +COM_TJCERTIFICATE_BULK_ADD_FORM_LBL_NOTIFY_USERS="Notify Users" +COM_TJCERTIFICATE_BULK_ADD_FORM_LBL_NOTIFY_USERS_DESC="Please tick this box if you want to send record add email to selected users" +COM_TJCERTIFICATE_FORM_VALIDATATION_FAILED="Form Validation Failed" +COM_TJCERTIFICATE_PAGE_ADD_TRAINING_RECORDS="Training Records" +COM_TJCERTIFICATE_TOTAL_RECORDS_ADDED="Records added for %s user(s)" +COM_TJCERTIFICATE_RECORDS_ADDED_TO_QUEUE_SUCCESSFULLY="Records added in queue" diff --git a/src/components/com_tjcertificate/administrator/libraries/certificate.php b/src/components/com_tjcertificate/administrator/libraries/certificate.php index 08a045ee..fbd68450 100644 --- a/src/components/com_tjcertificate/administrator/libraries/certificate.php +++ b/src/components/com_tjcertificate/administrator/libraries/certificate.php @@ -80,6 +80,8 @@ class TjCertificateCertificate extends CMSObject public $created_by = ""; + public $notify = 1; + /** * Constructor activating the default information of the Certificate * diff --git a/src/components/com_tjcertificate/administrator/models/bulktrainingrecord.php b/src/components/com_tjcertificate/administrator/models/bulktrainingrecord.php new file mode 100644 index 00000000..f9d7bc8e --- /dev/null +++ b/src/components/com_tjcertificate/administrator/models/bulktrainingrecord.php @@ -0,0 +1,138 @@ + + * @copyright Copyright (C) 2009 - 2021 Techjoomla. All rights reserved. + * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL + */ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\Model\AdminModel; +use Joomla\CMS\Table\Table; +use Joomla\CMS\Component\ComponentHelper; +use Joomla\CMS\Factory; +use Joomla\CMS\Language\Text; +use TJQueue\Admin\TJQueueProduce; + +if (ComponentHelper::getComponent('com_tjqueue', true)->enabled) +{ + jimport('tjqueueproduce', JPATH_ADMINISTRATOR . '/components/com_tjqueue/libraries'); +} + +/** + * TjCertificate Bulk Training Record Model. + * + * @since __DEPLOY_VERSION__ + */ +class TjCertificateModelBulkTrainingRecord extends AdminModel +{ + protected $comMultiAgency = 'com_multiagency'; + + public $params; + + public $user; + + /** + * Constructor. + * + * @param array $config An optional associative array of configuration settings. + * + * @since __DEPLOY_VERSION__ + */ + public function __construct($config = array()) + { + $this->params = ComponentHelper::getParams('com_tjcertificate'); + $this->user = Factory::getuser(); + + parent::__construct($config); + } + + /** + * Method to get the record form. + * + * @param array $data Data for the form. + * @param boolean $loadData True if the form is to load its own data (default case), false if not. + * + * @return JForm|boolean A JForm object on success, false on failure + * + * @since __DEPLOY_VERSION__ + */ + public function getForm($data = array(), $loadData = true) + { + // Get the form. + $form = $this->loadForm('com_tjcertificate.bulktrainingrecord', 'bulktrainingrecord', array('control' => 'jform', 'load_data' => $loadData)); + + return empty($form) ? false : $form; + } + + /** + * Method to validate the form data. + * + * @param \JForm $form The form to validate against. + * @param Array $data The data to validate. + * @param string $group The name of the field group to validate. + * + * @return array|boolean Array of filtered data if valid, false otherwise. + * + * @since __DEPLOY_VERSION__ + */ + public function validate($form, $data, $group = null) + { + $return = true; + $return = parent::validate($form, $data, $group); + + if (!empty($data['expired_on']) && $data['expired_on'] != '0000-00-00 00:00:00') + { + if ($data['issued_on'] > $data['expired_on']) + { + $this->setError(Text::_('COM_TJCERTIFICATE_EXPIRY_DATE_VALIDATION_MESSAGE')); + $return = false; + } + } + + return $return; + } + + /** + * Method to push data in queue. + * + * @param array $data record data + * + * @return array + * + * @since __DEPLOY_VERSION__ + */ + public function addToQueue($data) + { + $return = array(); + $messageBody = (object) $data; + + try + { + $TJQueueProduce = new TJQueueProduce; + + // Set message body + $TJQueueProduce->message->setBody(json_encode($messageBody)); + + // @Params client, value + $TJQueueProduce->message->setProperty('client', 'certificate.records'); + $TJQueueProduce->produce(); + } + catch (Exception $e) + { + $return['success'] = 0; + $return['message'] = $e->getMessage(); + + return $return; + } + + $return['success'] = 1; + $return['message'] = ''; + + return $return; + } +} diff --git a/src/components/com_tjcertificate/site/models/fields/agencies.php b/src/components/com_tjcertificate/administrator/models/fields/agencies.php similarity index 100% rename from src/components/com_tjcertificate/site/models/fields/agencies.php rename to src/components/com_tjcertificate/administrator/models/fields/agencies.php diff --git a/src/components/com_tjcertificate/administrator/models/forms/bulktrainingrecord.xml b/src/components/com_tjcertificate/administrator/models/forms/bulktrainingrecord.xml new file mode 100644 index 00000000..844166b5 --- /dev/null +++ b/src/components/com_tjcertificate/administrator/models/forms/bulktrainingrecord.xml @@ -0,0 +1,106 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ diff --git a/src/components/com_tjcertificate/administrator/models/forms/trainingrecord.xml b/src/components/com_tjcertificate/administrator/models/forms/trainingrecord.xml index 1507ebaf..b57d4e6b 100644 --- a/src/components/com_tjcertificate/administrator/models/forms/trainingrecord.xml +++ b/src/components/com_tjcertificate/administrator/models/forms/trainingrecord.xml @@ -1,6 +1,6 @@
-
+
diff --git a/src/components/com_tjcertificate/administrator/views/bulktrainingrecord/tmpl/edit.php b/src/components/com_tjcertificate/administrator/views/bulktrainingrecord/tmpl/edit.php new file mode 100644 index 00000000..3547aacc --- /dev/null +++ b/src/components/com_tjcertificate/administrator/views/bulktrainingrecord/tmpl/edit.php @@ -0,0 +1,94 @@ + + * @copyright Copyright (C) 2009 - 2021 Techjoomla. All rights reserved. + * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL + */ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\Factory; +use Joomla\CMS\Language\Text; +use Joomla\CMS\HTML\HTMLHelper; + +HTMLHelper::addIncludePath(JPATH_COMPONENT . '/helpers/html'); + +HTMLHelper::_('jquery.token'); +HTMLHelper::_('behavior.framework'); +HTMLHelper::_('behavior.formvalidator'); +HTMLHelper::_('behavior.keepalive'); +HTMLHelper::_('formbehavior.chosen', 'select'); + +$options['relative'] = true; +HTMLHelper::_('script', 'media/com_tjcertificate/vendors/loader/js/loadingoverlay.min.js'); +HTMLHelper::_('script', 'com_tjcertificate/tjCertificateService.min.js', $options); +HTMLHelper::_('script', 'com_tjcertificate/certificate.min.js', $options); + +$userLimit = $this->params->get('users_select_limit'); +$message = Text::sprintf("COM_TJCERTIFICATE_USER_LIMIT_MESSAGE", $userLimit); + +?> +
+
+ + sidebar)) + { + ?> +
+ sidebar; ?> +
+
+ +
+ +
+ + +
+ isAgencyEnabled) + { + + echo $this->form->renderField('agency_id'); + } + ?> + + form->renderField('assigned_user_id'); ?> + form->renderField('name'); ?> + form->renderField('issuing_org'); ?> + form->renderField('issued_on'); ?> + form->renderField('expired_on'); ?> + form->renderField('status'); ?> + form->renderField('state'); ?> + form->renderField('notify_users'); ?> + +
+ + + +
+ +
+
+ diff --git a/src/components/com_tjcertificate/administrator/views/bulktrainingrecord/view.html.php b/src/components/com_tjcertificate/administrator/views/bulktrainingrecord/view.html.php new file mode 100644 index 00000000..c769e515 --- /dev/null +++ b/src/components/com_tjcertificate/administrator/views/bulktrainingrecord/view.html.php @@ -0,0 +1,103 @@ + + * @copyright Copyright (C) 2009 - 2021 Techjoomla. All rights reserved. + * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL + */ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\Factory; +use Joomla\CMS\Language\Text; +use Joomla\CMS\MVC\View\HtmlView; +use Joomla\CMS\Component\ComponentHelper; +use Joomla\CMS\Toolbar\ToolbarHelper; +use Joomla\CMS\Toolbar\Toolbar; + +/** + * View to edit + * + * @since __DEPLOY_VERSION__ + */ +class TjCertificateViewBulkTrainingRecord extends HtmlView +{ + /** + * The JForm object + * + * @var JForm + */ + protected $form; + + public $isAgencyEnabled = false; + + protected $comMultiAgency = 'com_multiagency'; + + /** + * Display the view + * + * @param string $tpl Template name + * + * @return void + * + * @throws Exception + */ + public function display($tpl = null) + { + $this->form = $this->get('Form'); + $this->input = Factory::getApplication()->input; + $this->params = ComponentHelper::getParams('com_tjcertificate'); + + if (ComponentHelper::isEnabled($this->comMultiAgency) && $this->params->get('enable_multiagency')) + { + $this->isAgencyEnabled = true; + } + + $layout = $this->input->get('layout', 'edit'); + + $this->addToolbar(); + + parent::display($tpl); + } + + /** + * Add the page title and toolbar. + * + * @return void + * + * @since __DEPLOY_VERSION__ + */ + protected function addToolbar() + { + $app = Factory::getApplication(); + + $layout = $app->input->get("layout"); + + JLoader::import('administrator.components.com_tjcertificate.helpers.tjcertificate', JPATH_SITE); + TjCertificateHelper::addSubmenu('certificates'); + + if ($app->isClient('administrator')) + { + $this->sidebar = JHtmlSidebar::render(); + } + + if ($layout != "default") + { + $app->input->set('hidemainmenu', true); + + ToolbarHelper::title( + Text::_('COM_TJCERTIFICATE_PAGE_ADD_TRAINING_RECORDS'), + 'pencil-2 certificate-add' + ); + + $layout = ''; + + Toolbar::getInstance('toolbar')->appendButton('Custom', $layout); + ToolbarHelper::cancel('certificate.cancel'); + } + } +} diff --git a/src/components/com_tjcertificate/administrator/views/certificates/view.html.php b/src/components/com_tjcertificate/administrator/views/certificates/view.html.php index 2923f6c8..1567474a 100644 --- a/src/components/com_tjcertificate/administrator/views/certificates/view.html.php +++ b/src/components/com_tjcertificate/administrator/views/certificates/view.html.php @@ -157,6 +157,7 @@ protected function addToolbar() if ($canDo->get('certificate.external.create')) { JToolbarHelper::addNew('trainingrecord.add', 'COM_TJCERTIFICATE_ADD_EXTERNAL_CERTIFICATE'); + JToolbarHelper::addNew('bulktrainingrecord.add', 'COM_TJCERTIFICATE_ADD_EXTERNAL_CERTIFICATES'); } if ($canDo->get('core.edit')) diff --git a/src/components/com_tjcertificate/media/js/certificate.js b/src/components/com_tjcertificate/media/js/certificate.js index 83e83773..f6e17ef7 100644 --- a/src/components/com_tjcertificate/media/js/certificate.js +++ b/src/components/com_tjcertificate/media/js/certificate.js @@ -205,5 +205,37 @@ var certificate = { clusterusers.trigger("liszt:updated"); } }); + }, + addRecords: function() { + certificate.showLoader(); + var formData = jQuery('.add-records').serialize(); + var params = {}; + params['async'] = true; + var promise = tjCertificateService.addRecords(formData,params); + + promise.fail( + function(response) { + var messages = {"error": [response.responseText]}; + Joomla.renderMessages(messages); + } + ).done(function(response) { + jQuery.LoadingOverlay("hide"); + + if (!response.success && response.message){ + var messages = { "error": [response.message]}; + Joomla.renderMessages(messages); + } + + if (response.success) { + certificate.renderMessage(response.data.msg); + jQuery('#adminForm').trigger("reset"); + jQuery('#jform_assigned_user_id').trigger("liszt:updated"); + } + }); + }, + showLoader: function() { + jQuery.LoadingOverlay("show", { + image : Joomla.getOptions('system.paths').root + "/media/com_tjcertificate/images/loader/loader.gif", + }); } }; diff --git a/src/components/com_tjcertificate/media/js/certificate.min.js b/src/components/com_tjcertificate/media/js/certificate.min.js index 0e9ee1f3..129392a1 100644 --- a/src/components/com_tjcertificate/media/js/certificate.min.js +++ b/src/components/com_tjcertificate/media/js/certificate.min.js @@ -1 +1 @@ -var certificate={validateFile:function(e){if("file"!=jQuery(e).attr("type"))return!1;jQuery("#system-message-container").empty();var r=jQuery(e)[0].files[0],t=r.type,a=r.name.split("."),s=allowedAttachments.split(","),i=0,n=new Array;return""===a[a.length-1]&&null===a[a.length-1]||-1!=jQuery.inArray(t,s)||(i="1",n.push(Joomla.JText._("COM_TJCERTIFICATE_MEDIA_INVALID_FILE_TYPE"))),r.size>1024*attachmentMaxSize*1024&&(i="1",n.push(Joomla.JText._("COM_TJCERTIFICATE_MEDIA_UPLOAD_ERROR")),console.log("COM_TIMELOG_FILE_SIZE_ERROR")),i?(Joomla.renderMessages({error:n}),jQuery("html, body").animate({scrollTop:0},500),!1):void 0},deleteAttachment:function(e){if(1==confirm(Joomla.JText._("COM_TJCERTIFICATE_CONFIRM_DELETE_ATTACHMENT"))){var r={};if(""==e||void 0===e)return!1;r.certificateId=jQuery(e).attr("data-aid"),r.mediaId=jQuery(e).attr("data-mid"),tjCertificateService.deleteAttachment(r).fail(function(e){var r={error:[e.responseText]};certificate.renderMessage(r)}).done(function(r){if(!r.success&&r.message){var t={error:[r.message]};certificate.renderMessage(t)}r.messages&&certificate.renderMessage(r.messages),r.success&&certificate.renderMessage(r.message),jQuery(e).closest("span.fileupload").remove()})}},deleteItem:function(e,r){if(1==confirm(Joomla.JText._("COM_TJCERTIFICATE_DELETE_CERTIFICATE_MESSAGE"))){var t={};if(""==e||void 0===e)return!1;t.certificateId=e,tjCertificateService.deleteItem(t).fail(function(e){var r={error:[e.responseText]};certificate.renderMessage(r)}).done(function(e){if(!e.success&&e.message){var t={error:[e.message]};certificate.renderMessage(t)}e.messages&&certificate.renderMessage(e.messages),e.success&&certificate.renderMessage(e.message),jQuery(r).closest("tr").remove()})}},renderMessage:function(e){Joomla.renderMessages({"alert alert-success":[e]}),jQuery("html, body").animate({scrollTop:0},2e3)},validationEndDate:function(e){var r=jQuery(e).val(),t=jQuery("#jform_issued_on").val();jQuery(document).ready(function(){document.formvalidator.setHandler("expdate",function(e){return!(t>r)||(certificate.renderMessage(Joomla.JText._("COM_TJCERTIFICATE_EXPIRY_DATE_VALIDATION_MESSAGE")),jQuery("#jform_expired_on").val(""),!1)})})},getAgencyUsers:function(e){var r={},t=jQuery("#jform_assigned_user_id"),a=jQuery("#assigned_user_id").val();r.agency_id=jQuery(e).val(),tjCertificateService.getAgencyUsers(r).fail(function(e){var r={error:[e.responseText]};Joomla.renderMessage(r)}).done(function(e){if(!e)return!1;if(e.success){t.empty(),t.trigger("liszt:updated");for(var r=e.data,s=0;s "+r[s].text+"",t.append(op);t.trigger("liszt:updated")}})}}; +var certificate={validateFile:function(e){if("file"!=jQuery(e).attr("type"))return!1;jQuery("#system-message-container").empty();var r=jQuery(e)[0].files[0],t=r.type,a=r.name.split("."),s=allowedAttachments.split(","),i=0,o=new Array;return""===a[a.length-1]&&null===a[a.length-1]||-1!=jQuery.inArray(t,s)||(i="1",o.push(Joomla.JText._("COM_TJCERTIFICATE_MEDIA_INVALID_FILE_TYPE"))),r.size>1024*attachmentMaxSize*1024&&(i="1",o.push(Joomla.JText._("COM_TJCERTIFICATE_MEDIA_UPLOAD_ERROR")),console.log("COM_TIMELOG_FILE_SIZE_ERROR")),i?(Joomla.renderMessages({error:o}),jQuery("html, body").animate({scrollTop:0},500),!1):void 0},deleteAttachment:function(e){if(1==confirm(Joomla.JText._("COM_TJCERTIFICATE_CONFIRM_DELETE_ATTACHMENT"))){var r={};if(""==e||void 0===e)return!1;r.certificateId=jQuery(e).attr("data-aid"),r.mediaId=jQuery(e).attr("data-mid"),tjCertificateService.deleteAttachment(r).fail(function(e){var r={error:[e.responseText]};certificate.renderMessage(r)}).done(function(r){if(!r.success&&r.message){var t={error:[r.message]};certificate.renderMessage(t)}r.messages&&certificate.renderMessage(r.messages),r.success&&certificate.renderMessage(r.message),jQuery(e).closest("span.fileupload").remove()})}},deleteItem:function(e,r){if(1==confirm(Joomla.JText._("COM_TJCERTIFICATE_DELETE_CERTIFICATE_MESSAGE"))){var t={};if(""==e||void 0===e)return!1;t.certificateId=e,tjCertificateService.deleteItem(t).fail(function(e){var r={error:[e.responseText]};certificate.renderMessage(r)}).done(function(e){if(!e.success&&e.message){var t={error:[e.message]};certificate.renderMessage(t)}e.messages&&certificate.renderMessage(e.messages),e.success&&certificate.renderMessage(e.message),jQuery(r).closest("tr").remove()})}},renderMessage:function(e){Joomla.renderMessages({"alert alert-success":[e]}),jQuery("html, body").animate({scrollTop:0},2e3)},validationEndDate:function(e){var r=jQuery(e).val(),t=jQuery("#jform_issued_on").val();jQuery(document).ready(function(){document.formvalidator.setHandler("expdate",function(e){return!(t>r)||(certificate.renderMessage(Joomla.JText._("COM_TJCERTIFICATE_EXPIRY_DATE_VALIDATION_MESSAGE")),jQuery("#jform_expired_on").val(""),!1)})})},getAgencyUsers:function(e){var r={},t=jQuery("#jform_assigned_user_id"),a=jQuery("#assigned_user_id").val();r.agency_id=jQuery(e).val(),tjCertificateService.getAgencyUsers(r).fail(function(e){var r={error:[e.responseText]};Joomla.renderMessage(r)}).done(function(e){if(!e)return!1;if(e.success){t.empty(),t.trigger("liszt:updated");for(var r=e.data,s=0;s "+r[s].text+"",t.append(op);t.trigger("liszt:updated")}})},addRecords:function(){certificate.showLoader();var e=jQuery(".add-records").serialize(),r={async:!0};tjCertificateService.addRecords(e,r).fail(function(e){var r={error:[e.responseText]};Joomla.renderMessages(r)}).done(function(e){if(jQuery.LoadingOverlay("hide"),!e.success&&e.message){var r={error:[e.message]};Joomla.renderMessages(r)}e.success&&(certificate.renderMessage(e.data.msg),jQuery("#adminForm").trigger("reset"),jQuery("#jform_assigned_user_id").trigger("liszt:updated"))})},showLoader:function(){jQuery.LoadingOverlay("show",{image:Joomla.getOptions("system.paths").root+"/media/com_tjcertificate/images/loader/loader.gif"})}}; diff --git a/src/components/com_tjcertificate/media/js/tjCertificateService.js b/src/components/com_tjcertificate/media/js/tjCertificateService.js index 5d43f1ec..156332b3 100644 --- a/src/components/com_tjcertificate/media/js/tjCertificateService.js +++ b/src/components/com_tjcertificate/media/js/tjCertificateService.js @@ -15,6 +15,7 @@ var tjCertificateService = { deleteAttachmentUrl: '/index.php?option=com_tjcertificate&task=trainingrecord.deleteAttachment&format=json', deleteItemUrl: '/index.php?option=com_tjcertificate&task=trainingrecord.delete&format=json', getAgencyUsersUrl: '/index.php?option=com_tjcertificate&task=agency.getAgencyUsers&format=json', + addRecordsUrl: '/index.php?option=com_tjcertificate&task=bulktrainingrecord.save&format=json', postData: function(url, formData, params) { if(!params){ @@ -46,5 +47,8 @@ var tjCertificateService = { }, getAgencyUsers: function (formData, params) { return this.postData(this.getAgencyUsersUrl, formData, params); - } + }, + addRecords: function (formData, params) { + return this.postData(this.addRecordsUrl, formData, params); + }, } diff --git a/src/components/com_tjcertificate/media/js/tjCertificateService.min.js b/src/components/com_tjcertificate/media/js/tjCertificateService.min.js index b8a26d7c..2eeb58b9 100644 --- a/src/components/com_tjcertificate/media/js/tjCertificateService.min.js +++ b/src/components/com_tjcertificate/media/js/tjCertificateService.min.js @@ -1 +1 @@ -var tjCertificateService={siteRoot:Joomla.getOptions("system.paths").base,loadDefaultTemplateUrl:"/index.php?option=com_tjcertificate&task=template.loadDefaultTemplate&format=json",loadCustomTemplateUrl:"/index.php?option=com_tjcertificate&task=template.loadCustomTemplate&format=json",deleteAttachmentUrl:"/index.php?option=com_tjcertificate&task=trainingrecord.deleteAttachment&format=json",deleteItemUrl:"/index.php?option=com_tjcertificate&task=trainingrecord.delete&format=json",getAgencyUsersUrl:"/index.php?option=com_tjcertificate&task=agency.getAgencyUsers&format=json",postData:function(t,e,a){return a||(a={}),a.url=this.siteRoot+t,a.data=e,a.type=void 0!==a.type?a.type:"POST",a.async=void 0!==a.async&&a.async,a.dataType=void 0!==a.datatype?a.datatype:"json",a.contentType=void 0!==a.contentType?a.contentType:"application/x-www-form-urlencoded; charset=UTF-8",a.processData=void 0===a.processData||a.processData,jQuery.ajax(a)},loadDefaultTemplate:function(t,e){return this.postData(this.loadDefaultTemplateUrl,t,e)},loadCustomTemplate:function(t,e){return this.postData(this.loadCustomTemplateUrl,t,e)},deleteAttachment:function(t,e){return this.postData(this.deleteAttachmentUrl,t,e)},deleteItem:function(t,e){return this.postData(this.deleteItemUrl,t,e)},getAgencyUsers:function(t,e){return this.postData(this.getAgencyUsersUrl,t,e)}}; +var tjCertificateService={siteRoot:Joomla.getOptions("system.paths").base,loadDefaultTemplateUrl:"/index.php?option=com_tjcertificate&task=template.loadDefaultTemplate&format=json",loadCustomTemplateUrl:"/index.php?option=com_tjcertificate&task=template.loadCustomTemplate&format=json",deleteAttachmentUrl:"/index.php?option=com_tjcertificate&task=trainingrecord.deleteAttachment&format=json",deleteItemUrl:"/index.php?option=com_tjcertificate&task=trainingrecord.delete&format=json",getAgencyUsersUrl:"/index.php?option=com_tjcertificate&task=agency.getAgencyUsers&format=json",addRecordsUrl:"/index.php?option=com_tjcertificate&task=bulktrainingrecord.save&format=json",postData:function(t,e,a){return a||(a={}),a.url=this.siteRoot+t,a.data=e,a.type=void 0!==a.type?a.type:"POST",a.async=void 0!==a.async&&a.async,a.dataType=void 0!==a.datatype?a.datatype:"json",a.contentType=void 0!==a.contentType?a.contentType:"application/x-www-form-urlencoded; charset=UTF-8",a.processData=void 0===a.processData||a.processData,jQuery.ajax(a)},loadDefaultTemplate:function(t,e){return this.postData(this.loadDefaultTemplateUrl,t,e)},loadCustomTemplate:function(t,e){return this.postData(this.loadCustomTemplateUrl,t,e)},deleteAttachment:function(t,e){return this.postData(this.deleteAttachmentUrl,t,e)},deleteItem:function(t,e){return this.postData(this.deleteItemUrl,t,e)},getAgencyUsers:function(t,e){return this.postData(this.getAgencyUsersUrl,t,e)},addRecords:function(t,e){return this.postData(this.addRecordsUrl,t,e)}}; diff --git a/src/components/com_tjcertificate/plugins/tjqueue/certificate/certificate.php b/src/components/com_tjcertificate/plugins/tjqueue/certificate/certificate.php new file mode 100644 index 00000000..6a4166e4 --- /dev/null +++ b/src/components/com_tjcertificate/plugins/tjqueue/certificate/certificate.php @@ -0,0 +1,38 @@ + + * @copyright Copyright (c) 2009-2021 TechJoomla. All rights reserved. + * @license GNU General Public License version 2 or later. + */ + +// No direct access +defined('_JEXEC') or die; + +use Joomla\CMS\Plugin\CMSPlugin; + +/** + * TjQueue + * + * @package Techjoomla.Libraries + * @subpackage Tjqueue + * @since 1.0 + */ +class PlgTjqueueRecords extends CMSPlugin +{ + /** + * Load the language file on instantiation. Note this is only available in Joomla 3.1 and higher. + * + * @var boolean + * @since 3.1 + */ + protected $autoloadLanguage = true; + + /** + * Plugin method with the same name as the event will be called automatically. + */ + public function __construct() + { + return true; + } +} diff --git a/src/components/com_tjcertificate/plugins/tjqueue/certificate/certificate.xml b/src/components/com_tjcertificate/plugins/tjqueue/certificate/certificate.xml new file mode 100644 index 00000000..fc7748b1 --- /dev/null +++ b/src/components/com_tjcertificate/plugins/tjqueue/certificate/certificate.xml @@ -0,0 +1,23 @@ + + + plg_tjqueue_certificate + Techjoomla + 31st March 2021 + Copyright (C) 2016 - 2021 Techjoomla. All rights reserved. + http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL + extensions@techjoomla.com + https://techjoomla.com + 1.0.0 + PLG_TJQUEUE_CERTIFICATE_XML_DESCRIPTION + + + certificate.php + index.html + consumers + + + + en-GB/en-GB.plg_tjqueue_certificate.ini + en-GB/en-GB.plg_tjqueue_certificate.sys.ini + + diff --git a/src/components/com_tjcertificate/plugins/tjqueue/certificate/consumers/index.html b/src/components/com_tjcertificate/plugins/tjqueue/certificate/consumers/index.html new file mode 100644 index 00000000..0dc101b5 --- /dev/null +++ b/src/components/com_tjcertificate/plugins/tjqueue/certificate/consumers/index.html @@ -0,0 +1 @@ + diff --git a/src/components/com_tjcertificate/plugins/tjqueue/certificate/consumers/records.php b/src/components/com_tjcertificate/plugins/tjqueue/certificate/consumers/records.php new file mode 100644 index 00000000..2e5a49c9 --- /dev/null +++ b/src/components/com_tjcertificate/plugins/tjqueue/certificate/consumers/records.php @@ -0,0 +1,43 @@ + + * @copyright Copyright (c) 2009-2021 TechJoomla. All rights reserved. + * @license GNU General Public License version 2 or later. + */ + +// No direct access +defined('_JEXEC') or die; + +use \Joomla\Registry\Registry; +JLoader::import('components.com_tjcertificate.includes.tjcertificate', JPATH_ADMINISTRATOR); + +/** + * TjQueue + * + * @package Techjoomla.Libraries + * @subpackage Tjqueue + * @since __DEPLOY_VERSION__ + */ +class TjqueueCertificateRecords +{ + /** + * Plugin method with the same name as the event will be called automatically. + * + * @param string $message A Message + * + * @return boolean This method should return acknowledgement flag + * + * @since __DEPLOY_VERSION__ + */ + public function consume($message) + { + $messageBody = $message->getBody(); + $messageData = new Registry($messageBody); + $messageData = $messageData->toArray(); + $certificateModel = TJCERT::model('Certificate', array('ignore_request' => true)); + $certificateModel->save($messageData); + + return true; + } +} diff --git a/src/components/com_tjcertificate/plugins/tjqueue/certificate/index.html b/src/components/com_tjcertificate/plugins/tjqueue/certificate/index.html new file mode 100644 index 00000000..0dc101b5 --- /dev/null +++ b/src/components/com_tjcertificate/plugins/tjqueue/certificate/index.html @@ -0,0 +1 @@ + diff --git a/src/components/com_tjcertificate/plugins/tjqueue/certificate/languages/en-GB/en-GB.plg_tjqueue_certificate.ini b/src/components/com_tjcertificate/plugins/tjqueue/certificate/languages/en-GB/en-GB.plg_tjqueue_certificate.ini new file mode 100644 index 00000000..4b8c66d2 --- /dev/null +++ b/src/components/com_tjcertificate/plugins/tjqueue/certificate/languages/en-GB/en-GB.plg_tjqueue_certificate.ini @@ -0,0 +1,2 @@ +PLG_TJQUEUE_CERTIFICATE="TjQueue plugin for TjCertificate" +PLG_TJQUEUE_CERTIFICATE_XML_DESCRIPTION="This plugin used to add bulk records using TjQueue" diff --git a/src/components/com_tjcertificate/plugins/tjqueue/certificate/languages/en-GB/en-GB.plg_tjqueue_certificate.sys.ini b/src/components/com_tjcertificate/plugins/tjqueue/certificate/languages/en-GB/en-GB.plg_tjqueue_certificate.sys.ini new file mode 100644 index 00000000..5477f68c --- /dev/null +++ b/src/components/com_tjcertificate/plugins/tjqueue/certificate/languages/en-GB/en-GB.plg_tjqueue_certificate.sys.ini @@ -0,0 +1,3 @@ +PLG_TJQUEUE_CERTIFICATE="TjQueue plugin for TjCertificate" +PLG_TJQUEUE_CERTIFICATE_XML_DESCRIPTION="This plugin used to add bulk records using TjQueue" + diff --git a/src/components/com_tjcertificate/script.tjcertificate.php b/src/components/com_tjcertificate/script.tjcertificate.php index 6d825c39..5547111e 100644 --- a/src/components/com_tjcertificate/script.tjcertificate.php +++ b/src/components/com_tjcertificate/script.tjcertificate.php @@ -23,6 +23,17 @@ */ class Com_TjcertificateInstallerScript { + /** @var array The list of extra modules and plugins to install */ + private $installation_queue = array( + + // Plugins => { (folder) => { (element) => (published) }* }* + 'plugins' => array( + 'tjqueue' => array( + 'certificate' => 0, + ) + ) + ); + /** * Runs after install, update or discover_update * @@ -48,6 +59,9 @@ public function postflight($type, $parent) $this->installNotificationsTemplates(); + // Install subextensions + $this->_installSubextensions($parent); + return true; } @@ -81,4 +95,74 @@ public function installNotificationsTemplates() } } } + + /** + * Installs subextensions (modules, plugins) bundled with the main extension + * + * @param JInstaller $parent + * + * @return JObject The subextension installation status + */ + private function _installSubextensions($parent) + { + $src = $parent->getParent()->getPath('source'); + + $db = JFactory::getDbo(); + + // Plugins installation + if (count($this->installation_queue['plugins'])) + { + foreach ($this->installation_queue['plugins'] as $folder => $plugins) + { + if (count($plugins)) + { + foreach ($plugins as $plugin => $published) + { + $path = "$src/plugins/$folder/$plugin"; + + if (!is_dir($path)) + { + $path = "$src/plugins/$folder/plg_$plugin"; + } + + if (!is_dir($path)) + { + $path = "$src/plugins/$plugin"; + } + + if (!is_dir($path)) + { + $path = "$src/plugins/plg_$plugin"; + } + + if (!is_dir($path)) + { + continue; + } + + // Was the plugin already installed? + $query = $db->getQuery(true)->select('COUNT(*)')->from($db->qn('#__extensions'))->where($db->qn('element') . ' = ' . $db->q($plugin))->where($db->qn('folder') . ' = ' . $db->q($folder)); + $db->setQuery($query); + $count = $db->loadResult(); + + $installer = new JInstaller; + $result = $installer->install($path); + + $status->plugins[] = array( + 'name' => 'plg_' . $plugin, + 'group' => $folder, + 'result' => $result + ); + + if ($published && !$count) + { + $query = $db->getQuery(true)->update($db->qn('#__extensions'))->set($db->qn('enabled') . ' = ' . $db->q('1'))->where($db->qn('element') . ' = ' . $db->q($plugin))->where($db->qn('folder') . ' = ' . $db->q($folder)); + $db->setQuery($query); + $db->execute(); + } + } + } + } + } + } } diff --git a/src/components/com_tjcertificate/site/controllers/bulktrainingrecord.json.php b/src/components/com_tjcertificate/site/controllers/bulktrainingrecord.json.php new file mode 100644 index 00000000..8b2fb0ea --- /dev/null +++ b/src/components/com_tjcertificate/site/controllers/bulktrainingrecord.json.php @@ -0,0 +1,14 @@ + + * @copyright Copyright (C) 2009 - 2021 Techjoomla. All rights reserved. + * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL + */ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +require_once JPATH_ADMINISTRATOR . '/components/com_tjcertificate/controllers/bulktrainingrecord.json.php'; diff --git a/src/components/com_tjcertificate/site/events/record.php b/src/components/com_tjcertificate/site/events/record.php index 75c10941..31646666 100644 --- a/src/components/com_tjcertificate/site/events/record.php +++ b/src/components/com_tjcertificate/site/events/record.php @@ -15,6 +15,8 @@ use Joomla\CMS\Component\ComponentHelper; JLoader::import('components.com_tjcertificate.libraries.mails', JPATH_ADMINISTRATOR); +jimport('techjoomla.tjnotifications.tjnotifications'); + /** * Tjcertificate triggers class for record. * @@ -52,7 +54,7 @@ public function __construct() */ public function onAfterRecordSave($recordDetails, $isNew) { - switch ($isNew) + switch ($isNew && $recordDetails->notify) { case true: /* Send mail on record create */ diff --git a/src/components/com_tjcertificate/site/languages/en-GB/en-GB.com_tjcertificate.ini b/src/components/com_tjcertificate/site/languages/en-GB/en-GB.com_tjcertificate.ini index 5c5c7e73..e913b148 100644 --- a/src/components/com_tjcertificate/site/languages/en-GB/en-GB.com_tjcertificate.ini +++ b/src/components/com_tjcertificate/site/languages/en-GB/en-GB.com_tjcertificate.ini @@ -104,7 +104,7 @@ COM_TJCERTIFICATE_CERTIFICATE_FORM_LBL_COUPON_CREATED_BY_DESC="Record created by COM_TJCERTIFICATE_FORM_LBL_ASSIGNED_USER="Select user" COM_TJCERTIFICATE_FORM_LBL_ASSIGNED_USER_DESC="Select user to assign a training record" COM_TJCERTIFICATE_CERTIFICATE_USER_SELECT_OPTION="Select user" -COM_TJCERTIFICATE_CERTIFICATE_FORM_LBL_CERTIFICATE_STATUS="Status" +COM_TJCERTIFICATE_CERTIFICATE_FORM_LBL_CERTIFICATE_STATUS="Record Status" COM_TJCERTIFICATE_CERTIFICATE_FORM_LBL_CERTIFICATE_STATUS_DESC="Select record status" COM_TJCERTIFICATE_CERTIFICATE_FORM_STATUS_ATTENDED="Attended" COM_TJCERTIFICATE_CERTIFICATE_FORM_STATUS_COMPLETED="Completed" @@ -140,3 +140,13 @@ COM_TJCERTIFICATE_AGENCY_USER_SELECT="Select User" COM_TJCERTIFICATE_CERTIFICATE_FORM_LBL_CERTIFICATE_COMMENT_DESC="Add Comment" COM_TJCERTIFICATE_INVALID_ORGANIZATION_USER="Invalid User" COM_TJCERTIFICATE_INVALID_ORGANIZATION="Invalid Organization" + +;Bulk add form +COM_TJCERTIFICATE_BULK_ADD_FORM_LBL_ASSIGNED_USERS="Select Users" +COM_TJCERTIFICATE_BULK_ADD_FORM_LBL_NOTIFY_USERS="Notify Users" +COM_TJCERTIFICATE_BULK_ADD_FORM_LBL_NOTIFY_USERS_DESC="Please tick this box if you want to send record add email to selected users" +COM_TJCERTIFICATE_ADD_EXTERNAL_CERTIFICATES="Bulk Training Records" +COM_TJCERTIFICATE_FORM_VALIDATATION_FAILED="Form Validation Failed" +COM_TJCERTIFICATE_TOTAL_RECORDS_ADDED="Records added for %s user(s)" +COM_TJCERTIFICATE_RECORDS_ADDED_TO_QUEUE_SUCCESSFULLY="Records added in queue" +COM_TJCERTIFICATE_USER_LIMIT_MESSAGE="You cannot add more than the %s records." diff --git a/src/components/com_tjcertificate/site/models/bulktrainingrecord.php b/src/components/com_tjcertificate/site/models/bulktrainingrecord.php new file mode 100644 index 00000000..de23cb5a --- /dev/null +++ b/src/components/com_tjcertificate/site/models/bulktrainingrecord.php @@ -0,0 +1,14 @@ + + * @copyright Copyright (C) 2009 - 2021 Techjoomla. All rights reserved. + * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL + */ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +JLoader::import('components.com_tjcertificate.models.bulktrainingrecord', JPATH_ADMINISTRATOR); diff --git a/src/components/com_tjcertificate/site/models/forms/bulktrainingrecord.xml b/src/components/com_tjcertificate/site/models/forms/bulktrainingrecord.xml new file mode 100644 index 00000000..bf02b6c7 --- /dev/null +++ b/src/components/com_tjcertificate/site/models/forms/bulktrainingrecord.xml @@ -0,0 +1,104 @@ + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
diff --git a/src/components/com_tjcertificate/site/models/forms/trainingrecord.xml b/src/components/com_tjcertificate/site/models/forms/trainingrecord.xml index 510d8464..e1104adb 100644 --- a/src/components/com_tjcertificate/site/models/forms/trainingrecord.xml +++ b/src/components/com_tjcertificate/site/models/forms/trainingrecord.xml @@ -1,6 +1,6 @@
-
+
@@ -134,6 +132,19 @@ rows="10" /> + + + + + diff --git a/src/components/com_tjcertificate/site/views/bulktrainingrecord/tmpl/edit.php b/src/components/com_tjcertificate/site/views/bulktrainingrecord/tmpl/edit.php new file mode 100644 index 00000000..5a0bd594 --- /dev/null +++ b/src/components/com_tjcertificate/site/views/bulktrainingrecord/tmpl/edit.php @@ -0,0 +1,93 @@ + + * @copyright Copyright (C) 2009 - 2021 Techjoomla. All rights reserved. + * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL + */ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\HTML\HTMLHelper; +use Joomla\CMS\Language\Text; + +HTMLHelper::_('behavior.formvalidation'); +HTMLHelper::_('behavior.modal'); +HTMLHelper::_('behavior.keepalive'); +HTMLHelper::_('behavior.tooltip'); +HTMLHelper::_('bootstrap.framework'); +HTMLHelper::StyleSheet('media/com_tjcertificate/css/tjCertificate.css'); +HTMLHelper::_('jquery.token'); +HTMLHelper::_('formbehavior.chosen', 'select'); + +$options['relative'] = true; +HTMLHelper::_('script', 'media/com_tjcertificate/vendors/loader/js/loadingoverlay.min.js'); +HTMLHelper::_('script', 'com_tjcertificate/tjCertificateService.min.js', $options); +HTMLHelper::_('script', 'com_tjcertificate/certificate.min.js', $options); + +$userLimit = $this->params->get('users_select_limit'); +$message = Text::sprintf("COM_TJCERTIFICATE_USER_LIMIT_MESSAGE", $userLimit); + +?> + +
+
+
+

+ +

+ isAgencyEnabled) + { + echo $this->form->renderField('agency_id'); + } + + echo $this->form->renderField('assigned_user_id'); + echo $this->form->renderField('name'); + echo $this->form->renderField('issuing_org'); + echo $this->form->renderField('issued_on'); + echo $this->form->renderField('expired_on'); + echo $this->form->renderField('status'); + echo $this->form->renderField('state'); + ?> + + + form->renderField('notify_users'); + echo $this->form->renderField('created_by', null, null, ['class' => 'hidden']); + ?> +
+
+
+ +
+
+ + +
+
+ + + + + + diff --git a/src/components/com_tjcertificate/site/views/bulktrainingrecord/tmpl/edit.xml b/src/components/com_tjcertificate/site/views/bulktrainingrecord/tmpl/edit.xml new file mode 100644 index 00000000..b83513e8 --- /dev/null +++ b/src/components/com_tjcertificate/site/views/bulktrainingrecord/tmpl/edit.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/src/components/com_tjcertificate/site/views/bulktrainingrecord/view.html.php b/src/components/com_tjcertificate/site/views/bulktrainingrecord/view.html.php new file mode 100644 index 00000000..cf4cf9aa --- /dev/null +++ b/src/components/com_tjcertificate/site/views/bulktrainingrecord/view.html.php @@ -0,0 +1,74 @@ + + * @copyright Copyright (C) 2009 - 2021 Techjoomla. All rights reserved. + * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL + */ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +use Joomla\CMS\MVC\View\HtmlView; +use Joomla\CMS\Factory; +use Joomla\CMS\Language\Text; +use Joomla\CMS\Component\ComponentHelper; + +/** + * Training records view + * + * @since __DEPLOY_VERSION__ + */ +class TjCertificateViewBulkTrainingRecord extends HtmlView +{ + protected $form; + + protected $params; + + public $isAgencyEnabled = false; + + /** + * Manage Permissions + * + * @var boolean + */ + public $manage; + + protected $comMultiAgency = 'com_multiagency'; + + /** + * Display the view + * + * @param string $tpl The name of the template file to parse; automatically searches through the template paths. + * + * @return mixed A string if successful, otherwise a Error object. + * + * @since __DEPLOY_VERSION__ + */ + public function display($tpl = null) + { + $app = Factory::getApplication(); + $this->input = $app->input; + $this->user = Factory::getUser(); + $this->params = ComponentHelper::getParams('com_tjcertificate'); + $this->manage = $this->user->authorise('certificate.external.manage', 'com_tjcertificate'); + + if (!$this->manage) + { + $app->enqueueMessage(Text::_('JERROR_ALERTNOAUTHOR'), 'warning'); + + return false; + } + + if (ComponentHelper::isEnabled($this->comMultiAgency) && $this->params->get('enable_multiagency')) + { + $this->isAgencyEnabled = true; + } + + $this->form = $this->get('Form'); + + parent::display($tpl); + } +} diff --git a/src/components/com_tjcertificate/site/views/certificates/tmpl/my.php b/src/components/com_tjcertificate/site/views/certificates/tmpl/my.php index ec40c906..d4ca52c7 100644 --- a/src/components/com_tjcertificate/site/views/certificates/tmpl/my.php +++ b/src/components/com_tjcertificate/site/views/certificates/tmpl/my.php @@ -54,13 +54,26 @@ $recordFormLink = 'index.php?option=com_tjcertificate&view=trainingrecord&layout=edit'; $addRecordLink = Route::_($recordFormLink);?> + manage) + { + $recordsFormLink = 'index.php?option=com_tjcertificate&view=bulktrainingrecord&layout=edit'; + $addRecordsLink = Route::_($recordsFormLink);?> +
+ + + +
+
items)) diff --git a/src/components/com_tjcertificate/site/views/trainingrecord/tmpl/edit.php b/src/components/com_tjcertificate/site/views/trainingrecord/tmpl/edit.php index c5952bde..cd0daa2d 100644 --- a/src/components/com_tjcertificate/site/views/trainingrecord/tmpl/edit.php +++ b/src/components/com_tjcertificate/site/views/trainingrecord/tmpl/edit.php @@ -54,13 +54,18 @@ echo $this->form->renderField('assigned_user_id'); } - echo $this->form->renderField('name'); + echo $this->form->renderField('name'); echo $this->form->renderField('unique_certificate_id'); - echo $this->form->renderField('cert_url'); - echo $this->form->renderField('issuing_org'); - echo $this->form->renderField('issued_on'); - echo $this->form->renderField('expired_on'); - echo $this->form->renderField('status'); + echo $this->form->renderField('cert_url'); + echo $this->form->renderField('issuing_org'); + echo $this->form->renderField('issued_on'); + echo $this->form->renderField('expired_on'); + echo $this->form->renderField('status'); + + if ($this->manage) + { + echo $this->form->renderField('state'); + } ?>
form->getLabel('cert_file'); ?>
From 930a65b856357accac8a358d425db2bd5c2559e8 Mon Sep 17 00:00:00 2001 From: Tushar Shekokar Date: Wed, 5 May 2021 12:00:42 +0530 Subject: [PATCH 14/25] Feature #169954 chore: Certificates query improvment for multiagency, add lang const, update sql file for key change, fix minor issues (#108) * Feature #169954 chore: Add training records in bulk * Feature #169954 chore: Add training records in bulk * Feature #169954 chore: Add training records in bulk * Feature #169954 chore: Add training records in bulk * Feature #169954 chore: Resolve comments * Feature #169954 chore: Resolve comments * Feature #169954 chore: Resolve comments * Feature #169954 chore: Resolve comments * Feature #169954 chore: Resolve comments * Feature #169954 chore: Resolve comments * Feature #169954 chore: Resolve comments * Feature #169954 chore: Resolve comments * Feature #169954 chore: Resolve comments * Feature #169954 chore: Add plugin install script * Feature #169954 chore: Certificates query improvment for multiagency, add lang const, update sql file for key change, fix minor issues * Feature #169954 chore: resolve comments * Feature #169954 chore: resolve comments --- .../languages/en-GB/en-GB.com_tjcertificate.sys.ini | 3 +++ .../com_tjcertificate/administrator/models/certificates.php | 4 ++-- .../administrator/sql/updates/mysql/1.0.6.sql | 1 + .../administrator/tjcertificateTemplate.json | 2 +- .../site/models/forms/filter_certificates.xml | 2 +- .../site/views/bulktrainingrecord/tmpl/edit.xml | 4 ++-- src/components/com_tjcertificate/tjcertificate.xml | 2 +- 7 files changed, 11 insertions(+), 7 deletions(-) create mode 100644 src/components/com_tjcertificate/administrator/sql/updates/mysql/1.0.6.sql diff --git a/src/components/com_tjcertificate/administrator/languages/en-GB/en-GB.com_tjcertificate.sys.ini b/src/components/com_tjcertificate/administrator/languages/en-GB/en-GB.com_tjcertificate.sys.ini index 732ce6ba..a0a332fc 100644 --- a/src/components/com_tjcertificate/administrator/languages/en-GB/en-GB.com_tjcertificate.sys.ini +++ b/src/components/com_tjcertificate/administrator/languages/en-GB/en-GB.com_tjcertificate.sys.ini @@ -29,3 +29,6 @@ COM_TJCERTIFICATE_CERTIFICATE_FIELDSET_CLIENT_SELECT_DESC="Client" ;Add record menu COM_TJCERTIFICATE_ADD_EXTERNAL_CERTIFICATE="Add training record" + +;Add bulk record menu +COM_TJCERTIFICATE_ADD_BULK_RECORDS="Add bulk training records" diff --git a/src/components/com_tjcertificate/administrator/models/certificates.php b/src/components/com_tjcertificate/administrator/models/certificates.php index e3a792da..8390b695 100644 --- a/src/components/com_tjcertificate/administrator/models/certificates.php +++ b/src/components/com_tjcertificate/administrator/models/certificates.php @@ -112,10 +112,10 @@ protected function getListQuery() { $query->select('agency.title as title'); - $query->join('INNER', $db->qn('#__tj_cluster_nodes', 'nodes') . + $query->join('LEFT', $db->qn('#__tj_cluster_nodes', 'nodes') . ' ON (' . $db->qn('users.id') . ' = ' . $db->qn('nodes.user_id') . ')'); - $query->join('INNER', $db->qn('#__tj_clusters', 'clusters') . + $query->join('LEFT', $db->qn('#__tj_clusters', 'clusters') . ' ON (' . $db->qn('clusters.id') . ' = ' . $db->qn('nodes.cluster_id') . ' AND ' . $db->qn('clusters.client') . " = " . $db->q($this->comMultiAgency) . ')'); diff --git a/src/components/com_tjcertificate/administrator/sql/updates/mysql/1.0.6.sql b/src/components/com_tjcertificate/administrator/sql/updates/mysql/1.0.6.sql new file mode 100644 index 00000000..53bed3cb --- /dev/null +++ b/src/components/com_tjcertificate/administrator/sql/updates/mysql/1.0.6.sql @@ -0,0 +1 @@ +UPDATE `#__tj_notification_templates` SET `key` = "recordApprovedMailToUser" WHERE `key` = "recordPublishMailToUser"; diff --git a/src/components/com_tjcertificate/administrator/tjcertificateTemplate.json b/src/components/com_tjcertificate/administrator/tjcertificateTemplate.json index dce916ef..dfabeed8 100644 --- a/src/components/com_tjcertificate/administrator/tjcertificateTemplate.json +++ b/src/components/com_tjcertificate/administrator/tjcertificateTemplate.json @@ -120,7 +120,7 @@ "template4": { "id": "", "client": "com_tjcertificate", - "key": "recordPublishMailToUser", + "key": "recordApprovedMailToUser", "title": "Learning Record Approval Email Sent to user", "user_control": 1, "state": 1, diff --git a/src/components/com_tjcertificate/site/models/forms/filter_certificates.xml b/src/components/com_tjcertificate/site/models/forms/filter_certificates.xml index fc16b86c..6040e4b5 100644 --- a/src/components/com_tjcertificate/site/models/forms/filter_certificates.xml +++ b/src/components/com_tjcertificate/site/models/forms/filter_certificates.xml @@ -24,7 +24,7 @@ filter="integer" label="COM_TJCERTIFICATE_CERTIFICATE_FILTER_CERTIFICATE_CLIENT" description="COM_TJCERTIFICATE_CERTIFICATE_FILTER_DESC_CERTIFICATE_CLIENT" - addfieldpath="/components/com_tjcertificate/models/fields" + addfieldpath="administrator/components/com_tjcertificate/models/fields" onchange="this.form.submit();" /> - + - + diff --git a/src/components/com_tjcertificate/tjcertificate.xml b/src/components/com_tjcertificate/tjcertificate.xml index 0fe41b16..adde293d 100644 --- a/src/components/com_tjcertificate/tjcertificate.xml +++ b/src/components/com_tjcertificate/tjcertificate.xml @@ -8,7 +8,7 @@ extensions@techjoomla.com http://techjoomla.com - 1.0.5 + 1.0.6 From b24de0e5f0dcbcb790341c4519a43f4cf0135d54 Mon Sep 17 00:00:00 2001 From: Tushar Shekokar Date: Wed, 12 May 2021 16:30:59 +0530 Subject: [PATCH 15/25] Bug #171258 fix: Issue date is not getting saved if not using current date (#109) * Feature #169954 chore: Add training records in bulk * Feature #169954 chore: Add training records in bulk * Feature #169954 chore: Add training records in bulk * Feature #169954 chore: Add training records in bulk * Feature #169954 chore: Resolve comments * Feature #169954 chore: Resolve comments * Feature #169954 chore: Resolve comments * Feature #169954 chore: Resolve comments * Feature #169954 chore: Resolve comments * Feature #169954 chore: Resolve comments * Feature #169954 chore: Resolve comments * Feature #169954 chore: Resolve comments * Feature #169954 chore: Resolve comments * Feature #169954 chore: Add plugin install script * Feature #169954 chore: Certificates query improvment for multiagency, add lang const, update sql file for key change, fix minor issues * Feature #169954 chore: resolve comments * Feature #169954 chore: resolve comments * Bug #171258 fix: Issue date is not getting saved if not using current date --- .../com_tjcertificate/administrator/libraries/certificate.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/com_tjcertificate/administrator/libraries/certificate.php b/src/components/com_tjcertificate/administrator/libraries/certificate.php index fbd68450..bde7a78f 100644 --- a/src/components/com_tjcertificate/administrator/libraries/certificate.php +++ b/src/components/com_tjcertificate/administrator/libraries/certificate.php @@ -472,7 +472,8 @@ public function save() // Check if new record $isNew = empty($this->id); - if ($isNew) + // Set current date if issued_on date is not set + if ($isNew && !$table->issued_on) { $table->issued_on = Factory::getDate()->toSql(); } From 4afa6c1cdb221d9a0edf52d7eee2b45a9f9a1d54 Mon Sep 17 00:00:00 2001 From: divyachaudhari <58217051+divyachaudhari@users.noreply.github.com> Date: Tue, 8 Jun 2021 10:17:30 +0530 Subject: [PATCH 16/25] Task #171054 Chore: Resolving php 7.4 Notices (#110) * Task #171054 Chore: Resolving php 7.4 Notices * Task #171054 Chore: Resolving php 7.4 Notices --- .../administrator/views/trainingrecord/tmpl/edit.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/com_tjcertificate/administrator/views/trainingrecord/tmpl/edit.php b/src/components/com_tjcertificate/administrator/views/trainingrecord/tmpl/edit.php index a3f9daf3..8668149c 100644 --- a/src/components/com_tjcertificate/administrator/views/trainingrecord/tmpl/edit.php +++ b/src/components/com_tjcertificate/administrator/views/trainingrecord/tmpl/edit.php @@ -51,15 +51,15 @@ } ?>
- - + 'general')); + echo HTMLHelper::_('bootstrap.addTab', 'myTab', 'general', Text::_('COM_TJCERTIFICATE_TITLE_CERTIFICATE')); ?>
form->renderField('id'); ?> isAgencyEnabled) { - echo $this->form->renderField('agency_id'); } ?> @@ -77,7 +77,7 @@
form->getInput('cert_file'); ?> item->mediaData[0]) + if (!empty($this->item->mediaData[0])) { $downloadAttachmentLink = Uri::root() . 'index.php?option=com_tjcertificate&task=trainingrecord.downloadAttachment&id=' . $this->item->mediaData[0]->media_id . '&recordId=' . $this->item->id; echo ''; From 4093c6c07c52804988f0065f4f5f62cc2922335a Mon Sep 17 00:00:00 2001 From: divyachaudhari <58217051+divyachaudhari@users.noreply.github.com> Date: Wed, 16 Jun 2021 10:57:10 +0530 Subject: [PATCH 17/25] Bug #172375 Fix: Backend > Issued Certificates > Bulk Training Records > On submitting the record, notices and deprecated errors displayed (#111) --- .../administrator/libraries/certificate.php | 5 ++++- .../administrator/views/bulktrainingrecord/tmpl/edit.php | 5 +++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/components/com_tjcertificate/administrator/libraries/certificate.php b/src/components/com_tjcertificate/administrator/libraries/certificate.php index bde7a78f..c09abf6a 100644 --- a/src/components/com_tjcertificate/administrator/libraries/certificate.php +++ b/src/components/com_tjcertificate/administrator/libraries/certificate.php @@ -562,7 +562,10 @@ public function bind(&$array) // Set private properties foreach ($getPrivateProperties as $key => $value) { - $this->{$value->name} = $array[$value->name]; + if (!empty($array[$value->name])) + { + $this->{$value->name} = $array[$value->name]; + } } // Make sure its an integer diff --git a/src/components/com_tjcertificate/administrator/views/bulktrainingrecord/tmpl/edit.php b/src/components/com_tjcertificate/administrator/views/bulktrainingrecord/tmpl/edit.php index 3547aacc..a3543da8 100644 --- a/src/components/com_tjcertificate/administrator/views/bulktrainingrecord/tmpl/edit.php +++ b/src/components/com_tjcertificate/administrator/views/bulktrainingrecord/tmpl/edit.php @@ -54,12 +54,13 @@ ?>
- + 'general')); + echo HTMLHelper::_('bootstrap.addTab', 'myTab', 'general', Text::_('COM_TJCERTIFICATE_TITLE_CERTIFICATE')); ?>
isAgencyEnabled) { - echo $this->form->renderField('agency_id'); } ?> From 98d6e6e5651cca0d339e3cc6dc701d06a9dd97d9 Mon Sep 17 00:00:00 2001 From: divyachaudhari <58217051+divyachaudhari@users.noreply.github.com> Date: Fri, 18 Jun 2021 10:29:23 +0530 Subject: [PATCH 18/25] Bug #172375 Fix: Backend > Issued Certificates > Bulk Training Records > On submitting the record, notices and deprecated errors displayed (#112) * Bug #172375 Fix: Backend > Issued Certificates > Bulk Training Records > On submitting the record, notices and deprecated errors displayed * Bug #172375 Fix: Backend > Issued Certificates > Bulk Training Records > On submitting the record, notices and deprecated errors displayed * Bug #172375 Fix: Backend > Issued Certificates > Bulk Training Records > On submitting the record, notices and deprecated errors displayed --- .../administrator/includes/tjcertificate.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/com_tjcertificate/administrator/includes/tjcertificate.php b/src/components/com_tjcertificate/administrator/includes/tjcertificate.php index 3fc1b78c..cd3fd3f8 100644 --- a/src/components/com_tjcertificate/administrator/includes/tjcertificate.php +++ b/src/components/com_tjcertificate/administrator/includes/tjcertificate.php @@ -162,7 +162,7 @@ public static function init($location = 'site') * * @since __DEPLOY_VERSION__ */ - public function getClient() + public static function getClient() { return self::$client; } @@ -174,7 +174,7 @@ public function getClient() * * @since __DEPLOY_VERSION__ */ - public function getMediaPath() + public static function getMediaPath() { return self::$mediaPath; } From a62cb564fedd99feb704ef594ed0a004fd513e49 Mon Sep 17 00:00:00 2001 From: pranotiTechjoomla Date: Mon, 19 Jul 2021 11:54:56 +0530 Subject: [PATCH 19/25] Bug #173454 fix: Certificate preview popup not getting hide in edit certificate view (#114) --- .../com_tjcertificate/administrator/layouts/preview.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/com_tjcertificate/administrator/layouts/preview.php b/src/components/com_tjcertificate/administrator/layouts/preview.php index b88239d0..02495bd8 100644 --- a/src/components/com_tjcertificate/administrator/layouts/preview.php +++ b/src/components/com_tjcertificate/administrator/layouts/preview.php @@ -20,7 +20,7 @@ overflow-y: auto; } -