Skip to content

Commit 831d50c

Browse files
author
Volodymyr Kopytin
committed
Finished adjusting todo logic
1 parent 2ca0309 commit 831d50c

File tree

6 files changed

+63
-26
lines changed

6 files changed

+63
-26
lines changed

src/examples/reflux-ts/components/main/index.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ export const selectCompleteItems = (items = []) => pick(items, item => selectIte
1212
export const selectNewTodoTitle = ({ newTodoTitle = '' }) => newTodoTitle;
1313
export const selectToggleAllComplete = ({ toggleAllComplete }) => toggleAllComplete;
1414

15-
1615
export const [MainActions, MainActionTypes, mainReducer] = declareActions({
1716
UI_CREATE_TODO: {
1817
uiCreateTodo: (type, payload) => ({ type, payload })
@@ -109,7 +108,7 @@ export const main = () => {
109108
),
110109
pipe(
111110
ofType(MainActionTypes.UI_CLEAR_COMPLETED),
112-
withArg(pipe(onState, queryMain, queryItems, queryCompleteItems)),
111+
withArg(pipe(onState, queryTodos, queryItems, queryCompleteItems)),
113112
map(([a, completeItems = []]) => completeItems.map(item => ToDoActions.deleteTodo(item.id)))
114113
)
115114
);
@@ -120,7 +119,7 @@ export const main = () => {
120119
),
121120
pipe(
122121
merge(createItem, deleteItem),
123-
map(() => [ToDoActions.fetchItems()])
122+
map(() => ToDoActions.fetchItems())
124123
),
125124
pipe(
126125
merge(changeItems, createItem, deleteItem),

src/examples/reflux-ts/components/main/template.tsx

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,6 @@ function mapDispatchToProps(dispatch, props) {
5252
export const MainView = connect(mapStateToProps, mapDispatchToProps)(({ dispatch, ...props } = {
5353

5454
} as ReturnType<typeof mapDispatchToProps> & ReturnType<typeof mapStateToProps>) => <main>
55-
<TodoListView items={props.errors}>
56-
</TodoListView>
57-
<TodoListView items={props}>{(item, key) => <div><span>{key}</span>:<span>{JSON.stringify(item)}</span></div>}</TodoListView>
5855
<section className="todoapp device-content">
5956
<header className="bar bar-nav">
6057
<button className={cn('btn pull-left ?active', props.toggleAllComplete)}>
@@ -90,13 +87,13 @@ export const MainView = connect(mapStateToProps, mapDispatchToProps)(({ dispatch
9087
</section>
9188
<footer className={cn('footer bar bar-standard bar-footer ?hidden', props.hasTodos)}>
9289
<span className="todo-count title">
93-
<strong>{props.todoCount}</strong>&nbsp;
94-
{props.manyTasks
90+
<strong>{props.activeItems ? props.activeItems.length : 0}</strong>&nbsp;
91+
{!(props.activeItems && props.activeItems.length === 1)
9592
? <span className="items-word">items</span>
9693
: <span className="item-word">item</span>
9794
}
9895
&nbsp;left from&nbsp;
99-
<span className="total">{props.totalText}</span>
96+
<span className="total">{props.items ? props.items.length : 0}</span>
10097
</span>
10198
</footer>
10299
<section className={cn('content ?hidden', props.hasTodos)}>

src/examples/reflux-ts/components/todoItem/template.tsx

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,24 @@ function mapDispatchToProps(dispatch, props) {
4444
};
4545
}
4646

47+
function setCaretAtStartEnd(node, atEnd) {
48+
const sel = document.getSelection();
49+
node = node.firstChild;
50+
51+
if (sel.rangeCount) {
52+
['Start', 'End'].forEach(pos =>
53+
sel.getRangeAt(0)["set" + pos](node, atEnd ? node.length : 0)
54+
)
55+
}
56+
}
57+
58+
function focusEditbox(el) {
59+
el.focus();
60+
if (el.textContent) {
61+
setCaretAtStartEnd(el, true);
62+
}
63+
}
64+
4765
export const TodoListViewItem = connect(mapStateToProps, mapDispatchToProps)(({ dispatch, ...props } = {
4866

4967
} as ReturnType<typeof mapDispatchToProps> & ReturnType<typeof mapStateToProps>) => <div className={cn(
@@ -56,13 +74,13 @@ export const TodoListViewItem = connect(mapStateToProps, mapDispatchToProps)(({
5674
onChange={e => props.uiSetComplete(props.id, e.target['checked'])}
5775
/>
5876
</span>
59-
<span>{`${props.id}`}</span>&nbsp;-&nbsp;
6077
<span className="input-group" style={"display: inline-block; width: 70%;" as any}>
6178
{(props.current && props.current.id === props.id) || <label className="view input" style={"padding: 1px 1px 1px 1px;" as any}
6279
onClick={e => props.uiSetCurrentItem(props.id)}
6380
>{props.title}</label>}
6481
{(props.current && props.current.id === props.id) && <div className="edit" style={"border: 1px solid grey;outline: none;" as any}
6582
contentEditable={true}
83+
ref={el => focusEditbox(el)}
6684
onInput={e => props.uiUpdateCurrentTitle(e.target['innerText'])}
6785
onKeyPress={e => props.updateOnEnter(e, props.current.id)}
6886
onKeyUp={e => props.revertOnEscape(e)}

src/examples/reflux-ts/models/todos.ts

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,8 @@ export const [ToDoActions, ToDoActionTypes, toDoReducer] = declareActions({
6464
items: {
6565
...selectItems(state),
6666
[payload.id]: payload
67-
}
67+
},
68+
order: [payload.id, ...selectOrder(state)]
6869
};
6970
}
7071
},
@@ -146,11 +147,12 @@ export const [ToDoActions, ToDoActionTypes, toDoReducer] = declareActions({
146147
},
147148
DELETE_TODO_RESULT: {
148149
deleteTodoResult: (type, payload) => ({ type, payload }),
149-
reducer: ({ loading, ...state }: any = {}, { type, payload: { id } }) => {
150-
const { [id]: removed, ...items } = selectItems(state) as any;
150+
reducer: ({ loading, ...state }: any = {}, { type, payload: id }) => {
151+
const { [id]: removed, ...items } = selectItemsInternal(state) as any;
151152
return {
152153
...state,
153-
items
154+
items,
155+
order: selectOrder(state).filter(pos => pos !== id)
154156
};
155157
}
156158
},
@@ -160,7 +162,7 @@ export const [ToDoActions, ToDoActionTypes, toDoReducer] = declareActions({
160162
(async () => {
161163
try {
162164
const item = await adapter.deleteTodo(id);
163-
dispatch(ToDoActions.deleteTodoResult(item));
165+
dispatch(ToDoActions.deleteTodoResult(id));
164166
} catch (ex) {
165167
dispatch(ToDoActions.deleteTodoError(ex));
166168
}
@@ -184,8 +186,9 @@ const selectItemsById = (items = []) => items.reduce((res, item) => ({
184186
[item.id]: item
185187
}), {});
186188
const selectItemsOrder = (items = []) => items.map(({ id }) => id);
189+
const selectOrder = ({ order }) => order;
187190
export const selectTodos = ({ todos }) => todos;
188-
export const selectItemsInternal = ({ items = [] }) => items;
191+
export const selectItemsInternal = ({ items = {} }) => items;
189192
export const selectItems = ({ items = {}, order = [] }) => order.map(id => items[id]);
190193

191194
export const queryTodos = map(selectTodos);

src/examples/reflux-ts/utils.ts

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,28 @@ export function className(str: string, ...args) {
1919
return res.join(' ');
2020
}
2121

22+
function isArray(input) {
23+
if (input instanceof Array || Object.prototype.toString.call(input) === '[object Array]') {
24+
return true;
25+
} else return false;
26+
}
27+
2228
export function pick(obj, fn) {
2329
const keys = Object.keys(obj);
24-
return keys.reduce((res, key) => {
30+
return keys.reduce((res: any, key) => {
2531
if (fn(obj[key])) {
26-
return {
27-
...res,
28-
[key]: obj[key]
29-
};
32+
if (isArray(obj)) {
33+
return [
34+
...res,
35+
obj[key]
36+
];
37+
} else {
38+
return {
39+
...res,
40+
[key]: obj[key]
41+
};
42+
}
3043
}
3144
return res;
32-
}, {});
45+
}, isArray(obj) ? [] : {});
3346
}

src/examples/reflux-ts/virtualDom.ts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,9 @@ function arrayMerge(array1, array2) {
3636
}
3737

3838
export function el(type, attrs = {}, ...children) {
39-
children = [].concat(...children).filter(a => [undefined, true, false].indexOf(a) === -1);
39+
children = [].concat(...children)
40+
.filter(a => [undefined, true, false].indexOf(a) === -1)
41+
.map(item => (['object', 'function'].indexOf(typeof item) === -1 ? '' + item : item));
4042
if (typeof type === 'function') {
4143
return type({ ...attrs, store: currentStore, children: children.length > 1 ? children : children[0] }, children);
4244
}
@@ -54,7 +56,7 @@ export function makeVdom(oldDom, store) {
5456
if (node === undefined) {
5557
return document.createTextNode('');
5658
}
57-
if (typeof node === 'string') {
59+
if (['object', 'function'].indexOf(typeof node) === -1) {
5860
return document.createTextNode(node);
5961
}
6062
if (typeof node.type === 'function') {
@@ -65,14 +67,16 @@ export function makeVdom(oldDom, store) {
6567
return $el;
6668
}
6769
const { type, attrs = {}, children } = node;
68-
return dom.el(type, attrs, ...[].concat(children).map(child => createElement(child)));
70+
const { ref, ...attributes } = (attrs || {});
71+
const el = dom.el(type, attributes, ...[].concat(children).map(child => createElement(child)));
72+
return el;
6973
}
7074

7175
function compare($el, newNode, oldNode) {
7276
if (typeof newNode !== typeof oldNode) {
7377
return true;
7478
}
75-
if (typeof newNode === 'string') {
79+
if (['object', 'function'].indexOf(typeof newNode) === -1) {
7680
if (newNode !== oldNode) {
7781
const oldValue = $el.textContent;
7882
if (oldValue !== newNode) {
@@ -179,6 +183,9 @@ export function makeVdom(oldDom, store) {
179183
)];
180184
}
181185
}
186+
if (newNode && newNode.attrs && newNode.attrs.ref) {
187+
newNode.attrs.ref($parent.childNodes[index]);
188+
}
182189
return nodesToRemove;
183190
}
184191

0 commit comments

Comments
 (0)