diff --git a/api/application.properties b/api/application.properties index ed95897..71e1c15 100644 --- a/api/application.properties +++ b/api/application.properties @@ -1,5 +1,5 @@ spring.datasource.driver-class-name=org.postgresql.Driver -spring.datasource.url=jdbc:postgresql://localhost:5432/applications +spring.datasource.url=jdbc:postgresql://kronos:5432/applications spring.datasource.username=applications spring.datasource.password=applications diff --git a/api/src/main/kotlin/com/andr3h3nriqu3s/applications/ApplicationsController.kt b/api/src/main/kotlin/com/andr3h3nriqu3s/applications/ApplicationsController.kt index cfe5531..1143131 100644 --- a/api/src/main/kotlin/com/andr3h3nriqu3s/applications/ApplicationsController.kt +++ b/api/src/main/kotlin/com/andr3h3nriqu3s/applications/ApplicationsController.kt @@ -30,7 +30,9 @@ data class Application( var extra_data: String, var payrange: String, var status: Int, - var flairs: List + var company: String, + var recruiter: String, + var flairs: List, ) { companion object : RowMapper { override public fun mapRow(rs: ResultSet, rowNum: Int): Application { @@ -44,6 +46,8 @@ data class Application( rs.getString("extra_data"), rs.getString("payrange"), rs.getInt("status"), + rs.getString("company"), + rs.getString("recruiter"), emptyList() ) } @@ -60,6 +64,8 @@ data class FlairRequest(val id: String, val text: String) data class UpdateUrl(val id: String, val url: String) +data class CVData(val company: String, val recruiter: String, val flairs: List) + @RestController @ControllerAdvice @RequestMapping("/api/application") @@ -69,6 +75,23 @@ class ApplicationsController( val flairService: FlairService ) { + @GetMapping(path = ["/cv/{id}"], produces = [MediaType.APPLICATION_JSON_VALUE]) + public fun getCV( + @PathVariable id: String, + @RequestHeader("token") token: String + ): CVData? { + print("here!"); + val user = sessionService.verifyToken(token); + + val application = applicationService.findApplicationByIdNoUser(id); + + if (application == null) return null; + + val flairs = application.flairs.map {it.toFlairSimple()}; + + return CVData(application.company, application.recruiter, flairs); + } + @PostMapping(path = ["/text"], produces = [MediaType.APPLICATION_JSON_VALUE]) public fun submitText( @RequestBody submit: SubmitRequest, @@ -179,6 +202,8 @@ class ApplicationsController( "", "", 0, + "", + "", emptyList() ) } @@ -435,13 +460,27 @@ class ApplicationService(val db: JdbcTemplate, val flairService: FlairService) { return application } + public fun findApplicationByIdNoUser(id: String): Application? { + var applications = db.query("select * from applications where id=?", arrayOf(id), Application).toList() + + if (applications.size == 0) { + return null + } + + var application = applications[0] + + application.flairs = flairService.listFromLinkApplicationId(application.id) + + return application + } + public fun createApplication(user: UserDb, application: Application): Boolean { if (this.findApplicationByUrl(user, application.url, application.unique_url) != null) { return false } db.update( - "insert into applications (id, url, original_url, unique_url, title, user_id, extra_data, payrange, status) values (?, ?, ?, ?, ?, ?, ?, ?, ?);", + "insert into applications (id, url, original_url, unique_url, title, user_id, extra_data, payrange, status, company, recruiter) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);", application.id, application.url, application.original_url, @@ -451,6 +490,8 @@ class ApplicationService(val db: JdbcTemplate, val flairService: FlairService) { application.extra_data, application.payrange, application.status, + application.company, + application.recruiter ) return true @@ -476,7 +517,7 @@ class ApplicationService(val db: JdbcTemplate, val flairService: FlairService) { public fun update(application: Application): Application { db.update( - "update applications set url=?, original_url=?, unique_url=?, title=?, user_id=?, extra_data=?, payrange=?, status=? where id=?", + "update applications set url=?, original_url=?, unique_url=?, title=?, user_id=?, extra_data=?, payrange=?, status=?, company=?, recruiter=? where id=?", application.url, application.original_url, application.unique_url, @@ -485,6 +526,8 @@ class ApplicationService(val db: JdbcTemplate, val flairService: FlairService) { application.extra_data, application.payrange, application.status, + application.company, + application.recruiter, application.id, ) return application diff --git a/api/src/main/kotlin/com/andr3h3nriqu3s/applications/Flair.kt b/api/src/main/kotlin/com/andr3h3nriqu3s/applications/Flair.kt index 829f1e2..f97ae79 100644 --- a/api/src/main/kotlin/com/andr3h3nriqu3s/applications/Flair.kt +++ b/api/src/main/kotlin/com/andr3h3nriqu3s/applications/Flair.kt @@ -68,6 +68,12 @@ class FlairController(val sessionService: SessionService, val flairService: Flai } } +data class SimpleFlair( + val name: String, + val description: String, + val color: String, +) + data class Flair( var id: String, var user_id: String, @@ -88,6 +94,10 @@ data class Flair( ) } } + + fun toFlairSimple(): SimpleFlair { + return SimpleFlair(this.name, this.description, this.color); + } } data class FlairLink(var id: String, var application_id: String, var flair_id: String) @@ -134,14 +144,14 @@ public class FlairService(val db: JdbcTemplate) { public fun listFromLinkApplicationId(id: String): List = db.query( - "select f.id, f.user_id, f.color, f.name, f.expr, f.description from flair_link as fl inner join flair as f on f.id = fl.flair_id where application_id=?;", + "select f.id, f.user_id, f.color, f.name, f.expr, f.description from flair_link as fl inner join flair as f on f.id = fl.flair_id where application_id=? order by name asc;", arrayOf(id), Flair ) .toList() public fun listUser(user: UserDb): List = - db.query("select * from flair where user_id=?;", arrayOf(user.id), Flair).toList() + db.query("select * from flair where user_id=? order by name asc;", arrayOf(user.id), Flair).toList() public fun getById(user: UserDb, id: String): Flair? { val items = diff --git a/api/src/main/resources/schema.sql b/api/src/main/resources/schema.sql index 4b95332..c1b5141 100644 --- a/api/src/main/resources/schema.sql +++ b/api/src/main/resources/schema.sql @@ -16,6 +16,8 @@ create table if not exists applications ( url text not null, original_url text, unique_url text, + company text, + recruiter text, title text, user_id text, extra_data text, diff --git a/extensions/definitions.js b/extensions/definitions.js index adb5589..c8fdd3b 100644 --- a/extensions/definitions.js +++ b/extensions/definitions.js @@ -1,20 +1,28 @@ -browser.runtime.onMessage.addListener(function (message) { +browser.runtime.onMessage.addListener((message) => { if (message.type === "MY_GET_URL_R") { window.postMessage(message); } else if (message.type === "GET_DATA_FROM_PAGE") { - let company = document + const company = document .querySelector('header[data-test="job-details-header"]') .children[0].children[0].querySelector("h4").innerHTML; - let jobTitle = document + const jobTitle = document .querySelector('header[data-test="job-details-header"]') .querySelector("h1").innerHTML; - browser.runtime.sendMessage({ type: "GOT_INFO_R", company, jobTitle }); + + let money = "" + + 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 ?? '' + } + + browser.runtime.sendMessage({ type: "GOT_INFO_R", company, jobTitle, money }); } else if (message.type === "GOT_INFO_R") { window.postMessage(message); } }); -window.addEventListener("message", function (e) { +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") { diff --git a/site/src/lib/ApplicationsStore.svelte.ts b/site/src/lib/ApplicationsStore.svelte.ts index c26a2bc..53c1d63 100644 --- a/site/src/lib/ApplicationsStore.svelte.ts +++ b/site/src/lib/ApplicationsStore.svelte.ts @@ -32,6 +32,8 @@ export type Application = { extra_data: string; payrange: string; status: number; + recruiter: string; + company: string; flairs: Flair[]; }; diff --git a/site/src/lib/HasUser.svelte b/site/src/lib/HasUser.svelte index 7f54872..18b2daa 100644 --- a/site/src/lib/HasUser.svelte +++ b/site/src/lib/HasUser.svelte @@ -4,10 +4,10 @@ let ready = $state(false); - const { children }: { children: Snippet } = $props(); + const { children, redirect }: { children: Snippet, redirect: string } = $props(); onMount(() => { - ready = userStore.checkLogin(); + ready = userStore.checkLogin(redirect); }); diff --git a/site/src/lib/UserStore.svelte.ts b/site/src/lib/UserStore.svelte.ts index a9dba78..08e74e4 100644 --- a/site/src/lib/UserStore.svelte.ts +++ b/site/src/lib/UserStore.svelte.ts @@ -22,23 +22,19 @@ function createUserStore() { } return { - checkLogin(redirect = true) { - console.log('test1'); + checkLogin(redirect = "/login") { if (user !== undefined) { return true; } - console.log('test2'); if (redirect) { - goto('/login'); + goto(redirect); } - console.log('test3'); return false; }, get isLoggedIn() { - console.log(user); return user !== undefined; }, diff --git a/site/src/routes/+page.svelte b/site/src/routes/+page.svelte index 335aa9c..79a2f9c 100644 --- a/site/src/routes/+page.svelte +++ b/site/src/routes/+page.svelte @@ -6,7 +6,7 @@ import AppliyedList from './AppliyedList.svelte'; - +
diff --git a/site/src/routes/ApplicationsList.svelte b/site/src/routes/ApplicationsList.svelte index d8a6776..45d0263 100644 --- a/site/src/routes/ApplicationsList.svelte +++ b/site/src/routes/ApplicationsList.svelte @@ -23,7 +23,14 @@ return true; } const f = new RegExp(filter, 'ig'); - return i.title.match(f); + + let x = i.title; + + if (i.company) { + x = `${x} @ ${i.company}`; + } + + return x.match(f); }) as item}

