feat: base level auto skip for new on expeired
This commit is contained in:
parent
842fb23275
commit
e591af4d73
@ -3,81 +3,115 @@
|
||||
});*/
|
||||
|
||||
browser.runtime.onMessage.addListener(async (message, sender, sendResponse) => {
|
||||
if (message.type === "REGISTER_INTEREST") {
|
||||
let interestList =
|
||||
(await browser.storage.local.get("interesetWindows"))
|
||||
.interesetWindows ?? [];
|
||||
// Already has interest!
|
||||
if (interestList.includes(sender.tab.id)) {
|
||||
return;
|
||||
}
|
||||
interestList.push(sender.tab.id);
|
||||
if (message.type === "REGISTER_INTEREST") {
|
||||
let interestList =
|
||||
(await browser.storage.local.get("interesetWindows"))
|
||||
.interesetWindows ?? [];
|
||||
// Already has interest!
|
||||
if (interestList.includes(sender.tab.id)) {
|
||||
return;
|
||||
}
|
||||
interestList.push(sender.tab.id);
|
||||
|
||||
await browser.storage.local.set({
|
||||
interesetWindows: interestList,
|
||||
});
|
||||
await browser.storage.local.set({
|
||||
interesetWindows: interestList,
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
if (message.type === "GOT_INFO_R") {
|
||||
// TODO then send this information back to that page
|
||||
let interestList =
|
||||
(await browser.storage.local.get("interesetWindows"))
|
||||
.interesetWindows ?? [];
|
||||
let windowList = (await browser.storage.local.get("windows")).windows;
|
||||
if (windowList) {
|
||||
console.log("here sending got interest");
|
||||
browser.tabs.sendMessage(sender.tab.id, {
|
||||
type: "GOT_INTEREST",
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (message.type === "AUTOLOAD_NOTIFY_URL") {
|
||||
// TODO then send this information back to that page
|
||||
let interestList =
|
||||
(await browser.storage.local.get("interesetWindows"))
|
||||
.interesetWindows ?? [];
|
||||
|
||||
interestList.forEach((a) => {
|
||||
browser.tabs.sendMessage(a, message);
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (message.type === "R_GET_DATA_FROM_PAGE") {
|
||||
let windowList = (await browser.storage.local.get("windows")).windows;
|
||||
interestList.forEach((a) => {
|
||||
browser.tabs.sendMessage(a, {
|
||||
type: "MY_GET_URL_R",
|
||||
url: message.url,
|
||||
});
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (
|
||||
message.type === "GOT_INFO_R" ||
|
||||
message.type === "AUTOLOAD_FOUND_GLASSDOOR_SEARCH"
|
||||
) {
|
||||
// TODO then send this information back to that page
|
||||
let interestList =
|
||||
(await browser.storage.local.get("interesetWindows"))
|
||||
.interesetWindows ?? [];
|
||||
|
||||
interestList.forEach((a) => {
|
||||
browser.tabs.sendMessage(a, message);
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (message.type === "R_GET_DATA_FROM_PAGE") {
|
||||
let windowList = (await browser.storage.local.get("windows")).windows;
|
||||
if (!windowList) return;
|
||||
const tab = await browser.tabs.get(windowList);
|
||||
const tab = await browser.tabs.get(windowList);
|
||||
browser.tabs.sendMessage(tab.id, {
|
||||
type: "GET_DATA_FROM_PAGE",
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (message.type !== "MY_GET_URL") return;
|
||||
if (message.type === "CHANGE_PAGE") {
|
||||
let windowList = (await browser.storage.local.get("windows")).windows;
|
||||
if (!windowList) return;
|
||||
const tab = await browser.tabs.get(windowList);
|
||||
browser.tabs.sendMessage(tab.id, {
|
||||
type: "CHANGE_PAGE",
|
||||
new_url: message.new_url,
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (message.type !== "MY_GET_URL") return;
|
||||
|
||||
let windowList = (await browser.storage.local.get("windows")).windows;
|
||||
if (!windowList) {
|
||||
browser.tabs.sendMessage(sender.tab.id, {
|
||||
type: "MY_GET_URL_R",
|
||||
error: "Invalid number of pages marked as target",
|
||||
data: windowList,
|
||||
});
|
||||
return;
|
||||
}
|
||||
let windowList = (await browser.storage.local.get("windows")).windows;
|
||||
if (!windowList) {
|
||||
browser.tabs.sendMessage(sender.tab.id, {
|
||||
type: "MY_GET_URL_R",
|
||||
error: "Invalid number of pages marked as target",
|
||||
data: windowList,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const tab = await browser.tabs.get(windowList);
|
||||
const tab = await browser.tabs.get(windowList);
|
||||
|
||||
browser.tabs.sendMessage(tab.id, {
|
||||
type: "GET_DATA_FROM_PAGE",
|
||||
});
|
||||
browser.tabs.sendMessage(tab.id, {
|
||||
type: "GET_DATA_FROM_PAGE",
|
||||
});
|
||||
|
||||
browser.tabs.sendMessage(sender.tab.id, {
|
||||
type: "MY_GET_URL_R",
|
||||
url: tab.url,
|
||||
all_data: tab,
|
||||
});
|
||||
browser.tabs.sendMessage(sender.tab.id, {
|
||||
type: "MY_GET_URL_R",
|
||||
url: tab.url,
|
||||
all_data: tab,
|
||||
});
|
||||
});
|
||||
|
||||
async function startup() {
|
||||
console.log("Exp startup application")
|
||||
await browser.storage.local.set({
|
||||
windows: null,
|
||||
interesetWindows: [],
|
||||
});
|
||||
console.log("Exp startup application");
|
||||
await browser.storage.local.set({
|
||||
windows: null,
|
||||
interesetWindows: [],
|
||||
});
|
||||
|
||||
// Clear the menus from the prev install / startup
|
||||
browser.menus.removeAll();
|
||||
browser.menus.create({
|
||||
id: "mark-page",
|
||||
title: "Mark Page As the Url target",
|
||||
contexts: ["all"],
|
||||
});
|
||||
// Clear the menus from the prev install / startup
|
||||
browser.menus.removeAll();
|
||||
browser.menus.create({
|
||||
id: "mark-page",
|
||||
title: "Mark Page As the Url target",
|
||||
contexts: ["all"],
|
||||
});
|
||||
}
|
||||
|
||||
browser.runtime.onInstalled.addListener(startup);
|
||||
@ -85,9 +119,35 @@ browser.runtime.onStartup.addListener(startup);
|
||||
browser.runtime.onConnect.addListener(startup);
|
||||
browser.menus.onClicked.addListener(async function (e, tab) {
|
||||
if (e.menuItemId === "mark-page") {
|
||||
console.log("set mark-page", tab.id)
|
||||
console.log("set mark-page", tab.id);
|
||||
await browser.storage.local.set({
|
||||
windows: tab.id,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
var timeout;
|
||||
var lastOrigin;
|
||||
|
||||
async function detectRequest(requestDetails) {
|
||||
let windowList = (await browser.storage.local.get("windows")).windows;
|
||||
if (!windowList || requestDetails.tabId !== windowList) return;
|
||||
if (
|
||||
requestDetails.originUrl === lastOrigin ||
|
||||
(!requestDetails.url.includes("glassdoor") &&
|
||||
!requestDetails.url.includes("linkedin"))
|
||||
) {
|
||||
return;
|
||||
}
|
||||
console.log(`Mon: ${requestDetails.url}`);
|
||||
if (timeout) clearTimeout(timeout);
|
||||
timeout = setTimeout(() => {
|
||||
console.log("autoload detected");
|
||||
lastOrigin = requestDetails.originUrl;
|
||||
browser.tabs.sendMessage(windowList, { type: "AUTOLOAD_FINISHED" });
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
browser.webRequest.onBeforeRequest.addListener(detectRequest, {
|
||||
urls: ["<all_urls>"],
|
||||
});
|
||||
|
@ -1,62 +1,169 @@
|
||||
browser.runtime.onMessage.addListener((message) => {
|
||||
if (message.type === "MY_GET_URL_R") {
|
||||
window.postMessage(message);
|
||||
} else if (message.type === "GET_DATA_FROM_PAGE") {
|
||||
// Parse things for linkedin
|
||||
if (window.location.host.includes("linkedin")) {
|
||||
if (window.location.host.includes("merchantpool1")) {
|
||||
return;
|
||||
}
|
||||
const jobTitle = document.querySelector('h1').textContent;
|
||||
const company = document.querySelector('.relative a[target="_self"]').textContent;
|
||||
|
||||
const money =
|
||||
document.querySelector('ul li div div div li-icon[type="job"]')?.parentNode?.parentNode?.parentNode?.parentNode?.children[1]?.children[0]?.textContent?.replaceAll(/\s{2,}/g, '') ??
|
||||
Object.values(document.querySelector('button[class="job-details-preferences-and-skills"]')?.children ?? []).find(a => a.innerText.match(/\d/) && !a.innerText.match('skill'))?.innerText ??
|
||||
'';
|
||||
|
||||
const inperson_type = (Object.values(document.querySelector('button[class="job-details-preferences-and-skills"]')?.children).find(a => a.innerText.match(/hybrid|remote|on-site/i))?.innerText?.split('\n') ?? [])[0]?.trim() ?? ''
|
||||
|
||||
const location = document.querySelector('div[class^="job-details-jobs-unified-top-card__primary-description-container"]')?.children[0]?.children[0]?.innerText ?? ''
|
||||
|
||||
const description = document.querySelector('article').textContent;
|
||||
|
||||
browser.runtime.sendMessage({ type: "GOT_INFO_R", company, jobTitle, money, description, location, inperson_type });
|
||||
function getPageData() {
|
||||
// Parse things for linkedin
|
||||
if (window.location.host.includes("linkedin")) {
|
||||
if (window.location.host.includes("merchantpool1")) {
|
||||
return;
|
||||
}
|
||||
// Ignore everything that is no glassdoor
|
||||
if (!window.location.host.includes("glassdoor")) return;
|
||||
const company = document.querySelector('header[data-test="job-details-header"]')
|
||||
.children[0].children[0].querySelector("h4").innerHTML;
|
||||
const jobTitle = document
|
||||
.querySelector('header[data-test="job-details-header"]')
|
||||
.querySelector("h1").innerHTML;
|
||||
const jobTitle = document.querySelector("h1").textContent;
|
||||
const company = document.querySelector(
|
||||
'.relative a[target="_self"]',
|
||||
).textContent;
|
||||
|
||||
const description = [...document.querySelector('header[data-test="job-details-header"]').parentNode.querySelectorAll('button')].filter(a => a.textContent == "Show more")[0]?.parentNode?.parentNode?.textContent;
|
||||
const money =
|
||||
document
|
||||
.querySelector('ul li div div div li-icon[type="job"]')
|
||||
?.parentNode?.parentNode?.parentNode?.parentNode?.children[1]?.children[0]?.textContent?.replaceAll(
|
||||
/\s{2,}/g,
|
||||
"",
|
||||
) ??
|
||||
Object.values(
|
||||
document.querySelector(
|
||||
'button[class="job-details-preferences-and-skills"]',
|
||||
)?.children ?? [],
|
||||
).find(
|
||||
(a) => a.innerText.match(/\d/) && !a.innerText.match("skill"),
|
||||
)?.innerText ??
|
||||
"";
|
||||
|
||||
let money = document.querySelectorAll('div[class^="SalaryEstimate_salaryRange"]')?.[0]?.innerText ?? '';
|
||||
const inperson_type =
|
||||
(Object.values(
|
||||
document.querySelector(
|
||||
'button[class="job-details-preferences-and-skills"]',
|
||||
)?.children,
|
||||
)
|
||||
.find((a) => a.innerText.match(/hybrid|remote|on-site/i))
|
||||
?.innerText?.split("\n") ?? [])[0]?.trim() ?? "";
|
||||
|
||||
const location = document.querySelector('div[data-test="location"]')?.innerText ?? '';
|
||||
const location =
|
||||
document.querySelector(
|
||||
'div[class^="job-details-jobs-unified-top-card__primary-description-container"]',
|
||||
)?.children[0]?.children[0]?.innerText ?? "";
|
||||
|
||||
const moneySectionNode = document.querySelector('section>section');
|
||||
if (moneySectionNode && ["Base pay range", "Base pay"].includes(moneySectionNode.querySelector('h2')?.textContent)) {
|
||||
money = moneySectionNode.querySelector("div>div>div").children[1]?.textContent ?? ''
|
||||
const description = document.querySelector("article").textContent;
|
||||
|
||||
let status = undefined;
|
||||
|
||||
const maybeStatus = document.querySelector(
|
||||
".artdeco-inline-feedback__message",
|
||||
)?.innerText;
|
||||
|
||||
if (maybeStatus === "No longer accepting applications") {
|
||||
status = "expired";
|
||||
}
|
||||
|
||||
browser.runtime.sendMessage({ type: "GOT_INFO_R", company, jobTitle, money, description, location, inperson_type: '' });
|
||||
} else if (message.type === "GOT_INFO_R") {
|
||||
window.postMessage(message);
|
||||
}
|
||||
browser.runtime.sendMessage({
|
||||
type: "GOT_INFO_R",
|
||||
company,
|
||||
jobTitle,
|
||||
money,
|
||||
description,
|
||||
location,
|
||||
inperson_type,
|
||||
status,
|
||||
});
|
||||
return;
|
||||
}
|
||||
// Ignore everything that is no glassdoor
|
||||
if (!window.location.host.includes("glassdoor")) return;
|
||||
const company = document
|
||||
.querySelector('header[data-test="job-details-header"]')
|
||||
.children[0].children[0].querySelector("h4").innerHTML;
|
||||
const jobTitle = document
|
||||
.querySelector('header[data-test="job-details-header"]')
|
||||
.querySelector("h1").innerHTML;
|
||||
|
||||
const description = [
|
||||
...document
|
||||
.querySelector('header[data-test="job-details-header"]')
|
||||
.parentNode.querySelectorAll("button"),
|
||||
].filter((a) => a.textContent == "Show more")[0]?.parentNode?.parentNode
|
||||
?.textContent;
|
||||
|
||||
let money =
|
||||
document.querySelectorAll(
|
||||
'div[class^="SalaryEstimate_salaryRange"]',
|
||||
)?.[0]?.innerText ?? "";
|
||||
|
||||
const location =
|
||||
document.querySelector('div[data-test="location"]')?.innerText ?? "";
|
||||
|
||||
const moneySectionNode = document.querySelector("section>section");
|
||||
if (
|
||||
moneySectionNode &&
|
||||
["Base pay range", "Base pay"].includes(
|
||||
moneySectionNode.querySelector("h2")?.textContent,
|
||||
)
|
||||
) {
|
||||
money =
|
||||
moneySectionNode.querySelector("div>div>div").children[1]
|
||||
?.textContent ?? "";
|
||||
}
|
||||
|
||||
let status = undefined;
|
||||
|
||||
if (!!document.querySelector("#expired-job-notice_Heading")) {
|
||||
status = "expired";
|
||||
}
|
||||
|
||||
browser.runtime.sendMessage({
|
||||
type: "GOT_INFO_R",
|
||||
company,
|
||||
jobTitle,
|
||||
money,
|
||||
description,
|
||||
location,
|
||||
inperson_type: "",
|
||||
status,
|
||||
});
|
||||
}
|
||||
browser.runtime.onMessage.addListener((message) => {
|
||||
if (message.type === "GET_DATA_FROM_PAGE") {
|
||||
getPageData();
|
||||
} else if (message.type === "CHANGE_PAGE") {
|
||||
window.location.href = message.new_url;
|
||||
} else if (
|
||||
message.type === "MY_GET_URL_R" ||
|
||||
message.type === "GOT_INFO_R" ||
|
||||
message.type === "GOT_INTEREST" ||
|
||||
message.type === "AUTOLOAD_FOUND_GLASSDOOR_SEARCH"
|
||||
) {
|
||||
window.postMessage(message);
|
||||
} else if (message.type === "AUTOLOAD_FINISHED") {
|
||||
if (
|
||||
window.location.href.includes("glassdoor") &&
|
||||
document.querySelector('a[data-test="for-you-page-link"]')
|
||||
) {
|
||||
browser.runtime.sendMessage({
|
||||
type: "AUTOLOAD_FOUND_GLASSDOOR_SEARCH",
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (
|
||||
!window.location.href.includes("glassdoor") &&
|
||||
!window.location.href.includes("linkedin")
|
||||
)
|
||||
return;
|
||||
browser.runtime.sendMessage({
|
||||
type: "AUTOLOAD_NOTIFY_URL",
|
||||
url: window.location.href,
|
||||
});
|
||||
setTimeout(getPageData, 1000);
|
||||
}
|
||||
});
|
||||
|
||||
window.addEventListener("message", (e) => {
|
||||
if (e.data.type === "MY_GET_URL") {
|
||||
browser.runtime.sendMessage({ type: "MY_GET_URL" });
|
||||
} else if (e.data.type === "HAS_EXTENSION_Q") {
|
||||
window.postMessage({ type: "HAS_EXTENSION" });
|
||||
} else if (e.data.type === "REGISTER_INTEREST") {
|
||||
browser.runtime.sendMessage({ type: "REGISTER_INTEREST" });
|
||||
} else if (e.data.type === "R_GET_DATA_FROM_PAGE") {
|
||||
browser.runtime.sendMessage({ type: "R_GET_DATA_FROM_PAGE" });
|
||||
if (e.data.type === "MY_GET_URL") {
|
||||
browser.runtime.sendMessage({ type: "MY_GET_URL" });
|
||||
} else if (e.data.type === "HAS_EXTENSION_Q") {
|
||||
window.postMessage({ type: "HAS_EXTENSION" });
|
||||
} else if (e.data.type === "REGISTER_INTEREST") {
|
||||
browser.runtime.sendMessage({ type: "REGISTER_INTEREST" });
|
||||
} else if (e.data.type === "R_GET_DATA_FROM_PAGE") {
|
||||
browser.runtime.sendMessage({ type: "R_GET_DATA_FROM_PAGE" });
|
||||
} else if (e.data.type === "CHANGE_PAGE") {
|
||||
browser.runtime.sendMessage({
|
||||
type: "CHANGE_PAGE",
|
||||
new_url: e.data.new_url,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
@ -1,29 +1,36 @@
|
||||
{
|
||||
"manifest_version": 2,
|
||||
"name": "Url Extractor Extension",
|
||||
"version": "1.0",
|
||||
"manifest_version": 2,
|
||||
"name": "Url Extractor Extension",
|
||||
"version": "1.0",
|
||||
|
||||
"description": "Allow my webpage to extract urls from other webpages",
|
||||
"description": "Allow my webpage to extract urls from other webpages",
|
||||
|
||||
"content_scripts": [
|
||||
{
|
||||
"matches": ["<all_urls>"],
|
||||
"js": ["definitions.js"],
|
||||
"all_frames": true
|
||||
}
|
||||
],
|
||||
"content_scripts": [
|
||||
{
|
||||
"matches": ["<all_urls>"],
|
||||
"js": ["definitions.js"],
|
||||
"all_frames": true
|
||||
}
|
||||
],
|
||||
|
||||
"permissions": ["activeTab", "menus", "tabs", "storage"],
|
||||
"permissions": [
|
||||
"activeTab",
|
||||
"menus",
|
||||
"tabs",
|
||||
"storage",
|
||||
"webRequest",
|
||||
"<all_urls>"
|
||||
],
|
||||
|
||||
"background": {
|
||||
"scripts": ["background-script.js"],
|
||||
"persistent": false,
|
||||
"type": "module"
|
||||
},
|
||||
"background": {
|
||||
"scripts": ["background-script.js"],
|
||||
"persistent": false,
|
||||
"type": "module"
|
||||
},
|
||||
|
||||
"applications": {
|
||||
"gecko": {
|
||||
"id": "me@andr3h3nriqu3s.com"
|
||||
}
|
||||
}
|
||||
"applications": {
|
||||
"gecko": {
|
||||
"id": "me@andr3h3nriqu3s.com"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,8 @@
|
||||
import ApplicationsList from './ApplicationsList.svelte';
|
||||
import WorkArea from './work-area/WorkArea.svelte';
|
||||
import ApplicationTypesList from './ApplicationTypesList.svelte';
|
||||
|
||||
let appList: ApplicationsList;
|
||||
</script>
|
||||
|
||||
<HasUser redirect="/cv">
|
||||
@ -11,8 +13,8 @@
|
||||
<NavBar />
|
||||
<div class="w-full px-4 grow h-full gap-3 flex flex-col">
|
||||
<div class="flex gap-3 flex-grow">
|
||||
<ApplicationsList />
|
||||
<WorkArea />
|
||||
<ApplicationsList bind:this={appList} />
|
||||
<WorkArea {appList} />
|
||||
</div>
|
||||
<ApplicationTypesList />
|
||||
<div class="p-3"></div>
|
||||
|
@ -49,9 +49,13 @@
|
||||
}
|
||||
}
|
||||
|
||||
export function requestNext() {
|
||||
applicationStore.loadItem = internal[0];
|
||||
}
|
||||
|
||||
function docKey(e: KeyboardEvent) {
|
||||
if (e.ctrlKey && e.code === 'KeyJ' && internal.length > 0) {
|
||||
applicationStore.loadItem = internal[0];
|
||||
requestNext();
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
return;
|
||||
@ -94,10 +98,7 @@
|
||||
}}
|
||||
role="none"
|
||||
>
|
||||
<div
|
||||
class="max-w-full"
|
||||
class:animate-pulse={applicationStore.dragging?.id === item.id}
|
||||
>
|
||||
<div class="max-w-full" class:animate-pulse={applicationStore.dragging?.id === item.id}>
|
||||
<h2 class="text-lg text-blue-500 flex gap-2 max-w-full overflow-hidden">
|
||||
<div class="flex-grow max-w-[90%]">
|
||||
<div class="whitespace-nowrap overflow-hidden">
|
||||
|
@ -3,9 +3,10 @@
|
||||
import { statusStore } from '$lib/Types.svelte';
|
||||
import { onMount } from 'svelte';
|
||||
import DropZone from './DropZone.svelte';
|
||||
import { deleteR, put } from '$lib/utils';
|
||||
import { put } from '$lib/utils';
|
||||
|
||||
let { index = $bindable() }: { index: number | undefined } = $props();
|
||||
let { index = $bindable(), onremove }: { index: number | undefined; onremove: () => void } =
|
||||
$props();
|
||||
|
||||
const derivedItem: Application | undefined = $derived(applicationStore.all[index ?? -1]);
|
||||
|
||||
@ -31,35 +32,19 @@
|
||||
applicationStore.loadItemOpen = false;
|
||||
}
|
||||
|
||||
async function remove() {
|
||||
if (!derivedItem) return;
|
||||
// Deactivate active item
|
||||
try {
|
||||
await deleteR(`application/${derivedItem.id}`);
|
||||
} catch (e) {
|
||||
// TODO: Show User
|
||||
console.log('info data', e);
|
||||
return;
|
||||
}
|
||||
applicationStore.removeByID(derivedItem.id);
|
||||
index = undefined;
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
statusStore.load();
|
||||
});
|
||||
</script>
|
||||
|
||||
{#if applicationStore.dragging && derivedItem}
|
||||
<div
|
||||
class="flex w-full flex-grow rounded-lg p-3 gap-2 absolute bottom-0 left-0 right-0 bg-white"
|
||||
>
|
||||
<div class="flex w-full flex-grow rounded-lg p-3 gap-2 absolute bottom-0 left-0 right-0 bg-white">
|
||||
{#each statusStore.dirLinks[derivedItem.status_id] as node}
|
||||
<DropZone icon={node.icon} ondrop={() => moveStatus(node.id, node.endable)}
|
||||
>{node.name}</DropZone
|
||||
>
|
||||
{/each}
|
||||
|
||||
<DropZone icon="trash-fill text-danger" ondrop={() => remove()}>Delete it</DropZone>
|
||||
<DropZone icon="trash-fill text-danger" ondrop={() => onremove()}>Delete it</DropZone>
|
||||
</div>
|
||||
{/if}
|
||||
|
114
site/src/routes/work-area/FoundExpire.svelte
Normal file
114
site/src/routes/work-area/FoundExpire.svelte
Normal file
@ -0,0 +1,114 @@
|
||||
<script lang="ts">
|
||||
import { applicationStore, type Application } from '$lib/ApplicationsStore.svelte';
|
||||
import { statusStore } from '$lib/Types.svelte';
|
||||
import { put } from '$lib/utils';
|
||||
|
||||
let {
|
||||
index = $bindable(),
|
||||
onnext
|
||||
}: {
|
||||
index: number | undefined;
|
||||
onnext: () => void;
|
||||
} = $props();
|
||||
|
||||
let dialog: HTMLDialogElement;
|
||||
|
||||
const derivedItem: Application | undefined = $derived(applicationStore.all[index ?? -1]);
|
||||
|
||||
async function moveStatus(status_id: string) {
|
||||
// Deactivate active item
|
||||
try {
|
||||
await put('application/status', {
|
||||
id: derivedItem?.id,
|
||||
status_id: status_id
|
||||
});
|
||||
} catch (e) {
|
||||
// TODO: Show User
|
||||
console.log('info data', e);
|
||||
return;
|
||||
}
|
||||
applicationStore.all[index ?? -1].status_id = status_id;
|
||||
applicationStore.reset();
|
||||
dialog.close();
|
||||
onnext();
|
||||
return;
|
||||
}
|
||||
|
||||
let status: string | null = $state(null);
|
||||
|
||||
let timeoutCount: number = $state(5);
|
||||
let timeout: undefined | number = undefined;
|
||||
$effect(() => {
|
||||
status = localStorage.getItem('expireStatus');
|
||||
return () => {
|
||||
if (timeout) clearTimeout(timeout);
|
||||
};
|
||||
});
|
||||
|
||||
export function open() {
|
||||
if (dialog) dialog.showModal();
|
||||
if (status) {
|
||||
timeoutCount = 5;
|
||||
|
||||
function timeoutF() {
|
||||
if (timeoutCount === 0) {
|
||||
moveStatus(status!);
|
||||
timeout = undefined;
|
||||
|
||||
return;
|
||||
}
|
||||
timeoutCount -= 1;
|
||||
timeout = setTimeout(timeoutF, 1000) as unknown as number;
|
||||
}
|
||||
|
||||
timeout = setTimeout(timeoutF, 1000) as unknown as number;
|
||||
}
|
||||
}
|
||||
|
||||
$effect(() => {
|
||||
localStorage.setItem('expireStatus', status ?? '');
|
||||
});
|
||||
|
||||
// TODO: Auto delete after of 5 secs of inactivity
|
||||
</script>
|
||||
|
||||
<dialog
|
||||
class="card"
|
||||
bind:this={dialog}
|
||||
onclose={() => {
|
||||
if (timeout) clearTimeout(timeout);
|
||||
}}
|
||||
>
|
||||
<div>
|
||||
<div class="text-center py-10">
|
||||
<span class="bi bi-exclamation-triangle-fill text-8xl text-orange-400"></span>
|
||||
</div>
|
||||
<h1 class="text-4xl py-5 text-center">Found Expired</h1>
|
||||
<div class="flex justify-center gap-10">
|
||||
<button
|
||||
class="btn-primary"
|
||||
onclick={() => {
|
||||
if (timeout) clearTimeout(timeout);
|
||||
dialog.close();
|
||||
}}
|
||||
>
|
||||
Ignore
|
||||
</button>
|
||||
<select bind:value={status} class="py-5">
|
||||
{#each statusStore.nodes as node}
|
||||
<option value={node.id}>
|
||||
{node.name}
|
||||
</option>
|
||||
{/each}
|
||||
</select>
|
||||
<button
|
||||
class="btn-danger"
|
||||
onclick={() => {
|
||||
if (status) moveStatus(status);
|
||||
}}
|
||||
>
|
||||
Move ({timeoutCount}) <span class="bi bi-clock-history animate-pulse"></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</dialog>
|
@ -43,7 +43,7 @@
|
||||
|
||||
$effect(() => {
|
||||
function onMessage(e: MessageEvent) {
|
||||
if (e.data.type === 'MY_GET_URL_R') {
|
||||
if (dialog.open && e.data.type === 'MY_GET_URL_R') {
|
||||
if (e.data.error) {
|
||||
if (e.data.data.length === 0) {
|
||||
console.log('TODO inform user to mark page');
|
||||
@ -52,6 +52,7 @@
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (!e.data.url) return;
|
||||
data.url = e.data.url ?? '';
|
||||
window.requestAnimationFrame(() => {
|
||||
if (!form?.reportValidity()) {
|
||||
|
59
site/src/routes/work-area/SearchFound.svelte
Normal file
59
site/src/routes/work-area/SearchFound.svelte
Normal file
@ -0,0 +1,59 @@
|
||||
<script lang="ts">
|
||||
let {
|
||||
ondelete
|
||||
}: {
|
||||
ondelete: () => void;
|
||||
} = $props();
|
||||
|
||||
let timeoutCount = $state(5);
|
||||
let timeout: undefined | number = undefined;
|
||||
let dialog: HTMLDialogElement;
|
||||
|
||||
export function open() {
|
||||
if (dialog) dialog.showModal();
|
||||
timeoutCount = 5;
|
||||
|
||||
function timeoutF() {
|
||||
if (timeoutCount === 0) {
|
||||
ondelete();
|
||||
timeout = undefined;
|
||||
return;
|
||||
}
|
||||
timeoutCount -= 1;
|
||||
timeout = setTimeout(timeoutF, 1000) as unknown as number;
|
||||
}
|
||||
|
||||
timeout = setTimeout(timeoutF, 1000) as unknown as number;
|
||||
}
|
||||
|
||||
// TODO: Auto delete after of 5 secs of inactivity
|
||||
</script>
|
||||
|
||||
<dialog
|
||||
class="card"
|
||||
bind:this={dialog}
|
||||
onclose={() => {
|
||||
if (timeout) clearTimeout(timeout);
|
||||
}}
|
||||
>
|
||||
<div>
|
||||
<div class="text-center py-10">
|
||||
<span class="bi bi-exclamation-triangle-fill text-8xl text-red-500"></span>
|
||||
</div>
|
||||
<h1 class="text-4xl py-5">Found Glassdoor Search</h1>
|
||||
<div class="flex justify-center gap-10">
|
||||
<button
|
||||
class="btn-primary"
|
||||
onclick={() => {
|
||||
dialog.close();
|
||||
if (timeout) clearTimeout(timeout);
|
||||
}}
|
||||
>
|
||||
Ignore
|
||||
</button>
|
||||
<button class="btn-danger" onclick={() => ondelete()}>
|
||||
Remove ({timeoutCount}) <span class="bi bi-clock-history animate-pulse"></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</dialog>
|
@ -6,7 +6,7 @@
|
||||
} from '$lib/ApplicationsStore.svelte';
|
||||
import { statusStore } from '$lib/Types.svelte';
|
||||
|
||||
let { application, showAll }: { application: Application; showAll: boolean } = $props();
|
||||
let { application }: { application: Application } = $props();
|
||||
|
||||
let events: (ApplicationEvent & { timeDiff: string })[] = $state([]);
|
||||
|
||||
@ -91,14 +91,10 @@
|
||||
class="shadow-sm shadow-violet-500 border rounded-full min-w-[50px] min-h-[50px] grid place-items-center bg-white z-10"
|
||||
>
|
||||
{#if event.event_type == EventType.Creation}
|
||||
<span
|
||||
title={`Created @\n ${new Date(event.time).toLocaleString()}`}
|
||||
class="bi bi-plus"
|
||||
<span title={`Created @\n ${new Date(event.time).toLocaleString()}`} class="bi bi-plus"
|
||||
></span>
|
||||
{:else if event.event_type == EventType.View}
|
||||
<span
|
||||
title={`Viewed @\n ${new Date(event.time).toLocaleString()}`}
|
||||
class="bi bi-eye"
|
||||
<span title={`Viewed @\n ${new Date(event.time).toLocaleString()}`} class="bi bi-eye"
|
||||
></span>
|
||||
{:else}
|
||||
<span
|
||||
|
@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { applicationStore, type Application } from '$lib/ApplicationsStore.svelte';
|
||||
|
||||
import { put, preventDefault, post, get } from '$lib/utils';
|
||||
import { put, preventDefault, post, get, deleteR } from '$lib/utils';
|
||||
import { onMount } from 'svelte';
|
||||
import ExtractTextDialog from './ExtractTextDialog.svelte';
|
||||
import Flair from '../flair/Flair.svelte';
|
||||
@ -14,6 +14,11 @@
|
||||
import CompanyField from './CompanyField.svelte';
|
||||
import AutoDropZone from './AutoDropZone.svelte';
|
||||
import { statusStore } from '$lib/Types.svelte';
|
||||
import SearchFound from './SearchFound.svelte';
|
||||
import FoundExpire from './FoundExpire.svelte';
|
||||
import ApplicationsList from '../ApplicationsList.svelte';
|
||||
|
||||
let { appList }: { appList: ApplicationsList } = $props();
|
||||
|
||||
// Not this represents the index in the store array
|
||||
let activeItem: number | undefined = $state();
|
||||
@ -23,6 +28,8 @@
|
||||
let extractTokens: HTMLDialogElement;
|
||||
let changeUrl: HTMLDialogElement;
|
||||
let linkApplication: HTMLDialogElement;
|
||||
let searchFound: SearchFound;
|
||||
let foundExpire: FoundExpire;
|
||||
|
||||
let lastExtData: any = $state(undefined);
|
||||
let autoExtData = false;
|
||||
@ -60,12 +67,17 @@
|
||||
lastExtData = undefined;
|
||||
}
|
||||
|
||||
let win: undefined | Window | null | true = $state(undefined);
|
||||
function openWindow(url: string) {
|
||||
if (!url.startsWith('https://')) {
|
||||
url = `https://${url}`;
|
||||
}
|
||||
|
||||
window.open(
|
||||
if (win && hasExt) {
|
||||
window.postMessage({ type: 'CHANGE_PAGE', new_url: url });
|
||||
return;
|
||||
}
|
||||
win = window.open(
|
||||
url,
|
||||
'new window',
|
||||
`location,height=${window.screen.height},width=${window.screen.width},scrollbars,status,toolbar,menubar,popup`
|
||||
@ -101,21 +113,44 @@
|
||||
//
|
||||
//
|
||||
|
||||
let hasExt = $state(false);
|
||||
// Load Ext
|
||||
$effect(() => {
|
||||
function onMessage(e: MessageEvent) {
|
||||
if (e.data.type === 'GOT_INFO_R') {
|
||||
lastExtData = e.data;
|
||||
if (autoExtData) {
|
||||
if ((autoExtData || derivedItem?.title === 'New Application') && derivedItem?.simple_url) {
|
||||
if (e.data.status === 'expired' && derivedItem?.status_id === null) {
|
||||
foundExpire.open();
|
||||
}
|
||||
window.requestAnimationFrame(() => {
|
||||
setExtData();
|
||||
});
|
||||
}
|
||||
}
|
||||
if (e.data.type === 'AUTOLOAD_FOUND_GLASSDOOR_SEARCH') {
|
||||
console.log('Found glassdoor search');
|
||||
if (changeUrl.open) {
|
||||
changeUrl.close();
|
||||
searchFound.open();
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (e.data.type === 'GOT_INTEREST') {
|
||||
console.log('Has for ext and has id!');
|
||||
hasExt = true;
|
||||
win = true;
|
||||
}
|
||||
if (e.data.type === 'HAS_EXTENSION') {
|
||||
console.log('Has for ext!');
|
||||
hasExt = true;
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener('message', onMessage);
|
||||
console.log('Sending request for ext!');
|
||||
window.postMessage({ type: 'REGISTER_INTEREST' });
|
||||
window.postMessage({ type: 'HAS_EXTENSION_Q' });
|
||||
return () => {
|
||||
window.removeEventListener('message', onMessage);
|
||||
};
|
||||
@ -139,7 +174,14 @@
|
||||
applicationStore.all[activeItem].inperson_type = (
|
||||
lastExtData.inperson_type as string
|
||||
).toLowerCase();
|
||||
applicationStore.all[activeItem].location = (lastExtData.location as string).split(',')[0];
|
||||
|
||||
if (lastExtData.location && lastExtData.location.includes(',')) {
|
||||
applicationStore.all[activeItem].location = (lastExtData.location as string).split(',')[0];
|
||||
} else if (lastExtData.location && lastExtData.location.includes('·')) {
|
||||
applicationStore.all[activeItem].location = (lastExtData.location as string)
|
||||
.split('·')[0]
|
||||
.trim();
|
||||
}
|
||||
|
||||
console.log(lastExtData);
|
||||
|
||||
@ -213,6 +255,23 @@
|
||||
console.log('info data', e);
|
||||
}
|
||||
}
|
||||
|
||||
async function remove(autoNext = false) {
|
||||
if (!derivedItem) return;
|
||||
// Deactivate active item
|
||||
try {
|
||||
await deleteR(`application/${derivedItem.id}`);
|
||||
} catch (e) {
|
||||
// TODO: Show User
|
||||
console.log('info data', e);
|
||||
return;
|
||||
}
|
||||
applicationStore.removeByID(derivedItem.id);
|
||||
activeItem = undefined;
|
||||
if (autoNext) {
|
||||
appList.requestNext();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="flex flex-col w-full gap-2 min-w-0 relative" role="none">
|
||||
@ -309,8 +368,7 @@
|
||||
payrange[0] = payrange[0] * 8 * 5 * 4 * 12;
|
||||
if (payrange[1] != undefined) {
|
||||
payrange[1] = payrange[1] * 8 * 5 * 4 * 12;
|
||||
applicationStore.all[activeItem!].payrange =
|
||||
`${payrange[0]}-${payrange[1]}`;
|
||||
applicationStore.all[activeItem!].payrange = `${payrange[0]}-${payrange[1]}`;
|
||||
|
||||
window.requestAnimationFrame(() => save());
|
||||
return;
|
||||
@ -404,8 +462,7 @@
|
||||
{item}
|
||||
allowDelete
|
||||
application={derivedItem}
|
||||
updateApplication={(item) =>
|
||||
(applicationStore.all[activeItem ?? -1] = item)}
|
||||
updateApplication={(item) => (applicationStore.all[activeItem ?? -1] = item)}
|
||||
/>
|
||||
{/each}
|
||||
</div>
|
||||
@ -466,11 +523,7 @@
|
||||
<button class="btn-primary" onclick={() => linkApplication.showModal()}>
|
||||
Link Application
|
||||
</button>
|
||||
<button
|
||||
class:btn-primary={drag}
|
||||
class:btn-danger={!drag}
|
||||
onclick={() => (drag = !drag)}
|
||||
>
|
||||
<button class:btn-primary={drag} class:btn-danger={!drag} onclick={() => (drag = !drag)}>
|
||||
👋
|
||||
</button>
|
||||
<button
|
||||
@ -483,7 +536,7 @@
|
||||
</div>
|
||||
<Timeline application={derivedItem} showAll={showExtraData} />
|
||||
</div>
|
||||
<AutoDropZone bind:index={activeItem} />
|
||||
<AutoDropZone bind:index={activeItem} onremove={remove} />
|
||||
{:else}
|
||||
<div
|
||||
class="p-2 h-full w-full gap-2 flex-grow card grid place-items-center min-h-[50vh]"
|
||||
@ -523,14 +576,19 @@
|
||||
activate(item, false);
|
||||
}}
|
||||
/>
|
||||
{/if}
|
||||
|
||||
{#if derivedItem}
|
||||
<LinkApplication
|
||||
application={derivedItem}
|
||||
bind:dialog={linkApplication}
|
||||
onreload={(item) => activate(item, false)}
|
||||
/>
|
||||
<FoundExpire
|
||||
bind:this={foundExpire}
|
||||
bind:index={activeItem}
|
||||
onnext={() => {
|
||||
appList.requestNext();
|
||||
}}
|
||||
/>
|
||||
<SearchFound bind:this={searchFound} ondelete={() => remove(true)} />
|
||||
{/if}
|
||||
|
||||
<SearchApplication
|
||||
|
Loading…
Reference in New Issue
Block a user