Skip to content

Commit

Permalink
year facet added
Browse files Browse the repository at this point in the history
  • Loading branch information
karolina-siemieniuk-morawska committed Nov 27, 2023
1 parent dccc0d5 commit 8ad828b
Show file tree
Hide file tree
Showing 9 changed files with 211 additions and 55 deletions.
15 changes: 13 additions & 2 deletions ui/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
{
"extends": ["next/babel","next/core-web-vitals"],
"root": true,
"extends": ["next/core-web-vitals"],
"overrides": [
{
"files": ["*.js"],
"parser": "espree",
"parserOptions": {
"ecmaVersion": 2020
}
}
],
"rules": {
"react/display-name": "off"
"react/display-name": "off",
"react-hooks/exhaustive-deps": "off"
}
}
2 changes: 2 additions & 0 deletions ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"dependencies": {
"@ant-design/cssinjs": "^1.17.2",
"antd": "^5.10.1",
"lodash.isequal": "^4.5.0",
"moment": "^2.29.4",
"next": "13.5.5",
"nextjs-progressbar": "^0.0.16",
Expand All @@ -20,6 +21,7 @@
"react-vis": "^1.12.1"
},
"devDependencies": {
"@types/lodash": "^4.14.201",
"@types/node": "^20",
"@types/react-html-parser": "^2.0.4",
"autoprefixer": "^10",
Expand Down
3 changes: 2 additions & 1 deletion ui/src/components/search/CheckboxFacet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import React, { useState, useEffect } from "react";
import { useRouter } from "next/navigation";
import { Card } from "antd";

import { getSearchUrl } from "@/utils/utils";
import { Country, Journal, Params } from "@/types";

Expand All @@ -28,7 +29,7 @@ const CheckboxFacet: React.FC<CheckboxFacetProps> = ({
}, []);

useEffect(() => {
router.push(getSearchUrl({ ...params, [type]: filters }));
router.push(getSearchUrl({ ...params, page: 1, [type]: filters }));
}, [filters]);

const shortJournalName = (value: string) => {
Expand Down
160 changes: 113 additions & 47 deletions ui/src/components/search/YearFacet.tsx
Original file line number Diff line number Diff line change
@@ -1,77 +1,143 @@
import React, { useState } from "react";
import React, { useEffect, useState } from "react";
import { FlexibleWidthXYPlot, VerticalBarSeries, Hint } from "react-vis";
import { Card, Slider } from "antd";
import { PublicationYear } from "@/types";
import 'react-vis/dist/style.css';
import { Button, Card, Slider } from "antd";
import { SliderMarks } from "antd/es/slider";
import { useRouter } from "next/navigation";
import * as isEqual from "lodash.isequal";

import { getSearchUrl } from "@/utils/utils";
import { PublicationYear, YearFacetData, Params } from "@/types";

interface YearFacetProps {
data: PublicationYear[];
params: Params;
}

const initialData = [
{ x: 2017, y: 8 },
{ x: 2018, y: 5 },
{ x: 2019, y: 4 },
{ x: 2020, y: 9 },
{ x: 2021, y: 1 },
{ x: 2022, y: 7 },
{ x: 2023, y: 6 },
{ x: 2024, y: 3 },
{ x: 2025, y: 2 },
{ x: 2026, y: 1 },
];

const data = [
{ x: 2020, y: 9 },
{ x: 2021, y: 1 },
{ x: 2022, y: 7 },
{ x: 2023, y: 6 },
];

const YearFacet: React.FC<YearFacetProps> = ({ data }) => {
const YearFacet: React.FC<YearFacetProps> = ({ data, params }) => {
const [hoveredBar, setHoveredBar] = useState<any>(null);
const [initialData, setInitialData] = useState(data);
const [sliderEndpoints, setSliderEndpoints] = useState([2017, 2026]);
const [filters, setFilters] = useState<YearFacetData[]>([]);
const [initialData, setInitialData] = useState<YearFacetData[]>([]);
const [initialEndpoints, setInitialEndpoints] = useState<number[]>([]);
const [sliderEndpoints, setSliderEndpoints] = useState<number[]>([]);
const [marks, setMarks] = useState<SliderMarks>(undefined);
const [reset, setReset] = useState<boolean>(false);
const router = useRouter();

useEffect(() => {
const initialData = mapInitialDataToYears(data);
setFilters(initialData);
setInitialData(initialData);
setSliderEndpoints(getSliderEndpoints(initialData));
setInitialEndpoints(getSliderEndpoints(initialData));
setMarks(getMarks(initialData));
}, []);

useEffect(() => {
router.push(
getSearchUrl({
...params,
page: 1,
publication_year__range: sliderEndpoints.join("__"),
})
);
}, [filters]);

const onBarClick = (value: number) => {
const endpoints = [value, value];
onSliderChange(endpoints);
const mapInitialDataToYears = (
initial: PublicationYear[]
): YearFacetData[] => {
return initial?.map((item) => ({
x: new Date(item?.key)?.getFullYear(),
y: item?.doc_count,
}));
};
const onSliderChange = (range: any) => {
setSliderEndpoints(range);
setInitialData(range);

const getSliderEndpoints = (initial: YearFacetData[]): number[] => {
if (initial.length === 1) return [initial[0]?.x];
return [initial[0]?.x, initial[initial.length - 1]?.x];
};

const getMarks = (initial: YearFacetData[]): SliderMarks => {
if (initial.length === 1) {
return {
[initial[0]?.x]: [initial[0]?.x],
};
}
return {
[initial[0]?.x]: [initial[0]?.x],
[initial[initial.length - 1]?.x]: [initial[initial.length - 1]?.x],
};
};

const updateStateAndMarks = (newFilters: YearFacetData[]) => {
setFilters(newFilters);
setSliderEndpoints(getSliderEndpoints(newFilters));
setMarks(getMarks(newFilters));
};

const onBarClick = (value: YearFacetData) => {
updateStateAndMarks([value]);
};

const onSliderChange = (data: number[]) => {
const firstIndex = initialData.findIndex(
(item: YearFacetData) => item.x === data[0]
);
const lastIndex = initialData.findIndex(
(item: YearFacetData) => item.x === data[data.length - 1]
);
const range = initialData.slice(firstIndex, lastIndex + 1);

updateStateAndMarks(range);
};

const onBarMouseHover = (bar: YearFacetData) => {
setHoveredBar({ [bar.x]: bar.y });
};

const onBarMouseHover = (bar: any) => setHoveredBar({ [bar.x]: bar.y });
const onBarMouseOut = () => setHoveredBar(null);

const resetFilters = () => {
setReset(!reset);
updateStateAndMarks(initialData);
};

return (
<Card title="Year" className="search-facets-facet mb-5">
<div className="mx-3">
<FlexibleWidthXYPlot height={150} margin={0}>
<div>
{!isEqual(initialData, filters) && (
<div className="text-right">
<Button onClick={resetFilters} className="ml-1" type="primary" size="small">
Reset
</Button>
</div>
)}
<FlexibleWidthXYPlot
height={80}
width={150}
margin={0}
className="year-facet"
>
<VerticalBarSeries
className="pointer"
colorType="literal"
data={data}
color="#3498db"
barWidth={0.6}
data={filters}
onValueClick={onBarClick}
onValueMouseOver={onBarMouseHover}
onValueMouseOut={onBarMouseOut}
/>
{hoveredBar && (
<Hint
value={hoveredBar}
align={{ vertical: "top", horizontal: "auto" }}
/>
)}
{hoveredBar && <Hint value={hoveredBar} />}
</FlexibleWidthXYPlot>
</div>
<Slider
range
className="year-facet-slider"
onChange={onSliderChange}
value={sliderEndpoints}
min={sliderEndpoints[0]}
max={sliderEndpoints[1]}
included
tooltip={{ open: false }}
min={initialEndpoints[0]}
max={initialEndpoints[1]}
marks={marks}
/>
</Card>
);
Expand Down
7 changes: 6 additions & 1 deletion ui/src/pages/search.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,12 @@ const SearchPage: React.FC<SearchPageProps> = ({
<div className="search-facets">
{results && results.length > 0 && (
<>
{/* <YearFacet /> */}
<YearFacet
data={
facets?._filter_publication_year?.publication_year?.buckets
}
params={query}
/>
<CheckboxFacet
data={facets?._filter_country?.country?.buckets}
title="Country / Region / Territory"
Expand Down
48 changes: 47 additions & 1 deletion ui/src/styles/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,6 @@ a {
display: flex;
align-items: center;
cursor: pointer;
color:
}

.ant-menu-item a {
Expand Down Expand Up @@ -385,6 +384,53 @@ a {
padding: 15px 10px !important;
}

.search-facets-facet .year-facet {
margin: 0 auto;
}

.search-facets-facet .year-facet-slider {
margin: 0.5rem auto 2.2rem auto;
width: 150px;
}

.search-facets-facet .year-facet-slider .ant-slider-rail {
background-color: #ccc;
}

.search-facets-facet .year-facet-slider .ant-slider-track {
background-color: #3498db;
}

.search-facets-facet .year-facet-slider .ant-slider-mark-text {
transform: rotate(-45deg) translateX(-50%) !important;
color: #3498db;
}

.search-facets-facet rect:hover {
stroke: #69c0ff !important;
fill: #69c0ff !important;
cursor: pointer;
}

.search-facets-facet .ant-btn {
background-color: #337ab7;
padding: 5px 10px;
font-size: 12px;
line-height: 1.5;
border-radius: 3px;
height: fit-content;
margin-top: -5px;
}

.search-facets-facet .ant-btn:hover {
background-color: #286090 !important;
}

.rv-hint {
top: 10px !important;
left: 80% !important;
}

/* DETAIL */

.detail-page-main {
Expand Down
10 changes: 9 additions & 1 deletion ui/src/theme/themeConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,18 @@ import type { ThemeConfig } from 'antd';
const theme: ThemeConfig = {
token: {
fontSize: 16,
colorPrimary: '#7a5380',
colorTextPlaceholder: '#777',
fontFamily: '"PT Sans Narrow", sans-serif'
},
components: {
Slider: {
handleColor: "#3498db",
handleSize: 7,
handleSizeHover: 10,
handleLineWidthHover: 2,
railSize: 3,
},
}
};

export default theme;
11 changes: 9 additions & 2 deletions ui/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ export const queryTypes = [
"search",
"country",
"journal",
"publication_year",
"publication_year__range",
] as const;

export type QueryType = (typeof queryTypes)[number];
Expand All @@ -15,7 +15,7 @@ export type Params = {
search?: string;
country?: string | string[];
journal?: string | string[];
publication_year?: string | string[];
publication_year__range?: string;
};

export interface Response {
Expand Down Expand Up @@ -143,3 +143,10 @@ export interface MenuItem {
export type Extension = "pdf" | "pdfa" | "xml";

export const supportedExtensions: Extension[] = ["pdf", "pdfa", "xml"];

export interface YearFacetData {
// year
x: number;
// count
y: number;
}
10 changes: 10 additions & 0 deletions ui/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,11 @@
resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee"
integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==

"@types/lodash@^4.14.201":
version "4.14.201"
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.201.tgz#76f47cb63124e806824b6c18463daf3e1d480239"
integrity sha512-y9euML0cim1JrykNxADLfaG0FgD1g/yTHwUs/Jg9ZIU7WKj2/4IW9Lbb1WZbvck78W/lfGXFfe+u2EGfIJXdLQ==

"@types/node@*", "@types/node@^20":
version "20.9.0"
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.9.0.tgz#bfcdc230583aeb891cf51e73cfdaacdd8deae298"
Expand Down Expand Up @@ -2075,6 +2080,11 @@ locate-path@^6.0.0:
dependencies:
p-locate "^5.0.0"

lodash.isequal@^4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0"
integrity sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==

lodash.merge@^4.6.2:
version "4.6.2"
resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a"
Expand Down

0 comments on commit 8ad828b

Please sign in to comment.