291 Commits

Author SHA1 Message Date
Yubraj
2844c5ad5e added something in the readme for the better understanding 2024-11-09 17:06:27 +00:00
richk21
40024c5945 Update README.md
Added - And the Mountains Echoed by Khaled Hosseini
2024-10-02 22:21:25 +01:00
Vishnu Ks
4a44d35985 Delete .github/workflows/updatejson.yml 2024-10-02 22:18:37 +01:00
coool9
dd9807a929 Remove credits and license from books category
And give them their own heading
2024-06-26 23:33:20 +01:00
La5u
11822842f0 Spelling and grammar in CONTRIBUTING.md 2024-06-19 20:13:42 +01:00
yashviradia
dafefcf6b3 added 'Limitless', 'Brain Food' and 'Super Human' in README 2023-10-10 23:17:27 +01:00
Love sonkar
07f1f66360 fixes goodread button link not opening in new tab 2023-09-30 20:45:53 -07:00
Darshit Domadiya
56ef6eecd0 corrected 'Ryan Holding' to 'Ryan Holiday'
edited README.md file.
=> corrected 'Ryan Holding' to 'Ryan Holiday'.
2023-09-22 10:34:59 +01:00
XanderRubio
650d9ba116 Adding book into the Autobiography and biographies section 2023-09-02 16:33:40 +01:00
Vishnu Ks
af2c3309fc Update CONTRIBUTING.md 2023-08-28 19:44:14 +01:00
Unknown
5a1a11d461 Added The Age of Em 2023-08-28 18:42:41 +01:00
Martin Suja
240aa60cbe Add books by Jorgenson and Snyder 2023-08-28 18:41:14 +01:00
Kushantha Charuka
35e0e76220 Added new design book 2023-08-28 18:39:37 +01:00
Abhishek Srivastav
962d13ba02 Added "The Magic of Thinking Big" book 2023-08-28 18:36:34 +01:00
Mari
897e916f62 add book: Of Fire and Stars 2023-08-28 18:36:17 +01:00
Daniel Teske
76b4feef0d ignore .DS_Store files 2023-08-28 18:35:50 +01:00
Daniel Teske
cb0f09f359 .DS_Store file dropped 2023-08-28 18:35:50 +01:00
Muhammad Saeed
bf88bcfaeb Add "The Millionaire Fastlane" to Startups and Business 2023-08-28 18:34:55 +01:00
Vytautas Kasparavičius
7a7505ac5e Added Roadside Picnic by Strugatsky brothers 2023-08-28 18:34:26 +01:00
AmOL-PiNGALE
a30a93569c feat: Add Crucial Conversations book 2023-08-28 18:30:55 +01:00
Aditya Muzumdar
41b4e47494 Added Man without Fear by Rajat Gupta
Life of this man is an outright expression of leadership, success and Indian ethos. A must read for all budding professionals.
2023-08-28 18:30:21 +01:00
Soumik8114
a18f7a23cf Added "The Way of the Monk" 2023-08-28 18:28:32 +01:00
Taylor
a5ecb7dab3 Added a book to the horror category in READ.ME 2023-08-28 18:26:56 +01:00
YorLecaros
32deebdcf6 Added a new book, Angels & Demons by Dan Brown 2023-08-28 18:26:43 +01:00
Hanee-Solanki
73efa4443c modified bookcard.js 2023-08-28 18:25:02 +01:00
jessb
9a55f9ab1e Added Project Hail Mary to Science Fiction 2023-08-28 18:24:51 +01:00
Mason Firman
357e72a887 Added "Breath: The New Science of a Lost Art" to Health 2023-08-28 18:24:42 +01:00
renjithjoseph87
d29ce7d24c Added Contact to the list of science fiction books 2023-08-28 18:24:24 +01:00
Evan C
76858735ed Fixed Soul of a New Machine Formatting
Fixed the formatting for Soul of a New Machine to match the sorting by rating.
2023-08-28 18:23:01 +01:00
Evan C
90959ff6c4 Added The Soul of a New Machine
Added The Soul of a New Machine to the history section.
2023-08-28 18:23:01 +01:00
Snimerjot Singh
0c4450a4a5 Update README.md 2023-08-28 18:22:02 +01:00
Snimerjot Singh
436a3e149a Update README.md 2023-08-28 18:20:48 +01:00
Charlie Sabino
046d0330be Added The Stormlight Archive
One of the most loved series in the fantasy community
2023-08-28 18:17:39 +01:00
Misha Klopukh
66737e2aab Add Thinking Forth 2023-08-28 18:17:10 +01:00
Vishnu Ks
42a1065c48 Update CONTRIBUTING.md 2023-08-28 18:14:17 +01:00
Vishnu Ks
483e534fcd Update README.md 2023-08-28 18:02:26 +01:00
Vishnu Ks
98f39c0ecf Update README.md 2023-08-28 18:01:23 +01:00
Vishnu Ks
402c8ce7ed Update README.md 2023-08-28 17:45:40 +01:00
Vitalii Voloshyn
febd71338f The Unix Haters Handbook 2023-08-28 12:02:47 +01:00
Varad Rane
bc5075dc80 Added Back to top buttons 2023-08-28 12:01:20 +01:00
Varad Rane
9eb334bf85 Update README.md 2023-08-28 12:01:20 +01:00
Vishnu Ks
8d02dbfd60 Remove website link 2023-03-05 19:11:57 +00:00
Rauros
e2d431d67d Creativity Inc book added
The book is a journey that tries to portray a healthy, creative and effective business culture. Based on real examples from companies like Pixar or Apple. A delight to put into practice in any company, large, small or teams.
2023-03-05 19:11:05 +00:00
Hélio Correia
6c42389d72 Add 'Principles: Life and Work' by 'Ray Dalio' 2022-08-07 20:10:50 +01:00
fk00750
a7f12ac7e5 this commit fixes Small typo #419 2022-08-07 20:09:23 +01:00
Nathan-Abegaz
52747a1b76 Added Prodigy to Science Fiction 2022-01-19 17:37:32 +00:00
Hiyab-Abegaz
90f9bc88f5 Update README.md 2022-01-19 17:36:50 +00:00
Chris Szczechowicz
0566905e42 Add Grain Brain health book 2022-01-19 17:35:58 +00:00
Miguel Sozinho Ramalho
13bbce624f fixing bad markdown in link 2022-01-19 17:35:14 +00:00
loyeleye
a9a7440ed3 Update README.md
Added "The Giver" to Fiction - Classics
2022-01-19 17:34:52 +00:00
loyeleye
3a41378d29 Update CONTRIBUTING.md
Small typo fix :)
2022-01-19 17:34:12 +00:00
tiago-nogueira
751a16ca3e Update README.md 2021-08-08 10:59:58 +05:30
Vishnu KS
ab70c2764b Use promise in gatsby-node. 2021-06-07 00:10:21 +05:30
Shweta Ranjan Anand
5ddeafb2fb Update for book cover of "The Discoverers"
Fix: #371
2021-06-04 12:52:14 +05:30
TLZ
53e2941d4a Add The Uninhabitable Earth by David Wallace-Wells 2021-03-19 01:16:24 +05:30
Jeremy Gautama
fe916127e2 Startups and Business update
Updated ratings
2021-02-25 22:31:32 +05:30
Derek OKeeffe
bef88206ae Fix goodreads link for Educated
Removed a stray comma
2020-12-24 11:51:37 +05:30
Vishnu KS
d898b99562 Check if Google Books API key is present. 2020-11-30 00:15:17 +05:30
PhilipWright96
e86b26a72e Make book reviews up to date (#321)
* Fix import typo

* Fix import typo

* Add yml file to schedule github action

* Undo import changes

* Formatting

* Fix imports

* Imports

* Add file extension

* Kick on branch

* Try using py

* Attempt adding semicolons

* Temporarily remove python call

* Remove space

* Leave only one line in

* Refactor syntax

* Update yml syntax

* Test

* Test

* Test

* Test

* Add import

* Add bs4 module

* Refactor yml

* Add missing quotation marks

* Cat newly created file for testing purposes

* Sort indents

* Properly sort indents

* Add extra import

* Update import

* Update JSON files

* Use secrets for API keys

* Update json

* Update JSON files

* Reorganize workflow

* Move into right directory

* Fix order

* Update JSON files

* Attempt to change account which makes commits

* Kick job

* Update JSON files

* Attempt commit with new bot email

* Kick

* Attempt new kick

* Update JSON files

* Attempt removing email

* Change for kick

* Update JSON files

* Re-add email

* Update JSON files

* Check pwd of github VM

* Update JSON files

* Attempt copying updating books.json to app data

* Update JSON files

* Remove the onpush setting

* Update install method

* Replace touch with just echo call

* Update JSON files

* Remove cat

* Rename email

* Stage individual files instead of all

* Update JSON files

Co-authored-by: Philip Wright <wrightphilip4@gmail.com.github.com>
Co-authored-by: Mind Expanding Books Bot <mindexpandingbooks@gmail.com.github.com>
Co-authored-by: mindexpandingbooksbot <runner@fv-az70-910.gpy01byny0buvbolry2rpgzvkd.bx.internal.cloudapp.net>
Co-authored-by: mindexpandingbooksbot <mindexpandingbooksbot@users.noreply.github.com>
2020-11-30 00:06:31 +05:30
Saurontm
48b16e1c8d added Slaughterhouse-Five by Kurt Vonnegut (#360) 2020-11-05 11:36:11 +05:30
Saurontm
ba8bd2f045 Update README.md
fixed book position
2020-11-05 11:34:44 +05:30
Sarah Almahmid
569741d47c added Factfullness 2020-11-05 11:34:44 +05:30
seemaj201274
923ef1ee9d Update README.md 2020-11-02 22:17:33 +05:30
seemaj201274
7a162b1f04 Update README.md 2020-10-31 11:06:37 +05:30
seemaj201274
a81ac25651 Update README.md 2020-10-31 11:06:37 +05:30
Sergio Baldo Junior
33efad1281 Added a new book Blindness - José Saramago 2020-10-31 11:05:31 +05:30
Sergio Baldo Junior
52918bae4d Book Blindness - Jose Saramado (Original Title - Ensaio sobre a cegueira) 2020-10-31 11:05:31 +05:30
Terrence Keane
a989ca1b6a add The Body 2020-10-31 11:04:35 +05:30
Jenni Macklin
e6382aa88a add the middle finger project 2020-10-31 11:02:16 +05:30
someshium
3890f96456 Added a new Book ' Karma Yoga' by Swami Vivekanand
sometimes a thought comes in mind to give up everything, there is so much attachment and suffering in this world. so should one leave everything a become a Sadhu? one should not move away from his responsibilities and one doesn't have to become the sadhu to get the peace. one can find peace in most noisy place in universe and in utmost silence. the book is somewhat different from normal self- help books.  it tells to not be attached to the work  which you are doing. 
it nicely explains the concept of religion and karma, work, why one needs to do the karma.
I feel this is the best book i have ever read.
2020-10-31 01:48:59 +05:30
seemaj20
add51b7e82 Added book to nature section. (#343)
* Update README.md

* Update README.md
2020-10-31 01:47:36 +05:30
Rehman Arshad
cc0515d66c added gatsby-plugin-manager which fixed the errors 2020-10-31 01:15:14 +05:30
Rehman Arshad
1632af7b67 added a dark mode class in global.css, and Fixed a ton of security vulnerabilities!!! 2020-10-31 01:15:14 +05:30
Jr Miranda
b405c7a806 Added the book The Disappearing Spoon 2020-10-31 01:12:26 +05:30
Kwame Violet Taylor
26656bafa9 Add Thus Spoke Zarathustra
This is one of my favorite books in general, and definitely my favorite philosophy book. I've read and re-read this book at pivotal moments in my life. Nietzsche is one of the first to spread the philosophy of "God is dead!" that now resembles Satanic beliefs, and is still a widely read book amongst Nihilists of all flavors. This book is not merely a critique on Christianity and organized religion; it is a manifesto of free will that people still read to this day. I highly recommend it as a mind-expanding book.
2020-10-31 01:04:13 +05:30
Cooper Hollmaier
9c966cc21e Added footer styles via footer-text 2020-10-29 12:48:44 +05:30
snehaj27
a39e38c580 Update README.md 2020-10-29 12:43:37 +05:30
Lucas Alves
2d71afbf5e Include everything beautiful by Jenna Bush Hager 2020-10-28 23:15:54 +05:30
seemaj20
6c43a5f56d Update README.md 2020-10-28 23:14:40 +05:30
Darko Bozhinovski
8c80de361c Fixes data entries for said books 2020-10-28 23:06:10 +05:30
Darko Bozhinovski
a893ef1171 Adds art as a category; Adds three book to art category; 2020-10-28 23:06:10 +05:30
Natalia Banasiewicz
b125c6e705 Fix typo in link to Goodreads 2020-10-28 23:03:40 +05:30
Natalia Banasiewicz
7fc9dca26e Added "Outnumbered" in Logic and Problem solving 2020-10-28 23:03:40 +05:30
Sebastian Sotavalta
de3b3db21e Added Data visualization handbook 2020-10-28 23:01:47 +05:30
Keerat Singh
9e415f4c73 fixed link formatting for "The Innovators" by Walter Isaacson 2020-10-28 13:56:17 +05:30
Keerat Singh
0e9f96be27 added "The Innovators" by Walter Isaacson 2020-10-28 13:56:17 +05:30
Shubham Ghimire
73058d651f Update README.md 2020-10-28 13:55:39 +05:30
Shubham Ghimire
fb0cba56bb Update README.md 2020-10-28 13:55:39 +05:30
Shubham Ghimire
5214f0cbba Update README.md 2020-10-28 13:55:39 +05:30
Dami
9d944378c8 Update CONTRIBUTING.md 2020-10-28 13:52:43 +05:30
tiagowutzke
7af707a571 adding data driven 2020-10-27 18:37:22 +05:30
Shubham Ghimire
9a821212bd Update README.md 2020-10-27 14:31:29 +05:30
Shubham Ghimire
f78852620c Update README.md 2020-10-27 14:31:29 +05:30
Kate Morf
e0c1230289 Add "AI Superpowers: China, Silicon Valley, and the New World Order" to Startups and Business 2020-10-27 13:38:09 +05:30
Yunus Kiper
283ddf3ced fix the name of Profiles of the Future 2020-10-27 00:54:15 +05:30
Yunus Kiper
bf4fda7318 Added Profiles of the Future by Arthur C. Clarke 2020-10-27 00:54:15 +05:30
amitesh03
2ac25fdbfb Added Autobiography of a Yogi 2020-10-26 22:57:04 +05:30
Celine
f8fe3e8953 Added 'Waters of the World' by Sarah Dry (#315) 2020-10-26 15:29:55 +05:30
Jenna Koslowski
10aa58a3ed edit for mobile and small screen readability 2020-10-26 12:34:19 +05:30
lapohjan
faa40a2130 about one mans journey to enlightenment but also about life itself 2020-10-25 23:08:01 +05:30
Saqib Ameen
3e9c89c4bc Update the order 2020-10-25 22:52:43 +05:30
Saqib Ameen
7a9b648e58 Add The Kite Runner by Khaled Hosseini 2020-10-25 22:52:43 +05:30
Sammy D
fee2000ed2 Added Brave New World by Aldous Huxley 2020-10-25 12:54:43 +05:30
a-thread
3e1fd761e8 removing extra parameters from book urls 2020-10-25 12:46:43 +05:30
a-thread
a284140772 adding cemetary boys, becoming a man, and paul takes the form of a mortal girl 2020-10-25 12:46:43 +05:30
yash016
4b192c8108 Added a book in Startup and Business section (#317)
* Added a new book in Startups and Business section

* Added a new book in Startups and Business section

Co-authored-by: Vishnu Ks <yo@vishnuks.com>
2020-10-25 12:46:00 +05:30
ariesthio
2bea8f1e1d Update books description 2020-10-25 12:43:36 +05:30
ariesthio
3c998f94fc Add google book api 2020-10-25 12:43:36 +05:30
Jonathan Martin
48ea125eba added a book under Science and Medicine
The Gene: An Intimate History by Siddhartha Mukherjee. 4.35 on Goodreads! A brilliant book that takes fascinating historical, social and scientific perspectives on genetics. Mukherjee discusses his own journey dealing with his family's genetics for Schizophrenia alongside the science he presents. This book is nothing if not mind expanding.
2020-10-25 12:31:14 +05:30
Jenna Schultz
9816ab055c Adding 2 new books (#311)
* Adding a book under Mystery

* Added a book under Science Fiction

Co-authored-by: Vishnu Ks <yo@vishnuks.com>
2020-10-25 12:30:14 +05:30
Troels Agergaard
55387bc554 Add space between nav-button and nav-item 2020-10-25 12:25:50 +05:30
Troels Agergaard
6648b56181 Add noreferrer to external link 2020-10-25 12:25:50 +05:30
Pravitha P
a3fa4726d7 updated year of publication
some of the year ofpublications were not in the table. that has been updated
2020-10-25 12:25:00 +05:30
YashAmin-01
5d5d90a20a added new book in mystery 2020-10-23 00:07:43 +05:30
YashAmin-01
700bfb7c9f Update README.md 2020-10-23 00:07:43 +05:30
YashAmin-01
275b1bcc97 added new science fiction book 2020-10-23 00:07:43 +05:30
Troels Agergaard
c13a65aeb2 Add alt attribute to Card.Img component 2020-10-23 00:07:15 +05:30
PrivateHank2
ee180c8068 Update README.md 2020-10-23 00:05:30 +05:30
Bhupendrapt5
0deea97ec6 updated Publish year of Classic fiction 2020-10-21 23:46:10 +05:30
YashAmin-01
cf43ea3086 Update README.md 2020-10-21 23:45:08 +05:30
YashAmin-01
5dcc780fc8 added new science fiction book 2020-10-21 23:45:08 +05:30
Sanket
0793edee1d Business book addition 2020-10-21 23:44:06 +05:30
Jackson Isaac
075a221392 Generalize nophoto url, update setting openlibrary URL 2020-10-21 23:42:02 +05:30
Jackson Isaac
4ec82e5448 Use openlibrary api when goodreads returns nophoto 2020-10-21 23:42:02 +05:30
Vagif
40eafd8623 Update README.md 2020-10-21 21:53:15 +05:30
Vagif
8615477f0c addded Deep work by Cal Newport to Education 2020-10-21 21:53:15 +05:30
snehaj27
4a8b11a5cc Update README.md 2020-10-21 21:52:38 +05:30
snehaj27
5117828a9d Update README.md 2020-10-21 21:52:38 +05:30
Samisha
e74a6e1ec0 fixed the text clashing pf reading list and filter 2020-10-20 23:03:14 +05:30
ana-vela
c9b56c3a4f Adding Bird by Bird 2020-10-20 23:00:43 +05:30
Bhupendrapt5
5c56e8540f Added One Day In Life Of Ivan denisovich 2020-10-20 23:00:06 +05:30
Bhupendrapt5
33d545a26b Added Thousands splendid Suns 2020-10-20 23:00:06 +05:30
Bhupendrapt5
3489f3d5c3 Updated publish year of The Book Thief & The Help 2020-10-20 23:00:06 +05:30
Sanket
28c6f9eaf8 Business book addition 2020-10-20 22:58:47 +05:30
Jackson Isaac
ce30d8b8b4 Fix typo in sample config file 2020-10-20 22:51:21 +05:30
Jackson Isaac
2656b43f51 Add new book: How Google Works 2020-10-20 22:50:25 +05:30
Jackson Isaac
50b542189c README.md: Add info about goodreads api 2020-10-20 00:51:51 +05:30
Sanket
3a0b94c846 Economics bood addition 2020-10-20 00:27:52 +05:30
Vladimir Tasic
2412ec36f9 Add react key for nav items 2020-10-20 00:26:59 +05:30
Vladimir Tasic
c2aae6dbd5 Remove react-native prop from react project (dev console error) 2020-10-20 00:26:32 +05:30
syd645
c03eab472b Added Educated by Tara Westover 2020-10-20 00:26:06 +05:30
Sanket
4bde8e6f0f Autobiography added 2020-10-18 23:01:27 +05:30
Vishnu KS
6bac7895ac Remove requirements.txt. 2020-10-18 16:29:03 +05:30
Vishnu KS
3bbc985ea3 utils: Include instructions on installing requirments. 2020-10-18 16:15:07 +05:30
Vishnu KS
a226450410 utils: Update requirments.txt. 2020-10-18 16:10:29 +05:30
veerbhadrasolanki
d5c6cd0be6 Add a book in Logic and Problem Solving 2020-10-18 11:42:40 +05:30
Irsyad Rahman
97522a0332 Improve bookcard UI responsiveness (#231)
* Improve bookcard responsive UI

* Hamburger menu

* Resolved conflict, mergin to upstream

* fix missing bookmark button
2020-10-18 11:39:57 +05:30
Deborah
d656841cb3 Edited the title of the book The Slight Edge 2020-10-17 23:06:54 +05:30
Deborah
f62088d411 Added The Slight Edge in Philosophy and Psychology 2020-10-17 23:06:54 +05:30
Eshan Agarwal
c85124cc55 Added a book Never Split the Difference in Startups and Business 2020-10-17 23:03:30 +05:30
Matteo Ruggiero
1489b1359e Adding a book (#262)
* Update README.md

Added The little prince, a classic book for children and old people, very educational

* Update README.md

* Update README.md
2020-10-17 01:17:57 +05:30
palak
e9e9b6755c changes to the sidebar, cards and footer (#237)
* added responsiveness to sidebar and sticky footer

* remobed unused vars

* added functionality to read more button

* a minor logical error fixed

* removed footer
2020-10-17 01:14:03 +05:30
Miguel Martín-Maestro López
18cc21b60d Update README.md
Add book The Sixth Extinction: An Unnatural History
2020-10-15 23:50:27 +05:30
Nickerchen
050ad48cd8 Added superforecasting (#265)
* Added The Language Instinct

* Added Superforecasting 


Removed extra book

Co-authored-by: Vishnu Ks <yo@vishnuks.com>
2020-10-15 23:49:06 +05:30
Sarrthak
eedf0ba7f1 Corrected Seq in Logic and Problem solving 2020-10-15 23:46:28 +05:30
Sarrthak
819ce9ba7c New book added to problem solving 2020-10-15 23:46:28 +05:30
Oleg Semenov
fe5aefd2c6 Added a book to Science and Medicine section 2020-10-15 23:37:54 +05:30
The Dude..io
30141d31f3 Smaller sidebar, visible header (#250) 2020-10-15 23:35:04 +05:30
Vishnu KS
1bfb3321a3 Add link to diff.blog. 2020-10-15 23:34:01 +05:30
Hrithik Singh
69d0848ed5 Added "My Inventions"
Added My Inventions: The Autobiography of Nikola Tesla into " Autobiographies and Biographies "
2020-10-15 01:52:56 +05:30
Unknown
43345db743 Added author of Passions within reason 2020-10-15 01:41:38 +05:30
Unknown
4daab218a0 Add passions within reason 2020-10-15 01:41:38 +05:30
Unknown
b3982bd426 Added The Language Instinct 2020-10-15 01:41:12 +05:30
Unknown
f258bea951 Added the elephant in the brain 2020-10-15 01:39:09 +05:30
ale2157
5163baa13b Added Gift of Fear
Added the book The Gift of Fear, a psychological and self-help book.
2020-10-15 01:35:33 +05:30
Hyunsujk
cd2c9ee334 ignore package-lock 2020-10-15 01:33:00 +05:30
Hyunsujk
8dbfeb1059 added key to FIELDS_TO_SORT_BY.map to resolve warning 2020-10-15 01:31:33 +05:30
Carl Dungca
9f2a822a54 Feature added: Mark to read (#252)
* Rendered a static reading list button to each bookcard component

* Attached click listener to bookmark button to log book data

* Clicking bookmark button saves book information to a localStorage array

* Updated card height to account for button

* Updated saveBookToLocalStorage function to use objects instead of arrays

* Can now toggle books in and out of localStorage

* Reverted previous 4 commits so that data isn't directly written to localStorage

* Created a sidebar link to reading list

* Added placeholder bookmarks page

* Bookmark button now updates state in index.js

* Initialized context API

* Wrote a reducer function to handle bookmark state changes

* Configured reducer to add books in and out of state

* Reading list is now preserved between state AND localStorage when changing categories

* Fixed some code format issues

* Rendered saved books in reading list component

* Toggle apperance of bookmark button

* Hacky fix for positioning of reading list sidebar link

* Adjusted style and alignment of bookmark button

* Added check to determine if window is defined in useEffect

* Exported the gatsby-ssr API
2020-10-15 01:30:46 +05:30
Elysia Ong
ef9fc03843 Style book card 2020-10-12 14:33:43 +05:30
Elysia Ong
454ada1ee6 Use goodreads icon 2020-10-12 14:33:43 +05:30
Elysia Ong
e2264c0eeb Fix typo in method name 2020-10-12 14:33:43 +05:30
Elysia Ong
695d92f465 Revert "Revert "Include goodreads image.""
This reverts commit f4446aff07.
2020-10-12 14:33:43 +05:30
Vishnu Ks
549b560748 Update CONTRIBUTING.md 2020-10-12 14:24:28 +05:30
Vishnu Ks
7bd8e6682b Update CONTRIBUTING.md 2020-10-12 14:23:22 +05:30
Vishnu KS
f4446aff07 Revert "Include goodreads image."
This reverts commit 872b09fe52.
2020-10-12 13:28:54 +05:30
Vishnu KS
fbec5ca04a Move when to run script to top. 2020-10-12 13:00:07 +05:30
Vishnu KS
c8634462fc Remove uncessary comment on the location of utils. 2020-10-12 12:57:51 +05:30
Vishnu KS
eee53f2f60 Fix books.json path in README. 2020-10-12 12:56:03 +05:30
Vishnu KS
c527547008 Include documentation on website and utils. 2020-10-12 12:53:50 +05:30
Vishnu KS
44c779acb5 Include race in index. 2020-10-12 11:46:30 +05:30
Vishnu KS
96d806ed6d Update description and mention app directory. 2020-10-12 11:45:39 +05:30
Vishnu KS
872b09fe52 Include goodreads image. 2020-10-12 11:44:57 +05:30
Taylor Johnston
fb36c7cde8 Added category "race" and book title 2020-10-12 11:34:49 +05:30
Samisha
5df6370439 Added And Then There Were None 2020-10-12 11:33:08 +05:30
Gal Elmalah
f36a9615a7 Update feed.js 2020-10-12 11:32:08 +05:30
Gal Elmalah
8cd6ba59d7 add useMemo and 3 more sortBy options 2020-10-12 11:32:08 +05:30
Gal Elmalah
e1962883f6 Update feed.js
to prevent books to be displayed out of order when the loading more books
2020-10-11 16:53:45 +05:30
Gal Elmalah
193f06bb21 Update feed.js 2020-10-11 16:53:45 +05:30
Gal Elmalah
68e0dbe1cb Update index.js 2020-10-11 16:53:45 +05:30
Gal Elmalah
dd7b9b6efb remove console.log form feed.js 2020-10-11 16:53:45 +05:30
Gal Elmalah
a1fa7011cd fix sorting by year and rating bug 2020-10-11 16:53:45 +05:30
Gal Elmalah
e50712e5bc remove console.logs 2020-10-11 16:53:45 +05:30
Gal Elmalah
c94bd9f3b3 sort by functionallity 2020-10-11 16:53:45 +05:30
Triin
de1bba855f Improved accessibility according to WCAG 2020-10-11 00:21:09 +05:30
testname
fbfd6d8384 Update PULL_REQUEST_TEMPLATE.md 2020-10-11 00:16:59 +05:30
testname
08ba2f9cbd Update PULL_REQUEST_TEMPLATE.md 2020-10-11 00:16:59 +05:30
Vishnu Ks
6bc3393293 Fix typo in installation instructions. 2020-10-11 00:05:57 +05:30
Vishnu Ks
04cc460bb5 Add instructions on setting up development environment. 2020-10-11 00:05:22 +05:30
Maureen Landgraf
3abe7db364 Added It by Stephen King
You can't have a list of horror books with Stephen King. 'It' will always be one of my favorite King books. The book effectively uses not only Pennywise as a horror element, but also real life threats such as Henry Bowers and his gang of school bullies and Bev's abusive father. While the book is plenty chilling, you also fall in love with the tight-knit group of misfits who are able to band together and defeat a monster that has existed since the beginning of time itself. The book is not only about monsters, but the power of friendship, which makes it so much more than your typical horror novel.
2020-10-09 23:40:23 +05:30
Vishnu KS
1a70bf665e readme: Include link to website. 2020-09-30 01:42:02 +05:30
Vishnu KS
5dc79eeca6 app: Use OutboundLink for Amazon links. 2020-09-27 22:39:41 +05:30
Vishnu KS
52e63d7c1d app: Include analytics. 2020-09-27 22:32:33 +05:30
Vishnu KS
c6197e9646 app: Include amazon links. 2020-09-27 16:02:12 +05:30
Samisha
18ef998136 app: Remove unused bookcard import. 2020-09-23 23:27:53 +05:30
Michelle Mei-Ling Sandford
64d9be9221 Update README.md 2020-09-19 16:33:49 +05:30
Lasse Schultebraucks
6e251e0699 Update README.md
added The Forever War
2020-09-17 13:27:31 +05:30
Michelle Mei-Ling Sandford
de9a3d4040 add Mismatch
add Mismatch: How Inclusion Shapes Design |  Kat Holmes
2020-09-16 21:38:31 +05:30
Vishnu KS
02148006ae Sort books by rating. 2020-08-23 23:46:26 +05:30
Vishnu KS
76f2f431c1 app: Update emoji in sidebar. 2020-08-23 23:37:13 +05:30
Vishnu KS
5bb6865ba6 utils: Run black. 2020-08-23 23:11:05 +05:30
Vishnu KS
9fe8505ea4 utils: Store only text as description. 2020-08-23 23:10:26 +05:30
Vishnu KS
52285301d1 utils: Update books.json. 2020-08-23 20:55:07 +05:30
Vishnu KS
843ed75db7 utils: Create basic tool to generate json files. 2020-08-23 16:07:56 +05:30
Vishnu KS
d723ec905b Install black. 2020-08-23 15:34:58 +05:30
Vishnu KS
3bd0ce9bd6 utils: Fix the REDAME input file name. 2020-08-23 15:27:44 +05:30
Vishnu KS
828a68fa75 Fix the category names. 2020-08-23 13:26:16 +05:30
Vishnu KS
1593c00620 Make category page work without errors 2020-08-23 12:49:02 +05:30
Vishnu KS
4d81bf3fe1 Configure eslint. 2020-08-23 00:58:19 +05:30
Vishnu KS
f985c157d9 Install eslint and prettier. 2020-08-23 00:57:54 +05:30
Vishnu KS
defa5cb196 Refactor feed into a component. 2020-08-23 00:28:09 +05:30
Vishnu KS
b4cde4c777 Make category pages work. 2020-08-22 23:06:37 +05:30
Vishnu KS
b8b957805e Bring back stars. 2020-08-22 16:50:14 +05:30
Vishnu KS
d620d9d08b Make basic version work using bootstrap. 2020-08-22 16:48:13 +05:30
Vishnu KS
0f3d13c58a Install react bootstrap. 2020-08-22 15:36:09 +05:30
Vishnu Ks
63633fcf57 Remove website. 2020-08-07 12:13:14 +05:30
SurajKhayamali
98013de897 Fix: Doesn't recognize scroll when html & body height are 100% 2020-06-17 22:14:46 +05:30
Suraj Khayamali
40d8e36880 Implemented infinite scroll 2020-06-17 22:14:46 +05:30
CEUK
302806920c Add "Happy" to Philosophy and Psychology 2020-02-24 18:46:56 +05:30
Eric Wehrmeister
629c6ef9d2 Fix ordering and update contribution guide 2020-01-27 12:17:46 +05:30
Eric Wehrmeister
6da704d06a Add Wheel of Time to Fiction/Fantsay 2020-01-27 12:17:46 +05:30
Igor Tarasenko
7cbabf11c3 Add "Behave" to "Evolution, Science and Medicine"
Add "Behave: The Biology of Humans at Our Best and Worst" by Robert M. Sapolsky
2020-01-24 13:29:52 +05:30
Parvathysubramanian
ad6e84654e Update the rating of The third Door
This is in reference to update the rating of The third door rating from 4.3 to 4.28, where I did mention as 4.3 in my previous pull request.
2019-12-21 00:05:04 +05:30
Parvathysubramanian
edad683fac Add The third door 2019-12-20 23:56:53 +05:30
Vishnu KS
a821f2a23d Remove BMC logo. 2019-12-06 20:05:15 +05:30
Bartłomiej Jacak
4e2f55598f Add "Homo Deus: A History of Tomorrow" to History 2019-11-04 00:31:19 +05:30
Liel Fridman
f50bdf9006 Improving the UI of book cards 2019-10-19 12:19:45 +05:30
Vishnu KS
edd2eef7f4 readme: Mention about the website. 2019-10-18 19:45:11 +05:30
Vishnu KS
3d24c54a6c src: Use shoe dog book as cover photo. 2019-10-18 19:43:07 +05:30
Denni Bevilacqua
b4b005460f Fix css class attribute in BookCard 2019-10-18 19:34:45 +05:30
Roberto Almeida
1e00c3442c Adds the book Illusions by Richard Bach 2019-10-18 19:21:11 +05:30
Josh RosenHanst
fb6e2e8b5d React error fixes (#180)
* fix className errors by replacing class= with className= in templates; remove unused imports

* fix component key warning by adding the node.id key to the component
2019-10-17 11:51:25 +05:30
Josh PC
89cdab6ad2 fix <div> inside <p> warning 2019-10-17 11:47:20 +05:30
Josh PC
bba3cfe578 add and implement react-star-ratings library 2019-10-17 11:47:20 +05:30
Josh PC
b9e8ae5bbf add year and ratings text display 2019-10-17 11:47:20 +05:30
Fred Adams
1acc7c9007 Fix order of books 2019-10-13 21:05:02 +05:30
xtrp
8022843544 add new book 2019-10-13 21:05:02 +05:30
Vishnu KS
15c5cd8505 app: Create basic app. 2019-10-13 20:19:56 +05:30
Vishnu KS
c2e244f784 utils: Add bunch of files to .gitignore. 2019-10-13 20:19:56 +05:30
Vishnu KS
49763eecd2 utils: Set book category in book object before storing. 2019-10-13 20:19:56 +05:30
Vishnu KS
63350a60a3 utils: Fix store_json dest. 2019-10-13 20:19:56 +05:30
Vishnu KS
5e02e59123 utils: Add flag to store json. 2019-10-13 20:19:56 +05:30
Vishnu KS
08b11eb478 utils: Add force option to always hit endpoint. 2019-10-13 20:19:56 +05:30
Vishnu KS
c619ae91f6 utils: Rename file_type to input_file_type. 2019-10-13 20:19:56 +05:30
Aditi Ahuja
a65474a397 Added an Oliver Sacks favourite 2019-10-09 14:43:17 +05:30
dzammit
3eb0b5b129 Added The Art of Deception
The world's most infamous hacker offers an insider's view of the low-tech threats to high-tech security
Kevin Mitnick's exploits as a cyber-desperado and fugitive form one of the most exhaustive FBI manhunts in history and have spawned dozens of articles, books, films, and documentaries.
2019-10-09 14:42:05 +05:30
dzammit
e8a127c823 Excellent exploration of the mind across different perspectives
A roller-coaster ride through the unpredictable, exciting, and challenging universe of computers, games, puzzles, mazes, and computer art. "Pickover's dazzling array of tortuous mind-benders and arcane minutiae delights and surprises. It's easy to get trapped in his enticing labyrinth of seductive mind games".--Science News.
2019-10-09 14:42:05 +05:30
Ashish Shenoy
b1b22e5a1f add George Orwell's 1984 to Classics 2019-10-09 14:41:31 +05:30
Prathamesh
98ebe2ffd9 Update the recent changes. 2019-10-04 13:51:36 +05:30
Prathamesh
45d98c7e39 Add Atomic Habits 2019-10-04 13:51:36 +05:30
Vishnu Ks
dcc0c64aea Add link to diff.blog. 2019-06-01 16:43:55 +05:30
Vishnu Ks
e66fb6c054 Remove PRs welcome badge.
It's obvious that PRs are welcome in a GitHub repositary.
2019-06-01 16:42:07 +05:30
Vishnu Ks
2989f26919 Remove link to books.zulipchat.com. 2019-06-01 16:42:07 +05:30
Sam Jeeves
5029549e2c Added The Martian to Science Fiction 2019-04-10 18:01:20 +05:30
Sam Jeeves
bbb331f0fa Added date for Hitchhiker's Guide to the Galaxy 2019-04-10 18:01:20 +05:30
Sean Campbell
c581cc1dfb updated ordering 2019-03-23 13:01:53 +05:30
Sean Campbell
708e20ba85 natac13 added Atlas Shrugged by Ayn Rand to Fiction/Classics 2019-03-23 13:01:53 +05:30
Sean Campbell
d34d8d49af Add 2 Napoleon Hill books 2019-03-23 02:31:37 +05:30
Daniele Ascione
810c497558 Added Einstein biography by Isaacson 2019-03-23 02:15:40 +05:30
Vishnu Ks
834854a36c Add link to zulip organization. 2019-02-22 23:07:36 +05:30
Vishnu Ks
066d05c0af Fix Lord of The Rings date. 2019-01-29 20:26:24 +05:30
bschlagel
9bf3627795 Add Cosmicomics
This is lesser-known Calvino, but actually my favorite of his works that I've read. It's just so weird! — a collection of stories about the deep history of the universe, featuring decidedly atypical protagonists (particles, formulae, evolving organisms, etc.) and a range of witty magical realism… Reads like vignettes from a strange alternate history of the cosmos…
2019-01-29 11:49:59 +05:30
bschlagel
2b92156cc1 Add Origins of Form
All about form and structure — how things are made, and how they're constrained, from the structural efficiencies and limitations of natural materials, to differences in building/manufacturing practices we might consider in light of what we want to optimize for… It's not only well-written, but graced with lovely illustrations on almost every page, of things ranging from cell structures to ancient tools to the various ways things can break. It also works up to some interesting conclusions…moving from elements of form and structure, to historical and evolutionary influences, the "dictates of chance" on what things exist, and unifying principles of the physical world.
2019-01-29 11:49:12 +05:30
bschlagel
4d0e21a999 Add Bolo'bolo
* Added "Bolo'bolo"

Weird and wonderful little book that proposes a whole societal structure of radical autonomous communities — complete with an invented language to describe the parts of this new community vision, and their machinations. Very eye-opening; in some ways it's a strange and impractical utopian dream; in others it's a sobering and critical plea for reorganizing society along lines of greater sustainability and social cohesion. Very interesting whichever way you look at it!
2019-01-29 11:48:29 +05:30
Vishnu Ks
7de464fa23 Added: Life at the Speed of Light (#132)
It covers the developments of synthetic biology through 2012, and the creation of the first synthetic lifeform by J. Craig Venter.
2019-01-28 12:09:17 +05:30
bschlagel
46feb27687 Added "Le Ton beau de Marot" (#150)
An incredible book about the art of translation, and a million other very welcome tangents. Hofstadter spins endless threads of ideas around a fascinating central premise: that a specific favorite poem of his, by a fairly obscure 16th century French poet, can spark an infinite variety of translations. There are 80+ of these translations sprinkled throughout the book, from friends and family, students and colleagues, noted translators and computer programs (and many by Hofstadter himself). Among them, a feast of academic lessons and personal reflections interwoven into a testament to the complexity and magic of translation and a whole lot of fascinating problems posed by language, literature, cognition and more. I've owned Hofstadter's infamous Gödel, Escher, Bach for a few years now, and still haven't finished swashbuckling my way through it — but I found this one thematically related yet more accessible, a great entrance point to a capacious and curious mind.
2019-01-28 12:08:18 +05:30
Utkarsh Gupta
9a2318c00c [Added] A book in the Autobiographies & Biographies Section. 2019-01-28 12:05:04 +05:30
lupeidi
8b982eb061 Added The Immortal Life of Henrietta Lacks 2019-01-28 12:03:13 +05:30
bschlagel
4e8712a154 Added "Pilgrim at Tinker Creek"
Really wonderful book about nature, the passage of time, and really paying attention to the world around you. The whole book could almost be categorized as prose poetry; it's not a large volume but took me a while to get through just due to the sheer density of lush and sensitive description. It chronicles a year in which both nothing and everything seems to happen; Dillard mostly hangs out around her home and its backyard creek (or at least, the book is constrained mostly to these experiences) but manages to evoke transcendent beauty and spirituality, capturing cycles of predator and prey, weather, and her own reactions to the unfolding of life in its infinite forms.
2019-01-28 12:01:14 +05:30
Solomon H
f741582866 Add Shoe Dog 2019-01-28 11:58:09 +05:30
Peter Pelberg
32e21b16ad Changing position to conform w/ Goodreads Rating rank 2019-01-24 13:02:48 +05:30
Alexander Weiher
37f4220178 update book to the correct position as suggested by @hackerid 2018-12-30 21:53:04 +05:30
defel
75f0f09275 add: Overcoming Gravity: A Systematic Approach to Gymnastics and Bodyweight Strength 2018-12-30 21:53:04 +05:30
Julien Chien
3c92a18525 capitalization + year for Jane Eyre 2018-12-05 00:11:57 +05:30
Ah-dri-Anna
71974a19fb Update README.md
Author's name is Ian MORRIS not "Morrisage"
https://www.amazon.com/Ian-Morris/e/B001IQZPSC
2018-06-12 23:36:49 +05:30
Ron Suhodrev
7ba90048f7 Add Mistborn by Brandon Sanderson
All of his Cosmere books are amazing, and I suggest people start with "The Final Empire" - the first book of the Mistborn trilogy.
2018-03-26 10:57:57 +05:30
Franciosi
896c165222 Update README.md 2018-03-12 15:44:54 +05:30
Vishnu Ks
91d197c82e fix odering of books in philisophy section. 2018-03-12 15:42:30 +05:30
Andre LaFleur
d056b55fc9 Fix Brene Brown link and add Meditations by Marcus Aurelius 2018-03-12 15:36:31 +05:30
Vishnu Ks
87198913ea Add link to BMAC account. 2018-03-04 15:08:21 +05:30
Vishnu Ks
3b70e71567 Use markdown for buy me a coffee. 2018-03-04 15:06:06 +05:30
Vishnu Ks
e865b1f12b readme: Add buy me a coffee badge. 2018-03-04 14:57:00 +05:30
61 changed files with 65794 additions and 511 deletions

View File

@@ -1,5 +1,7 @@
(todo:please remove this todo and the sections you did not check below before you make your pull request.
If you are unsure, please check other PRs like this one: https://github.com/hackerkid/Mind-Expanding-Books/pull/207#issue-377268434)
## In this pull request ## In this pull request
- [ ] I am adding a new book. - [ ] I am adding a new book.
- [ ] I am adding a new category - [ ] I am adding a new category
- [ ] Removing a book - [ ] Removing a book

1
.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
.DS_Store

View File

@@ -1,10 +1,24 @@
# Contribution Guidelines # Contribution Guidelines
Please ensure your pull request adheres to the following guidelines: ## What are the criteria for adding a new book?
The mission of this list is to curate books that can change the lives of people for the better.
- Search previous suggestions before making a new one, as yours may be a duplicate. So you should add a book that has changed your life!!
- if you want to add a new book you should have read the book.
- Use the following format: `| Book name | Author | [Goodreads rating](Goodreads url) | Year published |` Here are some questions that you can potentially ask yourself to help make this decision. If the answer is yes for most of them, feel free to create a pull request!
- Mention in pull request clearly why you think the book deserve to be in the list.
1. If you had the money to gift a book to every college graduate this year, would you gift this book?
2. Would you gift this book to your children at any point in their lives?
3. If there are only 3 books that you can keep a physical copy of in your life, would this book be one of them?
4. Would your life have been better off had you read this book 10 years back?
5. Would this book be relevant 1000 years from now?
## How to create a pull request?
- Search for existing books in [README.md](README.md) and make sure that you are not adding a duplicate.
- Insert the book in the following format in [README.md](README.md). Don't change any other files.
`| Book name | Author | [Goodreads rating](Goodreads url) | Year published |`
- Make sure that the book is inserted in the correct order according to the Goodreads rating.
- Mention in pull request clearly why you think the book deserves to be on the list.
Thank you! Thank you!

1028
README.md

File diff suppressed because it is too large Load Diff

22
app/.eslintrc.js Normal file
View File

@@ -0,0 +1,22 @@
module.exports = {
env: {
browser: true,
es2020: true,
},
extends: [
'plugin:react/recommended',
'airbnb',
],
parserOptions: {
ecmaFeatures: {
jsx: true,
},
ecmaVersion: 11,
sourceType: 'module',
},
plugins: [
'react',
],
rules: {
},
};

72
app/.gitignore vendored Normal file
View File

@@ -0,0 +1,72 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# Typescript v1 declaration files
typings/
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# dotenv environment variables file
.env
# gatsby files
.cache/
public
# Mac files
.DS_Store
# Yarn
yarn-error.log
.pnp/
.pnp.js
# Yarn Integrity file
.yarn-integrity
# ignore package-lock as it complicates merging
package-lock.json

4
app/.prettierignore Normal file
View File

@@ -0,0 +1,4 @@
.cache
package.json
package-lock.json
public

7
app/.prettierrc Normal file
View File

@@ -0,0 +1,7 @@
{
"endOfLine": "lf",
"semi": false,
"singleQuote": false,
"tabWidth": 2,
"trailingComma": "es5"
}

1
app/.prettierrc.json Normal file
View File

@@ -0,0 +1 @@
{}

22
app/LICENSE Normal file
View File

@@ -0,0 +1,22 @@
The MIT License (MIT)
Copyright (c) 2015 gatsbyjs
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

39
app/README.md Normal file
View File

@@ -0,0 +1,39 @@
`app/` directory contains the source code of the Mind Expanding Books [website](https://books.vishnuks.com)
## How to setup development environment
#### Verify Node Install
```
node -v
npm -v
```
#### Install Gatsby CLI
```
npm install -g gatsby-cli
```
```bash
git clone https://github.com/hackerkid/Mind-Expanding-Books
cd app/
npm install
gatsby develop
```
Once this is done, the development server should be accessible at http://localhost:8000
## High level overview of the website
- The website is made using Gatsby, which is a React based static site generator.
- The website is deployed in Netlify automatically whenever a commit is pushed to GitHub.
- When you create a pull request with changes to the source code, Netlify will automatically
create a website for previewing the changes. You can click on "Details" in the "Deploy preview ready!"
message in the pull request page for seeing the website.
## From where does the website fetches the data of the books?
Website fetches the data of the books from `app/src/data/books.json` file. See [README in utils directory](../utils/README.MD)
for details on how this file is generated.

14
app/gatsby-browser.js Normal file
View File

@@ -0,0 +1,14 @@
/**
* Implement Gatsby's Browser APIs in this file.
*
* See: https://www.gatsbyjs.org/docs/browser-apis/
*/
// You can delete this file if you're not using it
import React from "react"
import GlobalState from "./src/context/globalState"
export const wrapRootElement = ({ element }) => (
<GlobalState>{element}</GlobalState>
)

46
app/gatsby-config.js Normal file
View File

@@ -0,0 +1,46 @@
module.exports = {
siteMetadata: {
title: `Mind Expanding Books`,
description: `Kick off your next, great Gatsby project with this default starter. This barebones starter ships with the main Gatsby configuration files you might need.`,
author: `@gatsbyjs`,
},
plugins: [
`gatsby-plugin-react-helmet`,
{
resolve: `gatsby-source-filesystem`,
options: {
name: `images`,
path: `${__dirname}/src/images`,
},
},
`gatsby-transformer-sharp`,
`gatsby-plugin-sharp`,
{
resolve: `gatsby-plugin-manifest`,
options: {
name: `gatsby-starter-default`,
short_name: `starter`,
start_url: `/`,
background_color: `#663399`,
theme_color: `#663399`,
display: `minimal-ui`,
icon: `src/images/gatsby-icon.png`, // This path is relative to the root of the site.
},
},
`gatsby-plugin-offline`,
`gatsby-transformer-json`,
{
resolve: `gatsby-source-filesystem`,
options: {
path: `./src/data/`,
},
},
`gatsby-plugin-postcss`,
{
resolve: `gatsby-plugin-google-analytics`,
options: {
trackingId: "UA-139957969-2",
}
}
],
}

49
app/gatsby-node.js Normal file
View File

@@ -0,0 +1,49 @@
const fs = require('fs');
const categories = JSON.parse(fs.readFileSync('src/data/categories.json'));
const slugify = require('slugify');
exports.createPages = async function ({ actions, graphql }) {
const { createPage } = actions;
await Promise.all(
categories.map(async (category) => {
const data = await graphql(
`
query categoryBooksQuery($categoryName: String) {
allBooksJson(
filter: { category: { eq: $categoryName } }
sort: { fields: [rating], order: DESC }
) {
edges {
node {
id
title
url
rating
author
year
category
image_url
description
amazon_url
}
}
}
}
`,
{ categoryName: category.name },
);
console.log(category.name, data.data);
createPage({
path: slugify(category.name),
component: require.resolve('./src/templates/categoryTemplate.js'),
context: {
categoryName: category.name,
data: data.data,
image: category.emoji,
limit: null,
},
});
}),
);
};

14
app/gatsby-ssr.js Normal file
View File

@@ -0,0 +1,14 @@
/**
* Implement Gatsby's SSR (Server Side Rendering) APIs in this file.
*
* See: https://www.gatsbyjs.org/docs/ssr-apis/
*/
// You can delete this file if you're not using it
import React from "react"
import GlobalState from "./src/context/globalState"
export const wrapRootElement = ({ element }) => (
<GlobalState>{element}</GlobalState>
)

29267
app/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

69
app/package.json Normal file
View File

@@ -0,0 +1,69 @@
{
"name": "gatsby-starter-default",
"private": true,
"description": "A simple starter to get up and developing quickly with Gatsby",
"version": "0.1.0",
"author": "Kyle Mathews <mathews.kyle@gmail.com>",
"dependencies": {
"bootstrap": "^4.5.2",
"gatsby": "^2.24.91",
"gatsby-image": "^2.2.27",
"gatsby-plugin-google-analytics": "^2.3.14",
"gatsby-plugin-manifest": "^2.4.37",
"gatsby-plugin-offline": "^3.0.14",
"gatsby-plugin-postcss": "^2.1.11",
"gatsby-plugin-react-helmet": "^3.1.11",
"gatsby-plugin-sharp": "^2.6.43",
"gatsby-source-filesystem": "^2.1.31",
"gatsby-transformer-json": "^2.2.13",
"gatsby-transformer-sharp": "^2.2.21",
"prop-types": "^15.7.2",
"react": "^16.10.2",
"react-bootstrap": "^1.3.0",
"react-dom": "^16.10.2",
"react-helmet": "^5.2.1",
"react-star-rating-component": "^1.4.1",
"react-star-ratings": "^2.3.0",
"slugify": "^1.4.5"
},
"devDependencies": {
"eslint": "^7.7.0",
"eslint-config-airbnb": "^18.2.0",
"eslint-plugin-import": "^2.22.0",
"eslint-plugin-jsx-a11y": "^6.3.1",
"eslint-plugin-react": "^7.20.6",
"eslint-plugin-react-hooks": "^4.1.0",
"husky": "^4.3.0",
"lint-staged": ">=10",
"prettier": "1.19.1",
"tailwindcss": "^1.1.2"
},
"keywords": [
"gatsby"
],
"license": "MIT",
"scripts": {
"build": "gatsby build",
"develop": "gatsby develop",
"format": "prettier --write \"**/*.{js,jsx,json,md}\"",
"start": "npm run develop",
"serve": "gatsby serve",
"test": "echo \"Write tests! -> https://gatsby.dev/unit-testing \""
},
"repository": {
"type": "git",
"url": "https://github.com/gatsbyjs/gatsby-starter-default"
},
"bugs": {
"url": "https://github.com/gatsbyjs/gatsby/issues"
},
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"*.{js,jsx,json,md}": "prettier --write",
"*.js": "eslint --cache --fix"
}
}

3
app/postcss.config.js Normal file
View File

@@ -0,0 +1,3 @@
module.exports = () => ({
plugins: [require("tailwindcss")],
})

View File

@@ -0,0 +1,14 @@
import React from "react";
import { OutboundLink } from "gatsby-plugin-google-analytics"
const getTargetURL = (book) => {
return book.amazon_url + "?tag=vishnuks-20";
}
export default ({ book }) => {
return (
<OutboundLink href={getTargetURL(book)} target="_blank" rel="noreferrer">
<img alt="Amazon link" style={{ marginBottom: "-8px" }} src="https://img.icons8.com/color/48/000000/amazon.png"/>
</OutboundLink>
)
}

View File

@@ -0,0 +1,95 @@
import PropTypes from 'prop-types';
import React, { useState } from 'react';
import StarRatings from 'react-star-ratings';
import { Card, Row, Col } from 'react-bootstrap';
import AmazonURL from '../components/amazonurl';
import Bookmark from '../components/bookmark';
import GoodReadsImage from '../components/goodreadsimage';
const truncateContent = (content) => {
if (!content) {
return '';
}
return content.length > 350 ? content.substring(0, 350) + '...' : content;
};
const showFullText = (content) => {
if (!content) {
return '';
}
return content;
};
const BookCard = ({ book }) => {
const [ show, toggleShow ] = useState(false);
return (
<Card style={{ marginBottom: '15px' }}>
<Row>
<Col xs={6} sm={6} md={4} xl={2}>
<Card.Img
style={{
paddingLeft: '15px',
paddingRight: '15px',
paddingTop: '30px'
}}
src={book.image_url}
alt={book.title}
/>
</Col>
<Col xs={12} sm={6} md={8} xl={10}>
<Card.Body>
<Card.Title>{book.title}</Card.Title>
<Card.Subtitle className="text-muted">
<Card.Text style={{ paddingTop: '2px' }}>
{book.author} <b>{book.year ? book.year : null}</b>
</Card.Text>
<StarRatings
rating={parseFloat(book.rating)}
numberOfStars={5}
starDimension="18px"
starSpacing="1px"
starRatedColor="#fa604a"
/>
<div style={{ display: 'flex', alignItems: 'center', paddingTop: '.75rem' }}>
<div style={{ width: '30px', height: '30px', marginRight: '5px' }}>
{book.amazon_url ? <AmazonURL book={book} /> : null}
</div>
<div style={{ width: '30px', height: '30px' }}>
<a href={book.url} target="_blank">
<GoodReadsImage />
</a>
</div>
<Bookmark book={book} />
</div>
</Card.Subtitle>
<p style={{ color: 'gray', fontSize: '0.8rem', paddingTop: '1rem' }}>
{!show && truncateContent(book.description)}
{show && showFullText(book.description)}
</p>
{!show && book.description.length>350 &&(
<button className="btn btn-sm btn-primary " onClick={() => toggleShow(true)}>
Show More
</button>
)}
{show && (
<button className="btn btn-sm btn-primary " onClick={() => toggleShow(false)}>
Show Less
</button>
)}
</Card.Body>
</Col>
</Row>
</Card>
);
};
BookCard.propTypes = {
siteTitle: PropTypes.object
};
BookCard.defaultProps = {
book: {}
};
export default BookCard;

View File

@@ -0,0 +1,26 @@
import React, { useContext } from 'react'
import { Button } from "react-bootstrap"
import { BookmarkContext } from '../context/globalState'
export default ({ book }) => {
const { updateReadingList, readingList } = useContext(BookmarkContext)
const readingListIds = readingList.bookIds
return (
<div onClick={() => updateReadingList({ type: 'bookmark', retrievedBook: book })}>
<Button style={{
height: "30px",
width: "30px",
marginLeft: "0.25rem",
display: "grid",
justifyContent: "center",
alignContent: "center" }}
variant={ readingListIds.includes(book.id) ? "success" : "light"
}>
<span>
🔖
</span>
</Button>
</div>
)
}

View File

@@ -0,0 +1,12 @@
import React from "react";
export default ({categoryName, categoryImage}) => {
return (
<div className="my-2 mx-2" aria-labelledby="category-description">
<h4 id="category-description">
{categoryImage} {categoryName}
</h4>
</div>
)
}

View File

@@ -0,0 +1,28 @@
import React from 'react';
import '../styles/sidebar.css';
import BookCard from './bookcard';
import SortByDropdown, { FIELDS_TO_SORT_BY, compareFunctions } from './sortByDropdown';
export default ({ data, limit }) => {
const [sortBy, setSortBy] = React.useState(FIELDS_TO_SORT_BY[0]);
const sortedBooks = React.useMemo(() => [...data.allBooksJson.edges]
.sort(compareFunctions[sortBy.value]),
[sortBy]);
return (
<>
<SortByDropdown sortBy={sortBy.label} onSortByItemClick={setSortBy} />
{sortedBooks.map((x, index) => {
const book = x.node;
if (!limit || index < limit) {
if (!book.description || book.description.length < 10) {
return null;
}
return <BookCard book={book} key={book.id} />;
}
return null;
})}
</>
);
};

View File

@@ -0,0 +1,32 @@
import React from "react"
import { useStaticQuery, graphql } from "gatsby"
import Img from "gatsby-image"
/*
* This component is built using `gatsby-image` to automatically serve optimized
* images with lazy loading and reduced file sizes. The image is loaded using a
* `useStaticQuery`, which allows us to load the image from directly within this
* component, rather than having to pass the image data down from pages.
*
* For more information, see the docs:
* - `gatsby-image`: https://gatsby.dev/gatsby-image
* - `useStaticQuery`: https://www.gatsbyjs.org/docs/use-static-query/
*/
const Image = () => {
const data = useStaticQuery(graphql`
query {
placeholderImage: file(relativePath: { eq: "goodreads.png" }) {
childImageSharp {
fluid(maxWidth: 30) {
...GatsbyImageSharpFluid
}
}
}
}
`)
return <Img fluid={data.placeholderImage.childImageSharp.fluid} />
}
export default Image

View File

@@ -0,0 +1,28 @@
import { Link } from "gatsby"
import PropTypes from "prop-types"
import React from "react"
const Header = ({ siteTitle }) => (
<header className="mx-2 bg-red d-none d-lg-block custom-header" aria-labelledby='main-title'>
<h4 className="d-flex justify-content-end" id="main-title" style={{ margin: 16 }}>
<Link
to="/"
style={{
textDecorationColor: `none`,
}}
>
{siteTitle}
</Link>
</h4>
</header>
)
Header.propTypes = {
siteTitle: PropTypes.string,
}
Header.defaultProps = {
siteTitle: ``,
}
export default Header

View File

@@ -0,0 +1,32 @@
import React from "react"
import { useStaticQuery, graphql } from "gatsby"
import Img from "gatsby-image"
/*
* This component is built using `gatsby-image` to automatically serve optimized
* images with lazy loading and reduced file sizes. The image is loaded using a
* `useStaticQuery`, which allows us to load the image from directly within this
* component, rather than having to pass the image data down from pages.
*
* For more information, see the docs:
* - `gatsby-image`: https://gatsby.dev/gatsby-image
* - `useStaticQuery`: https://www.gatsbyjs.org/docs/use-static-query/
*/
const Image = () => {
const data = useStaticQuery(graphql`
query {
placeholderImage: file(relativePath: { eq: "gatsby-astronaut.png" }) {
childImageSharp {
fluid(maxWidth: 300) {
...GatsbyImageSharpFluid
}
}
}
}
`)
return <Img fluid={data.placeholderImage.childImageSharp.fluid} />
}
export default Image

View File

@@ -0,0 +1,622 @@
html {
font-family: sans-serif;
-ms-text-size-adjust: 100%;
-webkit-text-size-adjust: 100%;
}
body {
margin: 0;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
article,
aside,
details,
figcaption,
figure,
footer,
header,
main,
menu,
nav,
section,
summary {
display: block;
}
audio,
canvas,
progress,
video {
display: inline-block;
}
audio:not([controls]) {
display: none;
height: 0;
}
progress {
vertical-align: baseline;
}
[hidden],
template {
display: none;
}
a {
background-color: transparent;
-webkit-text-decoration-skip: objects;
}
a:active,
a:hover {
outline-width: 0;
}
abbr[title] {
border-bottom: none;
text-decoration: underline;
text-decoration: underline dotted;
}
b,
strong {
font-weight: inherit;
font-weight: bolder;
}
dfn {
font-style: italic;
}
h1 {
font-size: 2em;
margin: 0.67em 0;
}
mark {
background-color: #ff0;
color: #000;
}
small {
font-size: 80%;
}
sub,
sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
img {
border-style: none;
}
svg:not(:root) {
overflow: hidden;
}
code,
kbd,
pre,
samp {
font-family: monospace, monospace;
font-size: 1em;
}
figure {
margin: 1em 40px;
}
hr {
box-sizing: content-box;
height: 0;
overflow: visible;
}
button,
input,
optgroup,
select,
textarea {
font: inherit;
margin: 0;
}
optgroup {
font-weight: 700;
}
button,
input {
overflow: visible;
}
button,
select {
text-transform: none;
}
[type="reset"],
[type="submit"],
button,
html [type="button"] {
-webkit-appearance: button;
}
[type="button"]::-moz-focus-inner,
[type="reset"]::-moz-focus-inner,
[type="submit"]::-moz-focus-inner,
button::-moz-focus-inner {
border-style: none;
padding: 0;
}
[type="button"]:-moz-focusring,
[type="reset"]:-moz-focusring,
[type="submit"]:-moz-focusring,
button:-moz-focusring {
outline: 1px dotted ButtonText;
}
fieldset {
border: 1px solid silver;
margin: 0 2px;
padding: 0.35em 0.625em 0.75em;
}
legend {
box-sizing: border-box;
color: inherit;
display: table;
max-width: 100%;
padding: 0;
white-space: normal;
}
textarea {
overflow: auto;
}
[type="checkbox"],
[type="radio"] {
box-sizing: border-box;
padding: 0;
}
[type="number"]::-webkit-inner-spin-button,
[type="number"]::-webkit-outer-spin-button {
height: auto;
}
[type="search"] {
-webkit-appearance: textfield;
outline-offset: -2px;
}
[type="search"]::-webkit-search-cancel-button,
[type="search"]::-webkit-search-decoration {
-webkit-appearance: none;
}
::-webkit-input-placeholder {
color: inherit;
opacity: 0.54;
}
::-webkit-file-upload-button {
-webkit-appearance: button;
font: inherit;
}
html {
font: 112.5%/1.45em georgia, serif;
box-sizing: border-box;
overflow-y: scroll;
}
* {
box-sizing: inherit;
}
*:before {
box-sizing: inherit;
}
*:after {
box-sizing: inherit;
}
body {
color: hsla(0, 0%, 0%, 0.8);
font-family: georgia, serif;
font-weight: normal;
word-wrap: break-word;
font-kerning: normal;
-moz-font-feature-settings: "kern", "liga", "clig", "calt";
-ms-font-feature-settings: "kern", "liga", "clig", "calt";
-webkit-font-feature-settings: "kern", "liga", "clig", "calt";
font-feature-settings: "kern", "liga", "clig", "calt";
}
img {
max-width: 100%;
margin-left: 0;
margin-right: 0;
margin-top: 0;
padding-bottom: 0;
padding-left: 0;
padding-right: 0;
padding-top: 0;
margin-bottom: 1.45rem;
}
h1 {
margin-left: 0;
margin-right: 0;
margin-top: 0;
padding-bottom: 0;
padding-left: 0;
padding-right: 0;
padding-top: 0;
margin-bottom: 1.45rem;
color: inherit;
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
font-weight: bold;
text-rendering: optimizeLegibility;
font-size: 2.25rem;
line-height: 1.1;
}
h2 {
margin-left: 0;
margin-right: 0;
margin-top: 0;
padding-bottom: 0;
padding-left: 0;
padding-right: 0;
padding-top: 0;
margin-bottom: 1.45rem;
color: inherit;
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
font-weight: bold;
text-rendering: optimizeLegibility;
font-size: 1.62671rem;
line-height: 1.1;
}
h3 {
margin-left: 0;
margin-right: 0;
margin-top: 0;
padding-bottom: 0;
padding-left: 0;
padding-right: 0;
padding-top: 0;
margin-bottom: 1.45rem;
color: inherit;
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
font-weight: bold;
text-rendering: optimizeLegibility;
font-size: 1.38316rem;
line-height: 1.1;
}
h4 {
margin-left: 0;
margin-right: 0;
margin-top: 0;
padding-bottom: 0;
padding-left: 0;
padding-right: 0;
padding-top: 0;
margin-bottom: 1.45rem;
color: inherit;
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
font-weight: bold;
text-rendering: optimizeLegibility;
font-size: 1rem;
line-height: 1.1;
}
h5 {
margin-left: 0;
margin-right: 0;
margin-top: 0;
padding-bottom: 0;
padding-left: 0;
padding-right: 0;
padding-top: 0;
margin-bottom: 1.45rem;
color: inherit;
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
font-weight: bold;
text-rendering: optimizeLegibility;
font-size: 0.85028rem;
line-height: 1.1;
}
h6 {
margin-left: 0;
margin-right: 0;
margin-top: 0;
padding-bottom: 0;
padding-left: 0;
padding-right: 0;
padding-top: 0;
margin-bottom: 1.45rem;
color: inherit;
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
font-weight: bold;
text-rendering: optimizeLegibility;
font-size: 0.78405rem;
line-height: 1.1;
}
hgroup {
margin-left: 0;
margin-right: 0;
margin-top: 0;
padding-bottom: 0;
padding-left: 0;
padding-right: 0;
padding-top: 0;
margin-bottom: 1.45rem;
}
ul {
margin-left: 1.45rem;
margin-right: 0;
margin-top: 0;
padding-bottom: 0;
padding-left: 0;
padding-right: 0;
padding-top: 0;
margin-bottom: 1.45rem;
list-style-position: outside;
list-style-image: none;
}
ol {
margin-left: 1.45rem;
margin-right: 0;
margin-top: 0;
padding-bottom: 0;
padding-left: 0;
padding-right: 0;
padding-top: 0;
margin-bottom: 1.45rem;
list-style-position: outside;
list-style-image: none;
}
dl {
margin-left: 0;
margin-right: 0;
margin-top: 0;
padding-bottom: 0;
padding-left: 0;
padding-right: 0;
padding-top: 0;
margin-bottom: 1.45rem;
}
dd {
margin-left: 0;
margin-right: 0;
margin-top: 0;
padding-bottom: 0;
padding-left: 0;
padding-right: 0;
padding-top: 0;
margin-bottom: 1.45rem;
}
p {
margin-left: 0;
margin-right: 0;
margin-top: 0;
padding-bottom: 0;
padding-left: 0;
padding-right: 0;
padding-top: 0;
margin-bottom: 1.45rem;
}
figure {
margin-left: 0;
margin-right: 0;
margin-top: 0;
padding-bottom: 0;
padding-left: 0;
padding-right: 0;
padding-top: 0;
margin-bottom: 1.45rem;
}
pre {
margin-left: 0;
margin-right: 0;
margin-top: 0;
margin-bottom: 1.45rem;
font-size: 0.85rem;
line-height: 1.42;
background: hsla(0, 0%, 0%, 0.04);
border-radius: 3px;
overflow: auto;
word-wrap: normal;
padding: 1.45rem;
}
table {
margin-left: 0;
margin-right: 0;
margin-top: 0;
padding-bottom: 0;
padding-left: 0;
padding-right: 0;
padding-top: 0;
margin-bottom: 1.45rem;
font-size: 1rem;
line-height: 1.45rem;
border-collapse: collapse;
width: 100%;
}
fieldset {
margin-left: 0;
margin-right: 0;
margin-top: 0;
padding-bottom: 0;
padding-left: 0;
padding-right: 0;
padding-top: 0;
margin-bottom: 1.45rem;
}
blockquote {
margin-left: 1.45rem;
margin-right: 1.45rem;
margin-top: 0;
padding-bottom: 0;
padding-left: 0;
padding-right: 0;
padding-top: 0;
margin-bottom: 1.45rem;
}
form {
margin-left: 0;
margin-right: 0;
margin-top: 0;
padding-bottom: 0;
padding-left: 0;
padding-right: 0;
padding-top: 0;
margin-bottom: 1.45rem;
}
noscript {
margin-left: 0;
margin-right: 0;
margin-top: 0;
padding-bottom: 0;
padding-left: 0;
padding-right: 0;
padding-top: 0;
margin-bottom: 1.45rem;
}
iframe {
margin-left: 0;
margin-right: 0;
margin-top: 0;
padding-bottom: 0;
padding-left: 0;
padding-right: 0;
padding-top: 0;
margin-bottom: 1.45rem;
}
hr {
margin-left: 0;
margin-right: 0;
margin-top: 0;
padding-bottom: 0;
padding-left: 0;
padding-right: 0;
padding-top: 0;
margin-bottom: calc(1.45rem - 1px);
background: hsla(0, 0%, 0%, 0.2);
border: none;
height: 1px;
}
address {
margin-left: 0;
margin-right: 0;
margin-top: 0;
padding-bottom: 0;
padding-left: 0;
padding-right: 0;
padding-top: 0;
margin-bottom: 1.45rem;
}
b {
font-weight: bold;
}
strong {
font-weight: bold;
}
dt {
font-weight: bold;
}
th {
font-weight: bold;
}
li {
margin-bottom: calc(1.45rem / 2);
}
ol li {
padding-left: 0;
}
ul li {
padding-left: 0;
}
li > ol {
margin-left: 1.45rem;
margin-bottom: calc(1.45rem / 2);
margin-top: calc(1.45rem / 2);
}
li > ul {
margin-left: 1.45rem;
margin-bottom: calc(1.45rem / 2);
margin-top: calc(1.45rem / 2);
}
blockquote *:last-child {
margin-bottom: 0;
}
li *:last-child {
margin-bottom: 0;
}
p *:last-child {
margin-bottom: 0;
}
li > p {
margin-bottom: calc(1.45rem / 2);
}
code {
font-size: 0.85rem;
line-height: 1.45rem;
}
kbd {
font-size: 0.85rem;
line-height: 1.45rem;
}
samp {
font-size: 0.85rem;
line-height: 1.45rem;
}
abbr {
border-bottom: 1px dotted hsla(0, 0%, 0%, 0.5);
cursor: help;
}
acronym {
border-bottom: 1px dotted hsla(0, 0%, 0%, 0.5);
cursor: help;
}
abbr[title] {
border-bottom: 1px dotted hsla(0, 0%, 0%, 0.5);
cursor: help;
text-decoration: none;
}
thead {
text-align: left;
}
td,
th {
text-align: left;
border-bottom: 1px solid hsla(0, 0%, 0%, 0.12);
font-feature-settings: "tnum";
-moz-font-feature-settings: "tnum";
-ms-font-feature-settings: "tnum";
-webkit-font-feature-settings: "tnum";
padding-left: 0.96667rem;
padding-right: 0.96667rem;
padding-top: 0.725rem;
padding-bottom: calc(0.725rem - 1px);
}
th:first-child,
td:first-child {
padding-left: 0;
}
th:last-child,
td:last-child {
padding-right: 0;
}
tt,
code {
background-color: hsla(0, 0%, 0%, 0.04);
border-radius: 3px;
font-family: "SFMono-Regular", Consolas, "Roboto Mono", "Droid Sans Mono",
"Liberation Mono", Menlo, Courier, monospace;
padding: 0;
padding-top: 0.2em;
padding-bottom: 0.2em;
}
pre code {
background: none;
line-height: 1.42;
}
code:before,
code:after,
tt:before,
tt:after {
letter-spacing: -0.2em;
content: " ";
}
pre code:before,
pre code:after,
pre tt:before,
pre tt:after {
content: "";
}
@media only screen and (max-width: 480px) {
html {
font-size: 100%;
}
}

View File

@@ -0,0 +1,47 @@
/**
* Layout component that queries for data
* with Gatsby's useStaticQuery component
*
* See: https://www.gatsbyjs.org/docs/use-static-query/
*/
import React from "react"
import PropTypes from "prop-types"
import { useStaticQuery, graphql } from "gatsby"
import Header from "./header"
import "./layout.css"
import "bootstrap/dist/css/bootstrap.min.css"
import { Container } from "react-bootstrap"
const Layout = ({ children }) => {
const data = useStaticQuery(graphql`
query SiteTitleQuery {
site {
siteMetadata {
title
}
}
}
`)
return (
<>
<Header siteTitle={data.site.siteMetadata.title} />
<Container fluid>
<main>{children}</main>
<footer class ="footer-text">
© {new Date().getFullYear()}, Built with
{` `}
<a href="https://www.gatsbyjs.org">Gatsby</a>
</footer>
</Container>
</>
)
}
Layout.propTypes = {
children: PropTypes.node.isRequired,
}
export default Layout

88
app/src/components/seo.js Normal file
View File

@@ -0,0 +1,88 @@
/**
* SEO component that queries for data with
* Gatsby's useStaticQuery React hook
*
* See: https://www.gatsbyjs.org/docs/use-static-query/
*/
import React from "react"
import PropTypes from "prop-types"
import Helmet from "react-helmet"
import { useStaticQuery, graphql } from "gatsby"
function SEO({ description, lang, meta, title }) {
const { site } = useStaticQuery(
graphql`
query {
site {
siteMetadata {
title
description
author
}
}
}
`
)
const metaDescription = description || site.siteMetadata.description
return (
<Helmet
htmlAttributes={{
lang,
}}
title={title}
titleTemplate={`%s | ${site.siteMetadata.title}`}
meta={[
{
name: `description`,
content: metaDescription,
},
{
property: `og:title`,
content: title,
},
{
property: `og:description`,
content: metaDescription,
},
{
property: `og:type`,
content: `website`,
},
{
name: `twitter:card`,
content: `summary`,
},
{
name: `twitter:creator`,
content: site.siteMetadata.author,
},
{
name: `twitter:title`,
content: title,
},
{
name: `twitter:description`,
content: metaDescription,
},
].concat(meta)}
/>
)
}
SEO.defaultProps = {
lang: `en`,
meta: [],
description: ``,
}
SEO.propTypes = {
description: PropTypes.string,
lang: PropTypes.string,
meta: PropTypes.arrayOf(PropTypes.object),
title: PropTypes.string.isRequired,
}
export default SEO

View File

@@ -0,0 +1,49 @@
import React, { useContext } from "react"
import { Navbar, Nav } from "react-bootstrap"
import { StaticQuery, graphql, Link } from "gatsby"
import "../styles/sidebar.css"
import { BookmarkContext } from '../context/globalState'
var slugify = require('slugify')
export default () => {
const { readingList } = useContext(BookmarkContext)
return (
<StaticQuery
query={graphql`
query CategoryQuery {
allCategoriesJson {
edges {
node {
id
name
emoji
}
}
}
}
`}
render={data => (
<Navbar className="sidebar-sticky" collapseOnSelect expand="lg" bg="ligt" variant="light">
<Navbar.Toggle aria-controls="responsive-navbar-nav" />
<Navbar.Collapse>
<div>
<div style={{position: "relative", left: "0.9rem", paddingBottom: "0.2rem"}}>
<Link to="/readingList">🔖 Reading List ({readingList.bookIds.length})</Link>
</div>
{data.allCategoriesJson.edges.map(function(x, index) {
return (
<Nav.Item key={index}>
<Nav.Link href={slugify(x.node.name)}>
{x.node.emoji} {x.node.name}
</Nav.Link>
</Nav.Item>
)
})}
</div>
</Navbar.Collapse>
</Navbar>
)}
/>
)
}

View File

@@ -0,0 +1,40 @@
import React from 'react';
import { Dropdown } from 'react-bootstrap';
export const compareFunctions = {
title_a_z: ({ node: bookOne }, { node: bookTwo }) => bookOne.title.localeCompare(bookTwo.title),
title_z_a: ({ node: bookOne }, { node: bookTwo }) => bookTwo.title.localeCompare(bookOne.title),
year_descending: ({ node: bookOne }, { node: bookTwo }) => Number(bookTwo.year) - Number(bookOne.year),
year_ascending: ({ node: bookOne }, { node: bookTwo }) => Number(bookOne.year) - Number(bookTwo.year),
rating_descending: ({ node: bookOne }, { node: bookTwo }) => Number(bookTwo.rating) - Number(bookOne.rating),
rating_ascending: ({ node: bookOne }, { node: bookTwo }) => Number(bookOne.rating) - Number(bookTwo.rating),
};
export const FIELDS_TO_SORT_BY = [
{ label: 'Rating, high to low', value: 'rating_descending' },
{ label: 'Rating, low to high', value: 'rating_ascending' },
{ label: 'Publication year, new to old', value: 'year_descending' },
{ label: 'Publication year, old to new', value: 'year_ascending' },
{ label: 'Title, A-Z', value: 'title_a_z' },
{ label: 'Title, Z-A', value: 'title_z_a' },
];
export default ({ sortBy, onSortByItemClick }) => (
<div className="mb-2">
<Dropdown>
<Dropdown.Toggle variant="outline">
Sort By:
{' '}
{sortBy}
</Dropdown.Toggle>
<Dropdown.Menu>
{FIELDS_TO_SORT_BY.map((field, index) => (
<Dropdown.Item key={index} onClick={() => onSortByItemClick(field)}>
{field.label}
</Dropdown.Item>
))}
</Dropdown.Menu>
</Dropdown>
</div>
);

View File

@@ -0,0 +1,33 @@
export default function bookReducer(state, action) {
let readingListCopy = {...state}
switch (action.type) {
case 'init': {
if (action.content) {
return action.content
}
return readingListCopy
}
case 'bookmark': {
let { bookIds, books } = readingListCopy
const { retrievedBook } = action
const retrievedBookId = retrievedBook.id
// Delete existing bookmark
if (bookIds.includes(retrievedBookId)) {
readingListCopy.bookIds = bookIds.filter(id => id !== retrievedBookId)
delete books[retrievedBookId]
if (typeof window !== undefined) {
localStorage.setItem('Bookmarks', JSON.stringify(readingListCopy))
}
// Add new bookmark
} else {
books[retrievedBookId] = retrievedBook
bookIds.push(retrievedBookId)
if (typeof window !== undefined) {
localStorage.setItem('Bookmarks', JSON.stringify(readingListCopy))
}
}
return readingListCopy
}
}
}

View File

@@ -0,0 +1,25 @@
import React, { useReducer, useEffect } from 'react'
import bookReducer from './bookReducer'
export const BookmarkContext = React.createContext()
export default function GlobalState({children}) {
let [readingList, updateReadingList] = useReducer(bookReducer, {
books: {},
bookIds: []
})
useEffect(() => {
if (typeof window !== undefined) {
const retrievedBooks = JSON.parse(localStorage.getItem('Bookmarks'))
console.log(retrievedBooks)
updateReadingList({type: 'init', content: retrievedBooks})
}
}, [])
return (
<BookmarkContext.Provider value={{readingList, updateReadingList}}>
{children}
</BookmarkContext.Provider>
)
}

5728
app/src/data/books.json Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,74 @@
[
{
"name": "Startups and Business",
"emoji": "🚀"
},
{
"name": "Philosophy And Psychology",
"emoji": "☯️"
},
{
"name": "Autobiographies and Biographies",
"emoji": "👩🏾"
},
{
"name": "History",
"emoji": "📜"
},
{
"name": "Science and Medicine",
"emoji": "🔬"
},
{
"name": "Logic and Problem Solving",
"emoji": "🧩"
},
{
"name": "Politics",
"emoji": "🗳️"
},
{
"name": "Economics",
"emoji": "📈"
},
{
"name": "Gender",
"emoji": "🏳️‍🌈"
},
{
"name": "Sexuality",
"emoji": "😘"
},
{
"name": "Education",
"emoji": "🏫"
},
{
"name": "Writing",
"emoji": "📝"
},
{
"name": "Theater and Film",
"emoji": "🎬"
},
{
"name": "Health",
"emoji": "👩‍⚕️"
},
{
"name": "Travel",
"emoji": "🛩️"
},
{
"name": "Language",
"emoji": "🉐"
},
{
"name": "Nature",
"emoji": "🌲"
},
{
"name": "Art",
"emoji": "🖌️"
}
]

BIN
app/src/images/amazon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 163 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

14
app/src/pages/404.js Normal file
View File

@@ -0,0 +1,14 @@
import React from "react"
import Layout from "../components/layout"
import SEO from "../components/seo"
const NotFoundPage = () => (
<Layout>
<SEO title="404: Not found" />
<h1 id="title">NOT FOUND</h1>
<p>You just hit a route that doesn&#39;t exist... the sadness.</p>
</Layout>
)
export default NotFoundPage

79
app/src/pages/index.js Normal file
View File

@@ -0,0 +1,79 @@
import React, { useState, useEffect } from "react"
import { graphql } from "gatsby"
import Layout from "../components/layout"
import SEO from "../components/seo"
import SideBar from "../components/sidebar"
import { Container, Row, Col, Navbar } from "react-bootstrap"
import BookFeed from "../components/feed"
function myFunction(setMaximumBooksToShow, maximumBooksToShow) {
if (
document.documentElement.clientHeight +
document.documentElement.scrollTop >=
document.documentElement.scrollHeight
) {
setMaximumBooksToShow(maximumBooksToShow + 12)
}
}
export default ({ data }) => {
let [maximumBooksToShow, setMaximumBooksToShow] = useState(12)
useEffect(() => {
window.document.onscroll = () =>
myFunction(setMaximumBooksToShow, maximumBooksToShow)
})
return (
<Layout>
<SEO title="Home" />
<Container fluid>
<Row>
<Col lg={2}>
<SideBar />
</Col>
<Col lg={10}>
<BookFeed data={data} limit={maximumBooksToShow} />
</Col>
</Row>
<Row>
{/* <footer style={{marginLeft: 150,
width: `100%`,
position: `fixed`,
bottom: 0}}>
© {new Date().getFullYear()}, Built with
{` `}
<a href="https://www.gatsbyjs.org">Gatsby</a>
</footer> */}
</Row>
</Container>
</Layout>
)
}
export const query = graphql`
query MyQuery {
allBooksJson(
sort: {
fields: [rating]
order: DESC
}
) {
edges {
node {
id
title
url
rating
author
year
category
description
image_url
amazon_url
}
}
}
}
`

16
app/src/pages/page-2.js Normal file
View File

@@ -0,0 +1,16 @@
import React from "react"
import { Link } from "gatsby"
import Layout from "../components/layout"
import SEO from "../components/seo"
const SecondPage = () => (
<Layout>
<SEO title="Page two" />
<h1>Hi from the second page</h1>
<p>Welcome to page 2</p>
<Link to="/">Go back to the homepage</Link>
</Layout>
)
export default SecondPage

View File

@@ -0,0 +1,36 @@
import React, { useContext } from "react"
import { Link } from "gatsby"
import { Container, Row, Col } from "react-bootstrap"
import SideBar from "../components/sidebar"
import Layout from "../components/layout"
import SEO from "../components/seo"
import Bookcard from "../components/bookcard"
import { BookmarkContext } from "../context/globalState"
const ReadingList = () => {
const { readingList } = useContext(BookmarkContext)
return (
<Layout>
<SEO title="Reading list" />
<Container fluid>
<Row>
<Col xs={2}>
<SideBar />
</Col>
<Col>
<h2>Your reading list</h2>
<Link to="/">Go back to the homepage</Link>
{
readingList.bookIds.map(bookId => {
return <Bookcard book={readingList.books[bookId]} key={bookId} />
})
}
</Col>
</Row>
</Container>
<p>Reading List</p>
</Layout>
)}
export default ReadingList

11
app/src/styles/global.css Normal file
View File

@@ -0,0 +1,11 @@
.custom-header{
position: fixed;
}
.footer-text {
text-align:center;
padding-bottom:1 rem;
}
.dark-mode {
background-color: #3c4759;
}

View File

@@ -0,0 +1,38 @@
.sidebar {
position: fixed;
top: 0;
bottom: 0;
left: 0;
min-height: 100vh !important;
margin: 70px 0 0;
box-shadow: inset -1px 0 0 rgba(0, 0, 0, 0.1);
width: max-content;
}
.nav-link {
font-size: 0.9rem;
}
#sidebar-wrapper {
min-height: 100vh !important;
width: 100vw;
margin-left: -1rem;
-webkit-transition: margin 0.25s ease-out;
-moz-transition: margin 0.25s ease-out;
-o-transition: margin 0.25s ease-out;
transition: margin 0.25s ease-out;
}
#sidebar-wrapper .sidebar-heading {
padding: 0.875rem 1.25rem;
font-size: 1.2rem;
}
#page-content-wrapper {
min-width: 0;
width: 100%;
}
.navbar {
padding: 10px 0px;
}
.navbar-toggler {
margin-bottom: 1.2rem;
}

View File

@@ -0,0 +1,32 @@
import React, { useState, useEffect } from "react"
import { graphql } from "gatsby"
import Layout from "../components/layout"
import SEO from "../components/seo"
import SideBar from "../components/sidebar"
import CategoryDescription from "../components/categorydescription"
import { Container, Row, Col } from "react-bootstrap"
import BookFeed from "../components/feed"
const basicTemplate = props => {
const { pageContext } = props
const { categoryName, data, image } = pageContext
return (
<Layout>
<SEO title="Home" />
<Container fluid>
<Row>
<Col lg={2}>
<SideBar />
</Col>
<Col lg={10}>
<CategoryDescription categoryName={categoryName} categoryImage={image} />
<BookFeed data={data} categoryName={categoryName} />
</Col>
</Row>
</Container>
</Layout>
)
}
export default basicTemplate

16489
app/yarn.lock Normal file

File diff suppressed because it is too large Load Diff

3
package-lock.json generated Normal file
View File

@@ -0,0 +1,3 @@
{
"lockfileVersion": 1
}

7
utils/.gitignore vendored
View File

@@ -1,3 +1,8 @@
.idea .idea
__pycache__ __pycache__
config.py config.py
bin/
include/
lib/
out.json
pip-selfcheck.json

34
utils/HOUSEKEEPING.md Normal file
View File

@@ -0,0 +1,34 @@
This contains documentation on `housekeep.py` which was a command developed for converting from legacy README
format to the new format. This is not used anymore.
## Getting started
### Setup
1) Copy ```config-sample.py``` to ```config.py```
```bash
cp config-sample.py config.py
```
2) Get a GoodReads API key [here](https://www.goodreads.com/api/keys)
3) Copy your public key to the ```config.py``` file
### Converting
Run
```bash
python3 housekeep.py --file_type='old'
```
The ``--file_type='old'`` flag is needed if the books are displayed in the old format (in a list). New format is the default (when the records are displayed in tables).
This will convert to the new format and save it to ``README-new.md``.
**Note!** the first conversion can take some time, we wait 1 second between each request to GoodReads to not abuse the API.
After the first generation only missing records will be tried to be retrieved.
Run to see the available arguments
```bash
python3 housekeep.py --help
```

View File

@@ -1,34 +1,37 @@
# Utils for Mind-Expanding-Books `utils/` mainly contains scripts for generating `app/src/data/books.json` file from `README.md`
Simple command line interface to extend and order the Mind-Expanding-Books list. In most cases, you don't want to run the scripts in this directory or make changes to it.
The only time you want to mess with the scripts is when you want to fetch some extra data from `API` or
want to update the `app/src/data/books.json` file to include a newly added book or category.
## Getting started ## Generating `app/src/data/books.json`
### Setup The website shows name of the book, year, rating, cover, amazon link, etc in book card. Some of the
1) Copy ```config-sample.py``` to ```config.py``` data like name, year, rating etc is present in the [main README.md](../README.md). Other details
like cover photo, amazon link etc is fetched from various APIs.
The script that fetches all these extra data lives in `utils/update_json_files.py`
The script goes through all the books in [main README.md](../README.md) and starts fetching the extra details
from `Goodreads` and `Google Search` API. And the result is stored in `utils/books.json` and `utils/book_name_to_details.json`
(used for caching only).
Once the script completes the run, the `utils/books.json` file is copied to `app/src/data/books.json` **manually**.
And the website uses the data from `app/src/data/books.json` for generating the pages.
## Install packages for script
```bash ```bash
cp config-sample.py config.py cd utils
``` virtualenv .
2) Get a GoodReads API key [here](https://www.goodreads.com/api/keys) source bin/activate
3) Copy your public key to the ```config.py``` file pip install -r requirements.txt
### Converting
Run
```bash
python3 housekeep.py --file_type='old'
``` ```
The ``--file_type='old'`` flag is needed if the books are displayed in the old format (in a list). New format is the default (when the records are displayed in tables). ## Executing the script
This will convert to the new format and save it to ``README-new.md``. - Register at [goodreads](https://www.goodreads.com)
- Apply for a developer api [here](https://www.goodreads.com/api)
**Note!** the first conversion can take some time, we wait 1 second between each request to GoodReads to not abuse the API. - Copy utils/config-sample.py as utils/config.py
After the first generation only missing records will be tried to be retrieved. - Fill in the API Key credentials
Run to see the available arguments
```bash
python3 housekeep.py --help
```

File diff suppressed because it is too large Load Diff

5728
utils/books.json Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,2 +1,5 @@
# save this file as 'config.py' and then, fill it with you api key # save this file as 'config.py' and then, fill it with you api key
GOODREADS_PUBLIC_API_KEY = 'write here your goodreads public API key' GOODREADS_PUBLIC_API_KEY = "write here your goodreads public API key"
GOOGLE_SEARCH_RAPIDAPI_HOST = ""
GOOGLE_SEARCH_RAPIDAPI_KEY = ""
GOOGLE_BOOK_API_KEY = ""

View File

@@ -3,51 +3,105 @@ import xml.etree.ElementTree as ET
import urllib.request import urllib.request
import urllib.error import urllib.error
from config import GOODREADS_PUBLIC_API_KEY import requests
from bs4 import BeautifulSoup
from config import GOODREADS_PUBLIC_API_KEY, GOOGLE_SEARCH_RAPIDAPI_HOST, GOOGLE_SEARCH_RAPIDAPI_KEY, GOOGLE_BOOK_API_KEY
from googlesearch import search
def get_details(book_object): def get_details(book_object):
url = "http://www.goodreads.com/book/title.xml?key={}&title={}".format(GOODREADS_PUBLIC_API_KEY, url = "http://www.goodreads.com/book/title.xml?key={}&title={}".format(
urllib.parse.quote_plus(book_object['title'])) GOODREADS_PUBLIC_API_KEY, urllib.parse.quote_plus(book_object["title"])
)
print(url)
try: try:
tree = ET.ElementTree(file=urllib.request.urlopen(url)) time_to_sleep = 1
while True:
response = urllib.request.urlopen(url)
print(response.getcode())
if response.getcode() == 429:
time_to_sleep = time_to_sleep * 2
print("Sleeping for {}".format(time_to_sleep))
time.sleep(time_to_sleep)
else:
break
tree = ET.ElementTree(file=response)
root = tree.getroot() root = tree.getroot()
book = root.find('book') book = root.find("book")
book_object['year'] = book.find('publication_year').text or '' book_object["year"] = book.find("publication_year").text or ""
book_object['lang'] = book.find('language_code').text book_object["lang"] = book.find("language_code").text
book_object['rating'] = book.find('average_rating').text book_object["rating"] = book.find("average_rating").text
book_object['pages'] = book.find('num_pages').text book_object["pages"] = book.find("num_pages").text
book_object["image_url"] = book.find("image_url").text
book_object["isbn"] = book.find("isbn").text
description = book.find("description").text
if description:
book_object["description"] = BeautifulSoup(description).text
else:
book_object["description"] = ""
if GOOGLE_BOOK_API_KEY.strip(" "):
# Attempt to use Google Book API
url = "https://www.googleapis.com/books/v1/volumes?q={}+inauthor:{}&key={}".format(
book_object["title"], book_object["author"], GOOGLE_BOOK_API_KEY,
)
response = requests.request("GET", url)
for item in response.json()["items"]:
if "description" in item["volumeInfo"]:
book_object["description"] = item["volumeInfo"]["description"]
break
print("Fetching amazon link")
url = "https://google-search3.p.rapidapi.com/api/v1/search/q=site:amazon.com {} {}".format(book_object["title"], book_object["author"])
headers = {
'x-rapidapi-host': GOOGLE_SEARCH_RAPIDAPI_HOST,
'x-rapidapi-key': GOOGLE_SEARCH_RAPIDAPI_KEY,
}
response = requests.request("GET", url, headers=headers)
book_object["amazon_url"] = response.json()["results"][0]["link"]
return True
except urllib.error.HTTPError as e: except urllib.error.HTTPError as e:
print('Error getting book details from GoodReads for book: {}. \nGot error: '.format(book_object['title'])) print(
print(str(e.getcode()) + ' ' + e.msg) "Error getting book details from GoodReads for book: {}. \nGot error: ".format(
book_object["title"]
)
)
print(str(e.getcode()) + " " + e.msg)
return False
def get_goodread_info(library): def get_goodread_info(library, force):
import sys import sys
print('')
print('Getting GoodReads data...') print("")
print("Getting GoodReads data...")
processed = 0 processed = 0
total_book_count = 0 total_book_count = 0
for key in library: for key in library:
total_book_count += len(library[key]) total_book_count += len(library[key])
for category in library:
for chapter in library: book_list = library[category]
book_list = library[chapter]
for book in book_list: for book in book_list:
# do not call the api again if we already have the infomation # do not call the api again if we already have the infomation
if 'rating' in book and book['rating']: if not force and "rating" in book and book["rating"]:
processed += 1 processed += 1
continue continue
get_details(book) get_details(book)
processed += 1 processed += 1
print('{}/{} records processed.'.format(processed, total_book_count), end="\b") print(
sys.stdout.write('\r') "{}/{} records processed.".format(processed, total_book_count), end="\b"
)
sys.stdout.write("\r")
sys.stdout.flush() # <- makes python print it anyway sys.stdout.flush() # <- makes python print it anyway
# need to wait a second between the requests, to not abuse the API # need to wait a second between the requests, to not abuse the API
time.sleep(1) time.sleep(1)

View File

@@ -1,3 +1,5 @@
import simplejson
# we assume that every line after # Books # we assume that every line after # Books
# starting with * is a book title if file type is old # starting with * is a book title if file type is old
# starting with | (and not with | Name or |--) is a book if the file type is new # starting with | (and not with | Name or |--) is a book if the file type is new
@@ -5,51 +7,71 @@
# ARGUMENT HANDLING # ARGUMENT HANDLING
try: try:
import argparse import argparse
parser = argparse.ArgumentParser(description='Process file.')
parser = argparse.ArgumentParser(description="Process file.")
parser.add_argument("--in_file", help="File to process, defaults to ./../README.MD")
parser.add_argument( parser.add_argument(
'--in_file', "--out_file", help="File to save to, defaults to ./../README-NEW.MD"
help='File to process, defaults to ./../README.MD') )
parser.add_argument( parser.add_argument(
'--out_file', "--input_file_type",
help='File to save to, defaults to ./../README-NEW.MD') choices=["old", "new"],
help="old if links are displayed in a list, new if in a table",
)
parser.add_argument( parser.add_argument(
'--file_type', "--sort_by",
choices=['old', 'new'], choices=["rating", "title", "author", "year"],
help='old if links are displayed in a list, new if in a table') help="defaults to rating",
)
parser.add_argument("--force", dest="force", action="store_true", default=False)
parser.add_argument( parser.add_argument(
'--sort_by', "--store-json", dest="store_json", action="store_true", default=False
choices = ['rating', 'title', 'author', 'year'], )
help='defaults to rating')
flags = parser.parse_args() flags = parser.parse_args()
except ImportError: except ImportError:
flags = None flags = None
def sort(library, key_to_sort_on, reverse = False): def sort(library, key_to_sort_on, reverse=False):
new_library = {} new_library = {}
for key in library: for key in library:
books = library[key] books = library[key]
new_library[key] = sorted(books, key=lambda k: k[key_to_sort_on], reverse=reverse) new_library[key] = sorted(
books, key=lambda k: k[key_to_sort_on], reverse=reverse
)
return new_library return new_library
def format_library(library):
formated_library = []
for category in library:
for book in library[category]:
book["category"] = category[len("## ") :]
formated_library.append(book)
return formated_library
def main(): def main():
from read_file import load from read_file import load
from gooodreads import get_goodread_info from gooodreads import get_goodread_info
from write_file import render from write_file import render
in_file = flags.in_file or './../README.MD' in_file = flags.in_file or "./../README.md"
out_file = flags.out_file or './../README-new.md' out_file = flags.out_file or "./../README-new.md"
file_type = flags.file_type or 'new' input_file_type = flags.input_file_type or "new"
sort_by = flags.sort_by or 'rating' sort_by = flags.sort_by or "rating"
reverse = True if sort_by == 'rating' else False force = flags.force
store_json = flags.store_json
reverse = True if sort_by == "rating" else False
library = load(in_file, file_type) library = load(in_file, input_file_type)
get_goodread_info(library) get_goodread_info(library, force)
library = sort(library, sort_by, reverse) library = sort(library, sort_by, reverse)
render(in_file, out_file, library) render(in_file, out_file, library)
if store_json:
with open("out.json", "w") as f:
f.write(simplejson.dumps(format_library(library), indent=4, sort_keys=True))
if __name__ == '__main__':
if __name__ == "__main__":
main() main()

8
utils/pyvenv.cfg Normal file
View File

@@ -0,0 +1,8 @@
home = /usr
implementation = CPython
version_info = 3.8.5.final.0
virtualenv = 20.0.20
include-system-site-packages = false
base-prefix = /usr
base-exec-prefix = /usr
base-executable = /usr/bin/python3

View File

@@ -8,24 +8,24 @@ def read_file_content(file):
# old (list) # old (list)
def parse_book_string(book_string): def parse_book_string(book_string):
book = {} book = {}
book['title'] = book_string.split('[')[1].split(']')[0] book["title"] = book_string.split("[")[1].split("]")[0]
book['url'] = book_string.split(']')[1].split('(')[1].split(')')[0] book["url"] = book_string.split("]")[1].split("(")[1].split(")")[0]
book['author'] = book_string.split(' by ')[-1] book["author"] = book_string.split(" by ")[-1]
book['rating'] = '' book["rating"] = ""
book['year'] = '' book["year"] = ""
return book return book
# new (table) # new (table)
def parse_book_string_new(book_string): def parse_book_string_new(book_string):
book = {} book = {}
book_split = book_string.split('|') book_split = book_string.split("|")
# print(book_split) # print(book_split)
book['title'] = book_split[1].strip() book["title"] = book_split[1].strip()
book['author'] = book_split[2].strip() book["author"] = book_split[2].strip()
book['url'] = book_split[3].strip().split('[')[1].split('(')[1].split(')')[0] book["url"] = book_split[3].strip().split("[")[1].split("(")[1].split(")")[0]
book['rating'] = book_split[3].strip().split('[')[1].split(']')[0] book["rating"] = book_split[3].strip().split("[")[1].split("]")[0]
book['year'] = book_split[4].strip() book["year"] = book_split[4].strip()
return book return book
@@ -33,8 +33,8 @@ def load(file, file_type):
file = read_file_content(file) file = read_file_content(file)
# we start one line after tilte # Books # we start one line after tilte # Books
line_to_start = file.index('# Books') + 1 line_to_start = file.index("# Books") + 1
current_title = '' current_title = ""
books_under_current_title = [] books_under_current_title = []
library = {} library = {}
@@ -42,7 +42,7 @@ def load(file, file_type):
line = file[i] line = file[i]
# we have a title # we have a title
if line.startswith('##'): if line.startswith("##"):
if len(current_title) == 0: if len(current_title) == 0:
current_title = line current_title = line
else: else:
@@ -52,12 +52,16 @@ def load(file, file_type):
continue continue
# we have a book # we have a book
if file_type == 'old': if file_type == "old":
if line.startswith('*'): if line.startswith("*"):
book = parse_book_string(line) book = parse_book_string(line)
books_under_current_title.append(book) books_under_current_title.append(book)
else: else:
if line.startswith('|') and not line.startswith('| Name') and not line.startswith('|---'): if (
line.startswith("|")
and not line.startswith("| Name")
and not line.startswith("|---")
):
book = parse_book_string_new(line) book = parse_book_string_new(line)
books_under_current_title.append(book) books_under_current_title.append(book)

26
utils/requirements.txt Normal file
View File

@@ -0,0 +1,26 @@
appdirs==1.4.4
attrs==20.1.0
black==19.10b0
click==7.1.2
pathspec==0.8.0
regex==2020.7.14
toml==0.10.1
typed-ast==1.4.1
amzsear==2.0.1
appdirs==1.4.4
attrs==20.1.0
beautifulsoup4==4.9.1
black==19.10b0
bs4==0.0.1
certifi==2020.6.20
chardet==3.0.4
click==7.1.2
google==3.0.0
idna==2.10
pathspec==0.8.0
regex==2020.7.14
requests==2.24.0
soupsieve==2.0.1
toml==0.10.1
typed-ast==1.4.1
urllib3==1.25.10

View File

@@ -0,0 +1,94 @@
import json
import time
from read_file import load
from gooodreads import get_details
from bs4 import BeautifulSoup
required_fields = [
"title",
"author",
"url",
"rating",
"year",
"pages",
"image_url",
"description",
"category",
"amazon_url",
]
def book_has_all_fields(book):
for required_field in required_fields:
if required_field not in existing_book:
print(f"Missing {required_field}")
return False
return True
def clean_category(category_raw):
if "### " in category_raw:
return category_raw[4:]
if "## " in category_raw:
return category_raw[3:]
def validate_bookcover(book_details):
"""
Check if goodreads returns a nophoto
Use open library to fetch the book cover
based on ISBN
Args:
book_details: Book info returned as json by goodreads API
Returns:
This API checks for book cover, and returns with a valid
bookcover if nophoto found on goodreads, using openlibrary
"""
no_photo_url='https://s.gr-assets.com/assets/nophoto/book/'
open_library_url='http://covers.openlibrary.org/b/isbn/{isbn}-M.jpg'
if (book_details['image_url'].__contains__(no_photo_url)):
book_details['image_url'] = open_library_url.format(isbn=book_details['isbn'])
return book_details
if __name__ == "__main__":
library = load("../README.md", "new")
existing_book_names_to_details = json.load(open("book_name_to_details.json"))
for category in library:
category_name = clean_category(category)
for book in library[category]:
if (title := book["title"]) in existing_book_names_to_details:
existing_book = existing_book_names_to_details[title]
if book_has_all_fields(existing_book):
print(f"🆗 {title}")
continue
new_book = {
"title": title,
"author": book["author"],
"url": book["url"],
"category": category_name,
}
fetched = get_details(new_book)
if fetched:
print(f"{title}")
new_book = validate_bookcover(new_book)
existing_book_names_to_details[title] = new_book
with open("book_name_to_details.json", "w") as f:
json.dump(
existing_book_names_to_details,
f,
sort_keys=True,
indent=4,
separators=(",", ": "),
)
book_list = []
for _, book in existing_book_names_to_details.items():
book_list.append(book)
with open("books.json", "w") as f:
json.dump(book_list, f, sort_keys=True, indent=4, separators=(",", ": "))
else:
print(f"❌ Error while fetching {title}")

View File

@@ -4,14 +4,12 @@ import os
def render_book_line(book_object): def render_book_line(book_object):
book = book_object book = book_object
book['rating'] = '?' if not 'rating' in book else book['rating'] book["rating"] = "?" if not "rating" in book else book["rating"]
book['url'] = '' if not 'url' in book else book['url'] book["url"] = "" if not "url" in book else book["url"]
book['year'] = '' if not 'year' in book else book['year'] book["year"] = "" if not "year" in book else book["year"]
return '| {} | {} | [{}]({}) | {} | \n'.format(book['title'], return "| {} | {} | [{}]({}) | {} | \n".format(
book['author'], book["title"], book["author"], book["rating"], book["url"], book["year"]
book['rating'], )
book['url'],
book['year'])
# TODO: refine this logic # TODO: refine this logic
@@ -21,32 +19,37 @@ def render(in_file, out_file, library):
savig the new file to tmp_file location, the copying it to out-file and deleting tmp_file savig the new file to tmp_file location, the copying it to out-file and deleting tmp_file
this is done to prevent issues if the in and the out file are the same this is done to prevent issues if the in and the out file are the same
""" """
tmp_file = './.tmp-file.md' tmp_file = "./.tmp-file.md"
open(tmp_file, 'a').close() open(tmp_file, "a").close()
books_not_reached = True books_not_reached = True
with open(tmp_file, 'w') as out_file_tmp: with open(tmp_file, "w") as out_file_tmp:
with open(in_file) as original_file: with open(in_file) as original_file:
for line in original_file: for line in original_file:
if line.strip() in library: if line.strip() in library:
if not books_not_reached: out_file_tmp.write('\n') if not books_not_reached:
out_file_tmp.write("\n")
books_not_reached = False books_not_reached = False
# render chapter and start of the table # render chapter and start of the table
out_file_tmp.write(line) out_file_tmp.write(line)
if len(library[line.strip()]) > 0: if len(library[line.strip()]) > 0:
out_file_tmp.write('| Name | Author | Goodreads Rating | Year Published | \n') out_file_tmp.write(
out_file_tmp.write('|------|--------|------------------|----------------| \n') "| Name | Author | Goodreads Rating | Year Published | \n"
)
out_file_tmp.write(
"|------|--------|------------------|----------------| \n"
)
# render books # render books
for book in library[line.strip()]: for book in library[line.strip()]:
out_file_tmp.write(render_book_line(book)) out_file_tmp.write(render_book_line(book))
elif books_not_reached: elif books_not_reached:
out_file_tmp.write(line) out_file_tmp.write(line)
elif line.startswith('## License'): elif line.startswith("## License"):
out_file_tmp.write('\n') out_file_tmp.write("\n")
out_file_tmp.write('\n') out_file_tmp.write("\n")
out_file_tmp.write(line) out_file_tmp.write(line)
books_not_reached = True books_not_reached = True
copyfile(tmp_file, out_file) copyfile(tmp_file, out_file)
os.remove(tmp_file) os.remove(tmp_file)