mirror of
https://github.com/actualbudget/actual.git
synced 2026-03-11 12:43:09 -05:00
🔥 remove unused component library code (#704)
This commit is contained in:
committed by
GitHub
parent
c82f242c16
commit
019a1e2c42
@@ -1,17 +0,0 @@
|
||||
{
|
||||
"compatibleVersion": 3,
|
||||
"bundleVersion": 1,
|
||||
"commands": [
|
||||
{
|
||||
"name": "Loot",
|
||||
"identifier": "main",
|
||||
"script": "./src/sketch.js"
|
||||
}
|
||||
],
|
||||
"menu": {
|
||||
"isRoot": true,
|
||||
"items": [
|
||||
"main"
|
||||
]
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 24 KiB |
@@ -1,56 +0,0 @@
|
||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!-- Generator: Adobe Illustrator 16.0.4, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
width="160px" height="60px" viewBox="0 0 160 60" style="enable-background:new 0 0 160 60;" xml:space="preserve">
|
||||
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="46.9937" y1="-4.022" x2="125.8175" y2="74.8018">
|
||||
<stop offset="0" style="stop-color:#915AA5"/>
|
||||
<stop offset="1" style="stop-color:#696DB2"/>
|
||||
</linearGradient>
|
||||
<path style="fill:url(#SVGID_1_);" d="M152.708,48.43c-0.44,0-0.88,0.201-1.32,0.6c-0.72,0.64-1.51,1.161-2.37,1.56
|
||||
c-0.86,0.4-1.63,0.6-2.31,0.6c-1.24,0-2.22-0.36-2.94-1.08c-0.72-0.72-1.221-1.899-1.5-3.54c4.521-6.12,8.09-12.32,10.71-18.6
|
||||
c2.62-6.279,3.931-11.799,3.931-16.56c0-3.32-0.551-5.87-1.65-7.65c-1.101-1.779-2.609-2.67-4.53-2.67
|
||||
c-3.399,0-6.329,2.241-8.79,6.72c-2.46,4.48-4.319,9.84-5.579,16.08c-1.261,6.24-1.891,11.8-1.891,16.68
|
||||
c0,1.9,0.123,3.665,0.365,5.297c-1.478,1.729-2.681,3.016-3.604,3.853c-1.08,0.98-2,1.47-2.76,1.47c-0.48,0-0.87-0.18-1.17-0.54
|
||||
c-0.3-0.36-0.45-0.84-0.45-1.44c0-1.8,0.46-5,1.38-9.6c0.601-3.16,0.9-5.16,0.9-6c0-1.4-0.98-2.1-2.94-2.1
|
||||
c-0.92,0-1.8,0.081-2.64,0.24c-0.201-0.879-0.45-1.489-0.75-1.83c-0.3-0.339-0.891-0.51-1.771-0.51c-2.76,0-5.369,0.87-7.829,2.61
|
||||
c-2.461,1.74-4.431,4.041-5.91,6.9c-1.42,2.745-2.152,5.647-2.209,8.704c-0.798,0.871-1.494,1.573-2.081,2.096
|
||||
c-1.101,0.98-2.051,1.47-2.85,1.47c-0.521,0-0.94-0.21-1.261-0.63c-0.32-0.42-0.479-1.009-0.479-1.77c0-1.2,0.56-4.359,1.68-9.48
|
||||
c1-4.479,1.5-7.22,1.5-8.22c0-0.6-0.18-1.01-0.54-1.23c-0.359-0.22-1-0.33-1.92-0.33c-1.32,0-2.31,0.261-2.97,0.78
|
||||
c-0.66,0.521-1.15,1.38-1.47,2.58c-0.96,3.561-1.95,6.561-2.971,9c-1.02,2.44-1.979,4.26-2.88,5.46c-0.899,1.2-1.649,1.8-2.25,1.8
|
||||
c-0.44,0-0.76-0.17-0.96-0.51c-0.2-0.339-0.3-0.93-0.3-1.77c0-1.399,0.399-4.2,1.2-8.4c0.239-1.2,0.56-2.54,0.96-4.02
|
||||
c0.439-1.839,0.66-2.919,0.66-3.24c0-0.56-0.171-0.98-0.511-1.26c-0.34-0.279-0.95-0.42-1.83-0.42c-1.56,0-2.699,0.261-3.42,0.78
|
||||
c-0.72,0.521-1.28,1.38-1.68,2.58c-0.921,2.8-1.581,5.451-1.979,7.95c-0.288,1.798-0.468,3.729-0.549,5.786
|
||||
c-1.175,1.258-2.236,2.268-3.17,3.004c-1.32,1.041-2.841,1.56-4.56,1.56c-2.121,0-3.671-0.84-4.65-2.52
|
||||
c-0.98-1.68-1.47-4.6-1.47-8.76c0-1.119,0.039-2.679,0.12-4.68h7.319c4.521,0,6.78-1.38,6.78-4.14c0-0.759-0.141-1.28-0.42-1.56
|
||||
c-0.28-0.279-0.74-0.42-1.38-0.42h-6.72c5.199-4.6,7.8-10,7.8-16.2c0-2.24-0.48-4.1-1.44-5.58c-0.96-1.479-2.279-2.22-3.96-2.22
|
||||
c-2.279,0-4.41,1.08-6.39,3.24c-1.98,2.16-3.671,5.061-5.07,8.7c-1.4,3.64-2.44,7.66-3.12,12.06h-3.42c-1.8,0-2.7,1.12-2.7,3.36
|
||||
c0,0.96,0.21,1.66,0.631,2.1c0.42,0.44,1.229,0.66,2.43,0.66h2.34c-0.12,1.8-0.18,3.58-0.18,5.34c0,1.267,0.058,2.452,0.158,3.579
|
||||
c-0.472,0.084-0.906,0.344-1.298,0.801c-1.84,2.2-3.71,3.851-5.609,4.95C48.3,51,46.53,51.55,44.89,51.55
|
||||
c-4.04,0-6.06-2.319-6.06-6.96c0-1.68,0.24-3.219,0.72-4.62c0.48-1.4,1.119-2.51,1.92-3.33c0.8-0.819,1.66-1.23,2.58-1.23
|
||||
c0.48,0,0.85,0.141,1.11,0.42c0.26,0.28,0.39,0.681,0.39,1.2c0,0.521-0.1,1.08-0.3,1.68c-0.04,0.16-0.101,0.42-0.18,0.78
|
||||
c-0.081,0.36-0.12,0.681-0.12,0.96c0,0.64,0.229,1.14,0.689,1.5s1.07,0.54,1.83,0.54c1.2,0,2.17-0.58,2.91-1.74
|
||||
c0.74-1.16,1.11-2.58,1.11-4.26c0-2.04-0.61-3.709-1.83-5.01c-1.221-1.3-2.931-1.95-5.13-1.95c-2.241,0-4.38,0.66-6.42,1.98
|
||||
s-3.7,3.201-4.98,5.64c-1.28,2.44-1.92,5.28-1.92,8.52c0,0.704,0.053,1.374,0.135,2.024c-0.767,0.839-1.433,1.517-1.994,2.025
|
||||
c-1.08,0.98-2,1.47-2.76,1.47c-0.48,0-0.871-0.18-1.17-0.54c-0.301-0.36-0.451-0.84-0.451-1.44c0-1.8,0.461-5,1.381-9.6
|
||||
c0.6-3.16,0.9-5.16,0.9-6c0-1.4-0.98-2.1-2.941-2.1c-0.92,0-1.799,0.081-2.639,0.24c-0.201-0.879-0.451-1.489-0.75-1.83
|
||||
c-0.301-0.339-0.891-0.51-1.771-0.51c-2.76,0-5.369,0.87-7.828,2.61c-2.461,1.74-4.432,4.041-5.911,6.9
|
||||
c-1.48,2.86-2.22,5.89-2.22,9.09c0,2.92,0.74,5.28,2.22,7.08c1.479,1.8,3.459,2.7,5.94,2.7c3.158,0,5.779-1.68,7.859-5.04
|
||||
c0.561,1.56,1.391,2.79,2.49,3.69c1.1,0.9,2.311,1.35,3.631,1.35c1.719,0,3.498-0.699,5.34-2.1c0.957-0.729,1.886-1.549,2.789-2.451
|
||||
c0.312,0.425,0.643,0.837,1.02,1.221c2.18,2.22,5.229,3.33,9.149,3.33c2.439,0,4.97-0.63,7.59-1.89c2.62-1.26,4.87-3.05,6.75-5.37
|
||||
c0.122-0.153,0.217-0.326,0.319-0.494c1.803,5.161,5.43,7.754,10.901,7.754c2.641,0,4.98-0.68,7.021-2.04
|
||||
c0.95-0.633,1.861-1.357,2.742-2.155c0.246,0.604,0.528,1.182,0.887,1.705c1.141,1.66,2.61,2.49,4.41,2.49
|
||||
c1.56,0,3.02-0.729,4.38-2.19c1.359-1.459,2.38-3.549,3.061-6.27c0,2.681,0.449,4.761,1.35,6.24c0.9,1.48,2.31,2.22,4.229,2.22
|
||||
c2.521,0,4.771-0.68,6.75-2.04c0.829-0.569,1.63-1.221,2.414-1.923c0.252,0.446,0.534,0.871,0.857,1.264
|
||||
c1.479,1.8,3.459,2.7,5.939,2.7c3.159,0,5.78-1.68,7.86-5.04c0.56,1.56,1.39,2.79,2.49,3.69c1.1,0.9,2.31,1.35,3.63,1.35
|
||||
c1.719,0,3.499-0.699,5.34-2.1c1.397-1.064,2.737-2.315,4.021-3.749c0.17,0.369,0.347,0.732,0.539,1.078
|
||||
c1.759,3.18,4.539,4.77,8.34,4.77c2.64,0,4.999-0.859,7.08-2.58c1.199-1,1.8-2.34,1.8-4.02c0-0.76-0.15-1.41-0.45-1.95
|
||||
S153.188,48.43,152.708,48.43z M66.701,19.36c0.66-2.66,1.359-4.74,2.1-6.24s1.41-2.25,2.01-2.25c0.88,0,1.32,1.181,1.32,3.54
|
||||
c0,2.081-0.591,4.391-1.77,6.93c-1.181,2.541-2.951,4.83-5.311,6.87C65.49,24.97,66.041,22.021,66.701,19.36z M17.772,46.03
|
||||
c-0.359,1.72-0.941,3.1-1.74,4.14c-0.801,1.041-1.641,1.56-2.52,1.56c-0.881,0-1.57-0.3-2.07-0.9c-0.5-0.6-0.75-1.52-0.75-2.76
|
||||
c0-2.24,0.42-4.359,1.26-6.36c0.84-2,1.971-3.609,3.391-4.83c1.418-1.22,2.969-1.85,4.65-1.89L17.772,46.03z M119.649,46.03
|
||||
c-0.359,1.72-0.94,3.1-1.739,4.14c-0.801,1.041-1.641,1.56-2.521,1.56s-1.57-0.3-2.07-0.9c-0.5-0.6-0.75-1.52-0.75-2.76
|
||||
c0-2.24,0.42-4.359,1.261-6.36c0.84-2,1.97-3.609,3.39-4.83c1.419-1.22,2.97-1.85,4.65-1.89L119.649,46.03z M143.228,24.37
|
||||
c0.88-4.92,1.899-9.039,3.061-12.36c1.159-3.32,2.199-4.98,3.12-4.98c1.119,0,1.68,1.521,1.68,4.56c0,3.88-0.84,8.17-2.52,12.87
|
||||
c-1.681,4.7-3.94,9.39-6.78,14.07C141.868,34.01,142.348,29.29,143.228,24.37z"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 5.9 KiB |
@@ -1,71 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta
|
||||
name="viewport"
|
||||
content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no"
|
||||
/>
|
||||
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico" />
|
||||
<link rel="stylesheet" href="https://rsms.me/inter/inter.css" />
|
||||
<title>React App</title>
|
||||
<style type="text/css">
|
||||
html,
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-size: 13px;
|
||||
color: #102a43;
|
||||
background-color: #e5e5e5;
|
||||
padding-top: 1px;
|
||||
}
|
||||
|
||||
* {
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
html,
|
||||
body,
|
||||
button,
|
||||
input {
|
||||
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI',
|
||||
'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans',
|
||||
'Helvetica Neue', 'Helvetica', 'Arial', sans-serif;
|
||||
}
|
||||
|
||||
input,
|
||||
textarea {
|
||||
font-size: 1em;
|
||||
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI',
|
||||
'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans',
|
||||
'Helvetica Neue', 'Helvetica', 'Arial', sans-serif;
|
||||
}
|
||||
|
||||
html,
|
||||
body,
|
||||
#root {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.view {
|
||||
align-items: stretch;
|
||||
border-width: 0;
|
||||
border-style: solid;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
position: relative;
|
||||
/* fix flexbox bugs */
|
||||
min-height: 0;
|
||||
min-width: 0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,55 +0,0 @@
|
||||
import React from 'react';
|
||||
|
||||
import Component from '@reactions/component';
|
||||
|
||||
import { Section } from '../guide/components';
|
||||
|
||||
import Autocomplete, { MultiAutocomplete } from './Autocomplete';
|
||||
|
||||
let items = [
|
||||
{ id: 'one', name: 'James' },
|
||||
{ id: 'two', name: 'Sarah' },
|
||||
{ id: 'three', name: 'Evelina' },
|
||||
{ id: 'four', name: 'Georgia' },
|
||||
{ id: 'five', name: 'Charlotte' },
|
||||
{ id: 'six', name: 'Fannie' },
|
||||
{ id: 'seven', name: 'Lily' },
|
||||
{ id: 'eight', name: 'Gray' },
|
||||
];
|
||||
|
||||
export default () => (
|
||||
<Section>
|
||||
Autocomplete
|
||||
<Autocomplete
|
||||
suggestions={items}
|
||||
highlightFirst
|
||||
onUpdate={() => {}}
|
||||
containerProps={{ style: { width: 300 } }}
|
||||
/>
|
||||
Multi Autocomplete
|
||||
<Component initialState={{ items: [] }}>
|
||||
{({ state, setState }) => (
|
||||
<MultiAutocomplete
|
||||
suggestions={['#one', '#two', '#three']}
|
||||
highlightFirst
|
||||
value={state.items}
|
||||
onChange={items => setState({ items })}
|
||||
containerProps={{ style: { width: 300 } }}
|
||||
/>
|
||||
)}
|
||||
</Component>
|
||||
Multi Autocomplete (strict)
|
||||
<Component initialState={{ ids: [] }}>
|
||||
{({ state, setState }) => (
|
||||
<MultiAutocomplete
|
||||
suggestions={items}
|
||||
highlightFirst
|
||||
strict
|
||||
value={state.ids}
|
||||
onChange={ids => setState({ ids })}
|
||||
containerProps={{ style: { width: 300 } }}
|
||||
/>
|
||||
)}
|
||||
</Component>
|
||||
</Section>
|
||||
);
|
||||
@@ -1,17 +0,0 @@
|
||||
import React from 'react';
|
||||
|
||||
import { Section } from '../guide/components';
|
||||
|
||||
import DateSelect from './DateSelect';
|
||||
|
||||
export default () => (
|
||||
<Section>
|
||||
Date Select
|
||||
<DateSelect
|
||||
onUpdate={() => {}}
|
||||
isOpen={true}
|
||||
dateFormat="MM/dd/yyyy"
|
||||
containerProps={{ style: { width: 300 } }}
|
||||
/>
|
||||
</Section>
|
||||
);
|
||||
@@ -1,29 +0,0 @@
|
||||
import React from 'react';
|
||||
|
||||
import { Section } from '../guide/components';
|
||||
|
||||
import { Button, View } from './common';
|
||||
import RecurringSchedulePicker from './RecurringSchedulePicker';
|
||||
import { useTooltip } from './tooltips';
|
||||
|
||||
export default () => {
|
||||
const { isOpen, close, getOpenEvents } = useTooltip();
|
||||
const onChange = config => {};
|
||||
return (
|
||||
<Section direction="horizontal">
|
||||
Default
|
||||
<View>
|
||||
<Button {...getOpenEvents()}>
|
||||
{isOpen ? 'Hide' : 'Show'} Recurring Schedule Picker
|
||||
</Button>
|
||||
{isOpen && (
|
||||
<RecurringSchedulePicker
|
||||
closeTooltip={close}
|
||||
onSave={console.log}
|
||||
onChange={onChange}
|
||||
/>
|
||||
)}
|
||||
</View>
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
@@ -1,261 +0,0 @@
|
||||
import React from 'react';
|
||||
import { DndProvider } from 'react-dnd';
|
||||
import Backend from 'react-dnd-html5-backend';
|
||||
|
||||
import { generateCategoryGroups } from 'loot-core/src/mocks';
|
||||
import makeSpreadsheet from 'loot-core/src/mocks/spreadsheet';
|
||||
import * as monthUtils from 'loot-core/src/shared/months';
|
||||
|
||||
import { Section } from '../../guide/components';
|
||||
import { colors } from '../../style';
|
||||
import { View } from '../common';
|
||||
import SpreadsheetContext from '../spreadsheet/SpreadsheetContext';
|
||||
|
||||
import { BudgetMonthCountContext } from './BudgetMonthCountContext';
|
||||
import DynamicBudgetTable from './DynamicBudgetTable';
|
||||
import * as rollover from './rollover/rollover-components';
|
||||
import { RolloverContext } from './rollover/RolloverContext';
|
||||
|
||||
const categoryGroups = generateCategoryGroups([
|
||||
{
|
||||
name: 'Investments and Savings',
|
||||
categories: [
|
||||
{ name: 'food' },
|
||||
{ name: 'beer' },
|
||||
{ name: 'home' },
|
||||
{ name: 'general' },
|
||||
{ name: 'bills' },
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'other stuff',
|
||||
categories: [
|
||||
{ name: 'big projects' },
|
||||
{ name: 'beer' },
|
||||
{ name: 'home' },
|
||||
{ name: 'general' },
|
||||
{ name: 'bills' },
|
||||
{ name: 'beer' },
|
||||
{ name: 'home' },
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'yet more stuff',
|
||||
categories: [{ name: 'general' }, { name: 'bills' }],
|
||||
},
|
||||
{
|
||||
name: 'Income',
|
||||
is_income: true,
|
||||
categories: [
|
||||
{ name: 'income', is_income: true },
|
||||
{ name: 'salary', is_income: true },
|
||||
],
|
||||
},
|
||||
]);
|
||||
|
||||
function makeLoadedSpreadsheet() {
|
||||
let spreadsheet = makeSpreadsheet();
|
||||
let months = monthUtils.rangeInclusive(
|
||||
monthUtils.subMonths('2017-01', 3),
|
||||
'2017-10',
|
||||
);
|
||||
|
||||
// Something random
|
||||
let currentNumber = 2400;
|
||||
|
||||
for (let month of months) {
|
||||
// eslint-disable-next-line
|
||||
function value(name, v) {
|
||||
spreadsheet.set(
|
||||
monthUtils.sheetForMonth(month),
|
||||
name,
|
||||
v || currentNumber++,
|
||||
);
|
||||
}
|
||||
|
||||
let values = [
|
||||
value('available-funds'),
|
||||
value('last-month-overspent'),
|
||||
value('buffered'),
|
||||
value('total-budgeted'),
|
||||
value('to-budget'),
|
||||
|
||||
value('from-last-month'),
|
||||
value('total-income'),
|
||||
value('total-spent'),
|
||||
value('total-leftover'),
|
||||
];
|
||||
|
||||
for (let group of categoryGroups) {
|
||||
if (group.is_income) {
|
||||
values.push(value('total-income'));
|
||||
|
||||
for (let cat of group.categories) {
|
||||
values.push(value(`sum-amount-${cat.id}`));
|
||||
}
|
||||
} else {
|
||||
values = values.concat([
|
||||
value(`group-budget-${group.id}`),
|
||||
value(`group-sum-amount-${group.id}`),
|
||||
value(`group-leftover-${group.id}`),
|
||||
]);
|
||||
|
||||
for (let cat of group.categories) {
|
||||
let carryover = Math.random() < 0.2 ? true : false;
|
||||
values = values.concat([
|
||||
value(`budget-${cat.id}`),
|
||||
value(`sum-amount-${cat.id}`),
|
||||
value(`leftover-${cat.id}`, carryover ? -currentNumber : null),
|
||||
value(`carryover-${cat.id}`, carryover),
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return spreadsheet;
|
||||
}
|
||||
|
||||
export class LiveBudgetPage extends React.Component {
|
||||
state = {
|
||||
startMonth: '2017-01',
|
||||
categoryGroups,
|
||||
collapsed: [],
|
||||
newCategoryForGroup: false,
|
||||
};
|
||||
|
||||
render() {
|
||||
let { maxMonths } = this.props;
|
||||
let { startMonth, categoryGroups, collapsed, newCategoryForGroup } =
|
||||
this.state;
|
||||
|
||||
let rolloverComponents = {
|
||||
SummaryComponent: rollover.BudgetSummary,
|
||||
ExpenseCategoryComponent: rollover.ExpenseCategoryMonth,
|
||||
ExpenseGroupComponent: rollover.ExpenseGroupMonth,
|
||||
IncomeCategoryComponent: rollover.IncomeCategoryMonth,
|
||||
IncomeGroupComponent: rollover.IncomeGroupMonth,
|
||||
BudgetTotalsComponent: rollover.BudgetTotalsMonth,
|
||||
IncomeHeaderComponent: rollover.IncomeHeaderMonth,
|
||||
};
|
||||
|
||||
return (
|
||||
<DndProvider backend={Backend}>
|
||||
<RolloverContext
|
||||
categoryGroups={categoryGroups}
|
||||
summaryCollapsed={false}
|
||||
>
|
||||
<View
|
||||
style={{
|
||||
height: 800,
|
||||
backgroundColor: colors.n10,
|
||||
overflow: 'hidden',
|
||||
}}
|
||||
>
|
||||
<DynamicBudgetTable
|
||||
prewarmStartMonth={startMonth}
|
||||
startMonth={startMonth}
|
||||
monthBounds={{
|
||||
start: monthUtils.subMonths('2017-01', 3),
|
||||
end: '2017-10',
|
||||
}}
|
||||
maxMonths={maxMonths}
|
||||
onMonthSelect={month => {
|
||||
this.setState({ startMonth: month });
|
||||
}}
|
||||
categoryGroups={categoryGroups}
|
||||
collapsed={collapsed}
|
||||
setCollapsed={collapsed => {
|
||||
this.setState({ collapsed });
|
||||
}}
|
||||
newCategoryForGroup={newCategoryForGroup}
|
||||
dataComponents={rolloverComponents}
|
||||
// onAddCategory={groupId => {}}
|
||||
onSavePrefs={() => {}}
|
||||
onShowNewCategory={groupId => {
|
||||
this.setState({
|
||||
newCategoryForGroup: groupId,
|
||||
collapsed: collapsed.filter(c => c !== groupId),
|
||||
});
|
||||
}}
|
||||
onHideNewCategory={() => {
|
||||
this.setState({ newCategoryForGroup: null });
|
||||
}}
|
||||
onSaveCategory={cat => {
|
||||
if (cat.id === 'new') {
|
||||
cat.id = Math.random().toString();
|
||||
|
||||
this.setState({
|
||||
categoryGroups: categoryGroups.map(group => {
|
||||
if (group.id === cat.cat_group) {
|
||||
return {
|
||||
...group,
|
||||
categories: group.categories.concat([cat]),
|
||||
};
|
||||
}
|
||||
return group;
|
||||
}),
|
||||
newCategoryForGroup: null,
|
||||
});
|
||||
} else {
|
||||
this.setState({
|
||||
categoryGroups: categoryGroups.map(group => {
|
||||
if (group.id === cat.cat_group) {
|
||||
return {
|
||||
...group,
|
||||
categories: group.categories.map(c =>
|
||||
c.id === cat.id ? cat : c,
|
||||
),
|
||||
};
|
||||
}
|
||||
return group;
|
||||
}),
|
||||
});
|
||||
}
|
||||
}}
|
||||
onSaveGroup={group => {
|
||||
this.setState({
|
||||
categoryGroups: categoryGroups.map(g =>
|
||||
g.id === group.id ? group : g,
|
||||
),
|
||||
});
|
||||
}}
|
||||
onDeleteCategory={id => {
|
||||
this.setState({
|
||||
categoryGroups: categoryGroups.map(group => {
|
||||
return {
|
||||
...group,
|
||||
categories: group.categories.filter(c => c.id !== id),
|
||||
};
|
||||
}),
|
||||
});
|
||||
}}
|
||||
onDeleteGroup={id =>
|
||||
this.setState({
|
||||
categoryGroups: categoryGroups.filter(g => g.id !== id),
|
||||
})
|
||||
}
|
||||
onReorderCategory={sortInfo => {}}
|
||||
onReorderGroup={sortInfo => {}}
|
||||
/>
|
||||
</View>
|
||||
</RolloverContext>
|
||||
</DndProvider>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default () => (
|
||||
<BudgetMonthCountContext.Provider value={{ setDisplayMax: () => {} }}>
|
||||
<SpreadsheetContext.Provider value={makeLoadedSpreadsheet()}>
|
||||
<Section>
|
||||
Budget Table
|
||||
<LiveBudgetPage maxMonths={3} />
|
||||
</Section>
|
||||
{/*<Section>
|
||||
Budget Table (2 months)
|
||||
<LiveBudgetPage width={1000} maxMonths={2} />
|
||||
</Section>*/}
|
||||
</SpreadsheetContext.Provider>
|
||||
</BudgetMonthCountContext.Provider>
|
||||
);
|
||||
@@ -1,75 +0,0 @@
|
||||
import React from 'react';
|
||||
|
||||
import Component from '@reactions/component';
|
||||
|
||||
import { Section, TestModal } from '../guide/components';
|
||||
|
||||
import { Input, Modal, View, Button, Stack } from './common';
|
||||
|
||||
export default () => {
|
||||
return (
|
||||
<Section style={{ width: 200 }}>
|
||||
Input
|
||||
<Input defaultValue="value" onEnter={e => alert(e.target.value)} />
|
||||
Buttons
|
||||
<Stack
|
||||
align="flex-start"
|
||||
style={{ backgroundColor: 'white', padding: 15 }}
|
||||
>
|
||||
<Button>Hello</Button>
|
||||
<Button primary>Hello</Button>
|
||||
<Button bare>Hello</Button>
|
||||
</Stack>
|
||||
Modal
|
||||
<Component initialState={{ modalCount: 1 }}>
|
||||
{({ state, setState }) => {
|
||||
return (
|
||||
<TestModal width={600} height={500}>
|
||||
{node => {
|
||||
let modals = [];
|
||||
|
||||
for (let i = 0; i < state.modalCount; i++) {
|
||||
let modalProps = {
|
||||
onClose: () =>
|
||||
setState({ modalCount: state.modalCount - 1 }),
|
||||
isCurrent: i === state.modalCount - 1,
|
||||
stackIndex: i,
|
||||
parent: node,
|
||||
};
|
||||
|
||||
modals.push(
|
||||
<Modal {...modalProps}>
|
||||
<View style={{ height: 300 }}>
|
||||
Pushin' and poppin'
|
||||
<Button
|
||||
primary
|
||||
onClick={() =>
|
||||
setState({ modalCount: state.modalCount + 1 })
|
||||
}
|
||||
style={{ marginTop: 10, alignSelf: 'flex-start' }}
|
||||
>
|
||||
Push modal
|
||||
</Button>
|
||||
<Button
|
||||
primary
|
||||
onClick={() =>
|
||||
setState({ modalCount: state.modalCount - 1 })
|
||||
}
|
||||
style={{ marginTop: 10, alignSelf: 'flex-start' }}
|
||||
>
|
||||
Pop modal
|
||||
</Button>
|
||||
</View>
|
||||
</Modal>,
|
||||
);
|
||||
}
|
||||
|
||||
return modals;
|
||||
}}
|
||||
</TestModal>
|
||||
);
|
||||
}}
|
||||
</Component>
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
@@ -1,58 +0,0 @@
|
||||
import React, { useState } from 'react';
|
||||
|
||||
import { Section } from '../guide/components';
|
||||
|
||||
import { View, Button } from './common';
|
||||
|
||||
const context = require.context('../svg/v1', false, /\.js$/);
|
||||
const modules = {};
|
||||
context.keys().forEach(function (key) {
|
||||
var module = context(key);
|
||||
modules[key] = module;
|
||||
});
|
||||
|
||||
function pathToName(path) {
|
||||
const name = path.match(/^\.\/(.*)\.js$/)[1];
|
||||
return name[0].toUpperCase() + name.slice(1);
|
||||
}
|
||||
|
||||
export default () => {
|
||||
let [show, setShow] = useState(false);
|
||||
|
||||
return (
|
||||
<Section direction="vertical">
|
||||
{!show ? (
|
||||
<Button onClick={() => setShow(true)}>Show icons</Button>
|
||||
) : (
|
||||
<View
|
||||
style={{
|
||||
display: 'grid',
|
||||
gridTemplateColumns: 'repeat(6, 1fr)',
|
||||
gridGap: 10,
|
||||
width: 500,
|
||||
}}
|
||||
>
|
||||
{Object.keys(modules).map(path => {
|
||||
const Component = modules[path].default;
|
||||
return (
|
||||
<Section>
|
||||
{pathToName(path)}
|
||||
<div
|
||||
style={{
|
||||
width: 20,
|
||||
height: 20,
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
}}
|
||||
>
|
||||
<Component width={25} />
|
||||
</div>
|
||||
</Section>
|
||||
);
|
||||
})}
|
||||
</View>
|
||||
)}
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
@@ -1,33 +0,0 @@
|
||||
import React from 'react';
|
||||
|
||||
import { Section, TestModal } from '../../guide/components';
|
||||
import { colors } from '../../style';
|
||||
|
||||
import BudgetList from './BudgetList';
|
||||
|
||||
const files = [
|
||||
{ name: 'Finances 2', id: '1', state: 'local' },
|
||||
{ name: 'James', id: '2', state: 'detached' },
|
||||
{ name: 'Sarah', id: '3', state: 'broken' },
|
||||
{ name: 'Finances', id: '4', state: 'broken' },
|
||||
{ name: 'Finances 2', id: '5', state: 'synced' },
|
||||
{ name: 'Finances 2', id: '6', state: 'remote' },
|
||||
{ name: 'Shift Reset LLC', id: '7' },
|
||||
{ name: 'Shift Reset LLC', id: '8', state: 'unknown' },
|
||||
];
|
||||
|
||||
export default () => (
|
||||
<Section>
|
||||
Budget List Modal
|
||||
<TestModal backgroundColor={colors.n10}>
|
||||
{node => (
|
||||
<BudgetList
|
||||
key="modal"
|
||||
modalProps={{ isCurrent: true, parent: node }}
|
||||
files={files}
|
||||
actions={{}}
|
||||
/>
|
||||
)}
|
||||
</TestModal>
|
||||
</Section>
|
||||
);
|
||||
@@ -1,26 +0,0 @@
|
||||
import React from 'react';
|
||||
|
||||
import { Section, TestModal } from '../../guide/components';
|
||||
import { colors } from '../../style';
|
||||
|
||||
import DeleteFile from './DeleteFile';
|
||||
|
||||
export default () => (
|
||||
<Section>
|
||||
Budget List Modal
|
||||
<TestModal backgroundColor={colors.n10}>
|
||||
{node => (
|
||||
<DeleteFile
|
||||
modalProps={{ isCurrent: true, parent: node }}
|
||||
file={{
|
||||
name: 'Finances 2',
|
||||
id: 'msdfmsdf',
|
||||
cloudFileId: 'vxsfeqw',
|
||||
state: 'synced',
|
||||
}}
|
||||
actions={{}}
|
||||
/>
|
||||
)}
|
||||
</TestModal>
|
||||
</Section>
|
||||
);
|
||||
@@ -1,21 +0,0 @@
|
||||
import React from 'react';
|
||||
|
||||
import { Section, TestModal } from '../../guide/components';
|
||||
import { colors } from '../../style';
|
||||
|
||||
import Import from './Import';
|
||||
|
||||
export default () => (
|
||||
<Section>
|
||||
Import
|
||||
<TestModal backgroundColor={colors.n1}>
|
||||
{node => (
|
||||
<Import
|
||||
modalProps={{ isCurrent: true, parent: node }}
|
||||
availableImports={[]}
|
||||
actions={{ getYNAB4Imports: () => [] }}
|
||||
/>
|
||||
)}
|
||||
</TestModal>
|
||||
</Section>
|
||||
);
|
||||
@@ -1,51 +0,0 @@
|
||||
import React from 'react';
|
||||
import { MemoryRouter as Router } from 'react-router-dom';
|
||||
|
||||
import { generateAccount, generateCategoryGroups } from 'loot-core/src/mocks';
|
||||
|
||||
import { Section, TestModal } from '../../guide/components';
|
||||
|
||||
import CloseAccount from './CloseAccount';
|
||||
|
||||
const accounts = [
|
||||
generateAccount('Bank of America', null, null, false),
|
||||
generateAccount('Wells Fargo', null, null, false),
|
||||
generateAccount('Ally', null, null, false),
|
||||
generateAccount('Savings', null, null, true),
|
||||
generateAccount('Another', null, null, true),
|
||||
];
|
||||
|
||||
const categoryGroups = generateCategoryGroups([
|
||||
{
|
||||
name: 'Investments and Savings',
|
||||
categories: [{ name: 'Savings' }],
|
||||
},
|
||||
{
|
||||
name: 'Usual Expenses',
|
||||
categories: [{ name: 'Food' }, { name: 'General' }, { name: 'Home' }],
|
||||
},
|
||||
{
|
||||
name: 'Projects',
|
||||
categories: [{ name: 'Big Projects' }, { name: 'Shed' }],
|
||||
},
|
||||
]);
|
||||
|
||||
export default () => (
|
||||
<Router>
|
||||
<Section>
|
||||
Close Account Modal
|
||||
<TestModal width={700} height={600}>
|
||||
{node => (
|
||||
<CloseAccount
|
||||
modalProps={{ isCurrent: true, parent: node }}
|
||||
account={accounts[0]}
|
||||
accounts={accounts}
|
||||
categoryGroups={categoryGroups}
|
||||
balance={12000}
|
||||
canDelete={false}
|
||||
/>
|
||||
)}
|
||||
</TestModal>
|
||||
</Section>
|
||||
</Router>
|
||||
);
|
||||
@@ -1,58 +0,0 @@
|
||||
import React from 'react';
|
||||
|
||||
import { Section, TestModal } from '../../guide/components';
|
||||
|
||||
import ConfigureLinkedAccounts from './ConfigureLinkedAccounts';
|
||||
|
||||
export default () => (
|
||||
<Section>
|
||||
Link Account Modal
|
||||
<TestModal>
|
||||
{node => (
|
||||
<ConfigureLinkedAccounts
|
||||
modalProps={{
|
||||
isCurrent: true,
|
||||
parent: node,
|
||||
}}
|
||||
accounts={[
|
||||
{
|
||||
id: '1',
|
||||
name: 'Bank of America',
|
||||
mask: '1111',
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
name: 'Wells Fargo',
|
||||
mask: '2222',
|
||||
},
|
||||
{
|
||||
id: '3',
|
||||
name: 'Wells Fargo',
|
||||
mask: '3333',
|
||||
},
|
||||
{
|
||||
id: '4',
|
||||
name: 'Wells Fargo',
|
||||
mask: '4444',
|
||||
},
|
||||
{
|
||||
id: '5',
|
||||
name: 'Wells Fargo',
|
||||
mask: '5555',
|
||||
},
|
||||
{
|
||||
id: '6',
|
||||
name: 'Wells Fargo',
|
||||
mask: '6666',
|
||||
},
|
||||
{
|
||||
id: '7',
|
||||
name: 'Wells Fargo',
|
||||
mask: '7777',
|
||||
},
|
||||
]}
|
||||
/>
|
||||
)}
|
||||
</TestModal>
|
||||
</Section>
|
||||
);
|
||||
@@ -1,16 +0,0 @@
|
||||
import React from 'react';
|
||||
|
||||
import { Section, TestModal } from '../../guide/components';
|
||||
|
||||
import CreateLocalAccount from './CreateLocalAccount';
|
||||
|
||||
export default () => (
|
||||
<Section>
|
||||
Create Account Modal
|
||||
<TestModal>
|
||||
{node => (
|
||||
<CreateLocalAccount modalProps={{ isCurrent: true, parent: node }} />
|
||||
)}
|
||||
</TestModal>
|
||||
</Section>
|
||||
);
|
||||
@@ -1,40 +0,0 @@
|
||||
import React from 'react';
|
||||
|
||||
import { generateTransactions } from 'loot-core/src/mocks';
|
||||
import { TestProvider } from 'loot-core/src/mocks/redux';
|
||||
|
||||
import { Section, TestModal } from '../../guide/components';
|
||||
|
||||
import { ImportTransactions } from './ImportTransactions';
|
||||
|
||||
let transactions = generateTransactions(20, 'acct', 'group');
|
||||
// The mocks generate "internal" transactions... but we need the
|
||||
// "public" shape. Will reconcile this difference over time.
|
||||
transactions = transactions.map(trans => ({
|
||||
amount: trans.amount,
|
||||
date: trans.date,
|
||||
payee: trans.description,
|
||||
imported_payee: trans.description,
|
||||
notes: trans.notes,
|
||||
}));
|
||||
|
||||
export default () => (
|
||||
<Section>
|
||||
Import Transactions Modal
|
||||
<TestProvider>
|
||||
<TestModal width={1000} height={600}>
|
||||
{node => (
|
||||
<ImportTransactions
|
||||
modalProps={{ isCurrent: true, parent: node }}
|
||||
options={{ filename: 'file.csv' }}
|
||||
parseTransactions={filename => ({
|
||||
errors: [],
|
||||
transactions,
|
||||
})}
|
||||
prefs={{}}
|
||||
/>
|
||||
)}
|
||||
</TestModal>
|
||||
</TestProvider>
|
||||
</Section>
|
||||
);
|
||||
@@ -1,26 +0,0 @@
|
||||
import React from 'react';
|
||||
|
||||
import { Section, TestModal } from '../../guide/components';
|
||||
import { colors } from '../../style';
|
||||
|
||||
import LoadBackup from './LoadBackup';
|
||||
|
||||
const backups = [
|
||||
{ date: 'December 23, 2017 4:08 PM', id: 'sdflkj23' },
|
||||
{ date: 'January 21, 2018 4:20 PM', id: 'ds10dsm23rlk' },
|
||||
{ date: 'February 22, 2018 3:54 PM', id: 'k3dsjndlwe' },
|
||||
];
|
||||
|
||||
export default () => (
|
||||
<Section>
|
||||
Backup List Modal
|
||||
<TestModal backgroundColor={colors.sidebar}>
|
||||
{node => (
|
||||
<LoadBackup
|
||||
modalProps={{ isCurrent: true, parent: node }}
|
||||
backups={backups}
|
||||
/>
|
||||
)}
|
||||
</TestModal>
|
||||
</Section>
|
||||
);
|
||||
@@ -1,21 +0,0 @@
|
||||
import React from 'react';
|
||||
|
||||
import { Section, TestModal } from '../../guide/components';
|
||||
|
||||
import PlaidExternalMsg from './PlaidExternalMsg';
|
||||
|
||||
export default () => (
|
||||
<Section>
|
||||
Plaid External Msg Modal
|
||||
<TestModal>
|
||||
{node => (
|
||||
<PlaidExternalMsg
|
||||
modalProps={{
|
||||
isCurrent: true,
|
||||
parent: node,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</TestModal>
|
||||
</Section>
|
||||
);
|
||||
@@ -1,58 +0,0 @@
|
||||
import React from 'react';
|
||||
|
||||
import { Section, TestModal } from '../../guide/components';
|
||||
|
||||
import SelectLinkedAccounts from './SelectLinkedAccounts';
|
||||
|
||||
export default () => (
|
||||
<Section>
|
||||
Link Account Modal
|
||||
<TestModal>
|
||||
{node => (
|
||||
<SelectLinkedAccounts
|
||||
modalProps={{
|
||||
isCurrent: true,
|
||||
parent: node,
|
||||
}}
|
||||
accounts={[
|
||||
{
|
||||
id: '1',
|
||||
name: 'Bank of America',
|
||||
mask: '1111',
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
name: 'Wells Fargo',
|
||||
mask: '2222',
|
||||
},
|
||||
{
|
||||
id: '3',
|
||||
name: 'Wells Fargo',
|
||||
mask: '3333',
|
||||
},
|
||||
{
|
||||
id: '4',
|
||||
name: 'Wells Fargo',
|
||||
mask: '4444',
|
||||
},
|
||||
{
|
||||
id: '5',
|
||||
name: 'Wells Fargo',
|
||||
mask: '5555',
|
||||
},
|
||||
{
|
||||
id: '6',
|
||||
name: 'Wells Fargo',
|
||||
mask: '6666',
|
||||
},
|
||||
{
|
||||
id: '7',
|
||||
name: 'Wells Fargo',
|
||||
mask: '7777',
|
||||
},
|
||||
]}
|
||||
/>
|
||||
)}
|
||||
</TestModal>
|
||||
</Section>
|
||||
);
|
||||
@@ -1,132 +0,0 @@
|
||||
import React from 'react';
|
||||
|
||||
import Component from '@reactions/component';
|
||||
|
||||
import { TestProvider } from 'loot-core/src/mocks/redux';
|
||||
import { applyChanges } from 'loot-core/src/shared/util';
|
||||
|
||||
import { Section, TestModal } from '../guide/components';
|
||||
|
||||
import { ManagePayees } from './payees';
|
||||
|
||||
let categoryGroups = [
|
||||
{
|
||||
id: 'foo',
|
||||
name: 'Investments and Savings',
|
||||
is_income: 0,
|
||||
sort_order: 1,
|
||||
categories: [{ id: 'savings', name: 'Savings' }],
|
||||
},
|
||||
{
|
||||
id: 'usual',
|
||||
name: 'Usual Expenses',
|
||||
is_income: 0,
|
||||
sort_order: 2,
|
||||
categories: [
|
||||
{ id: 'food', name: 'Food' },
|
||||
{ id: 'general', name: 'General' },
|
||||
{ id: 'home', name: 'Home' },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'projects',
|
||||
name: 'Projects',
|
||||
categories: [
|
||||
{ id: 'big', name: 'Big Projects' },
|
||||
{ id: 'shed', name: 'Shed' },
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
let payees = [
|
||||
{ id: 'one', name: 'Kroger', ruleCount: 1 },
|
||||
{
|
||||
id: 'two',
|
||||
name: 'Lowes',
|
||||
category: categoryGroups[1].categories[1].id,
|
||||
ruleCount: 1,
|
||||
},
|
||||
{ id: 'three', name: 'Publix', ruleCount: 1 },
|
||||
{ id: 'four', name: 'Verizon', ruleCount: 3 },
|
||||
{ id: 'eight', name: 'Aldi', ruleCount: 3 },
|
||||
{ id: 'nine', name: 'T-Mobile', ruleCount: 2 },
|
||||
{ id: 'ten', name: 'Google', ruleCount: 1 },
|
||||
{ id: 'el', name: 'Sentry', ruleCount: 1 },
|
||||
{ id: 'tw', name: 'Aldi', ruleCount: 2 },
|
||||
{ id: 'th', name: 'T-Mobile', ruleCount: 3 },
|
||||
{ id: 'fou', name: 'Google', ruleCount: 1 },
|
||||
{ id: 'fifff', name: 'Sentry', ruleCount: 2 },
|
||||
{ id: 'sixxx', name: 'Aldi', ruleCount: 1 },
|
||||
{ id: 'nine1', name: 'T-Mobile', ruleCount: 2 },
|
||||
{ id: 'ten1', name: 'Google', ruleCount: 1 },
|
||||
{ id: 'el1', name: 'Sentry', ruleCount: 1 },
|
||||
{ id: 'tw1', name: 'Aldi', ruleCount: 2 },
|
||||
{ id: 'th1', name: 'T-Mobile', ruleCount: 3 },
|
||||
{ id: 'fou1', name: 'Google', ruleCount: 1 },
|
||||
{ id: 'fifff1', name: 'Sentry', ruleCount: 2 },
|
||||
{ id: 'sixxx1', name: 'Aldi', ruleCount: 1 },
|
||||
{ id: 'five', name: 'T-Mobile', transfer_acct: 'one', ruleCount: 5 },
|
||||
{ id: 'six', name: 'Google', transfer_acct: 'one', ruleCount: 1 },
|
||||
{ id: 'seven', name: 'Sentry', transfer_acct: 'one', ruleCount: 1 },
|
||||
];
|
||||
|
||||
for (let i = 0; i < 4; i++) {
|
||||
payees = payees.concat(payees.map(p => ({ ...p, id: p.id + i })));
|
||||
}
|
||||
|
||||
let defaultRules = [
|
||||
{ id: '1', type: 'equals', value: 'target' },
|
||||
{ id: '2', type: 'contains', value: 'targ#' },
|
||||
];
|
||||
|
||||
export default () => (
|
||||
<Section>
|
||||
Manage Payees
|
||||
<TestProvider>
|
||||
<TestModal width={1000} height={700}>
|
||||
{node => (
|
||||
<Component
|
||||
initialState={{ payees, rules: [...defaultRules], isCurrent: true }}
|
||||
>
|
||||
{({ state, setState }) => {
|
||||
let onViewRules = () => setState({ isCurrent: false });
|
||||
|
||||
return (
|
||||
<ManagePayees
|
||||
modalProps={{
|
||||
isCurrent: state.isCurrent,
|
||||
parent: node,
|
||||
onClose: () => setState({ isCurrent: true }),
|
||||
}}
|
||||
payees={state.payees}
|
||||
ruleCounts={
|
||||
new Map([
|
||||
['three', 1],
|
||||
['tw', 3],
|
||||
])
|
||||
}
|
||||
categoryGroups={categoryGroups}
|
||||
onBatchChange={changes => {
|
||||
setState({ payees: applyChanges(changes, state.payees) });
|
||||
}}
|
||||
onViewRules={onViewRules}
|
||||
initialSelectedIds={new Set([])}
|
||||
ruleActions={{
|
||||
loadRules: () =>
|
||||
new Promise(resolve => resolve(state.rules)),
|
||||
deleteRule: id => {},
|
||||
saveRule: rule => {},
|
||||
addRule: rule => {
|
||||
return { ...rule, id: Math.random().toString() };
|
||||
},
|
||||
listenForUndo: () => {},
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
</Component>
|
||||
)}
|
||||
</TestModal>
|
||||
</TestProvider>
|
||||
</Section>
|
||||
);
|
||||
@@ -1,60 +0,0 @@
|
||||
import React from 'react';
|
||||
import { DndProvider } from 'react-dnd';
|
||||
import Backend from 'react-dnd-html5-backend';
|
||||
import { MemoryRouter as Router } from 'react-router-dom';
|
||||
|
||||
import lively from '@jlongster/lively';
|
||||
|
||||
import { generateAccount } from 'loot-core/src/mocks';
|
||||
import makeSpreadsheet from 'loot-core/src/mocks/spreadsheet';
|
||||
|
||||
import { Section } from '../guide/components';
|
||||
|
||||
import { Sidebar } from './sidebar';
|
||||
import SpreadsheetContext from './spreadsheet/SpreadsheetContext';
|
||||
|
||||
function withState(state, render) {
|
||||
const Component = lively(render, { getInitialState: () => state });
|
||||
return <Component />;
|
||||
}
|
||||
|
||||
const accounts = [
|
||||
generateAccount('Bank of America', true),
|
||||
generateAccount('Wells Fargo', true),
|
||||
generateAccount('Ally'),
|
||||
{ ...generateAccount('401k'), closed: 1 },
|
||||
{ ...generateAccount('Old Savings'), closed: 1 },
|
||||
];
|
||||
|
||||
function makeSidebar(selected) {
|
||||
return withState({ selected }, ({ state: { selected }, setState }) => {
|
||||
return (
|
||||
<Router initialEntries={[selected]} initialIndex={0}>
|
||||
<DndProvider backend={Backend}>
|
||||
<Sidebar
|
||||
budgetName="Personal"
|
||||
accounts={accounts}
|
||||
getBalanceQuery={account => ({ expr: 10000 })}
|
||||
getOnBudgetBalance={() => ({ expr: 30000 })}
|
||||
getOffBudgetBalance={() => ({ expr: 10000 })}
|
||||
showClosedAccounts={true}
|
||||
style={{ paddingBottom: 100 }}
|
||||
/>
|
||||
</DndProvider>
|
||||
</Router>
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
export default () => (
|
||||
<SpreadsheetContext.Provider value={makeSpreadsheet()}>
|
||||
<Section direction="horizontal">
|
||||
Sidebar
|
||||
{makeSidebar('/budget')}
|
||||
Sidebar Sidebar with Accounts Selected
|
||||
{makeSidebar('/accounts')}
|
||||
Sidebar Sidebar with One Account Selected
|
||||
{makeSidebar('/accounts/' + accounts[1].id)}
|
||||
</Section>
|
||||
</SpreadsheetContext.Provider>
|
||||
);
|
||||
@@ -1,164 +0,0 @@
|
||||
import React, { useState } from 'react';
|
||||
|
||||
import { Section, Component } from '../guide/components';
|
||||
|
||||
import { View, Text } from './common';
|
||||
import {
|
||||
TableWithNavigator as Table,
|
||||
Row,
|
||||
Cell,
|
||||
InputCell,
|
||||
useTableNavigator,
|
||||
} from './table';
|
||||
|
||||
let uuid = require('loot-core/src/platform/uuid');
|
||||
|
||||
function PersonRow({ person, editing, focusedField, onEdit, onUpdate }) {
|
||||
let { id } = person;
|
||||
return (
|
||||
<Row style={{ width: 500 }} borderColor="#f0f0f0" collapsed={true}>
|
||||
<InputCell
|
||||
width="flex"
|
||||
value={person.name}
|
||||
exposed={focusedField === 'name'}
|
||||
onUpdate={value => onUpdate(id, 'name', value)}
|
||||
onExpose={() => onEdit(id, 'name')}
|
||||
/>
|
||||
{person.poop ? (
|
||||
<InputCell
|
||||
width="100"
|
||||
value={person.poop}
|
||||
exposed={focusedField === 'poop'}
|
||||
onUpdate={value => onUpdate(id, 'poop', value)}
|
||||
onExpose={() => onEdit(id, 'poop')}
|
||||
/>
|
||||
) : (
|
||||
<Cell width="100" />
|
||||
)}
|
||||
<InputCell
|
||||
width="100"
|
||||
value={person.age}
|
||||
exposed={focusedField === 'age'}
|
||||
onUpdate={value => onUpdate(id, 'age', value)}
|
||||
onExpose={() => onEdit(id, 'age')}
|
||||
/>
|
||||
<InputCell
|
||||
width="100"
|
||||
value={person.height}
|
||||
exposed={focusedField === 'height'}
|
||||
onUpdate={value => onUpdate(id, 'height', value)}
|
||||
onExpose={() => onEdit(id, 'height')}
|
||||
/>
|
||||
</Row>
|
||||
);
|
||||
}
|
||||
|
||||
let people = [
|
||||
{ id: 1, name: 'James', age: 34, height: 6 },
|
||||
{ id: 2, name: 'Sarah', poop: 1, age: 33, height: 5.6 },
|
||||
{ id: 3, name: 'Evy', age: 4, height: 3 },
|
||||
{ id: 4, name: 'Georgia', poop: 2, age: 3, height: 2.5 },
|
||||
{ id: 5, name: 'Charlotte', age: 0, height: 1.2 },
|
||||
];
|
||||
|
||||
let getFields = item =>
|
||||
item.poop ? ['name', 'poop', 'age', 'height'] : ['name', 'age', 'height'];
|
||||
|
||||
export default () => (
|
||||
<Section>
|
||||
Input Cell Example
|
||||
<Component>
|
||||
{() => {
|
||||
let [value, setValue] = useState('hello');
|
||||
let [exposed, setExposed] = useState(false);
|
||||
|
||||
return (
|
||||
<View style={{ backgroundColor: 'white', width: 200 }}>
|
||||
<InputCell
|
||||
value={value}
|
||||
exposed={exposed}
|
||||
onUpdate={value => setValue(value)}
|
||||
onExpose={() => setExposed(true)}
|
||||
onBlur={() => setExposed(false)}
|
||||
style={{ height: 30 }}
|
||||
/>
|
||||
<Text style={{ padding: 10 }}>{value}</Text>
|
||||
</View>
|
||||
);
|
||||
}}
|
||||
</Component>
|
||||
Multiple Cells
|
||||
<Component>
|
||||
{() => {
|
||||
let [items, setItems] = useState(() => {
|
||||
return [...people];
|
||||
});
|
||||
let { onEdit, editingId, focusedField, getNavigatorProps } =
|
||||
useTableNavigator(items, getFields);
|
||||
|
||||
function onUpdate(id, name, value) {
|
||||
let idx = items.findIndex(item => item.id === id);
|
||||
items[idx] = { ...items[idx], [name]: value };
|
||||
setItems(items);
|
||||
}
|
||||
|
||||
return (
|
||||
<View
|
||||
style={{ backgroundColor: 'white', width: 500 }}
|
||||
{...getNavigatorProps()}
|
||||
>
|
||||
{items.map(item => {
|
||||
let editing = editingId === item.id;
|
||||
return (
|
||||
<PersonRow
|
||||
person={item}
|
||||
editing={editing}
|
||||
focusedField={editing && focusedField}
|
||||
onEdit={onEdit}
|
||||
onUpdate={onUpdate}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</View>
|
||||
);
|
||||
}}
|
||||
</Component>
|
||||
Using Table
|
||||
<Component>
|
||||
{() => {
|
||||
let [items, setItems] = useState(() => {
|
||||
let lots = [];
|
||||
for (let i = 0; i < 100; i++) {
|
||||
lots = lots.concat(
|
||||
people.map(person => ({ ...person, id: uuid.v4Sync() })),
|
||||
);
|
||||
}
|
||||
return lots;
|
||||
});
|
||||
|
||||
function onUpdate(id, name, value) {
|
||||
let idx = items.findIndex(item => item.id === id);
|
||||
items[idx] = { ...items[idx], [name]: value };
|
||||
setItems(items);
|
||||
}
|
||||
|
||||
return (
|
||||
<Table
|
||||
items={items}
|
||||
fields={getFields}
|
||||
style={{ width: 500, height: 200 }}
|
||||
renderItem={({ props, item, editing, focusedField, onEdit }) => (
|
||||
<PersonRow
|
||||
person={item}
|
||||
editing={editing}
|
||||
focusedField={focusedField}
|
||||
onEdit={onEdit}
|
||||
onUpdate={onUpdate}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
</Component>
|
||||
</Section>
|
||||
);
|
||||
@@ -1,161 +0,0 @@
|
||||
import React from 'react';
|
||||
|
||||
import { css } from 'glamor';
|
||||
|
||||
export function Section({
|
||||
children,
|
||||
style,
|
||||
contentStyle,
|
||||
direction = 'vertical',
|
||||
}) {
|
||||
const arr = React.Children.toArray(children);
|
||||
|
||||
const items = [];
|
||||
let i = 0;
|
||||
while (i < arr.length) {
|
||||
if (typeof arr[i] !== 'string') {
|
||||
items.push(arr[i]);
|
||||
i++;
|
||||
} else {
|
||||
items.push([arr[i], arr[i + 1]]);
|
||||
i += 2;
|
||||
}
|
||||
}
|
||||
|
||||
const margin = direction === 'horizontal' ? '0 15px' : '15px 0';
|
||||
|
||||
return (
|
||||
<div
|
||||
{...css(
|
||||
{
|
||||
display: 'flex',
|
||||
flexDirection: direction === 'horizontal' ? 'row' : 'column',
|
||||
},
|
||||
style,
|
||||
)}
|
||||
data-section="true"
|
||||
>
|
||||
{items.map((item, i) => {
|
||||
return Array.isArray(item) ? (
|
||||
<div style={{ margin }} key={i}>
|
||||
<div style={{ color: '#a0a0a0', fontSize: 10, marginBottom: 5 }}>
|
||||
{item[0]}
|
||||
</div>
|
||||
|
||||
<div {...css(contentStyle)}>{item[1]}</div>
|
||||
</div>
|
||||
) : (
|
||||
<div {...css({ margin }, contentStyle)} key={i}>
|
||||
{item}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function MobileSection({ style, headerComponent, children }) {
|
||||
return (
|
||||
<Section
|
||||
contentStyle={[
|
||||
{
|
||||
width: 375,
|
||||
height: 667,
|
||||
border: '1px solid #f0f0f0',
|
||||
overflow: 'hidden',
|
||||
display: 'flex',
|
||||
backgroundColor: '#fafafa',
|
||||
},
|
||||
style,
|
||||
]}
|
||||
>
|
||||
{children}
|
||||
</Section>
|
||||
);
|
||||
}
|
||||
|
||||
export function WithHeader({ title, style, children }) {
|
||||
return (
|
||||
<div
|
||||
{...css([
|
||||
{
|
||||
flex: 1,
|
||||
fontSize: 14,
|
||||
fontWeight: 500,
|
||||
color: '#303030',
|
||||
},
|
||||
style,
|
||||
])}
|
||||
>
|
||||
<div {...css({ textAlign: 'center', paddingTop: 10, paddingBottom: 5 })}>
|
||||
{title}
|
||||
</div>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function MobileScreen({ children }) {
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
width: 375,
|
||||
height: 667,
|
||||
overflow: 'hidden',
|
||||
display: 'flex',
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function Note({ top, left, width, children }) {
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
position: 'absolute',
|
||||
top: top || 0,
|
||||
left: left || 0,
|
||||
width: width,
|
||||
backgroundColor: '#fff971',
|
||||
padding: 5,
|
||||
fontSize: 12,
|
||||
fontStyle: 'italic',
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export class TestModal extends React.Component {
|
||||
state = { parentNode: null };
|
||||
|
||||
componentDidMount() {
|
||||
this.setState({ parentNode: this.parent });
|
||||
}
|
||||
|
||||
render() {
|
||||
const { children, backgroundColor, width = 800, height = 500 } = this.props;
|
||||
const { parentNode } = this.state;
|
||||
|
||||
return [
|
||||
<div
|
||||
key="parent"
|
||||
ref={el => (this.parent = el)}
|
||||
style={{
|
||||
width,
|
||||
height,
|
||||
position: 'relative',
|
||||
backgroundColor: backgroundColor || '#f0f0f0',
|
||||
}}
|
||||
/>,
|
||||
parentNode && children(parentNode),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
export function Component({ children }) {
|
||||
return children();
|
||||
}
|
||||
@@ -1,133 +0,0 @@
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { Text, View, render as renderReactNative } from 'react-native';
|
||||
|
||||
import Platform from 'loot-core/src/client/platform';
|
||||
import { TestProvider } from 'loot-core/src/mocks/redux';
|
||||
|
||||
global.IS_DESIGN_MODE = true;
|
||||
window.Actual = {
|
||||
IS_FAKE_WEB: true,
|
||||
};
|
||||
|
||||
const modules = {};
|
||||
|
||||
function pathToName(path) {
|
||||
const name = path.match('./(.*).usage.js', '')[1];
|
||||
return name[0].toUpperCase() + name.slice(1);
|
||||
}
|
||||
|
||||
function Usage({ name, render }) {
|
||||
return (
|
||||
<TestProvider>
|
||||
<div
|
||||
style={{
|
||||
margin: 40,
|
||||
}}
|
||||
>
|
||||
<h1>{name}</h1>
|
||||
{render()}
|
||||
</div>
|
||||
</TestProvider>
|
||||
);
|
||||
}
|
||||
|
||||
async function installPolyfills() {
|
||||
if ('ResizeObserver' in window === false) {
|
||||
const module = await import('@juggle/resize-observer');
|
||||
window.ResizeObserver = module.ResizeObserver;
|
||||
}
|
||||
}
|
||||
|
||||
export default async function render(rootNode) {
|
||||
await installPolyfills();
|
||||
|
||||
let filterMatch = window.location.search.match(/f=(.*)/);
|
||||
let filter = filterMatch ? filterMatch[1] : '';
|
||||
|
||||
const guides = Object.keys(modules)
|
||||
.map(path => {
|
||||
// Do I need key???
|
||||
return {
|
||||
path,
|
||||
name: pathToName(path),
|
||||
key: path,
|
||||
};
|
||||
})
|
||||
.filter(guide => guide.path.toLowerCase().includes(filter.toLowerCase()))
|
||||
.sort();
|
||||
|
||||
guides.forEach(({ path, name, key }) => {
|
||||
const isMobileComponent = path.includes('/mobile');
|
||||
|
||||
if (Platform.isReactNativeWeb !== isMobileComponent) {
|
||||
// Skip if the component is not for this environment
|
||||
return;
|
||||
}
|
||||
|
||||
const mount = document.createElement('div');
|
||||
mount.id = path;
|
||||
rootNode.appendChild(mount);
|
||||
|
||||
if (Platform.isReactNativeWeb) {
|
||||
mount.style.float = 'left';
|
||||
|
||||
renderReactNative(
|
||||
<View style={{ margin: 40 }}>
|
||||
<Text style={{ fontSize: 20, fontWeight: 'bold', paddingBottom: 15 }}>
|
||||
{name}
|
||||
</Text>
|
||||
{modules[key].default()}
|
||||
</View>,
|
||||
mount,
|
||||
);
|
||||
} else {
|
||||
ReactDOM.render(
|
||||
<Usage name={name} render={modules[key].default} />,
|
||||
mount,
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Hot modules
|
||||
|
||||
var context = require.context('../components', true, /\.usage.js$/);
|
||||
|
||||
context.keys().forEach(function (key) {
|
||||
var module = context(key);
|
||||
modules[key] = module;
|
||||
});
|
||||
|
||||
if (module.hot) {
|
||||
module.hot.accept(context.id, function () {
|
||||
var reloadedContext = require.context('../components', true, /\.usage.js$/);
|
||||
var changedModules = reloadedContext
|
||||
.keys()
|
||||
.map(function (key) {
|
||||
return [key, reloadedContext(key)];
|
||||
})
|
||||
.filter(function (reloadedModule) {
|
||||
return modules[reloadedModule[0]] !== reloadedModule[1];
|
||||
});
|
||||
changedModules.forEach(function (module) {
|
||||
modules[module[0]] = module[1];
|
||||
reloadUsage(module[0], module[1]);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function reloadUsage(path, module) {
|
||||
try {
|
||||
const scrollTop = document.documentElement.scrollTop;
|
||||
const mount = document.getElementById(path);
|
||||
ReactDOM.unmountComponentAtNode(mount);
|
||||
ReactDOM.render(
|
||||
<Usage name={pathToName(path)} render={module.default} updated={true} />,
|
||||
mount,
|
||||
);
|
||||
document.documentElement.scrollTop = scrollTop;
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
import { plugins } from 'glamor';
|
||||
|
||||
import renderDocument from './guide/document';
|
||||
|
||||
plugins.clear();
|
||||
|
||||
renderDocument(document.getElementById('root'));
|
||||
Reference in New Issue
Block a user