{item.title} + {#if item.company} +
+ @ {item.company} +
+ {/if}

- + {item.url}
diff --git a/site/src/routes/cv/+page.svelte b/site/src/routes/cv/+page.svelte index 75e50f6..8008df6 100644 --- a/site/src/routes/cv/+page.svelte +++ b/site/src/routes/cv/+page.svelte @@ -1,5 +1,7 @@ @@ -21,10 +53,10 @@
-
+
-

Andre Henriques

+

Andre Henriques

@@ -56,42 +86,62 @@
- {#if application} -
-
TODO: Application Information
- {/if} -
-
-

Work Expericence

-
-
-

Senior Software Developer @ Planum Solucoes

-
-

4 year - May 2020 - Present

-

Working with:

-
    -
  • Python
  • -
  • Jenkins
  • -
  • GitLab CI
  • -
  • Ansible
  • -
  • Docker
  • -
-

Associated Software Developer / DevOps Engineer:

-
    -
  • Developed web-based tools for the DevOps team to use
  • -
  • - Updated Jenkins pipelines that the team uses to manage one of the - most important pipelines that the team manages. -
  • -
  • - Created new scripts that were used to clean up multiple terabytes of - unused data that led to improvements in the performance of the other - scripts running on the same server as well as the performance of the - backup system -
  • -
+
+ {#if application} +

+ 👋 Hello + {#if application.recruiter} + {application.recruiter} @ {application.company} + {:else if application.company} + recruiter @ {application.company} + {/if} +

+
+

Your Ad / My skills

+
+ {#each application.flairs as flair} +
+
+ {flair.name} + {#if flair.description} +
{flair.description}
+ {/if} +
-
+ {/each} +
+
+ {/if} +
+
+

Work Expericence

+
+ +
+ +
+
+

Senior Software Developer @ Planum Solucoes

+
+

4 year - May 2020 - Present

+

Developed various projects:

+
    +
  • Developing various websites using React and Svelte.
  • +
  • Interacting with a RESTful API
  • +
  • Implemented an ORM system using Java Reflection
  • +
  • Implemented automatic deployment with GitLab CI/CD tools.
  • +
  • Linux Server Administration
  • +
  • Technologies used: React, WebRTC, WebSockets, Rest, Google Maps AP
  • +
+
+
+
+ +
+ +
+
+

Associate Devops Engineer @ Sky UK

@@ -122,21 +172,24 @@
-
-
-

Education

+
+ +
+ +
+

Education

+
-
-

University of Surrey

-
-

July 2020 - June 2024

-
+

University of Surrey

+
+

July 2020 - June 2024

- -
+ + +
diff --git a/site/src/routes/work-area/DropZone.svelte b/site/src/routes/work-area/DropZone.svelte new file mode 100644 index 0000000..7fc4dc6 --- /dev/null +++ b/site/src/routes/work-area/DropZone.svelte @@ -0,0 +1,22 @@ + + +
{})} + ondragenter={preventDefault(() => {})} + {ondrop} +> + + +
{@render children()}
+
diff --git a/site/src/routes/work-area/WorkArea.svelte b/site/src/routes/work-area/WorkArea.svelte index e021006..e5b423f 100644 --- a/site/src/routes/work-area/WorkArea.svelte +++ b/site/src/routes/work-area/WorkArea.svelte @@ -11,6 +11,7 @@ import ExtractTextDialog from './ExtractTextDialog.svelte'; import Flair from '../flair/Flair.svelte'; import NewUrlDialog from './NewUrlDialog.svelte'; + import DropZone from './DropZone.svelte'; import { userStore } from '$lib/UserStore.svelte'; let activeItem: Application | undefined = $state(); @@ -42,6 +43,7 @@ if (item.status === 0) { openWindow(item.url); + openCV(item.id); } try { @@ -76,6 +78,14 @@ ); } + function openCV(id?: string) { + window.open( + `/cv?id=${id ?? activeItem!.id}`, + 'cv viwer', + `location,height=${window.screen.height},width=${window.screen.width},scrollbars,status,toolbar,menubar,popup` + ); + } + async function loadActive() { try { activeItem = await get('application/active'); @@ -107,7 +117,9 @@ function setExtData() { if (!lastExtData || !activeItem) return; - activeItem.title = `${lastExtData.company} - ${lastExtData.jobTitle}`; + activeItem.title = lastExtData.jobTitle; + activeItem.company = lastExtData.company; + activeItem.payrange = lastExtData.money; window.requestAnimationFrame(() => { save(); lastExtData = undefined; @@ -203,6 +215,16 @@ {statusMapping}
{/if} +
+
+ + +
+
+ + +
+
@@ -262,10 +284,7 @@ > Open -
{#if applicationStore.dragging}
+ + + { + moveStatus(ApplicationStatus.ToApply); + }}> + To apply + + -
{})} - ondragenter={preventDefault(() => {})} - ondrop={() => { - moveStatus(ApplicationStatus.Ignore); - }} - > - - -
Drop Application Ignore it.
-
+ { + moveStatus(ApplicationStatus.Ignore); + }}> + Ignore it + -
{})} - ondragenter={preventDefault(() => {})} - ondrop={() => { - if (activeItem && activeItem.status === ApplicationStatus.Expired) { - moveStatus(ApplicationStatus.ToApply); - } else { - moveStatus(ApplicationStatus.Expired); - } - }} - > - - -
Mark as expired.
-
+ { + if (activeItem && activeItem.status === ApplicationStatus.Expired) { + moveStatus(ApplicationStatus.ToApply); + } else { + moveStatus(ApplicationStatus.Expired); + } + }}> + Mark as expired + -
{})} - ondragenter={preventDefault(() => {})} - ondrop={() => { - remove(); - }} - > - - -
This is repeated
-
+ remove()}> + Delete it + -
{})} - ondragenter={preventDefault(() => {})} - ondrop={async () => { - await moveStatus(ApplicationStatus.Applyed); - applicationStore.loadAplyed(true); - }} - > - - -
Apply
-
+ { + await moveStatus(ApplicationStatus.Applyed); + applicationStore.loadAplyed(true); + }}> + Apply + -
{})} - ondragenter={preventDefault(() => {})} - ondrop={() => { - moveStatus(ApplicationStatus.ApplyedButSaidNo); - }} - > - - -
I was rejeted :(.
-
+ moveStatus(ApplicationStatus.ApplyedButSaidNo)}> + I was rejeted :( +
{/if} {:else}