Extending
It is possible to extend the geoprocessing framework to meet your needs right in your project code space. Here are some common use cases.
I need to do additional data preparation before data import
Maybe you need to copy data in from over the Internet or write a script that transforms a dataset further before being ready to be imported. Here's a couple of options that keeps your code to do this right in the data
directory.
- Write a standalone Typescript script that sorts a dataset. Can be run from the root project directory with
npm run ts-node data/ous-demographic-data-sort.ts
- Write a more complex Typescript script that uses Turf geoprocessing functions like this proof of concept
I need to change the data import scripts
Maybe you need to alter the parameters passed to gdal or ogr. Many of the scripts that get run during data import are loaded from your projects data/bin
directory. You can alter these scripts to meet your needs.
If you upgrade your geoprocessing library, the files in data/bin
will get overwritten and you'll need to look at the git code changes and re-merge your changes manually.
I need my own data import
If the escape hatches above aren't enough, it is possible to skip the use of data:import
entirely. Consider reserving this for datasource that you want to import directly into your but it won't be easy.
- Write your own script that pre-calculates metrics for your datasource
- Amend
project/projectClient.ts
to side-load your own custom datasource record and merge it with what is loaded fromdatasources.json
- You may The benefit of it is that it creates a datasource record in
project/datasources.json
which can then be referenced inproject/metrics.json
. These are read in by theProjectClient
inproject/projectClient.ts
, which is used by your functions and UI clients. To do this you can editprojectClient.ts
to add your own custom datasources outside of thedatasources.json
file and merge them in. It's up to you to pre-calculate datasource metrics, and structure them properly if you still want to be able to rundata:publish
I need to extend the base types or code
Most things exported via the client-core
and client-ui
modules can be extended in project-space
, whether it's UI components, base types/schemas, or utility functions. Here are some examples to get you started.
- The rbcs module is a great example of extending all of these to create things specific to use of the
regulation-based classification system
. - The ClassTable component is an extension of the baseTable component, capable of displaying metrics for one or more classes of data. And you can layer this multiple levels deep as the SketchClassTable component is an extension of the ClassTable component, capable of displaying metrics for all classes, for a SketchCollection with one or more sketches.
I need to print my reports / save reports to PDF
Enabling printing of reports involves adding a state variable isPrinting
which edits the UI so all our React elements are visible for the print dialog.
To begin, download and add Print.tsx to your src/util
directory. This file contains much of the code you'll need to set up printing.
To include a small map overview of your sketch in your printed reports, you'll also need to download PrintMap.tsx to your src/components
directory, and printMap.ts and it's test file printMapSmoke.test.ts to your src/functions
directory.
Run the following to install react-to-print
:
npm install react-to-print
Open MpaTabReport.tsx
. Start by importing the components we'll need:
import { useReactToPrint } from "react-to-print";
import { PrintButton, PrintPopup, SketchAttributes } from "../util/Print";
import React, { useState, useRef, useEffect } from "react";
Next, we need add the following code in the MpaTabReport component. printRef
will reference the component we wish to print, and isPrinting
will reflect whether our print button was pressed and the component should display a print state. The useEffect
hook waits to isPrinting
to become true, and if so it disables animations on the page and runs the handlePrint
command. In handlePrint
we call useReactToPrint
to print the component.
// Printing
const printRef = useRef(null);
const [isPrinting, setIsPrinting] = useState(false);
const [attributes] = useSketchProperties();
// Original animation durations saved during printing
const originalAnimationDurations: string[] = [
...document.querySelectorAll(".chart"),
].map((el) => (el as HTMLElement).style.animationDuration);
useEffect(() => {
// When printing, animations are disabled and the page is printed
if (isPrinting) {
[...document.querySelectorAll(".chart")].forEach(
(el) => ((el as HTMLElement).style.animationDuration = "0s"),
);
handlePrint();
}
// Return animation duration to normal after printing
return () => {
[...document.querySelectorAll(".chart")].forEach(
(el, index) =>
((el as HTMLElement).style.animationDuration =
originalAnimationDurations[index]),
);
};
}, [isPrinting]);
// Print function
const handlePrint = useReactToPrint({
content: () => printRef.current,
documentTitle: attributes.name,
onBeforeGetContent: () => {},
onAfterPrint: () => setIsPrinting(false),
});
Now that we've configured what elements to print, we need to add a print button in the returned component, which will trigger the print dialog when clicked:
<div
onClick={() => {
setIsPrinting(true);
}}
>
<PrintButton />
</div>;
{
isPrinting && <PrintPopup />;
}
Finally, we need to attach printRef
to our reports component. We also want to set all report pages to appear when isPrinting
is true.
<div
ref={printRef}
style={{ backgroundColor: isPrinting ? "#FFF" : "inherit" }}
>
<div style={{ display: isPrinting ? "block" : "none" }}>
<SketchAttributes {...attributes} />
</div>
<ReportPage hidden={!isPrinting && tab !== viabilityId}>
<ViabilityPage />
</ReportPage>
<ReportPage hidden={!isPrinting && tab !== representationId}>
<RepresentationPage />
</ReportPage>
</div>
Printing is now set up for your reports. Additional printing edits may be added and are described below.
Expanding collapsed dropdowns when printing
Many reports contain drop downs with additional data, such as Show By MPA
, Show by Zone
, or Learn More
dropdowns. To configure reports to open the dropdowns when isPrinting
is true, follow these instructions.
First, in MpaTabReport.tsx
, pass isPrinting
to all report pages:
<ViabilityPage printing={isPrinting} />
Then, within ViabilityPage.tsx
, pass props.printing
into each report:
<SizeCard printing={props.printing} />
Finally, within SizeCard.tsx
, edit the Collapse
object:
{
isCollection && (
<Collapse
title={t("Show by MPA")}
collapsed={!props.printing}
key={String(props.printing) + "MPA"}
>
{genNetworkSizeTable(data, precalcMetrics, metricGroup, t)}
</Collapse>
);
}
Additional printing configuration
Depending on your report design, more edits may have to be made so your reports can print clearly. Some examples include handling horizontal scroll objects and pagination. See fsm-nearshore-reports for examples in handling those particulars.