diff --git a/src/data/openalex-domains.json.ts b/src/data/openalex-domains.json.ts new file mode 100644 index 0000000..0f4f01a --- /dev/null +++ b/src/data/openalex-domains.json.ts @@ -0,0 +1,35 @@ +import { HttpClient, Terminal } from '@effect/platform' +import { NodeTerminal } from '@effect/platform-node' +import { Schema } from '@effect/schema' +import { Effect, Record } from 'effect' +import { DomainIdFromUrlSchema, DomainIdSchema } from '../lib/OpenAlex.js' +import { UrlFromStringSchema } from '../lib/Url.js' + +const Domains = Schema.Struct({ + results: Schema.Array( + Schema.Struct({ + id: Schema.compose(UrlFromStringSchema, DomainIdFromUrlSchema), + display_name: Schema.String, + }), + ), +}) + +const DomainNames = Schema.Record(DomainIdSchema, Schema.String) + +const program = Effect.gen(function* () { + const terminal = yield* Terminal.Terminal + + const request = HttpClient.request.get('https://api.openalex.org/domains?per-page=200') + + const data = yield* HttpClient.client + .fetchOk(request) + .pipe(Effect.andThen(HttpClient.response.schemaBodyJson(Domains)), Effect.scoped) + + const transformedData = Record.fromIterableWith(data.results, domain => [domain.id, domain.display_name]) + + const encoded = yield* Schema.encode(Schema.parseJson(DomainNames))(transformedData) + + yield* terminal.display(encoded) +}) + +await Effect.runPromise(program.pipe(Effect.provide(NodeTerminal.layer))) diff --git a/src/requests.md b/src/requests.md index 7ae8d58..34b85e9 100644 --- a/src/requests.md +++ b/src/requests.md @@ -15,6 +15,7 @@ const requests = FileAttachment('./data/requests.json') .json() .then(data => data.map(request => ({ ...request, timestamp: parseTimestamp(request.timestamp) }))) +const openAlexDomains = FileAttachment('./data/openalex-domains.json').json() const openAlexFields = FileAttachment('./data/openalex-fields.json').json() ``` @@ -23,6 +24,19 @@ const now = new Date() const firstRequest = d3.min(requests, request => request.timestamp) ``` +```js +const chosenDomain = view( + Inputs.select([null, ...Object.keys(openAlexDomains)], { + label: 'Domain', + format: domain => (domain ? openAlexDomains[domain] : 'All domains'), + }), +) +``` + +```js +const requestsSelected = chosenDomain ? requests.filter(d => d.domains.includes(chosenDomain)) : requests +``` + ```js const languageColor = Plot.scale({ color: { @@ -41,15 +55,16 @@ const languageColor = Plot.scale({ }, }) -const requestsByField = requests.flatMap(({ fields, ...request }) => - fields.map(field => ({ ...request, field: openAlexFields[field].name })), -) +const requestsByField = requestsSelected + .flatMap(({ fields, ...request }) => fields.map(field => ({ ...request, field }))) + .filter(request => (chosenDomain ? openAlexFields[request.field].domain === chosenDomain : true)) + .map(({ field, ...request }) => ({ ...request, field: openAlexFields[field].name })) ```