Skip to content

Commit

Permalink
A better approach - have a log per day
Browse files Browse the repository at this point in the history
  • Loading branch information
horia141 committed Jan 7, 2024
1 parent 0b8ce00 commit 39ce7a0
Show file tree
Hide file tree
Showing 9 changed files with 148 additions and 80 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
)


class JournalExistsForPeriodAndDateError(EntityAlreadyExistsError):
"""An error raised when a journal already exists for a period and date."""
class JournalExistsForDateError(EntityAlreadyExistsError):
"""An error raised when a journal already exists for a date."""


class JournalRepository(LeafEntityRepository[Journal], abc.ABC):
Expand Down
4 changes: 3 additions & 1 deletion src/core/jupiter/core/domain/journals/journal.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,4 +116,6 @@ def update_report(
@staticmethod
def build_name(right_now: ADate, period: RecurringTaskPeriod) -> EntityName:
"""Build the name of the journal."""
return EntityName(f"{period.value.capitalize()} journal for {ADate.to_user_date_str(right_now)}")
return EntityName(
f"{period.value.capitalize()} journal for {ADate.to_user_date_str(right_now)}"
)
4 changes: 2 additions & 2 deletions src/core/jupiter/core/repository/sqlite/domain/journals.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
JournalCollectionRepository,
)
from jupiter.core.domain.journals.infra.journal_repository import (
JournalExistsForPeriodAndDateError,
JournalExistsForDateError,
JournalRepository,
)
from jupiter.core.domain.journals.journal import Journal
Expand Down Expand Up @@ -161,7 +161,7 @@ def __init__(self, connection: AsyncConnection, metadata: MetaData) -> None:
Column("report", JSON, nullable=False),
keep_existing=True,
),
already_exists_err_cls=JournalExistsForPeriodAndDateError,
already_exists_err_cls=JournalExistsForDateError,
)

@staticmethod
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
"""Better indices on journal
Revision ID: 700375030fae
Revises: 008a3a72fb29
Create Date: 2024-01-07 16:39:03.373383
"""
from alembic import op


# revision identifiers, used by Alembic.
revision = "700375030fae"
down_revision = "008a3a72fb29"
branch_labels = None
depends_on = None


def upgrade() -> None:
op.execute(
"""
CREATE UNIQUE INDEX ix_journal_journal_collection_ref_id_right_now ON journal (journal_collection_ref_id, right_now)
WHERE archived=0;
"""
)
op.execute("""DROP INDEX ix_journal_journal_collection_ref_id_period_timeline;""")


