parent
d2a1d60df0
commit
5823ec15e2
@ -8,7 +8,9 @@
|
|||||||
"stripe/stripe-php": "^6.24",
|
"stripe/stripe-php": "^6.24",
|
||||||
"dompdf/dompdf": "^0.8.2",
|
"dompdf/dompdf": "^0.8.2",
|
||||||
"phpoffice/phpword": "^0.15.0",
|
"phpoffice/phpword": "^0.15.0",
|
||||||
"phpmailer/phpmailer": "^6.0"
|
"phpmailer/phpmailer": "^6.0",
|
||||||
|
"lapinator/ods-php-generator": "^0.0.3",
|
||||||
|
"league/csv": "^9.1"
|
||||||
},
|
},
|
||||||
"license": "MPL-2.0",
|
"license": "MPL-2.0",
|
||||||
"authors": [
|
"authors": [
|
||||||
|
112
composer.lock
generated
112
composer.lock
generated
@ -4,7 +4,7 @@
|
|||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "fc511c5441078b0d99375ed15cbe16a0",
|
"content-hash": "a0ad7932ffc1d635a64f0cba686125ba",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "catfan/medoo",
|
"name": "catfan/medoo",
|
||||||
@ -308,6 +308,116 @@
|
|||||||
],
|
],
|
||||||
"time": "2017-03-20T17:10:46+00:00"
|
"time": "2017-03-20T17:10:46+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "lapinator/ods-php-generator",
|
||||||
|
"version": "v0.0.3",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/Lapinator/odsPhpGenerator.git",
|
||||||
|
"reference": "575314c003c2ec3032813bedcc1d27032b7b7ab2"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/Lapinator/odsPhpGenerator/zipball/575314c003c2ec3032813bedcc1d27032b7b7ab2",
|
||||||
|
"reference": "575314c003c2ec3032813bedcc1d27032b7b7ab2",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=5.3"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"classmap": [
|
||||||
|
"src/"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"LGPL-3.0"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Laurent VUIBERT",
|
||||||
|
"email": "lapinator@gmx.fr",
|
||||||
|
"homepage": "http://lapinator.net",
|
||||||
|
"role": "Developer"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Open Document Spreadsheet (.ods) generator ",
|
||||||
|
"homepage": "https://odsphpgenerator.lapinator.net/",
|
||||||
|
"keywords": [
|
||||||
|
"LibreOffice",
|
||||||
|
"ods"
|
||||||
|
],
|
||||||
|
"time": "2016-04-14T21:51:27+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "league/csv",
|
||||||
|
"version": "9.1.4",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/thephpleague/csv.git",
|
||||||
|
"reference": "9c8ad06fb5d747c149875beb6133566c00eaa481"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/thephpleague/csv/zipball/9c8ad06fb5d747c149875beb6133566c00eaa481",
|
||||||
|
"reference": "9c8ad06fb5d747c149875beb6133566c00eaa481",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"ext-mbstring": "*",
|
||||||
|
"php": ">=7.0.10"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"ext-curl": "*",
|
||||||
|
"friendsofphp/php-cs-fixer": "^2.0",
|
||||||
|
"phpstan/phpstan": "^0.9.2",
|
||||||
|
"phpstan/phpstan-phpunit": "^0.9.4",
|
||||||
|
"phpstan/phpstan-strict-rules": "^0.9.0",
|
||||||
|
"phpunit/phpunit": "^6.0"
|
||||||
|
},
|
||||||
|
"suggest": {
|
||||||
|
"ext-iconv": "Needed to ease transcoding CSV using iconv stream filters"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-master": "9.x-dev"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"League\\Csv\\": "src"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"src/functions_include.php"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Ignace Nyamagana Butera",
|
||||||
|
"email": "nyamsprod@gmail.com",
|
||||||
|
"homepage": "https://github.com/nyamsprod/",
|
||||||
|
"role": "Developer"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Csv data manipulation made easy in PHP",
|
||||||
|
"homepage": "http://csv.thephpleague.com",
|
||||||
|
"keywords": [
|
||||||
|
"csv",
|
||||||
|
"export",
|
||||||
|
"filter",
|
||||||
|
"import",
|
||||||
|
"read",
|
||||||
|
"write"
|
||||||
|
],
|
||||||
|
"time": "2018-05-01T18:32:48+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "pclzip/pclzip",
|
"name": "pclzip/pclzip",
|
||||||
"version": "2.8.2",
|
"version": "2.8.2",
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
"Newsletter": "Newsletter",
|
"Newsletter": "Newsletter",
|
||||||
"Print": "Print",
|
"Print": "Print",
|
||||||
"Email and Print": "Email and Print",
|
"Email and Print": "Email and Print",
|
||||||
|
"Email+Print": "Email+Print",
|
||||||
"Children": "Children",
|
"Children": "Children",
|
||||||
"Born": "Born",
|
"Born": "Born",
|
||||||
"Graduated": "Graduated",
|
"Graduated": "Graduated",
|
||||||
@ -29,9 +30,13 @@
|
|||||||
"Event": "Event",
|
"Event": "Event",
|
||||||
"Download Reports": "Download Reports",
|
"Download Reports": "Download Reports",
|
||||||
"Member Directory": "Member Directory",
|
"Member Directory": "Member Directory",
|
||||||
|
"Expiring Memberships": "Expiring Memberships",
|
||||||
|
"Family List": "Family List",
|
||||||
"Office (ODT)": "Office (ODT)",
|
"Office (ODT)": "Office (ODT)",
|
||||||
|
"Spreadsheet (ODS)": "Spreadsheet (ODS)",
|
||||||
"HTML": "HTML",
|
"HTML": "HTML",
|
||||||
"DOCX": "DOCX",
|
"DOCX": "DOCX",
|
||||||
|
"CSV": "CSV",
|
||||||
"Amount": "Amount",
|
"Amount": "Amount",
|
||||||
"Date": "Date",
|
"Date": "Date",
|
||||||
"Status": "Status",
|
"Status": "Status",
|
||||||
@ -46,5 +51,8 @@
|
|||||||
"Expires": "Expires",
|
"Expires": "Expires",
|
||||||
"Choose...": "Choose...",
|
"Choose...": "Choose...",
|
||||||
"Mark as paid": "Mark as paid",
|
"Mark as paid": "Mark as paid",
|
||||||
"This payment is a membership renewal (automatically add one year to the family's membership)": "This payment is a membership renewal (automatically add one year to the family's membership)"
|
"This payment is a membership renewal (automatically add one year to the family's membership)": "This payment is a membership renewal (automatically add one year to the family's membership)",
|
||||||
|
"All members expired or expiring within a month.": "All members expired or expiring within a month.",
|
||||||
|
"All the data from the member directory in a spreadsheet.": "All the data from the member directory in a spreadsheet.",
|
||||||
|
"A formatted and up-to-date HACHE member directory.": "A formatted and up-to-date HACHE member directory."
|
||||||
}
|
}
|
||||||
|
137
lib/Report.lib.php
Normal file
137
lib/Report.lib.php
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
use League\Csv\Writer;
|
||||||
|
use League\Csv\HTMLConverter;
|
||||||
|
use odsPhpGenerator\ods;
|
||||||
|
use odsPhpGenerator\odsTable;
|
||||||
|
use odsPhpGenerator\odsTableRow;
|
||||||
|
use odsPhpGenerator\odsTableColumn;
|
||||||
|
use odsPhpGenerator\odsTableCellString;
|
||||||
|
use odsPhpGenerator\odsStyleTableColumn;
|
||||||
|
use odsPhpGenerator\odsStyleTableCell;
|
||||||
|
|
||||||
|
class Report {
|
||||||
|
|
||||||
|
private $title = "";
|
||||||
|
private $header = [];
|
||||||
|
private $data = [];
|
||||||
|
|
||||||
|
public function __construct(string $title = "", array $header = [], array $data = []) {
|
||||||
|
$this->title = $title;
|
||||||
|
$this->header = $header;
|
||||||
|
$this->data = $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setHeader(array $header) {
|
||||||
|
$this->header = $header;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function addDataRow(array $columns) {
|
||||||
|
$this->data[] = $columns;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getHeader(): array {
|
||||||
|
return $this->header;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getData(): array {
|
||||||
|
return $this->data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function output(string $format) {
|
||||||
|
switch ($format) {
|
||||||
|
case "ods":
|
||||||
|
$this->toODS();
|
||||||
|
break;
|
||||||
|
case "html":
|
||||||
|
$this->toHTML();
|
||||||
|
break;
|
||||||
|
case "csv":
|
||||||
|
default:
|
||||||
|
$this->toCSV();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function toODS() {
|
||||||
|
$ods = new ods();
|
||||||
|
$styleColumn = new odsStyleTableColumn();
|
||||||
|
$styleColumn->setUseOptimalColumnWidth(true);
|
||||||
|
$headerstyle = new odsStyleTableCell();
|
||||||
|
$headerstyle->setFontWeight("bold");
|
||||||
|
$table = new odsTable($this->title);
|
||||||
|
|
||||||
|
for ($i = 0; $i < count($this->header); $i++) {
|
||||||
|
$table->addTableColumn(new odsTableColumn($styleColumn));
|
||||||
|
}
|
||||||
|
|
||||||
|
$row = new odsTableRow();
|
||||||
|
foreach ($this->header as $cell) {
|
||||||
|
$row->addCell(new odsTableCellString($cell, $headerstyle));
|
||||||
|
}
|
||||||
|
$table->addRow($row);
|
||||||
|
|
||||||
|
foreach ($this->data as $cols) {
|
||||||
|
$row = new odsTableRow();
|
||||||
|
foreach ($cols as $cell) {
|
||||||
|
$row->addCell(new odsTableCellString($cell));
|
||||||
|
}
|
||||||
|
$table->addRow($row);
|
||||||
|
}
|
||||||
|
$ods->addTable($table);
|
||||||
|
// The @ is a workaround to silence the tempnam notice,
|
||||||
|
// which breaks the file. This is apparently the intended behavior:
|
||||||
|
// https://bugs.php.net/bug.php?id=69489
|
||||||
|
@$ods->downloadOdsFile($this->title . "_" . date("Y-m-d_Hi") . ".ods");
|
||||||
|
}
|
||||||
|
|
||||||
|
private function toHTML() {
|
||||||
|
global $SECURE_NONCE;
|
||||||
|
$data = array_merge([$this->header], $this->data);
|
||||||
|
// HTML exporter doesn't like null values
|
||||||
|
for ($i = 0; $i < count($data); $i++) {
|
||||||
|
for ($j = 0; $j < count($data[$i]); $j++) {
|
||||||
|
if (is_null($data[$i][$j])) {
|
||||||
|
$data[$i][$j] = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
header('Content-type: text/html');
|
||||||
|
$converter = new HTMLConverter();
|
||||||
|
$out = "<!DOCTYPE html>\n"
|
||||||
|
. "<meta charset=\"utf-8\">\n"
|
||||||
|
. "<meta name=\"viewport\" content=\"width=device-width\">\n"
|
||||||
|
. "<title>" . $this->title . "_" . date("Y-m-d_Hi") . "</title>\n"
|
||||||
|
. <<<STYLE
|
||||||
|
<style nonce="$SECURE_NONCE">
|
||||||
|
.table-csv-data {
|
||||||
|
border-collapse: collapse;
|
||||||
|
}
|
||||||
|
.table-csv-data tr:first-child {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.table-csv-data tr td {
|
||||||
|
border: 1px solid black;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
STYLE
|
||||||
|
. $converter->convert($data);
|
||||||
|
echo $out;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function toCSV() {
|
||||||
|
$csv = Writer::createFromString('');
|
||||||
|
$data = array_merge([$this->header], $this->data);
|
||||||
|
$csv->insertAll($data);
|
||||||
|
header('Content-type: text/csv');
|
||||||
|
header('Content-Disposition: attachment; filename="' . $this->title . "_" . date("Y-m-d_Hi") . ".csv" . '"');
|
||||||
|
echo $csv;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
120
lib/reports.php
Normal file
120
lib/reports.php
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
|
||||||
|
// Detect if loaded by the user or by PHP
|
||||||
|
if (count(get_included_files()) == 1) {
|
||||||
|
define("LOADED", true);
|
||||||
|
} else {
|
||||||
|
define("LOADED", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
require_once __DIR__ . "/../required.php";
|
||||||
|
|
||||||
|
dieifnotloggedin();
|
||||||
|
|
||||||
|
if (LOADED) {
|
||||||
|
if (isset($VARS['type']) && isset($VARS['format'])) {
|
||||||
|
generateReport($VARS['type'], $VARS['format']);
|
||||||
|
die();
|
||||||
|
} else {
|
||||||
|
$Strings->get("invalid parameters");
|
||||||
|
die();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a 2d array of the families in the database.
|
||||||
|
* @global type $database
|
||||||
|
* @param array $filter Medoo WHERE clause.
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
function getMemberReport($filter = []): Report {
|
||||||
|
global $database, $Strings;
|
||||||
|
|
||||||
|
if (empty($filter)) {
|
||||||
|
$report = new Report($Strings->get("Families", false));
|
||||||
|
$filter = ["ORDER" => ["familyname" => "ASC"]];
|
||||||
|
} else {
|
||||||
|
$report = new Report($Strings->get("Expiring Memberships", false));
|
||||||
|
}
|
||||||
|
|
||||||
|
$familyids = $database->select(
|
||||||
|
"families", "familyid", $filter
|
||||||
|
);
|
||||||
|
|
||||||
|
$report->setHeader([
|
||||||
|
$Strings->get("Name", false),
|
||||||
|
$Strings->get("Father", false),
|
||||||
|
$Strings->get("Mother", false),
|
||||||
|
$Strings->get("Phone", false),
|
||||||
|
$Strings->get("Email", false),
|
||||||
|
$Strings->get("Address", false),
|
||||||
|
$Strings->get("City", false),
|
||||||
|
$Strings->get("State", false),
|
||||||
|
$Strings->get("ZIP", false),
|
||||||
|
$Strings->get("Photo Permission", false),
|
||||||
|
$Strings->get("Newsletter", false),
|
||||||
|
$Strings->get("Expires", false),
|
||||||
|
$Strings->get("Children", false)
|
||||||
|
]);
|
||||||
|
$families = [];
|
||||||
|
foreach ($familyids as $id) {
|
||||||
|
$families[] = (new Family())->load($id);
|
||||||
|
}
|
||||||
|
foreach ($families as $f) {
|
||||||
|
$newsletter = "";
|
||||||
|
switch ($f->getNewsletter()) {
|
||||||
|
case 1:
|
||||||
|
$newsletter = $Strings->get("Email", false);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
$newsletter = $Strings->get("Print", false);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
$newsletter = $Strings->get("Email+Print", false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
$children = [];
|
||||||
|
foreach ($f->getChildren() as $c) {
|
||||||
|
$children[] = $c->getName() . " (" . date("n/d", $c->getBirthday()) . ")";
|
||||||
|
}
|
||||||
|
$report->addDataRow([
|
||||||
|
$f->getName(),
|
||||||
|
$f->getFather(),
|
||||||
|
$f->getMother(),
|
||||||
|
$f->getPhone() . "",
|
||||||
|
$f->getEmail(),
|
||||||
|
$f->getAddress(),
|
||||||
|
$f->getCity(),
|
||||||
|
$f->getState(),
|
||||||
|
$f->getZip() . "",
|
||||||
|
$f->getPhotoPermission() ? $Strings->get("Yes", false) : $Strings->get("No", false),
|
||||||
|
$newsletter,
|
||||||
|
date("Y-m-d", $f->getExpires()),
|
||||||
|
implode(", ", $children)
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
return $report;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getReport($type): Report {
|
||||||
|
switch ($type) {
|
||||||
|
case "members":
|
||||||
|
return getMemberReport();
|
||||||
|
break;
|
||||||
|
case "expiring":
|
||||||
|
return getMemberReport(["expires[<]" => date("Y-m-d", strtotime("+1 month")), "ORDER" => ["expires" => "ASC"]]);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return new Report("error", ["ERROR"], ["Invalid report type."]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function generateReport($type, $format) {
|
||||||
|
$report = getReport($type);
|
||||||
|
$report->output($format);
|
||||||
|
}
|
@ -19,16 +19,51 @@ if (!$user->hasPermission("HACHEPORTAL_VIEW")) {
|
|||||||
<?php $Strings->get("Download Reports"); ?>
|
<?php $Strings->get("Download Reports"); ?>
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<h4><?php $Strings->get("Member Directory"); ?></h4>
|
<div class="row">
|
||||||
<a class="btn btn-primary mb-1" href="./lib/mkmemberdirectory.php?format=odt">
|
<div class="col-12 col-md-4">
|
||||||
<i class="far fa-file-alt"></i> <?php $Strings->get("Office (ODT)"); ?>
|
<h4><?php $Strings->get("Member Directory"); ?></h4>
|
||||||
</a>
|
<p><?php $Strings->get("A formatted and up-to-date HACHE member directory."); ?></p>
|
||||||
<br />
|
<a class="btn btn-primary mb-1" href="./lib/mkmemberdirectory.php?format=odt">
|
||||||
<a class="btn btn-orange btn-sm mr-1" href="./lib/mkmemberdirectory.php?format=html">
|
<i class="far fa-file-alt"></i> <?php $Strings->get("Office (ODT)"); ?>
|
||||||
<i class="fas fa-globe"></i> <?php $Strings->get("HTML"); ?>
|
</a>
|
||||||
</a>
|
<br />
|
||||||
<a class="btn btn-secondary btn-sm" href="./lib/mkmemberdirectory.php?format=docx">
|
<a class="btn btn-orange btn-sm mr-1" href="./lib/mkmemberdirectory.php?format=html">
|
||||||
<i class="fas fa-file-word"></i> <?php $Strings->get("DOCX"); ?>
|
<i class="fas fa-globe"></i> <?php $Strings->get("HTML"); ?>
|
||||||
</a>
|
</a>
|
||||||
|
<a class="btn btn-secondary btn-sm" href="./lib/mkmemberdirectory.php?format=docx">
|
||||||
|
<i class="fas fa-file-word"></i> <?php $Strings->get("DOCX"); ?>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-12 col-md-4">
|
||||||
|
<h4><?php $Strings->get("Family List"); ?></h4>
|
||||||
|
<p><?php $Strings->get("All the data from the member directory in a spreadsheet."); ?></p>
|
||||||
|
<a class="btn btn-success mb-1" href="./lib/reports.php?type=members&format=ods">
|
||||||
|
<i class="fas fa-table"></i> <?php $Strings->get("Spreadsheet (ODS)"); ?>
|
||||||
|
</a>
|
||||||
|
<br />
|
||||||
|
<a class="btn btn-orange btn-sm mr-1" href="./lib/reports.php?type=members&format=html">
|
||||||
|
<i class="fas fa-globe"></i> <?php $Strings->get("HTML"); ?>
|
||||||
|
</a>
|
||||||
|
<a class="btn btn-secondary btn-sm" href="./lib/reports.php?type=members&format=csv">
|
||||||
|
<i class="fas fa-th"></i> <?php $Strings->get("CSV"); ?>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-12 col-md-4">
|
||||||
|
<h4><?php $Strings->get("Expiring Memberships"); ?></h4>
|
||||||
|
<p><?php $Strings->get("All members expired or expiring within a month."); ?></p>
|
||||||
|
<a class="btn btn-success mb-1" href="./lib/reports.php?type=expiring&format=ods">
|
||||||
|
<i class="fas fa-table"></i> <?php $Strings->get("Spreadsheet (ODS)"); ?>
|
||||||
|
</a>
|
||||||
|
<br />
|
||||||
|
<a class="btn btn-orange btn-sm mr-1" href="./lib/reports.php?type=expiring&format=html">
|
||||||
|
<i class="fas fa-globe"></i> <?php $Strings->get("HTML"); ?>
|
||||||
|
</a>
|
||||||
|
<a class="btn btn-secondary btn-sm" href="./lib/reports.php?type=expiring&format=csv">
|
||||||
|
<i class="fas fa-th"></i> <?php $Strings->get("CSV"); ?>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
Loading…
x
Reference in New Issue
Block a user