Skip to content

Commit

Permalink
Add support for top level headers in capture templates
Browse files Browse the repository at this point in the history
  • Loading branch information
DanielDe committed Sep 25, 2019
1 parent 4a81ffd commit fc5f1d3
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 59 deletions.
32 changes: 19 additions & 13 deletions src/components/OrgFile/components/CaptureModal/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,15 @@ import Drawer from '../../../UI/Drawer/';
import { headerWithPath } from '../../../../lib/org_utils';
import substituteTemplateVariables from '../../../../lib/capture_template_substitution';

import classNames from 'classnames';

export default ({ template, onCapture, headers, onClose }) => {
const [substitutedTemplate, initialCursorIndex] = useMemo(
() => substituteTemplateVariables(template.get('template')),
[template.get('template')]
);

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

const textarea = useRef(null);

useEffect(
() => {
if (textarea.current) {
textarea.current.focus();
if (initialCursorIndex !== null) {
textarea.current.selectionStart = initialCursorIndex;
textarea.current.selectionEnd = initialCursorIndex;
}
useEffect(() => {
if (textarea.current) {
textarea.current.focus();
if (initialCursorIndex !== null) {
textarea.current.selectionStart = initialCursorIndex;
textarea.current.selectionEnd = initialCursorIndex;
}
},
[textarea]
);
}
}, [textarea]);

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

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

<div className="capture-modal-header-path">{template.get('headerPaths').join(' > ')}</div>
<div
className={classNames('capture-modal-header-path', {
'capture-modal-header-path--top-level': isTopLevelTarget,
})}
>
{isTopLevelTarget ? 'Top level header' : template.get('headerPaths').join(' > ')}
</div>

{!!targetHeader ? (
{!!targetHeader || isTopLevelTarget ? (
<Fragment>
<textarea
className="textarea capture-modal-textarea"
Expand Down
4 changes: 4 additions & 0 deletions src/components/OrgFile/components/CaptureModal/stylesheet.css
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@
margin-top: 5px;
}

.capture-modal-header-path--top-level {
font-style: italic;
}

.capture-modal-textarea {
border: 1px solid lightgray;
font-family: Courier;
Expand Down
91 changes: 45 additions & 46 deletions src/reducers/org.js
Original file line number Diff line number Diff line change
Expand Up @@ -212,23 +212,20 @@ const advanceTodoState = (state, action) => {
secondTimestamp: null,
},
];
state = state.updateIn(
['headers', headerIndex, 'propertyListItems'],
propertyListItems =>
propertyListItems.some(item => item.get('property') === 'LAST_REPEAT')
? propertyListItems.map(
item =>
item.get('property') === 'LAST_REPEAT'
? item.set('value', fromJS(newLastRepeatValue))
: item
)
: propertyListItems.push(
fromJS({
property: 'LAST_REPEAT',
value: newLastRepeatValue,
id: generateId(),
})
)
state = state.updateIn(['headers', headerIndex, 'propertyListItems'], propertyListItems =>
propertyListItems.some(item => item.get('property') === 'LAST_REPEAT')
? propertyListItems.map(item =>
item.get('property') === 'LAST_REPEAT'
? item.set('value', fromJS(newLastRepeatValue))
: item
)
: propertyListItems.push(
fromJS({
property: 'LAST_REPEAT',
value: newLastRepeatValue,
id: generateId(),
})
)
);

state = state.updateIn(['headers', headerIndex], header => {
Expand Down Expand Up @@ -671,14 +668,12 @@ const moveTableColumnLeft = (state, action) => {
columnIndex === 0
? rows
: rows.map(row =>
row.update(
'contents',
contents =>
contents.size === 0
? contents
: contents
.insert(columnIndex - 1, contents.get(columnIndex))
.delete(columnIndex + 1)
row.update('contents', contents =>
contents.size === 0
? contents
: contents
.insert(columnIndex - 1, contents.get(columnIndex))
.delete(columnIndex + 1)
)
)
)
Expand All @@ -698,14 +693,12 @@ const moveTableColumnRight = (state, action) => {
columnIndex + 1 >= rows.getIn([0, 'contents']).size
? rows
: rows.map(row =>
row.update(
'contents',
contents =>
contents.size === 0
? contents
: contents
.insert(columnIndex, contents.get(columnIndex + 1))
.delete(columnIndex + 2)
row.update('contents', contents =>
contents.size === 0
? contents
: contents
.insert(columnIndex, contents.get(columnIndex + 1))
.delete(columnIndex + 2)
)
)
)
Expand All @@ -732,25 +725,33 @@ const insertCapture = (state, action) => {
const headers = state.get('headers');
const { template, content, shouldPrepend } = action;

const parentHeader = headerWithPath(headers, template.get('headerPaths'));
if (!parentHeader) {
const isTopLevelTarget = template.get('headerPaths').filter(path => path.length !== 0).size === 0;

const parentHeader = isTopLevelTarget
? null
: headerWithPath(headers, template.get('headerPaths'));
if (!parentHeader && !isTopLevelTarget) {
return state;
}

const newHeader = newHeaderFromText(content, state.get('todoKeywordSets')).set(
'nestingLevel',
parentHeader.get('nestingLevel') + 1
isTopLevelTarget ? 1 : parentHeader.get('nestingLevel') + 1
);

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

state = state.update('headers', headers => headers.insert(newIndex, newHeader));
state = state.update('headers', headers => headers.insert(newIndex, newHeader));

state = updateCookiesOfHeaderWithId(state, parentHeader.get('id'));
state = updateCookiesOfHeaderWithId(state, parentHeader.get('id'));

return state;
return state;
}
};

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

return state.updateIn(
['headers', headerIndex, 'planningItems'],
planningItems =>
!!planningItems ? planningItems.push(newPlanningItem) : List([newPlanningItem])
return state.updateIn(['headers', headerIndex, 'planningItems'], planningItems =>
!!planningItems ? planningItems.push(newPlanningItem) : List([newPlanningItem])
);
};

Expand Down

0 comments on commit fc5f1d3

Please sign in to comment.