Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(webapp): Annotations flot plugin #1605

Merged
merged 29 commits into from Oct 27, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
757cbb3
feat: Annotations flot plugin
pavelpashkovsky Oct 7, 2022
7d4e421
Merge branch 'main' into flot-annotations
pavelpashkovsky Oct 10, 2022
2e7a811
chore: adjust annotations marks appearance
pavelpashkovsky Oct 10, 2022
880cc71
fix: test w/o icons
pavelpashkovsky Oct 10, 2022
d6887fa
fix: reverse prev commit
pavelpashkovsky Oct 10, 2022
02b70da
chore: updating types for annotations plugin
pavelpashkovsky Oct 10, 2022
f2088cd
refactor: annotations icons
pavelpashkovsky Oct 10, 2022
d888f8c
refactor: annotation marks positioning & icons
pavelpashkovsky Oct 11, 2022
7942e4f
refactor: extractRange fn
pavelpashkovsky Oct 11, 2022
4eac5cf
refactor: remove triggering hovering events
pavelpashkovsky Oct 11, 2022
a2ae0ed
refactor: rename WRAPPER_ID
pavelpashkovsky Oct 11, 2022
bdb8876
refactor: remove shouldStartAnnotationsFunctionality
pavelpashkovsky Oct 11, 2022
fc39986
refactor: refactor plugin hooks
pavelpashkovsky Oct 11, 2022
110c234
refactor: use fns instead of arrow fns
pavelpashkovsky Oct 11, 2022
d46bfca
Merge branch 'main' into flot-annotations
pavelpashkovsky Oct 12, 2022
9f0c11f
refactor: ContextMenu.plugin
pavelpashkovsky Oct 12, 2022
d592291
refactor: composeAnnotationsList
pavelpashkovsky Oct 12, 2022
0df0419
chore: adjust annotation data modal input
pavelpashkovsky Oct 13, 2022
03ef37f
chore: tests (v2)
pavelpashkovsky Oct 13, 2022
cfbc3d0
remove cache
eh-am Oct 13, 2022
abbe15b
chore: adjust timeline title appearance for single view
pavelpashkovsky Oct 14, 2022
0d220b8
feat: add annotation mark visual feedback on hover
pavelpashkovsky Oct 14, 2022
34d31f0
chore: resolving issues from comments
pavelpashkovsky Oct 14, 2022
ec8f5b7
Merge branch 'main' into flot-annotations
pavelpashkovsky Oct 14, 2022
5f9bde6
fix: test raw
pavelpashkovsky Oct 14, 2022
bdb2397
refactor: cy test
pavelpashkovsky Oct 17, 2022
c02c12b
refactor: annotation mark appearance
pavelpashkovsky Oct 25, 2022
528e96d
refactor: assigning styles
pavelpashkovsky Oct 25, 2022
3df0a6b
fix: added extra nwline for svg icon
pavelpashkovsky Oct 25, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 0 additions & 4 deletions .github/workflows/cypress-tests.yml
Expand Up @@ -37,10 +37,6 @@ jobs:
- run: yarn install --frozen-lockfile
- run: make --version
- run: make -j e2e-build
- uses: actions/cache@v3
with:
path: bin/pyroscope
key: ${{ runner.os }}-pyroscope
- name: Cypress run
uses: cypress-io/github-action@v4
with:
Expand Down
51 changes: 51 additions & 0 deletions cypress/integration/webapp/annotations.ts
@@ -0,0 +1,51 @@
describe('Annotations', () => {
it('add annotation flow works as expected', () => {
const basePath = Cypress.env('basePath') || '';
cy.intercept(`${basePath}**/labels*`).as('labels');
cy.intercept(`${basePath}**/label-values*`, {
fixture: 'appNames.json',
}).as('labelValues');
cy.intercept('**/render*', {
fixture: 'render.json',
}).as('render');

cy.visit('/');

cy.wait('@labels');
cy.wait('@labelValues');
cy.wait('@render');

cy.get('canvas.flot-overlay').click();

cy.get('li[role=menuitem]').contains('Add annotation').click();

const content = 'test';
let time;

cy.get('form#annotation-form')
.findByTestId('annotation_timestamp_input')
.invoke('val')
.then((sometext) => (time = sometext));

cy.get('form#annotation-form')
.findByTestId('annotation_content_input')
.type(content);

cy.get('button[form=annotation-form]').click();

cy.get('div[data-testid="annotation_mark_wrapper"]').click();

cy.get('form#annotation-form')
.findByTestId('annotation_content_input')
.should('have.value', content);

cy.get('form#annotation-form')
.findByTestId('annotation_timestamp_input')
.invoke('val')
.then((sometext2) => assert.isTrue(sometext2 === time));

cy.get('button[form=annotation-form]').contains('Close').click();

cy.get('form#annotation-form').should('not.exist');
});
});
12 changes: 12 additions & 0 deletions webapp/images/comment.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

This file was deleted.

107 changes: 0 additions & 107 deletions webapp/javascript/components/TimelineChart/Annotation.spec.tsx

This file was deleted.

92 changes: 0 additions & 92 deletions webapp/javascript/components/TimelineChart/Annotation.tsx

This file was deleted.

@@ -0,0 +1,74 @@
/* eslint-disable default-case, consistent-return */
import Color from 'color';
import React, { useState } from 'react';
import classNames from 'classnames/bind';
import AnnotationInfo from '@webapp/pages/continuous/contextMenu/AnnotationInfo';
import useTimeZone from '@webapp/hooks/timeZone.hook';

import styles from './styles.module.scss';

const cx = classNames.bind(styles);

interface IAnnotationMarkProps {
type: 'message';
color: Color;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pretty sure color can be inferred from the type (which we currently only have message). Each type is gonna be an item/bg color, which is static. We won't allow people to mix and match these. At least not in the foreseeable future.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you please explain more what you want to see here

value: {
content: string;
timestamp: number;
};
}

const getIcon = (type: IAnnotationMarkProps['type']) => {
switch (type) {
case 'message':
return styles.message;
}
};

const AnnotationMark = ({ type, color, value }: IAnnotationMarkProps) => {
const { offset } = useTimeZone();
const [visible, setVisible] = useState(false);
const [target, setTarget] = useState<Element>();
const [hovered, setHovered] = useState(false);

const onClick = (e: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
e.stopPropagation();
setTarget(e.target as Element);
setVisible(true);
};

const annotationInfoPopover = target ? (
<AnnotationInfo
popoverAnchorPoint={{ x: 0, y: 27 }}
container={target}
value={value}
timezone={offset === 0 ? 'utc' : 'browser'}
timestamp={value.timestamp}
isOpen={visible}
onClose={() => setVisible(false)}
popoverClassname={styles.form}
/>
) : null;

const onHoverStyle = {
backgroundColor: hovered ? color.darken(0.2).hex() : color.hex(),
zIndex: hovered ? 2 : 1,
};

return (
<>
<div
data-testid="annotation_mark_wrapper"
onClick={onClick}
style={onHoverStyle}
className={cx(styles.wrapper, getIcon(type))}
role="none"
onMouseEnter={() => setHovered(true)}
onMouseLeave={() => setHovered(false)}
/>
{annotationInfoPopover}
</>
);
};

export default AnnotationMark;
@@ -0,0 +1,23 @@
.wrapper {
position: relative;
width: 18px;
height: 18px;
left: -9px;
top: -7px;
border-radius: 4px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
background-size: 14px;
background-position: center;
background-repeat: no-repeat;
}

.message {
background-image: url('../../../../images/comment.svg');
}

.form {
width: 180px;
}