def downgrade() -> None:
pass
8 changes: 4 additions & 4 deletions src/webapi/jupiter/webapi/jupiter.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
from jupiter.core.domain.core.email_address import EmailAddress
from jupiter.core.domain.features import FeatureUnavailableError
from jupiter.core.domain.journals.infra.journal_repository import (
JournalExistsForPeriodAndDateError,
JournalExistsForDateError,
)
from jupiter.core.domain.projects.errors import ProjectInSignificantUseError
from jupiter.core.domain.user.infra.user_repository import (
Expand Down Expand Up @@ -1532,15 +1532,15 @@ async def workspace_not_found_error_handler(
)


@app.exception_handler(JournalExistsForPeriodAndDateError)
@app.exception_handler(JournalExistsForDateError)
async def journal_exists_for_period_and_date_error_handler(
_request: Request,
_exc: JournalExistsForPeriodAndDateError,
_exc: JournalExistsForDateError,
) -> PlainTextResponse:
"""Transform JournalExistsForPeriodAndDateError to something that signals clients the app is in a not-ready state."""
return PlainTextResponse(
status_code=status.HTTP_409_CONFLICT,
content="Journal already exists for this period and date",
content="Journal already exists for this date",
)


Expand Down
24 changes: 12 additions & 12 deletions src/webui/app/components/journal-source-tag.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
import { JournalSource } from "jupiter-gen/dist/models/JournalSource";
import { SlimChip } from "./infra/chips";
import { journalSourceName } from "~/logic/domain/journal";
import { SlimChip } from "./infra/chips";

interface Props {
source: JournalSource;
source: JournalSource;
}

export function JournalSourceTag({ source }: Props) {
const tagName = journalSourceName(source);
const tagClass = sourceToClass(source);
return <SlimChip label={tagName} color={tagClass}/>;
const tagName = journalSourceName(source);
const tagClass = sourceToClass(source);
return <SlimChip label={tagName} color={tagClass} />;
}

function sourceToClass(source: JournalSource): "info" | "warning" {
switch (source) {
case JournalSource.USER:
return "info";
case JournalSource.RECURRING:
return "warning";
}
}
switch (source) {
case JournalSource.USER:
return "info";
case JournalSource.RECURRING:
return "warning";
}
}
21 changes: 9 additions & 12 deletions src/webui/app/components/show-report.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import {
import type {
InboxTasksSummary,
ReportPeriodResult,
UserScoreOverview,
WorkableSummary,
} from "jupiter-gen";
import {
Expand Down Expand Up @@ -120,17 +119,15 @@ export function ShowReport({ topLevelInfo, report }: ShowReportProps) {
</Typography>
</Box>

{isUserFeatureAvailable(topLevelInfo.user, UserFeature.GAMIFICATION) &&
report.user_score_overview && (
<>
<Divider>
<Typography variant="h6">💪 Score</Typography>
</Divider>
<ScoreOverview
scoreOverview={report.user_score_overview}
/>
</>
)}
{isUserFeatureAvailable(topLevelInfo.user, UserFeature.GAMIFICATION) &&
report.user_score_overview && (
<>
<Divider>
<Typography variant="h6">💪 Score</Typography>
</Divider>
<ScoreOverview scoreOverview={report.user_score_overview} />
</>
)}

<Tabs
value={showTab}
Expand Down
38 changes: 19 additions & 19 deletions src/webui/app/logic/domain/journal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,27 @@ import { compareADate } from "./adate";
import { comparePeriods } from "./period";

export function sortJournalsNaturally(journals: Array<Journal>): Journal[] {
return [...journals].sort((j1, j2) => {
if (j2.archived && !j1.archived) {
return -1;
}
return [...journals].sort((j1, j2) => {
if (j2.archived && !j1.archived) {
return -1;
}

if (j1.archived && !j2.archived) {
return 1;
}
if (j1.archived && !j2.archived) {
return 1;
}

return (
(-1 * compareADate(j1.right_now, j2.right_now)) ||
comparePeriods(j1.period, j2.period)
);
});
return (
-1 * compareADate(j1.right_now, j2.right_now) ||
comparePeriods(j1.period, j2.period)
);
});
}

export function journalSourceName(source: JournalSource) {
switch (source) {
case JournalSource.USER:
return "User";
case JournalSource.RECURRING:
return "Recurring";
}
}
switch (source) {
case JournalSource.USER:
return "User";
case JournalSource.RECURRING:
return "Recurring";
}
}
96 changes: 68 additions & 28 deletions src/webui/app/routes/workspace/journals.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
import { json, LoaderArgs } from "@remix-run/node";
import { Outlet, ShouldRevalidateFunction, useFetcher } from "@remix-run/react";
import { AnimatePresence } from "framer-motion";
import { Journal, RecurringTaskPeriod, ReportPeriodResult, UserFeature, WorkspaceFeature } from "jupiter-gen";
import {
Journal,
RecurringTaskPeriod,
ReportPeriodResult,
UserFeature,
WorkspaceFeature,
} from "jupiter-gen";
import { JournalFindResultEntry } from "jupiter-gen/dist/models/JournalFindResultEntry";
import { useContext } from "react";
import { getLoggedInApiClient } from "~/api-clients";
Expand Down Expand Up @@ -77,9 +83,9 @@ export default function Journals() {
<NestingAwareBlock shouldHide={shouldShowALeaf}>
<EntityStack>
{sortedJournals.map((journal) => {
const entry = entriesByRefId.get(
journal.ref_id.the_id
) as JournalFindResultEntry;
const entry = entriesByRefId.get(
journal.ref_id.the_id
) as JournalFindResultEntry;
return (
<EntityCard
key={entry.journal.ref_id.the_id}
Expand All @@ -93,11 +99,33 @@ export default function Journals() {
<EntityNameComponent name={entry.journal.name} />
<JournalSourceTag source={entry.journal.source} />
<PeriodTag period={entry.journal.period} />
{isUserFeatureAvailable(topLevelInfo.user, UserFeature.GAMIFICATION) &&
<GamificationTag period={entry.journal.period} report={entry.journal.report} />}
{entry.journal.report.global_inbox_tasks_summary.done.total_cnt} tasks done
{isWorkspaceFeatureAvailable(topLevelInfo.workspace, WorkspaceFeature.BIG_PLANS) &&
<>{" "}and {entry.journal.report.global_big_plans_summary.done_cnt} big plans done</>}
{isUserFeatureAvailable(
topLevelInfo.user,
UserFeature.GAMIFICATION
) && (
<GamificationTag
period={entry.journal.period}
report={entry.journal.report}
/>
)}
{
entry.journal.report.global_inbox_tasks_summary.done
.total_cnt
}{" "}
tasks done
{isWorkspaceFeatureAvailable(
topLevelInfo.workspace,
WorkspaceFeature.BIG_PLANS
) && (
<>
{" "}
and{" "}
{
entry.journal.report.global_big_plans_summary.done_cnt
}{" "}
big plans done
</>
)}
</EntityLink>
</EntityCard>
);
Expand All @@ -117,25 +145,37 @@ export const ErrorBoundary = makeErrorBoundary(
);

interface GamificationTagProps {
period: RecurringTaskPeriod;
report: ReportPeriodResult;
period: RecurringTaskPeriod;
report: ReportPeriodResult;
}

function GamificationTag({period, report}: GamificationTagProps) {
if (!report.user_score_overview) {
return null;
}
function GamificationTag({ period, report }: GamificationTagProps) {
if (!report.user_score_overview) {
return null;
}

switch (period) {
case RecurringTaskPeriod.DAILY:
return <>{report.user_score_overview.daily_score.total_score} points from{" "}</>;
case RecurringTaskPeriod.WEEKLY:
return <>{report.user_score_overview.weekly_score.total_score} points from{" "}</>;
case RecurringTaskPeriod.MONTHLY:
return <>{report.user_score_overview.monthly_score.total_score} points from{" "}</>;
case RecurringTaskPeriod.QUARTERLY:
return <>{report.user_score_overview.quarterly_score.total_score} points from{" "}</>;
case RecurringTaskPeriod.YEARLY:
return <>{report.user_score_overview.yearly_score.total_score} points from{" "}</>;
}
}
switch (period) {
case RecurringTaskPeriod.DAILY:
return (
<>{report.user_score_overview.daily_score.total_score} points from </>
);
case RecurringTaskPeriod.WEEKLY:
return (
<>{report.user_score_overview.weekly_score.total_score} points from </>
);
case RecurringTaskPeriod.MONTHLY:
return (
<>{report.user_score_overview.monthly_score.total_score} points from </>
);
case RecurringTaskPeriod.QUARTERLY:
return (
<>
{report.user_score_overview.quarterly_score.total_score} points from{" "}
</>
);
case RecurringTaskPeriod.YEARLY:
return (
<>{report.user_score_overview.yearly_score.total_score} points from </>
);
}
}

0 comments on commit 39ce7a0

Please sign in to comment.