Commit 65fc91cd authored by Lyza Danger Gardner's avatar Lyza Danger Gardner

Add `TagEditor` and `TagList` to `AnnotationOmega`

Render `TagEditor` or `TagList` appropriately and respond to tag and text
changes by updating the annotation’s state.
parent efa76f3a
...@@ -7,6 +7,8 @@ import { quote } from '../util/annotation-metadata'; ...@@ -7,6 +7,8 @@ import { quote } from '../util/annotation-metadata';
import AnnotationBody from './annotation-body'; import AnnotationBody from './annotation-body';
import AnnotationHeader from './annotation-header'; import AnnotationHeader from './annotation-header';
import AnnotationQuote from './annotation-quote'; import AnnotationQuote from './annotation-quote';
import TagEditor from './tag-editor';
import TagList from './tag-list';
/** /**
* The "new", migrated-to-preact annotation component. * The "new", migrated-to-preact annotation component.
...@@ -17,25 +19,23 @@ function AnnotationOmega({ ...@@ -17,25 +19,23 @@ function AnnotationOmega({
replyCount, replyCount,
showDocumentInfo, showDocumentInfo,
}) { }) {
const createDraft = useStore(store => store.createDraft);
// An annotation will have a draft if it is being edited
const draft = useStore(store => store.getDraft(annotation)); const draft = useStore(store => store.getDraft(annotation));
const tags = draft ? draft.tags : annotation.tags;
const text = draft ? draft.text : annotation.text;
// Annotation metadata
const hasQuote = !!quote(annotation); const hasQuote = !!quote(annotation);
const isSaving = false;
const isEditing = !!draft && !isSaving;
// Local component state const onEditTags = ({ tags }) => {
// TODO: `isEditing` will also take into account `isSaving` createDraft(annotation, { ...draft, tags });
const isEditing = !!draft;
const annotationState = () =>
draft || {
text: annotation.text,
tags: annotation.tags,
annotation,
}; };
// TODO const onEditText = ({ text }) => {
const fakeOnEditText = () => { createDraft(annotation, { ...draft, text });
alert('TBD');
}; };
return ( return (
...@@ -51,9 +51,11 @@ function AnnotationOmega({ ...@@ -51,9 +51,11 @@ function AnnotationOmega({
<AnnotationBody <AnnotationBody
annotation={annotation} annotation={annotation}
isEditing={isEditing} isEditing={isEditing}
onEditText={fakeOnEditText} onEditText={onEditText}
text={annotationState().text} text={text}
/> />
{isEditing && <TagEditor onEditTags={onEditTags} tagList={tags} />}
{!isEditing && <TagList annotation={annotation} tags={tags} />}
</div> </div>
); );
} }
......
import { mount } from 'enzyme'; import { mount } from 'enzyme';
import { createElement } from 'preact'; import { createElement } from 'preact';
import { act } from 'preact/test-utils';
import * as fixtures from '../../test/annotation-fixtures'; import * as fixtures from '../../test/annotation-fixtures';
...@@ -34,8 +35,8 @@ describe('AnnotationOmega', () => { ...@@ -34,8 +35,8 @@ describe('AnnotationOmega', () => {
fakeQuote = sinon.stub(); fakeQuote = sinon.stub();
fakeStore = { fakeStore = {
getDraft: sinon.stub(), createDraft: sinon.stub(),
getDefault: sinon.stub(), getDraft: sinon.stub().returns(null),
}; };
$imports.$mock(mockImportedComponents()); $imports.$mock(mockImportedComponents());
...@@ -51,6 +52,7 @@ describe('AnnotationOmega', () => { ...@@ -51,6 +52,7 @@ describe('AnnotationOmega', () => {
$imports.$restore(); $imports.$restore();
}); });
describe('annotation quote', () => {
it('renders quote if annotation has a quote', () => { it('renders quote if annotation has a quote', () => {
fakeQuote.returns('quote'); fakeQuote.returns('quote');
const wrapper = createComponent(); const wrapper = createComponent();
...@@ -67,4 +69,49 @@ describe('AnnotationOmega', () => { ...@@ -67,4 +69,49 @@ describe('AnnotationOmega', () => {
const quote = wrapper.find('AnnotationQuote'); const quote = wrapper.find('AnnotationQuote');
assert.isFalse(quote.exists()); assert.isFalse(quote.exists());
}); });
});
describe('annotation body and excerpt', () => {
it('updates annotation state when text edited', () => {
const wrapper = createComponent();
const body = wrapper.find('AnnotationBody');
act(() => {
body.props().onEditText({ text: 'updated text' });
});
assert.calledOnce(fakeStore.createDraft);
});
});
describe('tags', () => {
it('renders tag editor if `isEditing', () => {
// The presence of a draft will make `isEditing` `true`
fakeStore.getDraft.returns(fixtures.defaultDraft());
const wrapper = createComponent();
assert.isOk(wrapper.find('TagEditor').exists());
assert.notOk(wrapper.find('TagList').exists());
});
it('updates annotation state if tags changed', () => {
fakeStore.getDraft.returns(fixtures.defaultDraft());
const wrapper = createComponent();
wrapper
.find('TagEditor')
.props()
.onEditTags({ tags: ['uno', 'dos'] });
assert.calledOnce(fakeStore.createDraft);
});
it('renders tag list if not `isEditing', () => {
const wrapper = createComponent();
assert.isOk(wrapper.find('TagList').exists());
assert.notOk(wrapper.find('TagEditor').exists());
});
});
}); });
...@@ -16,12 +16,15 @@ export function defaultAnnotation() { ...@@ -16,12 +16,15 @@ export function defaultAnnotation() {
} }
/** /**
* Return a fake annotation created by a third-party user. * Return a fake draft based on a default annotation.
*/ */
export function thirdPartyAnnotation() { export function defaultDraft() {
return Object.assign(defaultAnnotation(), { return {
user: 'acct:ben@publisher.org', annotation: defaultAnnotation(),
}); text: '',
tags: [],
isPrivate: false,
};
} }
/** /**
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment