From b1799f0e549120c8f3d3837e9d5d8cbeb11d1b8f Mon Sep 17 00:00:00 2001 From: Zuby Javed Date: Fri, 30 Jun 2023 18:02:58 -0700 Subject: [PATCH 1/8] add amazon questions when the company tag is clicked --- src/background/background.ts | 18 ++++++++++ src/content-script/update-description-tab.ts | 14 +++++--- src/popup/company.html | 20 +++++++++++ src/popup/company.ts | 38 ++++++++++++++++++++ 4 files changed, 86 insertions(+), 4 deletions(-) create mode 100644 src/popup/company.html create mode 100644 src/popup/company.ts diff --git a/src/background/background.ts b/src/background/background.ts index 70730ee..1951f42 100644 --- a/src/background/background.ts +++ b/src/background/background.ts @@ -59,6 +59,24 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => { } }); +chrome.runtime.onMessage.addListener((request, sender, sendResponse) => { + if (request.action === "openCompanyPage") { + chrome.tabs.create({ + url: chrome.runtime.getURL("src/popup/company.html"), + active: true + }, function (tab) { + chrome.tabs.onUpdated.addListener(function listener(tabId, changedProps) { + // When the tab is done loading + if (tabId == tab.id && changedProps.status == "complete") { + chrome.tabs.sendMessage(tabId, request); + chrome.tabs.onUpdated.removeListener(listener); + } + }); + }); + } +}); + + chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => { // If descriptions tab is opened or updated, update the description let urlPattern = /^https:\/\/leetcode\.com\/problems\/.*\/(description\/)?/; diff --git a/src/content-script/update-description-tab.ts b/src/content-script/update-description-tab.ts index fd1a5cd..210c24e 100644 --- a/src/content-script/update-description-tab.ts +++ b/src/content-script/update-description-tab.ts @@ -97,15 +97,21 @@ function loadCompanyTags(problemTitle: string, companyTagContainer: HTMLElement) chrome.storage.local.get(['leetcodeProblems'], (result) => { const problem = result.leetcodeProblems.questions.find((problem: problem) => problem.title === problemTitle); if (problem.companies && problem.companies.length > 0) { - // slice the array to get only the first five companies const topCompanies = problem.companies.slice(0, 5); - // create a button for each company topCompanies.forEach((company: { name: string; score: any; }) => { const button = document.createElement('button'); + // opens the company page when the button is clicked + button.onclick = () => { + chrome.runtime.sendMessage({ + // passes the company name and score to the background script + action: 'openCompanyPage', company: company + }) + } + button.style.display = 'flex'; - button.style.alignItems = 'center'; // align items vertically in the center - button.style.justifyContent = 'center'; // align items horizontally in the center + button.style.alignItems = 'center'; + button.style.justifyContent = 'center'; const icon = document.createElement('img'); icon.src = `https://logo.clearbit.com/${company.name.toLowerCase().replace(/\s/g, '')}.com`; // replace spaces with nothing diff --git a/src/popup/company.html b/src/popup/company.html new file mode 100644 index 0000000..e5bbca7 --- /dev/null +++ b/src/popup/company.html @@ -0,0 +1,20 @@ + + + + + LeetCode Solutions + + + +

Company tags

+ + + + + + +
Problem NumberProblem TitleScore
+ + + + \ No newline at end of file diff --git a/src/popup/company.ts b/src/popup/company.ts new file mode 100644 index 0000000..0c32570 --- /dev/null +++ b/src/popup/company.ts @@ -0,0 +1,38 @@ + + +function main() { + chrome.storage.local.get("leetcodeProblems", function (data) { + const companyName = "Amazon"; + let solutions = []; + + console.log(data); + + data.leetcodeProblems.questions.forEach(question => { + if (!question.companies) return; + question.companies.forEach(company => { + if (company.name === companyName) { + solutions.push({ + id: question.frontend_id, + title: question.title, + score: company.score, + url: `https://leetcode.com/problems/${question.title.replace(/\s/g, '-')}/` + }); + } + }); + }); + + const table = document.getElementById("solutionTable"); + solutions.forEach(solution => { + const row = table.insertRow(-1); + row.insertCell(0).innerText = solution.id; + const titleCell = row.insertCell(1); + titleCell.innerHTML = `${solution.title}`; + row.insertCell(2).innerText = solution.score; + }); + }); + + document.getElementById("test")?.textContent = "Hello World!"; +} + +/* Run the script */ +main(); \ No newline at end of file From 9e4699210a89da5d8d562665d156a68d00aa4798 Mon Sep 17 00:00:00 2001 From: Zuby Javed Date: Fri, 30 Jun 2023 18:33:56 -0700 Subject: [PATCH 2/8] track the clicked company and display the problems asked sorted by the score --- src/background/background.ts | 42 +++++++++------- src/content-script/update-description-tab.ts | 12 ++++- src/popup/company.css | 50 ++++++++++++++++++++ src/popup/company.html | 10 ++-- src/popup/company.ts | 16 +++++-- 5 files changed, 106 insertions(+), 24 deletions(-) create mode 100644 src/popup/company.css diff --git a/src/background/background.ts b/src/background/background.ts index 1951f42..c6f03e5 100644 --- a/src/background/background.ts +++ b/src/background/background.ts @@ -11,11 +11,14 @@ chrome.runtime.onInstalled.addListener(() => { .catch((error) => { console.error(error); }); + + // Default settings chrome.storage.local.set({ language: 'python' }); chrome.storage.local.set({ fontSize: 14 }); chrome.storage.local.set({ showCompanyTags: true }); chrome.storage.local.set({ showExamples: true }); chrome.storage.local.set({ showDifficulty: true }); + chrome.storage.local.set({ clickedCompany: 'Amazon' }) }); chrome.runtime.onMessage.addListener( @@ -44,6 +47,28 @@ chrome.runtime.onMessage.addListener( } ); +chrome.runtime.onMessage.addListener((request, sender, sendResponse) => { + if (request.action === "openCompanyPage") { + chrome.storage.local.set({ clickedCompany: request.company }); + chrome.tabs.create({ + url: chrome.runtime.getURL("src/popup/company.html"), + active: true + }, function (tab) { + // Keep a reference to the listener so it can be removed later + let listener = function (tabId, changedProps) { + // When the tab is done loading + if (tabId == tab.id && changedProps.status == "complete") { + chrome.tabs.sendMessage(tabId, request); + // Remove the listener once the tab is loaded + chrome.tabs.onUpdated.removeListener(listener); + } + }; + // Attach the listener + chrome.tabs.onUpdated.addListener(listener); + }); + } +}); + chrome.runtime.onMessage.addListener((request: any) => { if (request.type === 'OPEN_LOGIN_PAGE') { chrome.tabs.create({ url: 'https://chat.openai.com' }); @@ -59,22 +84,7 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => { } }); -chrome.runtime.onMessage.addListener((request, sender, sendResponse) => { - if (request.action === "openCompanyPage") { - chrome.tabs.create({ - url: chrome.runtime.getURL("src/popup/company.html"), - active: true - }, function (tab) { - chrome.tabs.onUpdated.addListener(function listener(tabId, changedProps) { - // When the tab is done loading - if (tabId == tab.id && changedProps.status == "complete") { - chrome.tabs.sendMessage(tabId, request); - chrome.tabs.onUpdated.removeListener(listener); - } - }); - }); - } -}); + chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => { diff --git a/src/content-script/update-description-tab.ts b/src/content-script/update-description-tab.ts index 210c24e..3da5786 100644 --- a/src/content-script/update-description-tab.ts +++ b/src/content-script/update-description-tab.ts @@ -101,14 +101,24 @@ function loadCompanyTags(problemTitle: string, companyTagContainer: HTMLElement) // create a button for each company topCompanies.forEach((company: { name: string; score: any; }) => { const button = document.createElement('button'); + // opens the company page when the button is clicked button.onclick = () => { chrome.runtime.sendMessage({ // passes the company name and score to the background script - action: 'openCompanyPage', company: company + action: 'openCompanyPage', company: company.name }) } + + // on hover, set background color to black + button.onmouseover = () => { + button.style.color = 'orange'; + } + button.onmouseout = () => { + button.style.color = 'white'; + } + button.style.display = 'flex'; button.style.alignItems = 'center'; button.style.justifyContent = 'center'; diff --git a/src/popup/company.css b/src/popup/company.css new file mode 100644 index 0000000..427be2f --- /dev/null +++ b/src/popup/company.css @@ -0,0 +1,50 @@ +body { + background-color: #202020; + color: #f0f0f0; + font-size: 18px; + font-family: 'Roboto', sans-serif; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + margin: 0; + padding: 20px; +} + +h1 { + font-size: 36px; + margin-bottom: 20px; + color: lightcyan; +} + +table { + border-collapse: collapse; + margin: auto; + width: 500px; +} + +table, +th, +td { + border: 1px solid #FFFFFF; + padding: 10px; + text-align: center; +} + +th { + font-size: 18px; + background-color: #424242; +} + +td { + font-size: 16px; +} + +a { + color: lightgreen; + text-decoration: none; +} + +a:hover { + color: #a0a0a0; +} \ No newline at end of file diff --git a/src/popup/company.html b/src/popup/company.html index e5bbca7..ea6fe09 100644 --- a/src/popup/company.html +++ b/src/popup/company.html @@ -2,15 +2,19 @@ + LeetCode Solutions -

Company tags

+

Amazon

+

+ Score = How many times this question has been asked in interviews in the past 2 years. +

- - + +
Problem NumberProblem Title#Title Score
diff --git a/src/popup/company.ts b/src/popup/company.ts index 0c32570..f3dd9bf 100644 --- a/src/popup/company.ts +++ b/src/popup/company.ts @@ -1,8 +1,15 @@ +function main() { + let companyName = "Amazon"; + + + chrome.storage.local.get("clickedCompany", function (data) { + companyName = data.clickedCompany; + document.getElementById("title").textContent = companyName; + document.title = companyName + "'s favorite problems" + }); -function main() { chrome.storage.local.get("leetcodeProblems", function (data) { - const companyName = "Amazon"; let solutions = []; console.log(data); @@ -22,6 +29,9 @@ function main() { }); const table = document.getElementById("solutionTable"); + + solutions.sort((a, b) => b.score - a.score); + solutions.forEach(solution => { const row = table.insertRow(-1); row.insertCell(0).innerText = solution.id; @@ -30,8 +40,6 @@ function main() { row.insertCell(2).innerText = solution.score; }); }); - - document.getElementById("test")?.textContent = "Hello World!"; } /* Run the script */ From 8042bcc876e1b2522ee85351786d7cab5bd79ada Mon Sep 17 00:00:00 2001 From: Zuby Javed Date: Fri, 30 Jun 2023 18:44:58 -0700 Subject: [PATCH 3/8] styling updates, add header to explain the score property, update title with company name from local storage --- src/popup/company.css | 3 ++- src/popup/company.html | 5 ++++- src/popup/company.ts | 6 +----- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/popup/company.css b/src/popup/company.css index 427be2f..aacc72e 100644 --- a/src/popup/company.css +++ b/src/popup/company.css @@ -7,6 +7,7 @@ body { flex-direction: column; align-items: center; justify-content: center; + text-align: center; margin: 0; padding: 20px; } @@ -46,5 +47,5 @@ a { } a:hover { - color: #a0a0a0; + color: lightcyan; } \ No newline at end of file diff --git a/src/popup/company.html b/src/popup/company.html index ea6fe09..e11da2b 100644 --- a/src/popup/company.html +++ b/src/popup/company.html @@ -9,7 +9,10 @@

Amazon

- Score = How many times this question has been asked in interviews in the past 2 years. + Score = How likely the company is to ask this question on a scale of 1-10 +

+

+ Data collected from 2021-2023

diff --git a/src/popup/company.ts b/src/popup/company.ts index f3dd9bf..23f4ed9 100644 --- a/src/popup/company.ts +++ b/src/popup/company.ts @@ -1,7 +1,7 @@ function main() { let companyName = "Amazon"; - + let solutions = []; chrome.storage.local.get("clickedCompany", function (data) { companyName = data.clickedCompany; @@ -10,10 +10,6 @@ function main() { }); chrome.storage.local.get("leetcodeProblems", function (data) { - let solutions = []; - - console.log(data); - data.leetcodeProblems.questions.forEach(question => { if (!question.companies) return; question.companies.forEach(company => { From 0dae879a4445522f8f1bd9fcede9cea7205a0644 Mon Sep 17 00:00:00 2001 From: Zuby Javed Date: Fri, 30 Jun 2023 18:59:27 -0700 Subject: [PATCH 4/8] add ability to sort by id, title, and score --- src/popup/company.css | 11 +++++++++ src/popup/company.html | 6 ++--- src/popup/company.ts | 51 ++++++++++++++++++++++++++++++++++++++---- 3 files changed, 61 insertions(+), 7 deletions(-) diff --git a/src/popup/company.css b/src/popup/company.css index aacc72e..22c3f13 100644 --- a/src/popup/company.css +++ b/src/popup/company.css @@ -48,4 +48,15 @@ a { a:hover { color: lightcyan; +} + +.header { + color: lightgreen; + +} + +.header:hover { + cursor: pointer; + color: lightcyan; + background-color: #202020; } \ No newline at end of file diff --git a/src/popup/company.html b/src/popup/company.html index e11da2b..585bc5a 100644 --- a/src/popup/company.html +++ b/src/popup/company.html @@ -16,9 +16,9 @@

Amazon

- - - + + +
#TitleScore#TitleScore
diff --git a/src/popup/company.ts b/src/popup/company.ts index 23f4ed9..f6b5a36 100644 --- a/src/popup/company.ts +++ b/src/popup/company.ts @@ -1,7 +1,9 @@ +// define solutions and companyName outside of the functions so they can be accessed globally +let solutions = []; +let companyName = "Amazon"; + function main() { - let companyName = "Amazon"; - let solutions = []; chrome.storage.local.get("clickedCompany", function (data) { companyName = data.clickedCompany; @@ -9,6 +11,16 @@ function main() { document.title = companyName + "'s favorite problems" }); + addCompanyProblems("Score"); + + // attach click listeners to table headers for sorting + document.getElementById('#').addEventListener('click', () => sortBy('#')); + document.getElementById('Title').addEventListener('click', () => sortBy('Title')); + document.getElementById('Score').addEventListener('click', () => sortBy('Score')); +} + +// Adds the company problems by sorting method +function addCompanyProblems(sortMethod) { chrome.storage.local.get("leetcodeProblems", function (data) { data.leetcodeProblems.questions.forEach(question => { if (!question.companies) return; @@ -26,7 +38,9 @@ function main() { const table = document.getElementById("solutionTable"); - solutions.sort((a, b) => b.score - a.score); + if (sortMethod === "Score") { + solutions.sort((a, b) => b.score - a.score); + } solutions.forEach(solution => { const row = table.insertRow(-1); @@ -38,5 +52,34 @@ function main() { }); } +function sortBy(column) { + if (column === 'Score') { + solutions.sort((a, b) => b.score - a.score); + } + else if (column === 'Title') { + solutions.sort((a, b) => a.title.localeCompare(b.title)); + } + else { + solutions.sort((a, b) => a.id - b.id); + } + + // after sorting, you might want to re-render your table + const table = document.getElementById("solutionTable"); + + // remove all existing rows + while (table.rows.length > 1) { + table.deleteRow(1); + } + + // add sorted rows + solutions.forEach(solution => { + const row = table.insertRow(-1); + row.insertCell(0).innerText = solution.id; + const titleCell = row.insertCell(1); + titleCell.innerHTML = `${solution.title}`; + row.insertCell(2).innerText = solution.score; + }); +} + /* Run the script */ -main(); \ No newline at end of file +main(); From cda3a52b9e030428a25b68ea98eace897ee763ad Mon Sep 17 00:00:00 2001 From: Zuby Javed Date: Fri, 30 Jun 2023 19:05:15 -0700 Subject: [PATCH 5/8] add types --- src/popup/company.css | 4 ++-- src/popup/company.ts | 16 ++++++++-------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/popup/company.css b/src/popup/company.css index 22c3f13..9bd0ed2 100644 --- a/src/popup/company.css +++ b/src/popup/company.css @@ -51,12 +51,12 @@ a:hover { } .header { - color: lightgreen; + color: lightcyan; } .header:hover { + color: lightgreen; cursor: pointer; - color: lightcyan; background-color: #202020; } \ No newline at end of file diff --git a/src/popup/company.ts b/src/popup/company.ts index f6b5a36..38cae8f 100644 --- a/src/popup/company.ts +++ b/src/popup/company.ts @@ -1,5 +1,5 @@ // define solutions and companyName outside of the functions so they can be accessed globally -let solutions = []; +let solutions = [] as { id: number, title: string, score: number, url: string }[]; let companyName = "Amazon"; function main() { @@ -7,20 +7,20 @@ function main() { chrome.storage.local.get("clickedCompany", function (data) { companyName = data.clickedCompany; - document.getElementById("title").textContent = companyName; + document.getElementById("title")!.textContent = companyName; document.title = companyName + "'s favorite problems" }); addCompanyProblems("Score"); // attach click listeners to table headers for sorting - document.getElementById('#').addEventListener('click', () => sortBy('#')); - document.getElementById('Title').addEventListener('click', () => sortBy('Title')); - document.getElementById('Score').addEventListener('click', () => sortBy('Score')); + document.getElementById('#')!.addEventListener('click', () => sortBy('#')); + document.getElementById('Title')!.addEventListener('click', () => sortBy('Title')); + document.getElementById('Score')!.addEventListener('click', () => sortBy('Score')); } // Adds the company problems by sorting method -function addCompanyProblems(sortMethod) { +function addCompanyProblems(sortMethod: string) { chrome.storage.local.get("leetcodeProblems", function (data) { data.leetcodeProblems.questions.forEach(question => { if (!question.companies) return; @@ -43,7 +43,7 @@ function addCompanyProblems(sortMethod) { } solutions.forEach(solution => { - const row = table.insertRow(-1); + const row = table!.insertRow(-1); row.insertCell(0).innerText = solution.id; const titleCell = row.insertCell(1); titleCell.innerHTML = `${solution.title}`; @@ -52,7 +52,7 @@ function addCompanyProblems(sortMethod) { }); } -function sortBy(column) { +function sortBy(column: string) { if (column === 'Score') { solutions.sort((a, b) => b.score - a.score); } From 59822e0e58382f7e50052c90b3bbd580de258fdb Mon Sep 17 00:00:00 2001 From: Zuby Javed Date: Fri, 30 Jun 2023 19:09:59 -0700 Subject: [PATCH 6/8] update description --- manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manifest.json b/manifest.json index 4978e66..19bec77 100644 --- a/manifest.json +++ b/manifest.json @@ -2,7 +2,7 @@ "manifest_version": 3, "name": "Leetcode Explained", "version": "2.0.4", - "description": "Adds video solutions, company tags, and GPT code analysis into each problem.", + "description": "Adds video solutions, company tags, GPT code analysis and more.", "icons": { "16": "src/assets/images/logo/icon-16.png", "32": "src/assets/images/logo/icon-32.png", From e1adac997fe8d10465f67f0b69c2a39e7872992a Mon Sep 17 00:00:00 2001 From: Zuby Javed Date: Fri, 30 Jun 2023 19:13:18 -0700 Subject: [PATCH 7/8] bold the score --- src/popup/company.css | 5 +++++ src/popup/company.html | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/popup/company.css b/src/popup/company.css index 9bd0ed2..870cb3b 100644 --- a/src/popup/company.css +++ b/src/popup/company.css @@ -59,4 +59,9 @@ a:hover { color: lightgreen; cursor: pointer; background-color: #202020; +} + +#score { + color: lightgreen; + font-weight: bold; } \ No newline at end of file diff --git a/src/popup/company.html b/src/popup/company.html index 585bc5a..ca2f0f0 100644 --- a/src/popup/company.html +++ b/src/popup/company.html @@ -9,7 +9,7 @@

Amazon

- Score = How likely the company is to ask this question on a scale of 1-10 + Score = How likely the company is to ask this question on a scale of 1-10

Data collected from 2021-2023 From fd4d38978fa320046c38d394d6cc35a5fe8428f6 Mon Sep 17 00:00:00 2001 From: Zuby Javed Date: Fri, 30 Jun 2023 20:53:00 -0700 Subject: [PATCH 8/8] tell gpt to stop yappin --- src/popup/popup.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/popup/popup.ts b/src/popup/popup.ts index aa304bf..a1a66cf 100644 --- a/src/popup/popup.ts +++ b/src/popup/popup.ts @@ -109,7 +109,7 @@ function processCode( prompt = ` As an experienced software engineer, please analyze the Leetcode problem titled ${problemTitle} and the accompanying code below. Your analysis should be concise and straightforward, providing both time and space complexity in big O notation. - Please include a brief explanation (no more than 1-2 lines) for each complexity analysis. + Please include a brief, concise explanation (no more than 1-2 lines) for each complexity analysis. Space complexity should not include the output (return value) of the function. Your analysis should be direct and to the point. The code is provided below.