added search results page, chanhgen search bar, changed article component

This commit is contained in:
maximus 2022-10-11 11:53:20 +03:00
parent 5e46d6a098
commit a7534b589f
27 changed files with 307 additions and 680 deletions

412
package-lock.json generated
View File

@ -4060,11 +4060,6 @@
"@jridgewell/sourcemap-codec": "^1.4.10" "@jridgewell/sourcemap-codec": "^1.4.10"
} }
}, },
"node_modules/@juggle/resize-observer": {
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/@juggle/resize-observer/-/resize-observer-3.4.0.tgz",
"integrity": "sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA=="
},
"node_modules/@leichtgewicht/ip-codec": { "node_modules/@leichtgewicht/ip-codec": {
"version": "2.0.4", "version": "2.0.4",
"resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz", "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz",
@ -4415,26 +4410,6 @@
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz",
"integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==" "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw=="
}, },
"node_modules/@rsuite/icon-font": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/@rsuite/icon-font/-/icon-font-4.0.0.tgz",
"integrity": "sha512-rZTgpTH3H3HLczCA2rnkWfoMKm0ZXoRzsrkVujfP/FfslnKUMvO6w56pa8pCvhWGpNEPUsLS2ULnFGpTEcup/Q=="
},
"node_modules/@rsuite/icons": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@rsuite/icons/-/icons-1.0.2.tgz",
"integrity": "sha512-Y7vJNDQpJnFlyYSUXQ2iQ9Meg7+ZKcrIenhpYDdM3c7vYDE/L7pml+hrK28jk6QfV/QkVv5B504D+l7aM6AAJQ==",
"dependencies": {
"@rsuite/icon-font": "^4.0.0",
"classnames": "^2.2.5",
"insert-css": "^2.0.0",
"lodash": "^4.17.20"
},
"peerDependencies": {
"react": ">=16.8.0",
"react-dom": ">=16.8.0"
}
},
"node_modules/@rushstack/eslint-patch": { "node_modules/@rushstack/eslint-patch": {
"version": "1.1.4", "version": "1.1.4",
"resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.1.4.tgz", "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.1.4.tgz",
@ -11222,11 +11197,6 @@
"@types/node": "*" "@types/node": "*"
} }
}, },
"node_modules/@types/chai": {
"version": "4.3.3",
"resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.3.tgz",
"integrity": "sha512-hC7OMnszpxhZPduX+m+nrx+uFoLkWOMiR4oa/AZF3MuSETYTZmFfJAHqZEM8MVlvfG7BEUcgvtwoCTxBp6hm3g=="
},
"node_modules/@types/connect": { "node_modules/@types/connect": {
"version": "3.4.35", "version": "3.4.35",
"resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz",
@ -11526,25 +11496,6 @@
"@types/react": "*" "@types/react": "*"
} }
}, },
"node_modules/@types/react-virtualized": {
"version": "9.21.21",
"resolved": "https://registry.npmjs.org/@types/react-virtualized/-/react-virtualized-9.21.21.tgz",
"integrity": "sha512-Exx6I7p4Qn+BBA1SRyj/UwQlZ0I0Pq7g7uhAp0QQ4JWzZunqEqNBGTmCmMmS/3N9wFgAGWuBD16ap7k8Y14VPA==",
"dependencies": {
"@types/prop-types": "*",
"@types/react": "^17"
}
},
"node_modules/@types/react-virtualized/node_modules/@types/react": {
"version": "17.0.50",
"resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.50.tgz",
"integrity": "sha512-ZCBHzpDb5skMnc1zFXAXnL3l1FAdi+xZvwxK+PkglMmBrwjpp9nKaWuEvrGnSifCJmBFGxZOOFuwC6KH/s0NuA==",
"dependencies": {
"@types/prop-types": "*",
"@types/scheduler": "*",
"csstype": "^3.0.2"
}
},
"node_modules/@types/resolve": { "node_modules/@types/resolve": {
"version": "1.17.1", "version": "1.17.1",
"resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz",
@ -14686,6 +14637,7 @@
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/clsx/-/clsx-1.1.0.tgz", "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.1.0.tgz",
"integrity": "sha512-3avwM37fSK5oP6M5rQ9CNe99lwxhXDOeSWVPAOYF6OazUTgZCMb0yWlJpmdD74REy1gkEaFiub2ULv4fq9GUhA==", "integrity": "sha512-3avwM37fSK5oP6M5rQ9CNe99lwxhXDOeSWVPAOYF6OazUTgZCMb0yWlJpmdD74REy1gkEaFiub2ULv4fq9GUhA==",
"dev": true,
"engines": { "engines": {
"node": ">=6" "node": ">=6"
} }
@ -16019,18 +15971,6 @@
"node": ">=10" "node": ">=10"
} }
}, },
"node_modules/date-fns": {
"version": "2.29.3",
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.29.3.tgz",
"integrity": "sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA==",
"engines": {
"node": ">=0.11"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/date-fns"
}
},
"node_modules/debug": { "node_modules/debug": {
"version": "4.3.4", "version": "4.3.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
@ -16451,45 +16391,6 @@
"utila": "~0.4" "utila": "~0.4"
} }
}, },
"node_modules/dom-helpers": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz",
"integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==",
"dependencies": {
"@babel/runtime": "^7.8.7",
"csstype": "^3.0.2"
}
},
"node_modules/dom-helpers/node_modules/@babel/runtime": {
"version": "7.19.0",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.19.0.tgz",
"integrity": "sha512-eR8Lo9hnDS7tqkO7NsV+mKvCmv5boaXFSZ70DnfhcgiEne8hv9oCEd36Klw74EtizEqLsy4YnW8UWwpBVolHZA==",
"dependencies": {
"regenerator-runtime": "^0.13.4"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/dom-lib": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/dom-lib/-/dom-lib-3.1.3.tgz",
"integrity": "sha512-66NzehAJZM5HrH/2FW6C0tgaMIywDF5I9n7PWgvdSciohlYQbCFcSf5XA6hhIqQdFbfrnZDD8NGLo9pDRzO5hQ==",
"dependencies": {
"@babel/runtime": "^7.16.0"
}
},
"node_modules/dom-lib/node_modules/@babel/runtime": {
"version": "7.19.0",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.19.0.tgz",
"integrity": "sha512-eR8Lo9hnDS7tqkO7NsV+mKvCmv5boaXFSZ70DnfhcgiEne8hv9oCEd36Klw74EtizEqLsy4YnW8UWwpBVolHZA==",
"dependencies": {
"regenerator-runtime": "^0.13.4"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/dom-serializer": { "node_modules/dom-serializer": {
"version": "1.4.1", "version": "1.4.1",
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz",
@ -20643,11 +20544,6 @@
"resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.1.1.tgz", "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.1.1.tgz",
"integrity": "sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==" "integrity": "sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q=="
}, },
"node_modules/insert-css": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/insert-css/-/insert-css-2.0.0.tgz",
"integrity": "sha512-xGq5ISgcUP5cvGkS2MMFLtPDBtrtQPSFfC6gA6U8wHKqfjTIMZLZNxOItQnoSjdOzlXOLU/yD32RKC4SvjNbtA=="
},
"node_modules/internal-slot": { "node_modules/internal-slot": {
"version": "1.0.3", "version": "1.0.3",
"resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz",
@ -30388,11 +30284,6 @@
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
}, },
"node_modules/react-lifecycles-compat": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz",
"integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA=="
},
"node_modules/react-loading-skeleton": { "node_modules/react-loading-skeleton": {
"version": "3.1.0", "version": "3.1.0",
"resolved": "https://registry.npmjs.org/react-loading-skeleton/-/react-loading-skeleton-3.1.0.tgz", "resolved": "https://registry.npmjs.org/react-loading-skeleton/-/react-loading-skeleton-3.1.0.tgz",
@ -32595,23 +32486,6 @@
"integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==",
"dev": true "dev": true
}, },
"node_modules/react-virtualized": {
"version": "9.22.3",
"resolved": "https://registry.npmjs.org/react-virtualized/-/react-virtualized-9.22.3.tgz",
"integrity": "sha512-MKovKMxWTcwPSxE1kK1HcheQTWfuCxAuBoSTf2gwyMM21NdX/PXUhnoP8Uc5dRKd+nKm8v41R36OellhdCpkrw==",
"dependencies": {
"@babel/runtime": "^7.7.2",
"clsx": "^1.0.4",
"dom-helpers": "^5.1.3",
"loose-envify": "^1.4.0",
"prop-types": "^15.7.2",
"react-lifecycles-compat": "^3.0.4"
},
"peerDependencies": {
"react": "^15.3.0 || ^16.0.0-alpha",
"react-dom": "^15.3.0 || ^16.0.0-alpha"
}
},
"node_modules/read-cache": { "node_modules/read-cache": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
@ -35385,78 +35259,6 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/rsuite": {
"version": "5.19.0",
"resolved": "https://registry.npmjs.org/rsuite/-/rsuite-5.19.0.tgz",
"integrity": "sha512-KQD48UT2HJec+VNzcsrGlo65+OMas7kOjJnxkwR3GsiIugw2aQ9o2JUBmoaJFxhbAnwv1hjJ73ZgW3MH3Wo/Pw==",
"dependencies": {
"@babel/runtime": "^7.18.9",
"@juggle/resize-observer": "^3.3.1",
"@rsuite/icons": "^1.0.2",
"@types/chai": "^4.3.3",
"@types/lodash": "^4.14.184",
"@types/prop-types": "^15.7.4",
"@types/react-virtualized": "^9.21.11",
"classnames": "^2.3.1",
"date-fns": "^2.29.2",
"dom-lib": "^3.1.2",
"lodash": "^4.17.11",
"prop-types": "^15.8.1",
"react-virtualized": "^9.22.3",
"rsuite-table": "^5.7.1",
"schema-typed": "^2.0.3"
},
"peerDependencies": {
"react": ">=16.8.0",
"react-dom": ">=16.8.0"
}
},
"node_modules/rsuite-table": {
"version": "5.7.2",
"resolved": "https://registry.npmjs.org/rsuite-table/-/rsuite-table-5.7.2.tgz",
"integrity": "sha512-JwfxAR8lXVXM9PRQGJMbayciMcVFpHWExAhfY53h6JYKC7LfPeBx/Z6k4P7PO0grFkVGBdFW3ZgHxhCD1ur/eA==",
"dependencies": {
"@babel/runtime": "^7.12.5",
"@juggle/resize-observer": "^3.3.1",
"@rsuite/icons": "^1.0.0",
"classnames": "^2.3.1",
"dom-lib": "^3.1.3",
"lodash": "^4.17.21",
"react-is": "^17.0.2"
},
"peerDependencies": {
"prop-types": "^15.7.2",
"react": ">=16.8.0",
"react-dom": ">=16.8.0"
}
},
"node_modules/rsuite-table/node_modules/@babel/runtime": {
"version": "7.19.0",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.19.0.tgz",
"integrity": "sha512-eR8Lo9hnDS7tqkO7NsV+mKvCmv5boaXFSZ70DnfhcgiEne8hv9oCEd36Klw74EtizEqLsy4YnW8UWwpBVolHZA==",
"dependencies": {
"regenerator-runtime": "^0.13.4"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/rsuite-table/node_modules/react-is": {
"version": "17.0.2",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
"integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w=="
},
"node_modules/rsuite/node_modules/@babel/runtime": {
"version": "7.19.0",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.19.0.tgz",
"integrity": "sha512-eR8Lo9hnDS7tqkO7NsV+mKvCmv5boaXFSZ70DnfhcgiEne8hv9oCEd36Klw74EtizEqLsy4YnW8UWwpBVolHZA==",
"dependencies": {
"regenerator-runtime": "^0.13.4"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/rsvp": { "node_modules/rsvp": {
"version": "4.8.5", "version": "4.8.5",
"resolved": "https://registry.npmjs.org/rsvp/-/rsvp-4.8.5.tgz", "resolved": "https://registry.npmjs.org/rsvp/-/rsvp-4.8.5.tgz",
@ -35899,25 +35701,6 @@
"loose-envify": "^1.1.0" "loose-envify": "^1.1.0"
} }
}, },
"node_modules/schema-typed": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/schema-typed/-/schema-typed-2.0.3.tgz",
"integrity": "sha512-4KckVnJjTtVugYpSAoQrcH4quE4yIVTvI/nHEqtwdceBr/ZCuH2LfV8/gaZFrYU7cwwyufLKaswt28aqQ1T9ww==",
"dependencies": {
"@babel/runtime": "^7.16.0"
}
},
"node_modules/schema-typed/node_modules/@babel/runtime": {
"version": "7.19.0",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.19.0.tgz",
"integrity": "sha512-eR8Lo9hnDS7tqkO7NsV+mKvCmv5boaXFSZ70DnfhcgiEne8hv9oCEd36Klw74EtizEqLsy4YnW8UWwpBVolHZA==",
"dependencies": {
"regenerator-runtime": "^0.13.4"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/schema-utils": { "node_modules/schema-utils": {
"version": "3.1.1", "version": "3.1.1",
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz",
@ -42967,11 +42750,6 @@
"@jridgewell/sourcemap-codec": "^1.4.10" "@jridgewell/sourcemap-codec": "^1.4.10"
} }
}, },
"@juggle/resize-observer": {
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/@juggle/resize-observer/-/resize-observer-3.4.0.tgz",
"integrity": "sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA=="
},
"@leichtgewicht/ip-codec": { "@leichtgewicht/ip-codec": {
"version": "2.0.4", "version": "2.0.4",
"resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz", "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz",
@ -43211,22 +42989,6 @@
} }
} }
}, },
"@rsuite/icon-font": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/@rsuite/icon-font/-/icon-font-4.0.0.tgz",
"integrity": "sha512-rZTgpTH3H3HLczCA2rnkWfoMKm0ZXoRzsrkVujfP/FfslnKUMvO6w56pa8pCvhWGpNEPUsLS2ULnFGpTEcup/Q=="
},
"@rsuite/icons": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@rsuite/icons/-/icons-1.0.2.tgz",
"integrity": "sha512-Y7vJNDQpJnFlyYSUXQ2iQ9Meg7+ZKcrIenhpYDdM3c7vYDE/L7pml+hrK28jk6QfV/QkVv5B504D+l7aM6AAJQ==",
"requires": {
"@rsuite/icon-font": "^4.0.0",
"classnames": "^2.2.5",
"insert-css": "^2.0.0",
"lodash": "^4.17.20"
}
},
"@rushstack/eslint-patch": { "@rushstack/eslint-patch": {
"version": "1.1.4", "version": "1.1.4",
"resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.1.4.tgz", "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.1.4.tgz",
@ -48404,11 +48166,6 @@
"@types/node": "*" "@types/node": "*"
} }
}, },
"@types/chai": {
"version": "4.3.3",
"resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.3.tgz",
"integrity": "sha512-hC7OMnszpxhZPduX+m+nrx+uFoLkWOMiR4oa/AZF3MuSETYTZmFfJAHqZEM8MVlvfG7BEUcgvtwoCTxBp6hm3g=="
},
"@types/connect": { "@types/connect": {
"version": "3.4.35", "version": "3.4.35",
"resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz",
@ -48708,27 +48465,6 @@
"@types/react": "*" "@types/react": "*"
} }
}, },
"@types/react-virtualized": {
"version": "9.21.21",
"resolved": "https://registry.npmjs.org/@types/react-virtualized/-/react-virtualized-9.21.21.tgz",
"integrity": "sha512-Exx6I7p4Qn+BBA1SRyj/UwQlZ0I0Pq7g7uhAp0QQ4JWzZunqEqNBGTmCmMmS/3N9wFgAGWuBD16ap7k8Y14VPA==",
"requires": {
"@types/prop-types": "*",
"@types/react": "^17"
},
"dependencies": {
"@types/react": {
"version": "17.0.50",
"resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.50.tgz",
"integrity": "sha512-ZCBHzpDb5skMnc1zFXAXnL3l1FAdi+xZvwxK+PkglMmBrwjpp9nKaWuEvrGnSifCJmBFGxZOOFuwC6KH/s0NuA==",
"requires": {
"@types/prop-types": "*",
"@types/scheduler": "*",
"csstype": "^3.0.2"
}
}
}
},
"@types/resolve": { "@types/resolve": {
"version": "1.17.1", "version": "1.17.1",
"resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz",
@ -51185,7 +50921,8 @@
"clsx": { "clsx": {
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/clsx/-/clsx-1.1.0.tgz", "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.1.0.tgz",
"integrity": "sha512-3avwM37fSK5oP6M5rQ9CNe99lwxhXDOeSWVPAOYF6OazUTgZCMb0yWlJpmdD74REy1gkEaFiub2ULv4fq9GUhA==" "integrity": "sha512-3avwM37fSK5oP6M5rQ9CNe99lwxhXDOeSWVPAOYF6OazUTgZCMb0yWlJpmdD74REy1gkEaFiub2ULv4fq9GUhA==",
"dev": true
}, },
"cnbuilder": { "cnbuilder": {
"version": "3.1.0", "version": "3.1.0",
@ -52207,11 +51944,6 @@
} }
} }
}, },
"date-fns": {
"version": "2.29.3",
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.29.3.tgz",
"integrity": "sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA=="
},
"debug": { "debug": {
"version": "4.3.4", "version": "4.3.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
@ -52529,43 +52261,6 @@
"utila": "~0.4" "utila": "~0.4"
} }
}, },
"dom-helpers": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz",
"integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==",
"requires": {
"@babel/runtime": "^7.8.7",
"csstype": "^3.0.2"
},
"dependencies": {
"@babel/runtime": {
"version": "7.19.0",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.19.0.tgz",
"integrity": "sha512-eR8Lo9hnDS7tqkO7NsV+mKvCmv5boaXFSZ70DnfhcgiEne8hv9oCEd36Klw74EtizEqLsy4YnW8UWwpBVolHZA==",
"requires": {
"regenerator-runtime": "^0.13.4"
}
}
}
},
"dom-lib": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/dom-lib/-/dom-lib-3.1.3.tgz",
"integrity": "sha512-66NzehAJZM5HrH/2FW6C0tgaMIywDF5I9n7PWgvdSciohlYQbCFcSf5XA6hhIqQdFbfrnZDD8NGLo9pDRzO5hQ==",
"requires": {
"@babel/runtime": "^7.16.0"
},
"dependencies": {
"@babel/runtime": {
"version": "7.19.0",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.19.0.tgz",
"integrity": "sha512-eR8Lo9hnDS7tqkO7NsV+mKvCmv5boaXFSZ70DnfhcgiEne8hv9oCEd36Klw74EtizEqLsy4YnW8UWwpBVolHZA==",
"requires": {
"regenerator-runtime": "^0.13.4"
}
}
}
},
"dom-serializer": { "dom-serializer": {
"version": "1.4.1", "version": "1.4.1",
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz",
@ -55705,11 +55400,6 @@
"resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.1.1.tgz", "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.1.1.tgz",
"integrity": "sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==" "integrity": "sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q=="
}, },
"insert-css": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/insert-css/-/insert-css-2.0.0.tgz",
"integrity": "sha512-xGq5ISgcUP5cvGkS2MMFLtPDBtrtQPSFfC6gA6U8wHKqfjTIMZLZNxOItQnoSjdOzlXOLU/yD32RKC4SvjNbtA=="
},
"internal-slot": { "internal-slot": {
"version": "1.0.3", "version": "1.0.3",
"resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz",
@ -62750,11 +62440,6 @@
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
}, },
"react-lifecycles-compat": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz",
"integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA=="
},
"react-loading-skeleton": { "react-loading-skeleton": {
"version": "3.1.0", "version": "3.1.0",
"resolved": "https://registry.npmjs.org/react-loading-skeleton/-/react-loading-skeleton-3.1.0.tgz", "resolved": "https://registry.npmjs.org/react-loading-skeleton/-/react-loading-skeleton-3.1.0.tgz",
@ -64332,19 +64017,6 @@
} }
} }
}, },
"react-virtualized": {
"version": "9.22.3",
"resolved": "https://registry.npmjs.org/react-virtualized/-/react-virtualized-9.22.3.tgz",
"integrity": "sha512-MKovKMxWTcwPSxE1kK1HcheQTWfuCxAuBoSTf2gwyMM21NdX/PXUhnoP8Uc5dRKd+nKm8v41R36OellhdCpkrw==",
"requires": {
"@babel/runtime": "^7.7.2",
"clsx": "^1.0.4",
"dom-helpers": "^5.1.3",
"loose-envify": "^1.4.0",
"prop-types": "^15.7.2",
"react-lifecycles-compat": "^3.0.4"
}
},
"read-cache": { "read-cache": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
@ -66309,66 +65981,6 @@
} }
} }
}, },
"rsuite": {
"version": "https://registry.npmjs.org/rsuite/-/rsuite-5.19.0.tgz",
"integrity": "sha512-KQD48UT2HJec+VNzcsrGlo65+OMas7kOjJnxkwR3GsiIugw2aQ9o2JUBmoaJFxhbAnwv1hjJ73ZgW3MH3Wo/Pw==",
"requires": {
"@babel/runtime": "^7.18.9",
"@juggle/resize-observer": "^3.3.1",
"@rsuite/icons": "^1.0.2",
"@types/chai": "^4.3.3",
"@types/lodash": "^4.14.184",
"@types/prop-types": "^15.7.4",
"@types/react-virtualized": "^9.21.11",
"classnames": "^2.3.1",
"date-fns": "^2.29.2",
"dom-lib": "^3.1.2",
"lodash": "^4.17.11",
"prop-types": "^15.8.1",
"react-virtualized": "^9.22.3",
"rsuite-table": "^5.7.1",
"schema-typed": "^2.0.3"
},
"dependencies": {
"@babel/runtime": {
"version": "7.19.0",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.19.0.tgz",
"integrity": "sha512-eR8Lo9hnDS7tqkO7NsV+mKvCmv5boaXFSZ70DnfhcgiEne8hv9oCEd36Klw74EtizEqLsy4YnW8UWwpBVolHZA==",
"requires": {
"regenerator-runtime": "^0.13.4"
}
}
}
},
"rsuite-table": {
"version": "5.7.2",
"resolved": "https://registry.npmjs.org/rsuite-table/-/rsuite-table-5.7.2.tgz",
"integrity": "sha512-JwfxAR8lXVXM9PRQGJMbayciMcVFpHWExAhfY53h6JYKC7LfPeBx/Z6k4P7PO0grFkVGBdFW3ZgHxhCD1ur/eA==",
"requires": {
"@babel/runtime": "^7.12.5",
"@juggle/resize-observer": "^3.3.1",
"@rsuite/icons": "^1.0.0",
"classnames": "^2.3.1",
"dom-lib": "^3.1.3",
"lodash": "^4.17.21",
"react-is": "^17.0.2"
},
"dependencies": {
"@babel/runtime": {
"version": "7.19.0",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.19.0.tgz",
"integrity": "sha512-eR8Lo9hnDS7tqkO7NsV+mKvCmv5boaXFSZ70DnfhcgiEne8hv9oCEd36Klw74EtizEqLsy4YnW8UWwpBVolHZA==",
"requires": {
"regenerator-runtime": "^0.13.4"
}
},
"react-is": {
"version": "17.0.2",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
"integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w=="
}
}
},
"rsvp": { "rsvp": {
"version": "4.8.5", "version": "4.8.5",
"resolved": "https://registry.npmjs.org/rsvp/-/rsvp-4.8.5.tgz", "resolved": "https://registry.npmjs.org/rsvp/-/rsvp-4.8.5.tgz",
@ -66703,24 +66315,6 @@
"loose-envify": "^1.1.0" "loose-envify": "^1.1.0"
} }
}, },
"schema-typed": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/schema-typed/-/schema-typed-2.0.3.tgz",
"integrity": "sha512-4KckVnJjTtVugYpSAoQrcH4quE4yIVTvI/nHEqtwdceBr/ZCuH2LfV8/gaZFrYU7cwwyufLKaswt28aqQ1T9ww==",
"requires": {
"@babel/runtime": "^7.16.0"
},
"dependencies": {
"@babel/runtime": {
"version": "7.19.0",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.19.0.tgz",
"integrity": "sha512-eR8Lo9hnDS7tqkO7NsV+mKvCmv5boaXFSZ70DnfhcgiEne8hv9oCEd36Klw74EtizEqLsy4YnW8UWwpBVolHZA==",
"requires": {
"regenerator-runtime": "^0.13.4"
}
}
}
},
"schema-utils": { "schema-utils": {
"version": "3.1.1", "version": "3.1.1",
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz",

View File

@ -2,7 +2,7 @@ export interface Article {
id?: string; id?: string;
title?: string; title?: string;
authors?: string[]; authors?: string[];
topic?: string; topic?: string[];
summary?: string; summary?: string;
tags?: string[]; tags?: string[];
content?: string; content?: string;

View File

@ -6,9 +6,10 @@ import { ArticleTitle } from "./ArticleParts/ArticleTitle";
import { ArticleBreadcumbs } from "./ArticleParts/ArticleBreadcumbs"; import { ArticleBreadcumbs } from "./ArticleParts/ArticleBreadcumbs";
import { ArticleAuthors } from "./ArticleParts/ArticleAuthors"; import { ArticleAuthors } from "./ArticleParts/ArticleAuthors";
import { ArticleKeywords } from "./ArticleParts/ArticleKeywords"; import { ArticleKeywords } from "./ArticleParts/ArticleKeywords";
import { ArticleInteractionButtons } from "./ArticleParts/ArticleInteractionButtons"; import { ArticleInteractionButtons } from "./ArticleParts/InteractionButtons/ArticleInteractionButtons";
import { ArticleDescription } from "./ArticleParts/ArticleDescription"; import { ArticleDescription } from "./ArticleParts/ArticleDescription";
import { ArticleSubscriptionsButtons } from "./ArticleParts/ArticleSubscriptionsButton"; import { ArticleSubscriptionsButtons } from "./ArticleParts/ArticleSubscriptionsButton";
import classNames from "classnames";
/** /**
* Reduces a sequence of names to initials. * Reduces a sequence of names to initials.
@ -53,17 +54,17 @@ type ArticleTileExtentions = {
}; };
type ArticleTileProps = { type ArticleTileProps = {
/** Description of prop "foo". */ className?: string;
children?: React.ReactNode; children?: React.ReactNode;
}; };
export function Article({ export function Article({
/** Description of prop "foo". */ className,
children, children,
}: ArticleTileProps & ArticleTileExtentions) { }: ArticleTileProps & ArticleTileExtentions) {
const [isShowing, setIsShowing] = useState(false); const [isShowing, setIsShowing] = useState(false);
return <div className="flex flex-col w-full">{children}</div>; return <div className={classNames("flex flex-col w-full", className)}>{children}</div>;
} }
Article.Title = ArticleTitle; Article.Title = ArticleTitle;

View File

@ -6,24 +6,27 @@ import classNames from "classnames";
type ArticleBreadcumbsProps = { type ArticleBreadcumbsProps = {
emphasis?: "high" | "low"; emphasis?: "high" | "low";
children?: string[]; children?: string[];
className?: string;
}; };
export function ArticleBreadcumbs({ export function ArticleBreadcumbs({
children, children,
emphasis = "high", //Emphasis high uses when we display article page emphasis = "high",
className, //Emphasis high uses when we display article page
}: ArticleBreadcumbsProps) { }: ArticleBreadcumbsProps) {
return ( return (
<Breadcrumbs <Breadcrumbs
divider="slash" divider="slash"
className={classNames( className={classNames(
"text-xs leading-4 text-gray-700 flex flex-row items-center", "text-sm leading-4 text-gray-700 flex flex-row items-center",
{ {
"last:text-gray-900": emphasis === "high", "last:text-gray-900": emphasis === "high",
} },
className,
)} )}
> >
{emphasis === "high" ? <Logo className="w-4" fillColors="gray" /> : null} {emphasis === "high" ? <Logo className="w-4" fillColors="gray" /> : null}
{children} {children}
</Breadcrumbs> </Breadcrumbs>
); );
} }

View File

@ -1,32 +1,28 @@
import React from "react"; import React from "react";
import Typography from "components/typography/Typography"; import Typography from "components/typography/Typography";
import { Transition } from "@headlessui/react"; import { Transition } from "@headlessui/react";
import classNames from "classnames";
type ArticleDescriptionProps = { type ArticleDescriptionProps = {
children?: React.ReactNode; children?: React.ReactNode;
emphasis?: "low" | "high"; emphasis?: "low" | "high";
isShowing?: boolean; isShowing?: boolean;
className?: string;
}; };
export function ArticleDescription({ export function ArticleDescription({
children, children,
className,
emphasis = "high", emphasis = "high",
isShowing = false, isShowing = false,
}: ArticleDescriptionProps) { }: ArticleDescriptionProps) {
return emphasis === "low" ? ( return emphasis === "low" ? (
<div className="overflow-hidden"> <div
<Transition className={classNames("overflow-hidden", { "line-clamp-3": !isShowing })}
appear >
show={isShowing} <Typography className={classNames("text-base text-gray-900", className)}>
enter="ease-in-out duration-200" {children}
enterFrom="-translate-y-full" </Typography>
enterTo="translate-y-0"
leave="ease-in-out duration-200"
leaveFrom="translate-y-0"
leaveTo="-translate-y-full"
>
<Typography className="text-base text-gray-900">{children}</Typography>
</Transition>
</div> </div>
) : ( ) : (
<div> <div>

View File

@ -47,7 +47,13 @@ export function ArticleKeywords({
{emphasis === "low" ? ( {emphasis === "low" ? (
<SVGKey className="w-6 fill-gray-500 stroke-gray-500" /> <SVGKey className="w-6 fill-gray-500 stroke-gray-500" />
) : null} ) : null}
<div className="flex flex-row ml-2">{keywords}</div> <div
className={classNames("flex flex-row", {
"ml-2": emphasis === "low",
})}
>
{keywords}
</div>
</div> </div>
); );
} }

View File

@ -11,6 +11,7 @@ import {
SVGFolder, SVGFolder,
} from "components/icons"; } from "components/icons";
import classNames from "classnames"; import classNames from "classnames";
import { Transition } from "@headlessui/react";
const interactionButtonsStore = [ const interactionButtonsStore = [
{ {
@ -40,24 +41,32 @@ const interactionButtonsStore = [
]; ];
type ArticleButtonProps = { type ArticleButtonProps = {
isAbstractOpen: boolean;
openAbstract: () => void;
children?: React.ReactNode; children?: React.ReactNode;
className?: string; className?: string;
emphasis?: "high" | "low"; emphasis?: "high" | "low";
} & Omit<React.ComponentPropsWithoutRef<"button">, "">; } & Omit<React.ComponentPropsWithoutRef<"button">, "">;
export function ArticleInteractionButtons({ export function ArticleInteractionButtons({
isAbstractOpen = false,
children, children,
openAbstract = () => {},
className, className,
emphasis, //to change displaying of component emphasis = "high", //to change displaying of component
...props ...props
}: ArticleButtonProps) { }: ArticleButtonProps) {
const abstractButton = ( const abstractButton = (
<Button emphasis="medium" className="text-sm leading-4 items-center px-3"> <Button
emphasis="medium"
className="text-sm leading-4 items-center px-3 mr-2 focus:outline-none active:outline-none"
onClick={openAbstract}
>
<Typography fontWeightVariant="bold" className="pr-2"> <Typography fontWeightVariant="bold" className="pr-2">
Abstract Abstract
</Typography> </Typography>
<Button.Icon> <Button.Icon>
<SVGArrowDown className="w-4 fill-blue-700 stroke-blue-700" /> {!isAbstractOpen ? <SVGArrowDown className="w-4 fill-blue-700 stroke-blue-700" /> : <SVGArrowUp className="w-4 fill-blue-700 stroke-blue-700" />}
</Button.Icon> </Button.Icon>
</Button> </Button>
); );
@ -66,7 +75,7 @@ export function ArticleInteractionButtons({
return ( return (
<Button <Button
emphasis={button.buttonEmphasis === "high" ? "high" : "low"} emphasis={button.buttonEmphasis === "high" ? "high" : "low"}
className="h-max px-2" className="h-max mx-1 px-2"
> >
<Button.Icon> <Button.Icon>
{React.cloneElement(button.icon, { className: button.iconClassName })} {React.cloneElement(button.icon, { className: button.iconClassName })}

View File

@ -1,45 +0,0 @@
import React from "react";
import { Article } from "./Article";
export function ArticleSearch() {
return (
<Article>
<div className="flex flex-row justify-between">
<Article.Breadcumbs emphasis="high">
{["Yoda", "Lallalla", "Maxim"]}
</Article.Breadcumbs>
<Article.SubscriptionsButtons />
</div>
<div className="flex flex-row">
<Article.Title className="text-3xl">Yeanda lacreav</Article.Title>
</div>
<Article.Authors emphasis="low">
{["Reavap", "aldjfoa", "dkfjaoif"]}
</Article.Authors>
<Article.Keywords emphasis="low">
{["porn", "development", "frontend"]}
</Article.Keywords>
<Article.InteractionButtons emphasis="low">
low
</Article.InteractionButtons>
<Article.Description>
{" "}
Lorem ipsum dolor sit amet consectetur adipisicing elit. Facere quidem
provident temporibus! Fuga dolores placeat at voluptatem quia, vero
molestiae animi et itaque a, officia ullam expedita temporibus cum
deserunt.Lorem ipsum dolor sit amet consectetur adipisicing elit. Facere
quidem provident temporibus! Fuga dolores placeat at voluptatem quia,
vero molestiae animi et itaque a, officia ullam expedita temporibus cum
deserunt.Lorem ipsum dolor sit amet consectetur adipisicing elit. Facere
quidem provident temporibus! Fuga dolores placeat at voluptatem quia,
vero molestiae animi et itaque a, officia ullam expedita temporibus cum
deserunt.Lorem ipsum dolor sit amet consectetur adipisicing elit. Facere
quidem provident temporibus! Fuga dolores placeat at voluptatem quia,
vero molestiae animi et itaque a, officia ullam expedita temporibus cum
deserunt.
</Article.Description>
</Article>
);
}

View File

@ -0,0 +1,64 @@
import { useState } from "react";
import { Article } from "components/Article/Article";
import { Article as ArticleTypes } from "article/domain/ArticleEntity";
import classNames from "classnames";
import { debounce } from "lodash";
import { useSearchStoreImplementation } from "searchResults/data/searchStoreImplementation";
import { useSearchViewModel } from "searchResults/controller/searchResultsViewModel";
import { Loader } from "./Loader/Loader";
type Props = {
searchItem: ArticleTypes;
};
export const ArticleSearchResult = ({ searchItem }: Props) => {
const store = useSearchStoreImplementation();
const { isLoading } = useSearchViewModel(store);
const [openAbstract, setOpenAbstract] = useState(false);
const debouncedTask = debounce((task) => Promise.resolve(task()), 200);
function open() {
debouncedTask(() => setOpenAbstract(!openAbstract));
}
return (
<Article className=" pt-6 pb-3 ">
<div className="flex flex-row justify-between">
<Article.Breadcumbs emphasis="low" className="flex flex-wrap flex-row">
{[
`${searchItem.topic}`,
`${searchItem.topic}`,
`${searchItem.topic}`,
`${searchItem.topic}`,
]}
</Article.Breadcumbs>
<Article.SubscriptionsButtons />
</div>
<Article.Title linkTo={searchItem.id} className="text-2xl">
{searchItem.title}
</Article.Title>
<Article.Authors emphasis="low" className="flex flex-wrap flex-row">
{searchItem.authors}
</Article.Authors>
<Article.Keywords emphasis="low" className="flex flex-wrap flex-row py-2">
{searchItem.tags}
</Article.Keywords>
<Article.InteractionButtons
className="py-2 "
emphasis="low"
openAbstract={open}
isAbstractOpen={openAbstract}
/>
<Article.Description
emphasis="low"
isShowing={openAbstract}
className={classNames("my-2")}
>
{searchItem.summary}
</Article.Description>
</Article>
);
};

View File

@ -2,24 +2,25 @@
/* Imports */ /* Imports */
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
import React from "react"; import React from "react";
import {SearchBar} from "../../search/SearchBar"; import { SearchBar } from "../../search/SearchBar";
export default function MainSection() { export default function MainSection() {
return ( return (
<section className="bg-main bg-center bg-cover bg-origin-border bg-no-repeat min-h-[100vh] py-32 px-2 sm:px-6 md:px-6 lg:px-0 items-center"> <section className="bg-main bg-center bg-cover bg-origin-border bg-no-repeat min-h-[100vh] py-32 px-2 sm:px-6 md:px-6 lg:px-0 items-center flex justify-center ">
<div className="m-auto text-center font-bold text-4xl "> <div className="flex-col">
Scientific Library with Free Access <div className="m-auto text-center font-bold text-4xl ">
</div> Scientific Library with Free Access
<div className="flex flex-row items-center justify-center space-x-3 pt-2"> </div>
<div className=" text-2xl text-gray-400">Search</div> <div className="flex flex-row items-center justify-center space-x-3 pt-2">
<div className=" text-3xl text-blue-500">320 455</div> <div className=" text-2xl text-gray-400">Search</div>
<div className=" text-2xl text-gray-400">Items</div> <div className=" text-3xl text-blue-500">320 455</div>
</div> <div className=" text-2xl text-gray-400">Items</div>
<div className="max-w-xl m-auto pt-16 "> </div>
<SearchBar /> <div className="max-w-xl m-auto pt-16 ">
<div className="mt-7 pr-1 text-right font-semibold text-sm"> <SearchBar />
Advanced Search <div className="mt-7 pr-1 text-right font-semibold text-sm">
Advanced Search
</div>
</div> </div>
</div> </div>
</section> </section>

View File

@ -0,0 +1,44 @@
import React, { useState } from "react";
import Typography from "./typography/Typography";
import { useSearchStoreImplementation } from "searchResults/data/searchStoreImplementation";
import { useSearchViewModel } from "../searchResults/controller/searchResultsViewModel";
import { ArticleSearchResult } from "./ArticleSearchResult";
import { Loader } from "./Loader/Loader";
export const SearchResultSection = () => {
const store = useSearchStoreImplementation();
const { searchResults, isLoading } = useSearchViewModel(store);
function getResults() {
if (searchResults === undefined || searchResults?.data.length === 0) {
return (
<Typography
fontWeightVariant="semibold"
className="text-xl w-full text-center items-center py-3"
>
Nothing found.
</Typography>
);
} else {
const results = searchResults.data.map((searchItem) => (
<ArticleSearchResult searchItem={searchItem} />
));
return results;
}
}
return (
<div className="p-4 md:px-6 md:py-8">
<div className="pb-2">
<Typography fontWeightVariant="semibold" className="text-3xl">
Search Results
</Typography>
<Typography className="text-gray-300 text-sm">
Total results: {searchResults?.meta.total}
</Typography>
</div>
<hr className="w-full border-gray-100" />
<div className="divide divide-y divide-gray-100">{ getResults()}</div>
</div>
);
};

View File

@ -0,0 +1,17 @@
import React from "react";
import { SearchBar } from "./search/SearchBar";
export const SearchSection = ()=>{
return (
<section className="bg-main bg-center bg-cover bg-origin-border bg-no-repeat py-10 px-2 sm:px-6 md:px-6 lg:px-0 items-center flex justify-center ">
<div className="flex-col w-full md:w-3/5 lg:w-2/5">
<div className="w-full m-auto pt-16 ">
<SearchBar />
<div className="mt-4 pr-1 text-right font-semibold text-sm">
Advanced Search
</div>
</div>
</div>
</section>
)
}

View File

@ -35,7 +35,7 @@ export default function Breadcrumbs( { divider ,children, className }: Props ) {
for( let i = 0; i < childrenToArray.length; i++ ) { for( let i = 0; i < childrenToArray.length; i++ ) {
let dividerComponent = GetDivider( divider ) let dividerComponent = GetDivider( divider )
LinkAndDivider = LinkAndDivider.concat( childrenToArray[i] ).concat( dividerComponent ) LinkAndDivider = LinkAndDivider.concat( <div>{childrenToArray[i]}</div> ).concat( dividerComponent )
} }
LinkAndDivider.pop(); LinkAndDivider.pop();

View File

@ -1,6 +1,7 @@
.left-bar { .left-bar {
grid-area: lb; grid-area: lb;
max-width: 300px; max-width: 300px;
overflow: hidden;
} }
.main-bar { .main-bar {

View File

@ -1,20 +1,11 @@
import React, { import React, {
Fragment,
useState, useState,
useRef, useRef,
useEffect, useEffect,
FC,
isValidElement,
} from "react"; } from "react";
import { Dialog, Transition } from "@headlessui/react";
import { BottomSheetModal } from "components/containers/modal/BottomSheetModal";
import { BottomBarAcceptCookies } from "components/containers/modal/BottomBarAcceptCookies";
import { Button } from "components/Button/Button";
import classNames from "classnames";
import "./ColumnLayout.css"; import "./ColumnLayout.css";
import { Children } from "react";
import MainColumn from "./Maincolumn"; import MainColumn from "./Maincolumn";
import LeftColumn from "./LeftColumn"; import LeftColumn, {LeftColumnProps} from "./LeftColumn";
import RightColumn from "./RightColumn"; import RightColumn from "./RightColumn";
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
/* Custom hook to track container width */ /* Custom hook to track container width */
@ -100,10 +91,9 @@ export const ColumnLayout: React.FC<ColumnLayoutProps> & ColumnExtentions = ({
React.isValidElement(child) && React.isValidElement(child) &&
React.Children.only(child).type === LeftColumn React.Children.only(child).type === LeftColumn
) { ) {
return React.cloneElement(child, { return React.cloneElement(child as React.ReactElement<LeftColumnProps>,
openLeftBar: openLeftBar, { openLeftBar: openLeftBar, widthElement: widthElement },
widthElement: widthElement, );
});
} else { } else {
return child; return child;
} }

View File

@ -2,7 +2,7 @@ import React, { Fragment, FunctionComponent as FC } from "react";
import { Transition } from "@headlessui/react"; import { Transition } from "@headlessui/react";
import classNames from "classnames"; import classNames from "classnames";
type LeftColumnProps = { export type LeftColumnProps = {
children: React.ReactNode; children: React.ReactNode;
openLeftBar?: boolean; openLeftBar?: boolean;
widthElement?: number; widthElement?: number;

View File

@ -3,8 +3,6 @@ import Inputgroup from "./Inputgroup";
import SearchInput from "./SearchInput"; import SearchInput from "./SearchInput";
import { Button } from "components/Button/Button"; import { Button } from "components/Button/Button";
import { SVGSearch } from "components/icons"; import { SVGSearch } from "components/icons";
import { useSearchStoreImplementation } from "searchResults/data/searchStoreImplementation";
import { useSearchViewModel } from "searchResults/controller/searchResultsViewModel";
import Link from "components/typography/Link"; import Link from "components/typography/Link";
@ -25,7 +23,7 @@ export function SearchBar({ className }: Props) {
return ( return (
//TOdO Need to add dropdown with categories //TOdO Need to add dropdown with categories
<Inputgroup className="m-0 p-0 bg-white"> <Inputgroup className="m-0 p-0 bg-white">
<div className="flex items-center w-full divide-x-2 divide-solid divide-gray-200"> <div className="flex items-center w-full divide-x-2 divide-solid divide-gray-200 mr-2">
{/* <div className="flex w-1/3"> {/* <div className="flex w-1/3">
</div> */} </div> */}
<div className="w-full"> <div className="w-full">

View File

@ -52,7 +52,13 @@ const inputList = `
overflow-hidden overflow-hidden
focus:outline-none focus:outline-none
text-base text-base
sm:text-sm`; sm:text-sm
overflow-y-scroll
shadow-md
scrollbar-thin
scrollbar-thumb-gray-500
scrollbar-track-inherit
scrollbar-thumb-rounded`;
const inputInGroup = [ const inputInGroup = [
`border-none `border-none
@ -78,28 +84,16 @@ export default function SearchInput<T>({
}: Props<T>) { }: Props<T>) {
const store = useSearchStoreImplementation(); const store = useSearchStoreImplementation();
const { const {
search, changeInputValue,
changeSearchRequest, currentSearchState,
searchRequest, inputValue,
searchResults, searchResults,
isLoading, isLoading,
isFailed, isFailed,
} = useSearchViewModel(store); } = useSearchViewModel(store);
const [inputValue, setInputValue] = useState("");
const changeInputValue = (value: string) => {
setInputValue(value);
changeSearchRequest(value);
};
useEffect(() => {
if (searchRequest !== "") {
search();
}
}, [searchRequest, changeSearchRequest]);
return ( return (
<div> <div>
<Combobox value={inputValue} onChange={setInputValue}> <Combobox value={inputValue} onChange={changeInputValue}>
<div className="relative"> <div className="relative">
<div className="relative w-full bg-white text-left focus:outline-none sm:text-sm"> <div className="relative w-full bg-white text-left focus:outline-none sm:text-sm">
<Combobox.Input <Combobox.Input
@ -115,52 +109,51 @@ export default function SearchInput<T>({
/> />
</div> </div>
{searchRequest !== "" && !isFailed && !isLoading && ( {currentSearchState !== "" && !isFailed && !isLoading && (
<Transition
<Transition as="div"
as="div" className={`${inputList}`}
className={`${inputList}`} leave="transition ease-in duration-100"
leave="transition ease-in duration-100" leaveFrom="opacity-100"
leaveFrom="opacity-100" leaveTo="opacity-0"
leaveTo="opacity-0" >
> <Combobox.Options>
<Combobox.Options> {searchResults === undefined ||
{searchResults === undefined || (searchResults.data.length === 0 &&
(searchResults.data.length === 0 && searchRequest !== "") ? ( currentSearchState !== "") ? (
<div>Nothing found</div> <div>Nothing found</div>
) : null} ) : null}
{searchResults !== undefined && {searchResults !== undefined &&
searchResults.data.map((result) => ( searchResults.data.map((result) => (
<Combobox.Option <Combobox.Option
key={result.id} key={result.id}
className={({ active, selected }) => className={({ active, selected }) =>
classNames( classNames(
active active ? "text-gray-900 bg-blue-50" : "font-normal ",
? "text-gray-900 bg-blue-50" "cursor-default select-none relative py-2 pl-3 pr-9",
: "font-normal ", selected
"cursor-default select-none relative py-2 pl-3 pr-9", ? "text-gray-900 bg-blue-100"
selected : "font-normal "
? "text-gray-900 bg-blue-100" )
: "font-normal " }
) value={result.title}
onClick={() => {
if (result.title != undefined) {
changeInputValue(result.title);
} }
value={result.title} }}
onClick={() => { >
if (result.title != undefined) { <div>{result.title}</div>
changeInputValue(result.title); </Combobox.Option>
} ))}
}} </Combobox.Options>
> </Transition>
<div>{result.title}</div>
</Combobox.Option>
))}
</Combobox.Options>
</Transition>
)} )}
{isLoading && ( {isLoading && (
<div className={classNames(`${inputList}`, "mt-3")}> <div className={classNames(`${inputList}`, "mt-3")}>
<div className="w-full flex text-center py-2 items-center justify-center"> <div className="w-full flex text-center py-2 items-center justify-center">
<Loader className="w-5 h-5"/></div> <Loader className="w-5 h-5" />
</div>
</div> </div>
)} )}
</div> </div>

View File

@ -35,7 +35,7 @@ root.render(
<Route path="/account"> <Route path="/account">
<Route path="settings" element={<AccountSettings />} /> <Route path="settings" element={<AccountSettings />} />
</Route> </Route>
<Route path="/search-resilts" element={<SearchResultsPage />}></Route> <Route path="/search-results" element={<SearchResultsPage />}></Route>
</Routes> </Routes>
</BrowserRouter> </BrowserRouter>
</React.StrictMode> </React.StrictMode>

View File

@ -1,5 +1,27 @@
import React from "react"; import React from "react";
import BaseLayout from "components/BaseLayout";
import { SearchSection } from "components/SearchSection";
import { ColumnLayout } from "components/layouts/ThreeColumn/ColumnLayout";
import { SearchResultSection } from "components/SearchResultsSection";
import { useSearchStoreImplementation } from "searchResults/data/searchStoreImplementation";
import { useSearchViewModel } from "searchResults/controller/searchResultsViewModel";
import { Loader } from "components/Loader/Loader";
export const SearchResultsPage = () =>{ export const SearchResultsPage = () => {
return <div>Search results page</div> return (
} <BaseLayout>
<SearchSection />
<ColumnLayout>
<ColumnLayout.Left>
<div className="h-98 bg-blue-200 w-[300px]">left bar</div>
</ColumnLayout.Left>
<ColumnLayout.Main>
<SearchResultSection />
</ColumnLayout.Main>
<ColumnLayout.Right>
<div className="h-98 bg-blue-200 w-[300px]">right bar</div>
</ColumnLayout.Right>
</ColumnLayout>
</BaseLayout>
);
};

View File

@ -1,10 +1,10 @@
import React from "react"; import {useState, useEffect, useCallback} from "react";
import { SearchResultsStore } from "searchResults/domain/searchStore"; import { SearchResultsStore } from "searchResults/domain/searchStore";
import { changeSearchRequestUseCase } from "searchResults/useCases/changeSearchRequestUseCase"; import { changeSearchRequestUseCase } from "searchResults/useCases/changeSearchRequestUseCase";
import { searchUseCase } from "searchResults/useCases/searchUseCase"; import { searchUseCase } from "searchResults/useCases/searchUseCase";
function useSearchViewModel(store: SearchResultsStore) { function useSearchViewModel(store: SearchResultsStore) {
const search = React.useCallback( const search = useCallback(
function () { function () {
return searchUseCase({ return searchUseCase({
searchResults: store.searchResults, searchResults: store.searchResults,
@ -15,7 +15,7 @@ function useSearchViewModel(store: SearchResultsStore) {
[store.searchRequest, store.search, store.searchResults] [store.searchRequest, store.search, store.searchResults]
); );
const changeSearchRequest = React.useCallback( const changeSearchRequest = useCallback(
function (searchRequest: string) { function (searchRequest: string) {
return changeSearchRequestUseCase({ return changeSearchRequestUseCase({
searchRequest: searchRequest, searchRequest: searchRequest,
@ -24,15 +24,28 @@ function useSearchViewModel(store: SearchResultsStore) {
}, },
[store.searchRequest, store.changeSearchRequest] [store.searchRequest, store.changeSearchRequest]
); );
const [inputValue, setInputValue] = useState(store.searchRequest);
const changeInputValue = (value: string) => {
setInputValue(value);
changeSearchRequest(value);
};
useEffect(() => {
if (store.searchRequest !== "") {
search();
}
}, [store.searchRequest]);
return { return {
searchResults: store.searchResults, searchResults: store.searchResults,
searchRequest: store.searchRequest, currentSearchState: store.searchRequest,
failure: store.failure, failure: store.failure,
isLoading: store.isLoading, isLoading: store.isLoading,
isFailed: store.isFailed, isFailed: store.isFailed,
search, search,
changeSearchRequest, changeInputValue,
inputValue,
}; };
} }
export { useSearchViewModel }; export { useSearchViewModel };

View File

@ -1,13 +1,18 @@
export type SearchResultsDTO = { export type SearchResultsDTO = {
data: ArticleDTO[]; data: ArticleDTO[];
meta: SearchResultsMeta;
}; };
export type ArticleDTO = { export type ArticleDTO = {
id?: string; id?: string;
title?: string; title?: string;
authors?: string[]; authors?: string[];
topic?: string; topic?: string[];
summary?: string; summary?: string;
tags?: string[]; tags?: string[];
content?: string; content?: string;
}; };
export type SearchResultsMeta = {
total: string;
}

View File

@ -10,11 +10,11 @@ const searchEndpoint = "/papers/search";
async function search(request: string): Promise<SearchResults> { async function search(request: string): Promise<SearchResults> {
try { try {
const response = await integratorApiClient.get<SearchResultsDTO>( const response = await integratorApiClient.get<SearchResultsDTO>(
// searchEndpoint + `?query=` + request + `&page=1` // searchEndpoint + `?query=` + request + `&limit=10&offset=0`
"https://run.mocky.io/v3/89c8421d-86b1-4af7-850e-b71def846cfe" "https://run.mocky.io/v3/ea705665-2479-4039-8b81-412e011fc145"
); );
const dto = response.data; const dto = response.data;
return create({ data: dto.data }); return create({ data: dto.data, meta: dto.meta });
} catch (reason) { } catch (reason) {
if (axios.isAxiosError(reason)) { if (axios.isAxiosError(reason)) {
throw Failure.fromReason(reason, "failures.services.load"); throw Failure.fromReason(reason, "failures.services.load");

View File

@ -8,7 +8,7 @@ const searchSelector = (state: RootState): SearchStoreState =>
state.searchResults; state.searchResults;
const useSearchStoreImplementation = (): SearchResultsStore => { const useSearchStoreImplementation = (): SearchResultsStore => {
const { searchResults, failure, isFailed, isLoading, searchRequest } = const { searchResults, failure, isFailed, isLoading, searchRequest} =
useAppSelector(searchSelector); useAppSelector(searchSelector);
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();

View File

@ -2,4 +2,9 @@ import { Article } from "article/domain/ArticleEntity";
export interface SearchResults { export interface SearchResults {
data: Article[]; data: Article[];
meta:SearchResultsMeta ;
}
export interface SearchResultsMeta {
total: string;
} }

View File

@ -2,10 +2,12 @@ import { SearchResults } from "./searchResultsEntity";
export type CreateSearchResultParams = { export type CreateSearchResultParams = {
data: SearchResults["data"]; data: SearchResults["data"];
meta: SearchResults["meta"]
}; };
const create = (params: CreateSearchResultParams) => ({ const create = (params: CreateSearchResultParams) => ({
data: params.data, data: params.data,
meta: params.meta
}); });
export { create }; export { create };

View File

@ -1,92 +0,0 @@
import classNames from "classnames";
import React, { useState, useEffect } from "react";
import { useSearchViewModel } from "searchResults/controller/searchResultsViewModel";
import { useSearchStoreImplementation } from "searchResults/data/searchStoreImplementation";
const searchDropDownStyle = `
absolute
top-12 left-0
right-0
bg-white
w-full
max-h-[200px]
overflow-y-scroll
shadow-md
scrollbar-thin
scrollbar-thumb-gray-500
scrollbar-track-inherit
scrollbar-thumb-rounded
`
type Props = {
className?: string;
};
export const SearchView = ({ className }: Props) => {
const [value, setValue] = useState('');
const store = useSearchStoreImplementation();
const {
search,
changeSearchRequest,
searchRequest,
searchResults,
isLoading,
isFailed,
} = useSearchViewModel(store);
const changeInputValue = (value: string) => {
setValue(value);
changeSearchRequest(value)
}
useEffect(() => {
if (searchRequest !== "") {
search();
}
}, [searchRequest, changeSearchRequest]);
return (
<div className={classNames("relative", className)}>
<input
type="text"
className="w-full m-0 p-2 focus:outline-none"
placeholder="Search..."
onChange={e => changeInputValue(e.target.value)}
value={value}
/>
<div
className={classNames(
searchDropDownStyle,
{ "py-2": searchRequest != "" }
)}
>
<ul className="list-none w-full">
{isLoading && <p className="text-center">Is loading...</p>}
{isFailed && searchRequest != "" && (
<p className="text-center">
Sorry... Something went wrong from our side
</p>
)}
{!isLoading &&
!isFailed &&
searchResults != undefined &&
searchRequest != "" &&
searchResults.data.map((result) => (
<li
className="py-1.5 px-3 hover:bg-blue-100 transition-colors cursor-pointer"
onClick={() => {
if (result.title != undefined) {
changeInputValue(result.title)
}
}}
>
{result.title}
</li>
))}
</ul>
</div>
</div>
);
};