Skip to content

Commit

Permalink
WIP: Working saving data
Browse files Browse the repository at this point in the history
  • Loading branch information
digitalmaster committed Jan 2, 2023
1 parent 2b59b9b commit e0d1292
Show file tree
Hide file tree
Showing 11 changed files with 400 additions and 69 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"description": "Roam Spaced Repetition Plugin",
"author": "Jose Browne <[email protected]> (http://josebrowne.com/)",
"scripts": {
"start": "npm run dev",
"dev": "webpack --watch --mode development",
"build": "webpack build --mode production",
"format": "prettier --write \"./**/*.{js,jsx,json}\"",
Expand Down
1 change: 0 additions & 1 deletion src/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ const App = () => {
if (!refUid) return;

const cardData = practiceCardsData[refUid];
console.log('DEBUG:: ~ file: app.jsx ~ line 26 ~ cardData', cardData);

await practice({ ...cardData, grade, refUid, dataPageTitle });
};
Expand Down
5 changes: 0 additions & 5 deletions src/components/RoamSRImport.tsx

This file was deleted.

200 changes: 200 additions & 0 deletions src/components/RoamSrImportPanel.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
import * as React from 'react';
import * as Blueprint from '@blueprintjs/core';
import * as migration from '~/utils/migration';
import * as queries from '~/queries';
import * as asyncUtils from '~/utils/async';
import styled from '@emotion/styled';
import * as stringUtils from '~/utils/string';
import { Records } from '~/models/session';

const SessionsTable = ({ sessions }) => {
return (
<div className="overflow-scroll">
<table className="bp3-html-table bp3-small bp3-html-table-striped w-full">
<thead>
<tr>
<th>Grade</th>
<th>Date</th>
<th>eFactor</th>
<th>Interval</th>
<th>Streak</th>
<th>Due</th>
</tr>
</thead>
<tbody>
{sessions.map((session) => (
<tr>
<td>{session.grade}</td>
<td>{stringUtils.toDateString(session.dateCreated)}</td>
<td>{session.eFactor.toFixed(2)}</td>
<td>{session.interval}</td>
<td>{session.repetitions}</td>
<td>{stringUtils.toDateString(session.nextDueDate)}</td>
</tr>
))}
</tbody>
</table>
</div>
);
};

const Block = ({ uuid, sessions, isLast, selectedUids, setSelectedUids }) => {
const [blockInfo, setBlockInfo] = React.useState(null);
const [isSelected, setIsSelected] = React.useState(false);
const [isExpanded, setIsExpanded] = React.useState(false);

React.useEffect(() => {
if (selectedUids.includes(uuid)) {
setIsSelected(true);
} else {
setIsSelected(false);
}
}, [selectedUids]);

React.useEffect(() => {
(async () => {
const blockInfo = await queries.fetchBlockInfo(uuid);
setBlockInfo(blockInfo);
})();
}, []);

const handleCheckboxChange = (e) => {
setSelectedUids((currentUids) => {
if (e.target.checked) {
return [...currentUids, uuid];
} else {
return currentUids.filter((uid) => uid !== uuid);
}
});
};

return (
<>
<div className="flex flex-col px-4 py-4">
<div className="flex items-center">
<Blueprint.Checkbox checked={isSelected} onChange={handleCheckboxChange} />
<div
className="truncate w-full cursor-pointer"
onClick={() => setIsExpanded((bool) => !bool)}
>
<div>{blockInfo?.string}</div>
<div className="bp3-text-small bp3-text-muted">
Found {sessions.length} Practice Sessions
</div>
</div>
<div className={`px-5 cursor-pointer`} onClick={() => setIsExpanded((bool) => !bool)}>
<Blueprint.Icon
icon="chevron-down"
className={`${isExpanded ? 'transform rotate-180' : ''}`}
/>
</div>
</div>
{isExpanded && <SessionsTable sessions={sessions} />}
</div>
{!isLast && <Blueprint.Divider />}
</>
);
};

const ResultsWrapper = styled.div`
max-height: 500px;
overflow: scroll;
`;

const Dialog = styled(Blueprint.Dialog)`
width: 90%;
max-width: 700px;
`;

const Panel = ({ dataPageTitle }) => {
const [isLoading, setIsLoading] = React.useState(true);
const [isImporting, setIsImporting] = React.useState(false);
const [records, setRecords] = React.useState<Records>({});

const [selectedUids, setSelectedUids] = React.useState([]);
const [existingPracticeData, setExistingPracticeData] = React.useState();
const totalCardsFound = Object.keys(records).length;
const totalRecords = Object.values(records).reduce((acc, curr) => acc + curr.length, 0);

// Fetch records
React.useEffect(() => {
(async () => {
await asyncUtils.sleep(300); // fixes modal load delay
const oldReviewData = await queries.getOldRoamSrPracticeData();
const records = await queries.generateRecordsFromRoamSrData(oldReviewData, dataPageTitle);
setRecords(records);
setSelectedUids(Object.keys(records));

// Used to mark blocks that already exist
const existingPracticeData = await queries.getPluginPageData({
dataPageTitle: dataPageTitle,
});
setExistingPracticeData(existingPracticeData);
setIsLoading(false);
})();
}, []);

const executeImport = async () => {
setIsImporting(true);
await queries.bulkSavePracticeData({ records, selectedUids, dataPageTitle });
setIsImporting(false);
};

return (
// @ts-ignore
<Dialog
// onClose={onCloseCallback}
className="bp3-ui-text pb-0 bg-white select-none"
canEscapeKeyClose={false}
isOpen
>
{isLoading ? (
<div>loading...</div>
) : (
<div className="flex flex-col">
<div className="flex px-4 py-4 justify-between">
<div>
<h4 className="bp3-heading mb-1">Import Roam Sr. Data</h4>
<div className="bp3-text-small bp3-text-muted">
<>
Found <strong>{totalCardsFound}</strong> cards with a total of{' '}
<strong>{totalRecords}</strong> sessions.
</>
</div>
</div>
<div>
<Blueprint.Button onClick={executeImport} disabled={isImporting}>
Import{' '}
{selectedUids.length === totalCardsFound ? 'All' : `(${selectedUids.length})`}
</Blueprint.Button>
</div>
</div>
<ResultsWrapper>
{Object.keys(records).map((uuid, i, list) => (
<Block
uuid={uuid}
sessions={records[uuid]}
isLast={i === list.length - 1}
selectedUids={selectedUids}
setSelectedUids={setSelectedUids}
/>
))}
</ResultsWrapper>
</div>
)}
</Dialog>
);
};

const RoamSrImportPanel = ({ dataPageTitle }) => {
const [showPanel, setShowPanel] = React.useState(false);

return (
<div>
<Blueprint.Button onClick={() => setShowPanel(true)}>Preview</Blueprint.Button>
{showPanel && <Panel dataPageTitle={dataPageTitle} />}
</div>
);
};

export default RoamSrImportPanel;
12 changes: 12 additions & 0 deletions src/models/session.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export interface Session {
repetitions: number;
interval: number;
eFactor: number;
nextDueDate: Date;
grade: number;
dateCreated: Date;
}

export interface Records {
[key: string]: Session[];
}
17 changes: 11 additions & 6 deletions src/practice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ export const generatePracticeData = ({
};
};

interface Practice {
export interface PracticeProps {
interval: number;
repetitions: number;
eFactor: number;
Expand All @@ -75,10 +75,16 @@ interface Practice {
dateCreated: null | Date;
}

const practice = async (
{ interval, repetitions, eFactor, grade, refUid, dataPageTitle, dateCreated = null }: Practice,
isDryRun = false
) => {
const practice = async (practiceProps: PracticeProps, isDryRun = false) => {
const {
interval,
repetitions,
eFactor,
grade,
refUid,
dataPageTitle,
dateCreated = null,
} = practiceProps;
// Just don't want to store nextDueDateFromNow
// eslint-disable-next-line no-unused-vars
const { nextDueDateFromNow, ...practiceResultData } = generatePracticeData({
Expand All @@ -88,7 +94,6 @@ const practice = async (
eFactor,
baseDate: dateCreated,
});

if (!isDryRun) {
await savePracticeData({
refUid: refUid,
Expand Down
Loading

0 comments on commit e0d1292

Please sign in to comment.