Skip to content

Commit

Permalink
feat: Job/Project Description Also in Web App (#3)
Browse files Browse the repository at this point in the history
  • Loading branch information
hoosnick committed Jan 23, 2024
1 parent 6c65062 commit a157ad2
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 137 deletions.
3 changes: 1 addition & 2 deletions app/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
from app.config_reader import Settings
from app.db.tables import PROJECT_TABLES
from app.parser import get_kwork_projects, get_upwork_jobs
from app.web.routes import create_offer, get_offers, home, get_project_detail
from app.web.routes import create_offer, get_offers, home


async def database_connection(config: Settings, close=False, persist=True) -> None:
Expand Down Expand Up @@ -103,7 +103,6 @@ def main():
app.router.add_get("/", home)
app.router.add_post("/generate", create_offer)
app.router.add_get("/offers", get_offers)
app.router.add_get('/project-detail', get_project_detail)

SimpleRequestHandler(dispatcher=dp, bot=bot).register(app, path="/webhook")
setup_application(app, dp, bot=bot)
Expand Down
3 changes: 2 additions & 1 deletion app/gpt.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,5 @@ async def generate_offer(project_description: str, lang: str) -> Dict[str, bool
)
return {'ok': True, 'response': str(response)}
except BaseException as e:
return {'ok': False, 'err': f"{e.__class__.__name__}: {e}"}
# TODO: Too Long Error Message Issue
return {'ok': False, 'err': f"{e.__class__.__name__}"}
5 changes: 4 additions & 1 deletion app/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,10 @@ async def get_kwork_projects(bot: Bot, config: Settings):
)

for dict_project in other_projects["response"]:
projects.append(types.Project(**dict_project))
# pydantic_core._pydantic_core.ValidationError: 1 validation error for Project
# date_confirm Input should be a valid integer
# [type=int_type, input_value=None, input_type=NoneType]
projects.append(types.Project(**dict_project)) # fix

for project in projects:
url = "https://kwork.ru/projects/" + str(project.id)
Expand Down
172 changes: 57 additions & 115 deletions app/web/offers.html
Original file line number Diff line number Diff line change
Expand Up @@ -40,67 +40,29 @@
color-scheme: var(--tg-color-scheme);
}

a {
color: var(--tg-theme-link-color, #2678b6);
}

::selection {
background-color: #000000;
color: #ffffff;
}

h6 {
padding: 0;
margin: 5px 0;
color: #000000;
}

h5 {
text-align: center;
padding: 0;
color: var(--tg-theme-text-color);
font-size: 16px;
}

button.close_btn {
/*position: fixed;*/
position: absolute;
left: 0;
right: 0;
bottom: 0;
border-radius: 0;
margin: 0;
padding: 16px 20px;
text-transform: uppercase;
a {
color: var(--tg-theme-link-color, #2678b6);
}

#offerSection,
#projectDetail {
position: relative;
display: flex;
padding-right: 5px;
padding-left: 5px;
margin-bottom: 5px;
justify-content: center;
align-items: flex-start;
}

#projectDetail .detail {
padding: 10px !important;
}

#offerSection {
padding-top: 15px;
padding-right: 10px;
padding-left: 10px;
margin-bottom: 50px;
/*margin-bottom: 50px;*/
display: flex;
flex-wrap: wrap;
gap: 12px;
justify-content: center;
align-items: flex-start;
}

