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';
import AnnotationBody from './annotation-body';
import AnnotationHeader from './annotation-header';
import AnnotationQuote from './annotation-quote';
import TagEditor from './tag-editor';
import TagList from './tag-list';
/**
* The "new", migrated-to-preact annotation component.
......@@ -17,25 +19,23 @@ function AnnotationOmega({
replyCount,
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 tags = draft ? draft.tags : annotation.tags;
const text = draft ? draft.text : annotation.text;
// Annotation metadata
const hasQuote = !!quote(annotation);
const isSaving = false;
const isEditing = !!draft && !isSaving;
// Local component state
// TODO: `isEditing` will also take into account `isSaving`
const isEditing = !!draft;
const annotationState = () =>
draft || {
text: annotation.text,
tags: annotation.tags,
annotation,
};
const onEditTags = ({ tags }) => {
createDraft(annotation, { ...draft, tags });
};
// TODO
const fakeOnEditText = () => {
alert('TBD');
const onEditText = ({ text }) => {
createDraft(annotation, { ...draft, text });
};
return (
......@@ -51,9 +51,11 @@ function AnnotationOmega({
<AnnotationBody
annotation={annotation}
isEditing={isEditing}
onEditText={fakeOnEditText}
text={annotationState().text}
onEditText={onEditText}
text={text}
/>
{isEditing && <TagEditor onEditTags={onEditTags} tagList={tags} />}
{!isEditing && <TagList annotation={annotation} tags={tags} />}
</div>
);
}
......
import { mount } from 'enzyme';
import { createElement } from 'preact';
import { act } from 'preact/test-utils';
import * as fixtures from '../../test/annotation-fixtures';
......@@ -34,8 +35,8 @@ describe('AnnotationOmega', () => {
fakeQuote = sinon.stub();
fakeStore = {
getDraft: sinon.stub(),
getDefault: sinon.stub(),
createDraft: sinon.stub(),
getDraft: sinon.stub().returns(null),
};
$imports.$mock(mockImportedComponents());
......@@ -51,20 +52,66 @@ describe('AnnotationOmega', () => {
$imports.$restore();
});
it('renders quote if annotation has a quote', () => {
fakeQuote.returns('quote');
const wrapper = createComponent();
describe('annotation quote', () => {
it('renders quote if annotation has a quote', () => {
fakeQuote.returns('quote');
const wrapper = createComponent();
const quote = wrapper.find('AnnotationQuote');
assert.isTrue(quote.exists());
const quote = wrapper.find('AnnotationQuote');
assert.isTrue(quote.exists());
});
it('does not render quote if annotation does not have a quote', () => {
fakeQuote.returns(null);
const wrapper = createComponent();
const quote = wrapper.find('AnnotationQuote');
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);
});
});
it('does not render quote if annotation does not have a quote', () => {
fakeQuote.returns(null);
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();
const wrapper = createComponent();
wrapper
.find('TagEditor')
.props()
.onEditTags({ tags: ['uno', 'dos'] });
const quote = wrapper.find('AnnotationQuote');
assert.isFalse(quote.exists());
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() {
}
/**
* Return a fake annotation created by a third-party user.
* Return a fake draft based on a default annotation.
*/
export function thirdPartyAnnotation() {
return Object.assign(defaultAnnotation(), {
user: 'acct:ben@publisher.org',
});
export function defaultDraft() {
return {
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