Skip to content

Commit

Permalink
continue on licensing page
Browse files Browse the repository at this point in the history
  • Loading branch information
vsimakhin committed Jan 24, 2025
1 parent 52eb5e4 commit 86369f3
Show file tree
Hide file tree
Showing 7 changed files with 96 additions and 102 deletions.
49 changes: 0 additions & 49 deletions app/handlers_licensing.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"io"
"net/http"
"strings"
"time"

"github.com/go-chi/chi/v5"
"github.com/google/uuid"
Expand All @@ -26,54 +25,6 @@ func (app *application) HandlerApiGetLicensingRecords(w http.ResponseWriter, r *
//////////////////////////////////////////////
/////////////////////////////////////////////

// HandlerFlightRecordsData generates data for the logbook table at /logbook page
func (app *application) HandlerLicensingRecordsData(w http.ResponseWriter, r *http.Request) {

type TableData struct {
Data [][]string `json:"data"`
}

var tableData TableData

licenses, err := app.db.GetLicenses()
if err != nil {
app.errorLog.Println(err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}

for _, item := range licenses {
expire := ""
if item.ValidUntil != "" {
expireDate, err := time.Parse("02/01/2006", item.ValidUntil)
if err != nil {
app.errorLog.Printf("error parsing time %s: %s", item.ValidUntil, err.Error())
}

days := int(expireDate.Sub(time.Now().UTC()).Hours() / 24)
if days <= 0 {
expire = "Expired!"
} else if days <= 30 {
expire = fmt.Sprintf("In %d days", days)
} else {
expire = fmt.Sprintf("In %d months", int(days/30))
}
}

link := ""
if item.DocumentName != "" {
link = item.UUID
} else {
link = ""
}

tableRow := []string{item.Category, item.UUID, item.Name, item.Number, item.Issued, item.ValidFrom, item.ValidUntil, expire, link}
tableData.Data = append(tableData.Data, tableRow)
}

app.writeJSON(w, http.StatusOK, tableData)
}

// HandlerLicensingRecordByID is handler for a license record
func (app *application) HandlerLicensingRecordByID(w http.ResponseWriter, r *http.Request) {
uuid := chi.URLParam(r, "uuid")
Expand Down
1 change: 0 additions & 1 deletion app/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,6 @@ func (app *application) routes() *chi.Mux {
r.Get(APIMapData, app.HandlerMapData)

// documents
r.Get(APILicensingData, app.HandlerLicensingRecordsData)
r.Get(APILicensingUUID, app.HandlerLicensingRecordByID)
r.Get(APILicensingNew, app.HandlerLicensingRecordNew)
r.Get(APILicensingDownloadUUID, app.HandlerLicensingDownload)
Expand Down
38 changes: 0 additions & 38 deletions app/templates/licensing.page.gohtml

This file was deleted.

42 changes: 42 additions & 0 deletions app/ui/src/components/Licensing/CSVExportButton.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { useCallback } from 'react';
// MUI UI elements
import Tooltip from '@mui/material/Tooltip';
import IconButton from '@mui/material/IconButton';
// MUI Icons
import FileDownloadOutlinedIcon from '@mui/icons-material/FileDownloadOutlined';

import { mkConfig, generateCsv, download } from 'export-to-csv';

const csvConfig = mkConfig({
fieldSeparator: ',',
decimalSeparator: '.',
useKeysAsHeaders: true,
});

const handleExportRows = (rows) => {
const rowData = rows.map((row) => ({
"Category": row.original.category,
"Name": row.original.name,
"Number": row.original.number,
"Issued": row.original.issued,
"Valid From": row.original.valid_from,
"Valid Until": row.original.valid_until,
"Remarks": row.original.remarks,
}));
const csv = generateCsv(csvConfig)(rowData);
download(csvConfig)(csv);
};

export const CSVExportButton = ({ table }) => {
const handleCSVExport = useCallback((table) => {
handleExportRows(table.getPrePaginationRowModel().rows);
}, []);

return (
<Tooltip title="Quick CSV Export">
<IconButton onClick={() => handleCSVExport(table)} size="small"><FileDownloadOutlinedIcon /></IconButton>
</Tooltip>
)
}

export default CSVExportButton;
27 changes: 19 additions & 8 deletions app/ui/src/components/Licensing/Licensing.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import Typography from "@mui/material/Typography";
import { fetchLicenses } from "../../util/http/licensing";
import { useErrorNotification } from "../../hooks/useAppNotifications";
import LisencingTable from "./LicensingTable";
import { createDateColumn } from "./helpers";
import { calculateExpiry, createDateColumn, getExpireColor } from "./helpers";

export const Licensing = () => {
const navigate = useNavigate();
Expand All @@ -19,14 +19,8 @@ export const Licensing = () => {
});
useErrorNotification({ isError, error, fallbackMessage: 'Failed to load aircrafts list' });



const columns = useMemo(() => [
{
accessorKey: "category",
header: "Category",
size: 150,
},
{ accessorKey: "category", header: "Category", size: 150 },
{
accessorKey: "name",
header: "Name",
Expand All @@ -41,6 +35,23 @@ export const Licensing = () => {
createDateColumn("issued", "Issued"),
createDateColumn("valid_from", "Valid From"),
createDateColumn("valid_until", "Valid Until"),
{
accessorId: "expire",
header: "Expire",
Cell: ({ row }) => {
const expiry = calculateExpiry(row.original.valid_until);
if (!expiry) return null;

return (
<Typography variant="body2" color={getExpireColor(expiry.diffDays)}>
{expiry.diffDays < 0
? 'Expired'
: `${expiry.months} month${expiry.months === 1 ? '' : 's'} ${expiry.days} day${expiry.days === 1 ? '' : 's'}`}
</Typography>
);
},
size: 150,
},
{ accessorKey: "remarks", header: "Remarks", grow: true },
], []);

Expand Down
18 changes: 13 additions & 5 deletions app/ui/src/components/Licensing/LicensingTable.jsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { MaterialReactTable, useMaterialReactTable, MRT_TableHeadCellFilterContainer } from 'material-react-table';
import { MaterialReactTable, useMaterialReactTable, MRT_TableHeadCellFilterContainer, MRT_ExpandAllButton } from 'material-react-table';
import { useEffect, useMemo, useState } from 'react';
// MUI UI elements
import Box from '@mui/material/Box';
import Drawer from '@mui/material/Drawer';
import Stack from '@mui/material/Stack';

// Custom components and libraries
import { dateFilterFn } from './helpers';
// import CSVExportButton from './CSVExportButton';
import CSVExportButton from './CSVExportButton';
// import NewFlightRecordButton from './NewFlightRecordButton';

const tablePageKey = 'licensing-table-page-size';
Expand Down Expand Up @@ -41,7 +43,13 @@ export const LisencingTable = ({ columns, data, isLoading, ...props }) => {
const table = useMaterialReactTable({
columns: columns,
data: data ?? [],
initialState: { density: 'compact' },
initialState: {
density: 'compact',
expanded: true,
grouping: ['category']
},
positionToolbarAlertBanner: 'bottom',
groupedColumnMode: 'remove',
isLoading: isLoading,
enableColumnResizing: true,
enableGlobalFilterModes: true,
Expand All @@ -58,7 +66,7 @@ export const LisencingTable = ({ columns, data, isLoading, ...props }) => {
renderTopToolbarCustomActions: ({ table }) => (
<Box sx={{ display: 'flex', flexWrap: 'wrap' }}>
{/* <NewFlightRecordButton /> */}
{/* <CSVExportButton table={table} /> */}
<CSVExportButton table={table} />
</Box>
),
muiTablePaperProps: { variant: 'outlined', elevation: 0 },
Expand All @@ -84,7 +92,7 @@ export const LisencingTable = ({ columns, data, isLoading, ...props }) => {
}}>
<Box sx={{ width: 350, padding: 2 }}>
{table.getLeafHeaders().map((header) => {
if (header.id === 'mrt-row-spacer' || header.id === 'mrt-row-actions' || header.id.startsWith('center_1_')) return null;
if (header.id.startsWith('mrt-') || header.id.startsWith('Expire') || header.id.startsWith('center_1_')) return null;
return < MRT_TableHeadCellFilterContainer key={header.id} header={header} table={table} in />
})}
</Box>
Expand Down
23 changes: 22 additions & 1 deletion app/ui/src/components/Licensing/helpers.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,25 @@ export const createDateColumn = (id, name) => ({
size: 150,
filterVariant: "date-range", filterFn: "dateFilterFn",
muiFilterDatePickerProps: { format: "DD/MM/YYYY" },
})
})

export const calculateExpiry = (validUntil) => {
if (!validUntil) return null;

const today = dayjs();
const expiryDate = dayjs(validUntil, "DD/MM/YYYY");

if (!expiryDate.isValid()) return null;

const diffMonths = expiryDate.diff(today, 'month');
const remainingDays = expiryDate.diff(today.add(diffMonths, 'month'), 'day');
const diffDays = expiryDate.diff(today, 'day');

return { months: diffMonths, days: remainingDays, diffDays };
};

export const getExpireColor = (days) => {
if (days < 0) return 'error';
if (days < 90) return 'warning';
return 'inherit';
}

0 comments on commit 86369f3

Please sign in to comment.