Skip to content

Commit 2932a16

Browse files
authored
Merge pull request #22 from datopian/feat/portal-scoped-api
PortalJS Cloud portal-scoped APIs
2 parents 21e17ca + 8ab3ccc commit 2932a16

File tree

15 files changed

+42
-305
lines changed

15 files changed

+42
-305
lines changed

README.md

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -66,11 +66,7 @@ Then, you can start customizing it locally by following the development instruct
6666

6767
```bash
6868
# This is the URL of the CKAN instance. Use the example value if you are using PortalJS Cloud.
69-
NEXT_PUBLIC_DMS=https://api.cloud.portaljs.com
70-
71-
# Leave it empty if you are not using PortalJS Cloud. This is the name of the main organization for your portal in PortalJS Cloud.
72-
# You can find the this value in the Organizations page in the PortalJS Cloud dashboard.
73-
NEXT_PUBLIC_ORG=my-org
69+
NEXT_PUBLIC_DMS=https://api.cloud.portaljs.com/@my-portal-main-org-name
7470
```
7571

7672
4) Run `npm run dev` to start the development server
@@ -218,4 +214,4 @@ Let’s build better data portals together 🚀
218214

219215
**[📚 Docs](https://portaljs.com/docs)[ 🐛 Report a bug or suggest an idea](https://github.com/datopian/portaljs/issues)**
220216

221-
</div>
217+
</div>

components/dataset/individualPage/DatasetInfo.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ function uniqueFormat(resources) {
1919
export default function DatasetInfo({
2020
dataset,
2121
}: {
22-
dataset: Dataset & { _name: string };
22+
dataset: Dataset;
2323
}) {
2424
const [isTruncated, setIsTruncated] = useState(false);
2525
const [showFullDescription, setShowFullDescription] = useState(false);
@@ -212,7 +212,7 @@ export default function DatasetInfo({
212212
{metaFormats.map((item) => (
213213
<div key={item.format}>
214214
<Link
215-
href={`${process.env.NEXT_PUBLIC_DMS}/dataset/${dataset._name}.${item.format}`}
215+
href={`${process.env.NEXT_PUBLIC_DMS}/dataset/${dataset.name}.${item.format}`}
216216
className="font-semibold group flex gap-0.5 hover:text-darkaccent"
217217
>
218218
<div className="text-accent group-hover:text-darkaccent transition flex items-center justify-center">

components/dataset/search/DatasetCard.tsx

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@ import MultipleResourcesCard from "../_shared/MultipleResourcesCard";
44
import { resourceBgColors } from "../_shared/FormatsColors";
55
import { getTimeAgo } from "@/lib/utils";
66

7-
const mainOrg = process.env.NEXT_PUBLIC_ORG;
8-
97
export default function DatasetCard({
108
dataset,
119
showOrg = true,
@@ -68,10 +66,7 @@ export default function DatasetCard({
6866
);
6967
}
7068

71-
const datasetName =
72-
dataset.name?.indexOf(`${mainOrg}--`) >= 0
73-
? dataset.name?.split(`${mainOrg}--`)[1]
74-
: dataset.name;
69+
const datasetName = dataset.name;
7570

7671
return (
7772
<Link href={`/@${dataset.organization.name}/${datasetName}`} className="">

components/dataset/search/DatasetItem.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,8 @@ import {
66
RiOrganizationChart,
77
RiPriceTagLine,
88
} from "react-icons/ri";
9-
import { getDatasetName, getOrganizationName, getTimeAgo } from "@/lib/utils";
9+
import { getTimeAgo } from "@/lib/utils";
1010
import { useTheme } from "@/components/theme/theme-provider";
11-
import { TagIcon } from "@heroicons/react/20/solid";
1211

1312
export default function DatasetItem({
1413
dataset,
@@ -23,7 +22,7 @@ export default function DatasetItem({
2322

2423
return (
2524
<Link
26-
href={`/@${getOrganizationName(dataset.organization.name)}/${getDatasetName(dataset.name)}`}
25+
href={`/@${dataset.organization.name}/${dataset.name}`}
2726
className={`flex items-start gap-4 hover:bg-white hover:shadow-lg transition-all p-4 rounded-[10px] ${styles.shadowMd}`}
2827
>
2928
<span className="min-w-[5px] min-h-[5px] bg-accent rounded-full mt-3 hidden"></span>

components/home/mainSection/PopularDatasets.tsx

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import Link from "next/link";
22
import { useTheme } from "@/components/theme/theme-provider";
3-
import { getDatasetName, getOrganizationName } from "@/lib/utils";
43
import { Dataset } from "@/schemas/dataset.interface";
54

65
type DatasetLinkProps = Pick<Dataset, "title" | "metadata_modified">;
@@ -28,9 +27,7 @@ export default function PopularDatasets({
2827
{datasets.map((dataset, index) => (
2928
<Link
3029
key={index}
31-
href={`/@${getOrganizationName(dataset.organization.name)}/${getDatasetName(
32-
dataset.name
33-
)}`}
30+
href={`/@${dataset.organization.name}/${dataset.name}`}
3431
className="block mt-6 hover:text-accent transition-all"
3532
>
3633
<DatasetLink

lib/queries/dataset.ts

Lines changed: 5 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,13 @@
11
import { CKAN } from "@portaljs/ckan";
2-
import {
3-
privateToPublicDatasetName,
4-
privateToPublicOrgName,
5-
publicToPrivateDatasetName,
6-
} from "./utils";
72
import { Dataset, PackageSearchOptions } from "@/schemas/dataset.interface";
83
import CkanRequest, { CkanResponse } from "@portaljs/ckan-api-client-js";
94

105
const DMS = process.env.NEXT_PUBLIC_DMS;
11-
const mainOrg = process.env.NEXT_PUBLIC_ORG;
126

137
export async function searchDatasets(options: PackageSearchOptions) {
148
const baseAction = `package_search`;
15-
const tagVocabName = mainOrg ? `vocab_portal-tags--${mainOrg}` : "tags";
169

17-
const facetFields = ["groups", "organization", "res_format", tagVocabName]
10+
const facetFields = ["groups", "organization", "res_format", "tags"]
1811
.map((f) => `"${f}"`)
1912
.join(",");
2013

@@ -36,7 +29,7 @@ export async function searchDatasets(options: PackageSearchOptions) {
3629
queryParams.push(`sort=${options?.sort}`);
3730
}
3831

39-
let fqList: string[] = [mainOrg ? `main_org:${mainOrg}` : ""];
32+
let fqList: string[] = [];
4033

4134
if (options?.fq) {
4235
fqList.push(options.fq);
@@ -52,7 +45,7 @@ export async function searchDatasets(options: PackageSearchOptions) {
5245
}
5346

5447
if (options?.tags?.length) {
55-
fqListGroups.push(`${tagVocabName}:(${joinTermsWithOr(options?.tags)})`);
48+
fqListGroups.push(`tags:(${joinTermsWithOr(options?.tags)})`);
5649
}
5750

5851
if (options?.resFormat?.length) {
@@ -88,11 +81,6 @@ export async function searchDatasets(options: PackageSearchOptions) {
8881
}>
8982
>(action, { ckanUrl: DMS });
9083

91-
const facets = res.result && res.result.search_facets;
92-
if (facets && tagVocabName in facets) {
93-
res.result.search_facets["tags"] = facets[tagVocabName];
94-
}
95-
9684
return { ...res.result, datasets: res.result.results };
9785
}
9886

@@ -103,16 +91,6 @@ const joinTermsWithOr = (tems) => {
10391
export const getDataset = async ({ name }: { name: string }) => {
10492
const DMS = process.env.NEXT_PUBLIC_DMS;
10593
const ckan = new CKAN(DMS);
106-
const privateName = publicToPrivateDatasetName(name);
107-
const dataset = await ckan.getDatasetDetails(privateName);
108-
dataset.name = privateToPublicDatasetName(dataset.name);
109-
110-
return {
111-
...dataset,
112-
_name: privateName,
113-
organization: {
114-
...dataset.organization,
115-
name: privateToPublicOrgName(dataset.organization.name),
116-
},
117-
};
94+
const dataset = await ckan.getDatasetDetails(name);
95+
return dataset
11896
};

lib/queries/groups.ts

Lines changed: 6 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,62 +1,17 @@
1-
import { Dataset, Group } from "@portaljs/ckan";
2-
import {
3-
privateToPublicDatasetName,
4-
privateToPublicGroupName,
5-
privateToPublicOrgName,
6-
publicToPrivateGroupName,
7-
} from "./utils";
1+
import { Group } from "@portaljs/ckan";
82
import CkanRequest, { CkanResponse } from "@portaljs/ckan-api-client-js";
93

104
const DMS = process.env.NEXT_PUBLIC_DMS;
11-
const mainOrg = process.env.NEXT_PUBLIC_ORG;
12-
const mainGroup = `${mainOrg}-group`;
135

14-
export const getAllGroups = async ({
15-
detailed = true, // Whether to add group_show or not
16-
}: {
17-
detailed: boolean;
18-
}) => {
19-
if (!mainOrg) {
20-
const organizations = await CkanRequest.get<CkanResponse<Group[]>>(
6+
export const getAllGroups = async () => {
7+
const groups = await CkanRequest.get<CkanResponse<Group[]>>(
218
`group_list?all_fields=True`,
229
{
2310
ckanUrl: DMS,
2411
}
2512
);
2613

27-
return organizations.result.map((o) => {
28-
return { ...o, _name: o.name };
29-
});
30-
}
31-
32-
const groupsTree = await CkanRequest.get<
33-
CkanResponse<Group & { children: Group[] }>
34-
>(`group_tree_section?type=group&id=${mainGroup}`, {
35-
ckanUrl: DMS,
36-
});
37-
38-
let children = groupsTree.result.children;
39-
40-
if (detailed) {
41-
children = await Promise.all(
42-
children.map(async (g) => {
43-
const groupDetails = await CkanRequest.get<CkanResponse<Group>>(
44-
`group_show?id=${g.id}`,
45-
{
46-
ckanUrl: DMS,
47-
}
48-
);
49-
return groupDetails.result;
50-
})
51-
);
52-
}
53-
54-
children = children.map((c) => {
55-
const publicName = privateToPublicGroupName(c.name);
56-
return { ...c, name: publicName };
57-
});
58-
59-
return children;
14+
return groups.result
6015
};
6116

6217
export const getGroup = async ({
@@ -66,24 +21,10 @@ export const getGroup = async ({
6621
name: string;
6722
include_datasets?: boolean;
6823
}) => {
69-
const privateName = publicToPrivateGroupName(name);
70-
7124
const group = await CkanRequest.get<CkanResponse<Group>>(
72-
`group_show?id=${privateName}&include_datasets=${include_datasets}`,
25+
`group_show?id=${name}&include_datasets=${include_datasets}`,
7326
{ ckanUrl: DMS }
7427
);
7528

76-
if (include_datasets) {
77-
group.result.packages.forEach((dataset: Dataset) => {
78-
const publicOrgName = privateToPublicOrgName(dataset.organization.name);
79-
dataset.organization.name = publicOrgName;
80-
81-
const publicDatasetName = privateToPublicDatasetName(dataset.name);
82-
dataset.name = publicDatasetName;
83-
});
84-
}
85-
86-
const publicName = privateToPublicGroupName(group.result.name);
87-
88-
return { ...group.result, name: publicName, _name: group.result.name };
29+
return group.result
8930
};

lib/queries/orgs.ts

Lines changed: 11 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,7 @@
1-
import { Dataset, Organization } from "@portaljs/ckan";
2-
import {
3-
privateToPublicDatasetName,
4-
privateToPublicOrgName,
5-
publicToPrivateOrgName,
6-
} from "./utils";
1+
import { Organization } from "@portaljs/ckan";
72
import CkanRequest, { CkanResponse } from "@portaljs/ckan-api-client-js";
83

94
const DMS = process.env.NEXT_PUBLIC_DMS;
10-
const mainOrg = process.env.NEXT_PUBLIC_ORG;
115

126
export const getOrganization = async ({
137
name,
@@ -16,87 +10,21 @@ export const getOrganization = async ({
1610
name: string;
1711
include_datasets?: boolean;
1812
}) => {
19-
const privateName = publicToPrivateOrgName(name);
20-
2113
const organization = await CkanRequest.get<CkanResponse<Organization>>(
22-
`organization_show?id=${privateName}&include_datasets=${include_datasets}`,
14+
`organization_show?id=${name}&include_datasets=${include_datasets}`,
2315
{ ckanUrl: DMS }
2416
);
2517

26-
if (include_datasets) {
27-
organization.result.packages.forEach((dataset: Dataset) => {
28-
dataset.organization.name = name;
29-
dataset.name = privateToPublicDatasetName(dataset.name);
30-
});
31-
}
32-
33-
const publicName = privateToPublicOrgName(organization.result.name);
34-
35-
return {
36-
...organization.result,
37-
name: publicName,
38-
_name: organization.result.name,
39-
};
18+
return organization.result
4019
};
4120

42-
export const getAllOrganizations = async ({
43-
detailed = true, // Whether to add organization_show or not
44-
}: {
45-
detailed?: boolean;
46-
}) => {
47-
if (!mainOrg) {
48-
const organizations = await CkanRequest.get<CkanResponse<Organization[]>>(
49-
`organization_list?all_fields=True`,
50-
{
51-
ckanUrl: DMS,
52-
}
53-
);
54-
55-
return organizations.result.map((o) => {
56-
return { ...o, _name: o.name };
57-
});
58-
}
59-
60-
/*
61-
* Get hierarchy from root org
62-
*
63-
*/
64-
65-
const organizationsTree = await CkanRequest.get<
66-
CkanResponse<Organization & { children: Organization[]; _name: string }>
67-
>(`group_tree_section?type=organization&id=${mainOrg}`, {
68-
ckanUrl: DMS,
69-
});
70-
71-
/*
72-
* Flatten orgs hierarchy, fix name and preserve
73-
* internal name as `_name`
74-
*
75-
*/
76-
const { children, ...parent } = organizationsTree.result;
77-
78-
let organizations = children.map((c) => {
79-
const publicName = privateToPublicOrgName(c.name);
80-
return { ...c, name: publicName, _name: c.name };
81-
});
82-
83-
organizations.unshift({ ...parent, _name: parent.name });
84-
85-
/*
86-
* Get details for each org
87-
*
88-
*/
89-
if (organizations && detailed) {
90-
organizations = await Promise.all(
91-
organizations.map(async (o) => {
92-
const orgDetails = await getOrganization({
93-
name: o.name,
94-
});
95-
96-
return { ...o, ...orgDetails, name: o.name, _name: o._name };
97-
})
98-
);
99-
}
21+
export const getAllOrganizations = async () => {
22+
const organizations = await CkanRequest.get<CkanResponse<Organization[]>>(
23+
`organization_list?all_fields=True`,
24+
{
25+
ckanUrl: DMS,
26+
}
27+
);
10028

101-
return organizations;
29+
return organizations.result
10230
};

0 commit comments

Comments
 (0)