-
Notifications
You must be signed in to change notification settings - Fork 0
Feat/829 pdf backend #937
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Feat/829 pdf backend #937
Changes from all commits
9093548
32e3247
036b783
2170c97
36f2b02
3f52f89
24618e2
ae9967c
ebe7d16
c735324
afdc6fe
d30df5f
040674f
007ca1a
9df2252
1282789
be0687b
e16333f
70276ad
201c6bc
4d145bf
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
select array_agg(public.st_asgeojson(rmfg.geometry)) as spatial_feature_geometry, | ||
public.st_asgeojson(rsp.geometry) as site_point_geometry | ||
from rst.recreation_map_feature rmf | ||
inner join rst.recreation_map_feature_geom rmfg using (rmf_skey) | ||
left join rst.recreation_site_point rsp on rmf.rec_resource_id = rsp.rec_resource_id | ||
where rmf.rec_resource_id = $1 | ||
and rmf.retirement_date is null | ||
group by rsp.geometry; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
import axios from "axios"; | ||
import { createHash } from "crypto"; | ||
import { Readable } from "stream"; | ||
import FormData from "form-data"; | ||
|
||
declare const window: any; | ||
const NodeFormData = | ||
// eslint-disable-next-line @typescript-eslint/no-require-imports | ||
typeof window === "undefined" ? require("form-data") : null; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what is this for? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a technique used to test, because running vitest with form data we can instantiate while testing. |
||
|
||
const damUrl = `${process.env.DAM_URL}/api/?`; | ||
const private_key = process.env.DAM_PRIVATE_KEY ?? ""; | ||
const user = process.env.DAM_USER ?? ""; | ||
const pdfCollectionId = process.env.DAM_RST_PDF_COLLECTION_ID ?? ""; | ||
|
||
function sign(query) { | ||
return createHash("sha256").update(`${private_key}${query}`).digest("hex"); | ||
} | ||
|
||
function createFormData(params) { | ||
const queryString = new URLSearchParams(params).toString(); | ||
const signature = sign(queryString); | ||
const formData = | ||
typeof window === "undefined" ? new NodeFormData() : new FormData(); | ||
formData.append("query", queryString); | ||
formData.append("sign", signature); | ||
formData.append("user", user); | ||
return formData; | ||
} | ||
|
||
async function axiosPost(formData) { | ||
return await axios | ||
.post(damUrl, formData, { | ||
headers: formData.getHeaders(), | ||
}) | ||
.then((res) => { | ||
return res.data; | ||
}) | ||
.catch((err) => { | ||
throw err; | ||
}); | ||
} | ||
|
||
export async function createResource() { | ||
const params: any = { | ||
user, | ||
function: "create_resource", | ||
resource_type: 1, | ||
archive: 0, | ||
}; | ||
const formData = createFormData(params); | ||
|
||
return await axiosPost(formData); | ||
} | ||
|
||
export async function getResourcePath(resource: string) { | ||
const params: any = { | ||
user, | ||
function: "get_resource_all_image_sizes", | ||
resource, | ||
}; | ||
const formData = createFormData(params); | ||
|
||
return await axiosPost(formData); | ||
} | ||
|
||
export async function addResourceToCollection(resource: string) { | ||
const params: any = { | ||
user, | ||
function: "add_resource_to_collection", | ||
resource, | ||
collection: pdfCollectionId, | ||
}; | ||
const formData = createFormData(params); | ||
|
||
return await axiosPost(formData); | ||
} | ||
|
||
export async function uploadFile(ref: string, file: Express.Multer.File) { | ||
const params: any = { | ||
user, | ||
function: "upload_multipart", | ||
ref, | ||
no_exif: 1, | ||
revert: 0, | ||
}; | ||
const stream = Readable.from(file.buffer); | ||
|
||
const formData = createFormData(params); | ||
formData.append("file", stream, { | ||
filename: file.originalname, | ||
contentType: file.mimetype, | ||
}); | ||
|
||
return await axiosPost(formData); | ||
} | ||
|
||
export async function deleteResource(resource: string) { | ||
const params: any = { | ||
user, | ||
function: "delete_resource", | ||
resource, | ||
}; | ||
const formData = createFormData(params); | ||
|
||
return await axiosPost(formData); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import { Module } from "@nestjs/common"; | ||
import { PrismaService } from "./prisma.service"; | ||
|
||
@Module({ | ||
providers: [PrismaService], | ||
}) | ||
export class PrismaModule {} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
import { ApiProperty } from "@nestjs/swagger"; | ||
import { IsNotEmpty } from "class-validator"; | ||
|
||
/** | ||
* Enum representing available image size options for the recreation API | ||
*/ | ||
export enum RecreationResourceDocCode { | ||
/** Recreation Map */ | ||
RM = "RM", | ||
} | ||
|
||
export class RecreationResourceDocDto { | ||
@ApiProperty({ | ||
description: "Reference ID for the image", | ||
example: "1000", | ||
}) | ||
ref_id?: string; | ||
|
||
@ApiProperty({ | ||
description: "Doc title", | ||
example: "Campbell river site map", | ||
}) | ||
title: string | null; | ||
|
||
@ApiProperty({ | ||
description: "rec_resource_id", | ||
}) | ||
rec_resource_id: string | null; | ||
|
||
@ApiProperty({ | ||
description: "doc link", | ||
}) | ||
url?: string; | ||
|
||
@ApiProperty({ | ||
description: "Document code that indicates the type of document", | ||
enum: RecreationResourceDocCode, | ||
}) | ||
doc_code: RecreationResourceDocCode | null; | ||
|
||
@ApiProperty({ | ||
description: "Description of the document code", | ||
}) | ||
doc_code_description?: string; | ||
|
||
@ApiProperty({ | ||
description: "File extension", | ||
}) | ||
extension: string | null; | ||
} | ||
|
||
export class RecreationResourceDocBodyDto { | ||
@ApiProperty({ | ||
description: "Doc title", | ||
example: "Campbell river site map", | ||
}) | ||
@IsNotEmpty() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. shoud we add length and regex constraints here? |
||
title: string; | ||
} | ||
|
||
export class FileUploadDto { | ||
@ApiProperty({ | ||
type: "string", | ||
format: "binary", | ||
description: "File to upload", | ||
}) | ||
file: any; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it'd be better to have this imported under RecreationResourceModule