Skip to content

Commit fc5f1d3

Browse files
committed
Add support for top level headers in capture templates
1 parent 4a81ffd commit fc5f1d3

File tree

3 files changed

+68
-59
lines changed

3 files changed

+68
-59
lines changed

src/components/OrgFile/components/CaptureModal/index.js

+19-13
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,15 @@ import Drawer from '../../../UI/Drawer/';
99
import { headerWithPath } from '../../../../lib/org_utils';
1010
import substituteTemplateVariables from '../../../../lib/capture_template_substitution';
1111

12+
import classNames from 'classnames';
13+
1214
export default ({ template, onCapture, headers, onClose }) => {
1315
const [substitutedTemplate, initialCursorIndex] = useMemo(
1416
() => substituteTemplateVariables(template.get('template')),
1517
[template.get('template')]
1618
);
1719

20+
const isTopLevelTarget = template.get('headerPaths').filter(path => path.length !== 0).size === 0;
1821
const targetHeader = useMemo(() => headerWithPath(headers, template.get('headerPaths')), [
1922
headers,
2023
template.get('headerPaths'),
@@ -25,18 +28,15 @@ export default ({ template, onCapture, headers, onClose }) => {
2528

2629
const textarea = useRef(null);
2730

28-
useEffect(
29-
() => {
30-
if (textarea.current) {
31-
textarea.current.focus();
32-
if (initialCursorIndex !== null) {
33-
textarea.current.selectionStart = initialCursorIndex;
34-
textarea.current.selectionEnd = initialCursorIndex;
35-
}
31+
useEffect(() => {
32+
if (textarea.current) {
33+
textarea.current.focus();
34+
if (initialCursorIndex !== null) {
35+
textarea.current.selectionStart = initialCursorIndex;
36+
textarea.current.selectionEnd = initialCursorIndex;
3637
}
37-
},
38-
[textarea]
39-
);
38+
}
39+
}, [textarea]);
4040

4141
const handleCaptureClick = () => onCapture(template.get('id'), textareaValue, shouldPrepend);
4242

@@ -58,9 +58,15 @@ export default ({ template, onCapture, headers, onClose }) => {
5858
<span>{template.get('description')}</span>
5959
</div>
6060

61-
<div className="capture-modal-header-path">{template.get('headerPaths').join(' > ')}</div>
61+
<div
62+
className={classNames('capture-modal-header-path', {
63+
'capture-modal-header-path--top-level': isTopLevelTarget,
64+
})}
65+
>
66+
{isTopLevelTarget ? 'Top level header' : template.get('headerPaths').join(' > ')}
67+
</div>
6268

63-
{!!targetHeader ? (
69+
{!!targetHeader || isTopLevelTarget ? (
6470
<Fragment>
6571
<textarea
6672
className="textarea capture-modal-textarea"

src/components/OrgFile/components/CaptureModal/stylesheet.css

+4
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@
1010
margin-top: 5px;
1111
}
1212

13+
.capture-modal-header-path--top-level {
14+
font-style: italic;
15+
}
16+
1317
.capture-modal-textarea {
1418
border: 1px solid lightgray;
1519
font-family: Courier;

src/reducers/org.js

+45-46
Original file line numberDiff line numberDiff line change
@@ -212,23 +212,20 @@ const advanceTodoState = (state, action) => {
212212
secondTimestamp: null,
213213
},
214214
];
215-
state = state.updateIn(
216-
['headers', headerIndex, 'propertyListItems'],
217-
propertyListItems =>
218-
propertyListItems.some(item => item.get('property') === 'LAST_REPEAT')
219-
? propertyListItems.map(
220-
item =>
221-
item.get('property') === 'LAST_REPEAT'
222-
? item.set('value', fromJS(newLastRepeatValue))
223-
: item
224-
)
225-
: propertyListItems.push(
226-
fromJS({
227-
property: 'LAST_REPEAT',
228-
value: newLastRepeatValue,
229-
id: generateId(),
230-
})
231-
)
215+
state = state.updateIn(['headers', headerIndex, 'propertyListItems'], propertyListItems =>
216+
propertyListItems.some(item => item.get('property') === 'LAST_REPEAT')
217+
? propertyListItems.map(item =>
218+
item.get('property') === 'LAST_REPEAT'
219+
? item.set('value', fromJS(newLastRepeatValue))
220+
: item
221+
)
222+
: propertyListItems.push(
223+
fromJS({
224+
property: 'LAST_REPEAT',
225+
value: newLastRepeatValue,
226+
id: generateId(),
227+
})
228+
)
232229
);
233230

234231
state = state.updateIn(['headers', headerIndex], header => {
@@ -671,14 +668,12 @@ const moveTableColumnLeft = (state, action) => {
671668
columnIndex === 0
672669
? rows
673670
: rows.map(row =>
674-
row.update(
675-
'contents',
676-
contents =>
677-
contents.size === 0
678-
? contents
679-
: contents
680-
.insert(columnIndex - 1, contents.get(columnIndex))
681-
.delete(columnIndex + 1)
671+
row.update('contents', contents =>
672+
contents.size === 0
673+
? contents
674+
: contents
675+
.insert(columnIndex - 1, contents.get(columnIndex))
676+
.delete(columnIndex + 1)
682677
)
683678
)
684679
)
@@ -698,14 +693,12 @@ const moveTableColumnRight = (state, action) => {
698693
columnIndex + 1 >= rows.getIn([0, 'contents']).size
699694
? rows
700695
: rows.map(row =>
701-
row.update(
702-
'contents',
703-
contents =>
704-
contents.size === 0
705-
? contents
706-
: contents
707-
.insert(columnIndex, contents.get(columnIndex + 1))
708-
.delete(columnIndex + 2)
696+
row.update('contents', contents =>
697+
contents.size === 0
698+
? contents
699+
: contents
700+
.insert(columnIndex, contents.get(columnIndex + 1))
701+
.delete(columnIndex + 2)
709702
)
710703
)
711704
)
@@ -732,25 +725,33 @@ const insertCapture = (state, action) => {
732725
const headers = state.get('headers');
733726
const { template, content, shouldPrepend } = action;
734727

735-
const parentHeader = headerWithPath(headers, template.get('headerPaths'));
736-
if (!parentHeader) {
728+
const isTopLevelTarget = template.get('headerPaths').filter(path => path.length !== 0).size === 0;
729+
730+
const parentHeader = isTopLevelTarget
731+
? null
732+
: headerWithPath(headers, template.get('headerPaths'));
733+
if (!parentHeader && !isTopLevelTarget) {
737734
return state;
738735
}
739736

740737
const newHeader = newHeaderFromText(content, state.get('todoKeywordSets')).set(
741738
'nestingLevel',
742-
parentHeader.get('nestingLevel') + 1
739+
isTopLevelTarget ? 1 : parentHeader.get('nestingLevel') + 1
743740
);
744741

745-
const parentHeaderIndex = indexOfHeaderWithId(headers, parentHeader.get('id'));
746-
const numSubheaders = numSubheadersOfHeaderWithId(headers, parentHeader.get('id'));
747-
const newIndex = parentHeaderIndex + 1 + (shouldPrepend ? 0 : numSubheaders);
742+
if (isTopLevelTarget) {
743+
return state.update('headers', headers => headers.push(newHeader));
744+
} else {
745+
const parentHeaderIndex = indexOfHeaderWithId(headers, parentHeader.get('id'));
746+
const numSubheaders = numSubheadersOfHeaderWithId(headers, parentHeader.get('id'));
747+
const newIndex = parentHeaderIndex + 1 + (shouldPrepend ? 0 : numSubheaders);
748748

749-
state = state.update('headers', headers => headers.insert(newIndex, newHeader));
749+
state = state.update('headers', headers => headers.insert(newIndex, newHeader));
750750

751-
state = updateCookiesOfHeaderWithId(state, parentHeader.get('id'));
751+
state = updateCookiesOfHeaderWithId(state, parentHeader.get('id'));
752752

753-
return state;
753+
return state;
754+
}
754755
};
755756

756757
const clearPendingCapture = state => state.set('pendingCapture', null);
@@ -918,10 +919,8 @@ const addNewPlanningItem = (state, action) => {
918919
timestamp: getCurrentTimestamp(),
919920
});
920921

921-
return state.updateIn(
922-
['headers', headerIndex, 'planningItems'],
923-
planningItems =>
924-
!!planningItems ? planningItems.push(newPlanningItem) : List([newPlanningItem])
922+
return state.updateIn(['headers', headerIndex, 'planningItems'], planningItems =>
923+
!!planningItems ? planningItems.push(newPlanningItem) : List([newPlanningItem])
925924
);
926925
};
927926

0 commit comments

Comments
 (0)