Skip to content

Commit

Permalink
Merge pull request #602 from ZenUml/feature/share-preview-card
Browse files Browse the repository at this point in the history
feat(SharePanel, PreviewCard): add author info and optimize view
  • Loading branch information
MrCoder committed Nov 11, 2023
2 parents e18e363 + 9b1e34c commit e540485
Show file tree
Hide file tree
Showing 10 changed files with 662 additions and 340 deletions.
Binary file added src/assets/og_bg_default.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/tutorial.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
305 changes: 191 additions & 114 deletions src/components/ContentWrap.jsx

Large diffs are not rendered by default.

57 changes: 41 additions & 16 deletions src/components/PopOver.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { Component, createRef } from 'preact';
import PropTypes from 'prop-types';


export class Popover extends Component {
constructor(props) {
super(props);
Expand All @@ -12,40 +11,61 @@ export class Popover extends Component {
}

componentDidMount() {
document.addEventListener('click', this.handleDocumentClick, true);
document.addEventListener(
'click',
this.handleDocumentClick.bind(this),
true
);
}

componentWillUnmount() {
document.removeEventListener('click', this.handleDocumentClick);
document.removeEventListener('click', this.handleDocumentClick.bind(this));
}

togglePopover = () => {
this.setState((prevState) => ({
isVisible: !prevState.isVisible,
}));
if (this.props.isVisible !== undefined) {
this.props.onVisibilityChange &&
this.props.onVisibilityChange(!this.props.isVisible);
} else {
this.setState((prevState) => ({
isVisible: !prevState.isVisible,
}));
}
};

handleDocumentClick = (event) => {
if (this.popoverRef.current && !this.popoverRef.current.contains(event.target)) {
if (
this.popoverRef.current &&
!this.popoverRef.current.contains(event.target)
) {
this.props.onVisibilityChange && this.props.onVisibilityChange(false);
this.setState({ isVisible: false });
}
};


render() {
const { trigger, content } = this.props;
const { isVisible } = this.state;
const { trigger, content, closeOnBlur, placement, hasArrow, hasShadow } =
this.props;
const isVisible =
this.props.isVisible !== undefined
? this.props.isVisible
: this.state.isVisible;

return (
<div className="popover" >
<div className={`popover`}>
<div className="popover-trigger" onClick={this.togglePopover}>
{trigger}
</div>
{isVisible && (
<>
<div className="popover-backdrop" />
<div className="popover-content" ref={this.popoverRef}>
<div className="popover-arrow"></div>
{closeOnBlur && <div className="popover-backdrop" />}
<div
className={`popover-content ${placement} ${
hasShadow ? 'shadow' : ''
}`}
ref={this.popoverRef}
>
{hasArrow && <div className={`popover-arrow`}></div>}
{content}
</div>
</>
Expand All @@ -55,8 +75,13 @@ export class Popover extends Component {
}
}


Popover.propTypes = {
trigger: PropTypes.node.isRequired,
content: PropTypes.node.isRequired,
}
isVisible: PropTypes.bool,
onVisibilityChange: PropTypes.func,
closeOnBlur: PropTypes.bool,
hasArrow: PropTypes.bool,
hasShadow: PropTypes.bool,
placement: PropTypes.oneOf(['top', 'bottom']),
};
23 changes: 17 additions & 6 deletions src/components/PreviewCard.jsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,37 @@
import PropTypes from "prop-types";
import PropTypes from 'prop-types';

export function PreviewCard({ title, description, image }) {
export function PreviewCard({ title, author, description, imageBase64 }) {
return (
<div className="preview-card">
<div className="preview-card__content">
<div className="preview-card__title">
<img src="https://zenuml.cn/favicon.ico" />
<span>{title}</span>
<span className="text-ellipsis">{title}</span>
</div>
<div className="preview-card__subtitle">
<span class="material-symbols-outlined">account_circle</span>
<span className="text-ellipsis">Created by {author}</span>
</div>
<div className="preview-card__description">
<span>{description}</span>
<p>{description}</p>
</div>
<div className="preview-card__footer">
<img src="https://zenuml.cn/favicon.ico" />
<span>ZenUML</span>
</div>
</div>
<div className="preview-card__image">
<img src={image} />
<div className="overlay">
<img src={imageBase64} />
</div>
</div>
</div>
);
}

PreviewCard.propTypes = {
title: PropTypes.string.isRequired,
author: PropTypes.string.isRequired,
description: PropTypes.string.isRequired,
image: PropTypes.string.isRequired,
imageBase64: PropTypes.string,
};
94 changes: 67 additions & 27 deletions src/components/SharePanel.jsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,35 @@

import { Component } from 'preact';
import PropTypes from 'prop-types';
import { PreviewCard } from './PreviewCard';
import { syncDiagram, getShareLink } from '../services/syncService';
import { Popover } from './PopOver';
import { Button } from './common';

export class SharePanel extends Component {
constructor(props) {
super(props);
this.state = {
isLoading: true,
link: '',
}
isTooltipVisible: false,
};
}

async componentDidMount() {
const result = await syncDiagram(this.props.currentItem);
await this.syncDiagram(this.props.currentItem);
}

async componentDidUpdate(prevProps) {
if (prevProps.currentItem !== this.props.currentItem) {
await this.syncDiagram(this.props.currentItem);
}
}

async syncDiagram(currentItem) {
const result = await syncDiagram(currentItem);
if (!result) {
return;
}
this.setState({
isLoading: false,
link: getShareLink(result),
Expand All @@ -24,53 +39,78 @@ export class SharePanel extends Component {
handleCopyLink = () => {
const { link } = this.state;
navigator.clipboard.writeText(link);
}
this.setState({
isTooltipVisible: true,
});
setTimeout(() => {
this.setState({ isTooltipVisible: false });
}, 3000);
};

render() {
const { author, currentItem } = this.props;
const { link, isLoading } = this.state;


return (
<div className="share-panel">
<h3 style={{ marginTop: '4px' }}>Share the Diagram on Confluence<sup>*</sup></h3>
<h3 style={{ marginTop: '4px' }}>
Share the Diagram on Confluence<sup>*</sup>
</h3>
<>
<div>
<p>Paste the link on Confluence and select "Display as a Card"</p>
<img width={200} height={100} style="background: #acacac" />
<img style="width: 100%;" src="../assets/tutorial.png" />
</div>
<br />
<div>
<h4 style="margin-bottom: 8px;">Preview</h4>
<div className="preview" >
<div className="preview">
<PreviewCard
title="ZenUML Sequence"
description="ZenUML Sequence"
image="https://zenuml.cn/storage/diagrams/3/79.png"
title={currentItem.title}
author={author}
description="Click and check the latest diagram. Install our Confluence plugin for an enhanced expperience when viewing in Confluence."
imageBase64={currentItem.imageBase64}
/>
<Popover
isVisible={this.state.isTooltipVisible}
placement={'top'}
hasShadow={true}
trigger={
<Button
aria-label="Copy link"
className="button icon-button copy-button"
title={link}
onClick={this.handleCopyLink}
disabled={isLoading}
>
{isLoading ? (
<div className="loader" />
) : (
<span className="material-symbols-outlined">link</span>
)}
<span>Copy link</span>
</Button>
}
content={
<div className="tooltip">
<span class="material-symbols-outlined">check_circle</span>
<span>Link copied to clipboard</span>
</div>
}
/>
<button
aria-label="Copy link"
className="button icon-button copy-button" title={link}
onClick={this.handleCopyLink}
>
{isLoading ? <div className="loader" /> :
<span className="material-symbols-outlined">
link
</span>}
<span>Copy link</span>
</button>
</div>
</div>
<span className="footnote">* Anyone with the link can view the diagram. The view is optimised for Confluence.</span>
<span className="footnote">
* Anyone with the link can view the diagram. The view is optimised
for Confluence.
</span>
</>
</div>
);
}
}

SharePanel.propTypes = {
id: PropTypes.string,
dsl: PropTypes.string,
email: PropTypes.string,
image: PropTypes.string,
author: PropTypes.string,
currentItem: PropTypes.object,
};
26 changes: 26 additions & 0 deletions src/components/Tooltip.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import React, { Component } from 'react';

class Tooltip extends Component {
state = {
isTooltipVisible: false,
};

handleMouseOver = () => {
this.setState({ isTooltipVisible: true });
};

handleMouseOut = () => {
this.setState({ isTooltipVisible: false });
};

render() {
return (
<div>
{this.props.children}
{this.state.isTooltipVisible && (
<div className="tooltip">{this.props.children}</div>
)}
</div>
);
}
}
Loading

0 comments on commit e540485

Please sign in to comment.