Skip to content

Commit

Permalink
Integration tests topics org crud (#72)
Browse files Browse the repository at this point in the history
* Integration tests for orgs and topics

* Fix group type

* Fix build

* Fix build

* feat: add schemas for all entities

* feat: implement all fields for resources and datasets

* feat: review scehmas for organization and geography

* fix: validation for units

* fix: indexing for the topics field

* feat: index contributors

* feat: update the example env to include schema-related env vars

* feat: add documentation

* fix: documentation image

* feat: custom SOLR schema

* feat: update prod Dockerfile to have all dependencies

* feat: add geography_shape field to the geography custom group

* feat: upgrade TDC plugin version

* fix: tests

* feat: make extension versions fixed

* clean: clean dockerfiles

* setup dataset browse page

* fix review issues

* fix filters y space

* Update search.tsx

* fix badges cound

* fix: units field throwing error

* feat: upgrade live deployment to fix units field bug

* Integration tests for orgs and topics

---------

Co-authored-by: Demenech <[email protected]>
Co-authored-by: William Lima <[email protected]>
  • Loading branch information
3 people authored Sep 11, 2024
1 parent 7fac660 commit 6d1b3a3
Show file tree
Hide file tree
Showing 20 changed files with 278 additions and 425 deletions.
Binary file modified frontend/markdown.db
Binary file not shown.
5 changes: 4 additions & 1 deletion frontend/src/components/group/CreateGroupForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import Spinner from "@components/_shared/Spinner";
import notify from "@utils/notify";
import { Form } from "@components/ui/form";
import { slugify } from "@lib/utils";
import { toast } from "@/components/ui/use-toast";

export const CreateGroupForm: React.FC = () => {
const router = useRouter();
Expand All @@ -30,7 +31,9 @@ export const CreateGroupForm: React.FC = () => {
const utils = api.useContext();
const createGroup = api.group.create.useMutation({
onSuccess: async () => {
notify(`Successfully created the ${groupCreated} topic`);
toast({
description: `Successfully created the ${groupCreated} topic`,
});
formObj.reset();
setErrorMessage(null);
await utils.group.list.invalidate();
Expand Down
18 changes: 9 additions & 9 deletions frontend/src/components/group/EditGroupForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,14 @@ import { match } from "ts-pattern";
import Spinner from "@components/_shared/Spinner";
import notify from "@utils/notify";
import { Form } from "@components/ui/form";
import { toast } from "@/components/ui/use-toast";
import { useRouter } from "next/router";

export const EditGroupForm: React.FC<{
initialValues: Group;
}> = ({ initialValues }) => {
const [errorMessage, setErrorMessage] = useState<string | null>(null);
const router = useRouter();
const [groupEdited, setGroupEdited] = useState("");
const formObj = useForm<GroupFormType>({
resolver: zodResolver(GroupSchema),
Expand All @@ -26,9 +29,12 @@ export const EditGroupForm: React.FC<{
const utils = api.useContext();
const editGroup = api.group.patch.useMutation({
onSuccess: async () => {
notify(`Successfully edited the ${groupEdited} group`);
toast({
description: `Successfully edited the ${groupEdited} topic`,
});
setErrorMessage(null);
await utils.group.list.invalidate();
await router.push("/dashboard/topics");
},
onError: (error) => setErrorMessage(error.message),
});
Expand All @@ -46,18 +52,12 @@ export const EditGroupForm: React.FC<{
<div className="col-span-full">
{match(editGroup.isLoading)
.with(false, () => (
<Button
type="submit"
className="mt-8 w-full py-4"
>
<Button type="submit" className="mt-8 w-full py-4">
Edit Topic
</Button>
))
.otherwise(() => (
<Button
type="submit"
className="mt-8 flex w-full py-4"
>
<Button type="submit" className="mt-8 flex w-full py-4">
<Spinner className="hover:text-slate-900" />
Edit Topic
</Button>
Expand Down
16 changes: 5 additions & 11 deletions frontend/src/components/groups/GroupCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,25 +16,19 @@ export default function GroupCard({
}: GroupCardProps) {
const url = image_display_url ? new URL(image_display_url) : undefined;
return (
<div className="bg-white p-8 col-span-3 rounded-lg h-full shadow-lg">
<div className="col-span-3 h-full rounded-lg bg-white p-8 shadow-lg">
<Image
src={
image_display_url &&
url &&
getConfig().publicRuntimeConfig.DOMAINS.includes(url.hostname)
? image_display_url
: "/images/logos/DefaultOrgLogo.svg"
}
src={image_display_url}
alt={`${name}-collection`}
width="43"
height="43"
></Image>
<h3 className="font-inter font-semibold text-lg mt-4">{display_name}</h3>
<p className="font-inter font-medium text-sm mt-1 mb-6 line-clamp-2">
<h3 className="font-inter mt-4 text-lg font-semibold">{display_name}</h3>
<p className="font-inter mb-6 mt-1 line-clamp-2 text-sm font-medium">
{description}
</p>
<Link href={`/groups/${name}`}>
<span className="font-inter font-medium text-sm text-accent cursor-pointer">
<span className="font-inter cursor-pointer text-sm font-medium text-accent">
View -&gt;
</span>
</Link>
Expand Down
7 changes: 2 additions & 5 deletions frontend/src/components/groups/individualPage/GroupInfo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,8 @@ export default function GroupInfo({ group }: { group: Group }) {
width={120}
height={120}
src={
group.image_display_url &&
url &&
getConfig().publicRuntimeConfig.DOMAINS.includes(url.hostname)
? group.image_display_url
: "/images/logos/DefaultGroupLogo.svg"
group.image_display_url
?? "/images/logos/DefaultGroupLogo.svg"
}
alt={`${group.name}-collection`}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import Spinner from "@components/_shared/Spinner";
import notify from "@utils/notify";
import { Form } from "@components/ui/form";
import { slugify } from "@lib/utils";
import { toast } from "@/components/ui/use-toast";

export const CreateOrganizationForm: React.FC = () => {
const router = useRouter();
Expand All @@ -33,7 +34,9 @@ export const CreateOrganizationForm: React.FC = () => {
const utils = api.useContext();
const createOrganization = api.organization.create.useMutation({
onSuccess: async () => {
notify(`Successfully created the ${organizationCreated} organization`);
toast({
description: `Successfully created the ${organizationCreated} organization`,
});
formObj.reset();
setErrorMessage(null);
await utils.organization.list.invalidate();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { match } from "ts-pattern";
import Spinner from "@components/_shared/Spinner";
import { useRouter } from "next/router";
import notify from "@utils/notify";
import { toast } from "@/components/ui/use-toast";
import { Form } from "@components/ui/form";

export const EditOrganizationForm: React.FC<{
Expand All @@ -31,7 +32,9 @@ export const EditOrganizationForm: React.FC<{
const utils = api.useContext();
const editOrganization = api.organization.patch.useMutation({
onSuccess: async () => {
notify(`Successfully edited the ${organizationEdited} organization`);
toast({
description: `Successfully edited the ${organizationEdited} organization`,
});
setErrorMessage(null);
await utils.organization.list.invalidate();
await utils.organization.listForUser.invalidate();
Expand Down
16 changes: 5 additions & 11 deletions frontend/src/components/organization/OrgCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,25 +16,19 @@ export default function GroupCard({
}: OrgCardProps) {
const url = image_display_url ? new URL(image_display_url) : undefined;
return (
<div className="bg-white p-8 col-span-3 rounded-lg h-full shadow-lg">
<div className="col-span-3 h-full rounded-lg bg-white p-8 shadow-lg">
<Image
src={
image_display_url &&
url &&
getConfig().publicRuntimeConfig.DOMAINS.includes(url.hostname)
? image_display_url
: "/images/logos/DefaultOrgLogo.svg"
}
src={image_display_url ?? "/images/logos/DefaultOrgLogo.svg"}
alt={`${name}-collection`}
width="43"
height="43"
></Image>
<h3 className="font-inter font-semibold text-lg mt-4">{display_name}</h3>
<p className="font-inter font-medium text-sm mt-1 mb-6 line-clamp-2">
<h3 className="font-inter mt-4 text-lg font-semibold">{display_name}</h3>
<p className="font-inter mb-6 mt-1 line-clamp-2 text-sm font-medium">
{description}
</p>
<Link href={`/@${name}`}>
<span className="font-inter font-medium text-sm text-accent cursor-pointer">
<span className="font-inter cursor-pointer text-sm font-medium text-accent">
View -&gt;
</span>
</Link>
Expand Down
24 changes: 9 additions & 15 deletions frontend/src/components/organization/individualPage/OrgInfo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,25 +14,19 @@ export default function OrgInfo({ org }: { org: Organization }) {
<Image
width={120}
height={120}
src={
org.image_display_url &&
url &&
getConfig().publicRuntimeConfig.DOMAINS.includes(url.hostname)
? org.image_display_url
: "/images/logos/DefaultOrgLogo.svg"
}
src={org.image_display_url ?? "/images/logos/DefaultOrgLogo.svg"}
alt={`${org.name}-collection`}
/>
</div>
<div className="flex flex-col gap-y-3 mt-8">
<span className="font-medium text-gray-500 inline">
<div className="mt-8 flex flex-col gap-y-3">
<span className="inline font-medium text-gray-500">
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
strokeWidth={1.5}
stroke="currentColor"
className="w-5 h-5 text-accent inline mr-1"
className="mr-1 inline h-5 w-5 text-accent"
>
<path
strokeLinecap="round"
Expand All @@ -42,14 +36,14 @@ export default function OrgInfo({ org }: { org: Organization }) {
</svg>
Packages: {org.packages ? org.packages.length : 0}
</span>
<span className="font-medium text-gray-500 inline">
<span className="inline font-medium text-gray-500">
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
strokeWidth={1.5}
stroke="currentColor"
className="w-5 h-5 text-accent inline mr-1"
className="mr-1 inline h-5 w-5 text-accent"
>
<path
strokeLinecap="round"
Expand All @@ -60,15 +54,15 @@ export default function OrgInfo({ org }: { org: Organization }) {
Created: {org.created && format(org.created)}
</span>
</div>
<div className="py-4 my-4 border-y">
<p className="text-sm font-normal text-stone-500 line-clamp-4">
<div className="my-4 border-y py-4">
<p className="line-clamp-4 text-sm font-normal text-stone-500">
{org.description?.replace(/<\/?[^>]+(>|$)/g, "") || "No description"}
</p>
</div>
<div className="flex flex-wrap gap-1">
{org.tags?.map((tag: Tag) => (
<span
className="bg-accent px-4 py-1 rounded-full text-white"
className="rounded-full bg-accent px-4 py-1 text-white"
key={tag.id}
>
{tag.display_name}
Expand Down
6 changes: 6 additions & 0 deletions frontend/src/env.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ export const env = createEnv({
R2_ACCESS_KEY_ID: z.string(),
R2_SECRET_KEY_ID: z.string(),
SYS_ADMIN_API_KEY: z.string(),
MATOMO_AUTH_KEY: z.string(),
MATOMO_URL: z.string(),
MATOMO_SITE_ID: z.string(),
},

/**
Expand Down Expand Up @@ -53,6 +56,9 @@ export const env = createEnv({
NEXT_PUBLIC_R2_PUBLIC_URL: process.env.NEXT_PUBLIC_R2_PUBLIC_URL,
NEXT_PUBLIC_CKAN_URL: process.env.NEXT_PUBLIC_CKAN_URL,
NEXT_PUBLIC_PUBLIC_PORTAL_URL: process.env.NEXT_PUBLIC_PUBLIC_PORTAL_URL,
MATOMO_AUTH_KEY: process.env.MATOMO_AUTH_KEY,
MATOMO_URL: process.env.MATOMO_URL,
MATOMO_SITE_ID: process.env.MATOMO_SITE_ID,
},
/**
* Run `build` or `dev` with `SKIP_ENV_VALIDATION` to skip env validation.
Expand Down
3 changes: 3 additions & 0 deletions frontend/src/pages/[org]/[dataset]/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {
SelectValue,
} from "@components/ui/select";
import useMatomoTracker from "@lib/useMatomoTracker";
import { api } from "@utils/api";

const siteTitle = "TDC Data Portal";
const backend_url = env.NEXT_PUBLIC_CKAN_URL;
Expand Down Expand Up @@ -107,6 +108,8 @@ export default function DatasetPage({
label: `${dataset.organization?.title || dataset.organizatio?.name}`,
},
];
const matomo = api.matomo.getVisitorStats.useQuery()
console.log(matomo.data)
return (
<>
<Head>
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/server/api/root.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { resourceRouter } from "./routers/resource";
import { userRouter } from "./routers/user";
import { datapackageRouter } from "./routers/datapackage";
import { uploadsRouter } from "./routers/uploads";
import { matomoRouter } from "./routers/matomo";

/**
* This is the primary router for your server.
Expand All @@ -20,6 +21,7 @@ export const appRouter = createTRPCRouter({
organization: organizationRouter,
uploads: uploadsRouter,
datapackage: datapackageRouter,
matomo: matomoRouter
});

// export type definition of API
Expand Down
5 changes: 3 additions & 2 deletions frontend/src/server/api/routers/group.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
deleteGroups,
listGroups,
patchGroup,
getGroup
getGroup,
} from "@utils/group";
import { z } from "zod";

Expand All @@ -29,7 +29,8 @@ export const groupRouter = createTRPCRouter({
.mutation(async ({ input, ctx }) => {
const user = ctx.session.user;
const apiKey = user.apikey;
const group = await createGroup({ apiKey, input });
const _group = { ...input, type: "topic" };
const group = await createGroup({ apiKey, input: _group });
return group;
}),
patch: protectedProcedure
Expand Down
29 changes: 29 additions & 0 deletions frontend/src/server/api/routers/matomo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import {
createTRPCRouter,
protectedProcedure,
publicProcedure,
} from "@/server/api/trpc";
import { env } from "@/env.mjs";
import { z } from "zod";
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
import { GetObjectCommand } from "@aws-sdk/client-s3";
import r2 from "@/server/r2";

export const matomoRouter = createTRPCRouter({
getVisitorStats: publicProcedure.query(async ({ input }) => {
const matomoApiUrl = `${env.MATOMO_URL}/index.php`;
const params = {
module: "API",
method: "Actions.getPageUrls",
idSite: env.MATOMO_SITE_ID,
period: "day",
date: "today",
format: "JSON",
token_auth: env.MATOMO_AUTH_KEY,
};
const urlParams = new URLSearchParams(params).toString();
const response = await fetch(`${matomoApiUrl}?${urlParams}`);
const data = await response.json();
return data;
}),
});
Loading

0 comments on commit 6d1b3a3

Please sign in to comment.