.card, .detail {
.card {
background-color: #fff;
padding: 20px;
border-radius: 10px;
Expand All @@ -111,7 +73,8 @@
position: relative;
}

.largeText {
.largeText,
.projectDescription {
margin-bottom: 10px;
font-size: 11px;
line-height: 1.2;
Expand All @@ -133,12 +96,12 @@
font-size: 12px;
}

.copyButton {
.offerBy,
.freelancePlatform {
position: absolute;
bottom: 10px;
right: 10px;
right: 40px;
padding: 5px;
background: var(--tg-theme-button-color, #50a8eb);
color: #fff;
font-size: 10px;
border: none;
Expand All @@ -148,25 +111,19 @@
}

.offerBy {
position: absolute;
bottom: 10px;
right: 40px;
padding: 5px;
background: var(--tg-theme-button-color, #50a8eb);
color: #fff;
font-size: 10px;
border: none;
outline: none;
border-radius: 4px;
cursor: pointer;
}

.freelancePlatform {
background: #00a534;
}

.copyButton,
.toggleButton {
position: absolute;
bottom: 5px;
bottom: 10px;
right: 10px;
padding: 5px;
background: #00a534;
background: var(--tg-theme-button-color, #50a8eb);
color: #fff;
font-size: 10px;
border: none;
Expand All @@ -175,6 +132,11 @@
cursor: pointer;
}

#loadingText {
text-align: center;
color: var(--tg-theme-button-color, #50a8eb);
}

#fixed_wrap {
position: fixed;
left: 0;
Expand All @@ -187,11 +149,12 @@
<body style="visibility: hidden">
<div id="projectDetail"></div>

<br><hr>
<br />

<h5>Offers</h5>
<div id="offerSection"></div>

<div id="loadingText"></div>

<script src="https://webappcontent.telegram.org/js/jquery.min.js"></script>
<script>
Telegram.WebApp.ready();
Expand All @@ -216,7 +179,7 @@ <h5>Offers</h5>
type: "GET",
success: function (data) {
if (data.ok) {
displayOffers(data.offers);
displayOffers(data);
} else {
showError(data.err);
}
Expand All @@ -230,35 +193,13 @@ <h5>Offers</h5>
}
}

function fetchProjectDetail() {
const projectId = getProjectIdFromUrl();
if (projectId !== null) {
$.ajax(`/project-detail?id=${projectId}`, {
type: "GET",
success: function (data) {
if (data.ok) {
displayProjectDetail(data.project);
} else {
showError(data.err);
}
},
error: function () {
showError("Error fetching project detail");
},
});
} else {
showError("Project ID not found in the URL.");
}
}

function generateOffer() {
const projectId = getProjectIdFromUrl();
const lang = getLangFromUrl();

if (projectId !== null) {

Telegram.WebApp.MainButton.setText("Generating...")
.offClick(function () {});
Telegram.WebApp.MainButton.setText("Generating...").disable();
$("#loadingText").text("Generating...");

$.ajax(`/generate?for=${projectId}&lang=${lang}`, {
type: "POST",
Expand All @@ -277,36 +218,44 @@ <h5>Offers</h5>
showError("Error generating offer.");
},
complete: function () {
Telegram.WebApp.MainButton.setText("Generate")
.show()
.onClick(function () {
generateOffer();
});
Telegram.WebApp.MainButton.setText("Generate").enable();
$("#loadingText").text("");
},
});
} else {
$("#loadingText").text("");
showError("Project ID not found in the URL.");
}
}

function displayOffers(offers) {
function displayOffers(data) {
const offerSection = $("#offerSection");
offerSection.empty();

if (offers.length === 0) {
const projectDetail = $("#projectDetail");
projectDetail.html(
`<div class="card">
<h6>${data.project.title}</h6>
<div class="projectDescription" style="display: none;">${data.project.description}</div>
<div class="freelancePlatform">${data.project.freelance_platform}</div>
<button class="toggleButton" onclick="toggleDesc()">
<i class="fa fa-plus" aria-hidden="true"></i>
</button>
</div>
`
);

if (data.offers.length === 0) {
showAlert("Oops, no offers found. Let's generate!");
offerSection.append(
`<h5>There is no offer yet. Press the "Generate" button to generate one!</h5>`
);
} else {
offers.forEach((offer, index) => {
data.offers.forEach((offer, index) => {
offerSection.append(
`<div class="card">
<div class="index">${index + 1}</div>
<div class="largeText">${offer.offer}</div>
<div class="offerBy">${offer.offer_by}</div>
<button class="copyButton" onclick="copyText(${index})">
<i class="fa fa-clone"></i>
<i class="fa fa-clone" aria-hidden="true"></i>
</button>
</div>
`
Expand All @@ -315,24 +264,9 @@ <h5>Offers</h5>
}
}

function displayProjectDetail(project) {
const projectDetail = $("#projectDetail");
projectDetail.empty();

projectDetail.append(
`<div class="detail">
<h6>${project.title}</h6>
<div class="largeText">${project.description}</div>
<div class="freelancePlatform">${project.freelance_platform}</div>
</div>`);
}

function addOffer(offer) {
const offerSection = $("#offerSection");
const newOfferIndex = offerSection.children().length + 1;
offerSection.remove(
`<h5>There is no offer yet. Press the "Generate" button to generate one!</h5>`
);
const newOffer = $(
`<div class="card">
<div class="index">${newOfferIndex}</div>
Expand Down Expand Up @@ -383,6 +317,15 @@ <h6>${project.title}</h6>
showAlert("Text copied to clipboard!");
}

function toggleDesc() {
const projectDescription = $(".projectDescription");
const toggleButton = $(".toggleButton");

projectDescription.slideToggle(() =>
toggleButton.find("i").toggleClass("fa fa-plus fa fa-minus")
);
}

Telegram.WebApp.onEvent("themeChanged", function () {
$("#theme_data").html(
JSON.stringify(Telegram.WebApp.themeParams, null, 2)
Expand All @@ -397,7 +340,6 @@ <h6>${project.title}</h6>
});

$(document).ready(function () {
fetchProjectDetail();
fetchOffers();
});
</script>
Expand Down
29 changes: 11 additions & 18 deletions app/web/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,25 +71,18 @@ async def get_offers(request: Request):
Offer.project == project
))

return json_response({"ok": True, 'offers': offers})


async def get_project_detail(request: Request):
project_id = request.rel_url.query.get("id")
project = await Project.objects().get(Project.id == int(project_id))

if project is None:
return json_response({"ok": False, "err": "Project not found!"})

return json_response({
"ok": True,
"project": {
"url": project.url,
"title": project.title,
"description": project.description,
"freelance_platform": project.freelance_platform,
return json_response(
{
"ok": True,
"project": {
"url": project.url,
"title": project.title,
"description": project.description,
"freelance_platform": project.freelance_platform,
},
'offers': offers
}
})
)


async def parse_user(telegram_id: int):
Expand Down

0 comments on commit a157ad2

Please sign in to comment.