Skip to content

Commit

Permalink
Merge pull request #618 from ZenUml/feat/embedable
Browse files Browse the repository at this point in the history
feat: introduce embed mode
  • Loading branch information
MrCoder authored Dec 2, 2023
2 parents 05348e7 + b8c0a25 commit 1afdb65
Show file tree
Hide file tree
Showing 8 changed files with 225 additions and 110 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
"dependencies": {
"@emmetio/codemirror-plugin": "^1.1.3",
"@zenuml/core": "^3.14.5",
"clsx": "^2.0.0",
"code-blast-codemirror": "chinchang/code-blast-codemirror#web-maker",
"codemirror": "^5.65.16",
"dom-to-image": "github:MichalBryxi/dom-to-image",
Expand Down
8 changes: 8 additions & 0 deletions src/assets/external-link.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
22 changes: 22 additions & 0 deletions src/components/EmbedHeader.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
export default function EmbedHeader(props) {
return (
<div className="embed-header">
<div className="embed-header__left">
<div className="header-logo">
<img src="assets/zenuml-icon.png" alt="zenuml logo" />
</div>
<div className="tit">{this.props.title || 'Untitled'}</div>
</div>
<div className="embed-header__right">
<a
className="embed-header__external"
title="Edit on app.zenuml.com"
target="_blank"
href={this.props.link}
>
<img src="assets/external-link.svg" alt="link logo" />
</a>
</div>
</div>
);
}
39 changes: 17 additions & 22 deletions src/components/Tabs.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import Tab from './Tab';
class Tabs extends Component {
static propTypes = {
children: PropTypes.instanceOf(Array).isRequired,
}
};

constructor(props) {
super(props);
Expand All @@ -16,36 +16,32 @@ class Tabs extends Component {
this.state = {
activeTab: this.props.children[0].props.label,
};
}
};
onClickTabItem = async (tab) => {
await this.setState({activeTab: tab});
await this.setState({ activeTab: tab });
this.props.onChange(tab);
}
};

static modifyChildren(child, visible) {
const className = [child.props.className, visible ? '' : 'hide'].join(' ');

const props = {
className
className,
};

return React.cloneElement(child, props);
}
render() {
const {
onClickTabItem,
props: {
children,
},
state: {
activeTab,
}
props: { children },
state: { activeTab },
} = this;
return (
<div className="tabs" style="height:100%">
<ol className="tab-list editor-nav">
{children.map((child) => {
const { label,lineOfCode } = child.props;
const { label, lineOfCode } = child.props;
return (
<Tab
activeTab={activeTab}
Expand All @@ -57,16 +53,15 @@ class Tabs extends Component {
);
})}
</ol>
<div className="tab-content" style="height: calc(100% - 45px); overflow-y:auto;-webkit-overflow-scrolling: touch;">
{
React.Children.map(children,
(child) => {
if (child.props.label !== activeTab) {
return React.Children.map(child.props.children, c => Tabs.modifyChildren(c, false));
}
return child.props.children;
})
}
<div className="tab-content">
{React.Children.map(children, (child) => {
if (child.props.label !== activeTab) {
return React.Children.map(child.props.children, (c) =>
Tabs.modifyChildren(c, false)
);
}
return child.props.children;
})}
</div>
</div>
);
Expand Down
185 changes: 107 additions & 78 deletions src/components/app.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ import JSZip from 'jszip';
import { loadSubscriptionToApp } from '../javascript/firebase/subscription';
import { currentBrowserTab } from '../services/browserService';
import { syncDiagram, getShareLink } from '../services/syncService';
import clsx from 'clsx';
import EmbedHeader from './EmbedHeader.jsx';

if (module.hot) {
require('preact/debug');
Expand Down Expand Up @@ -110,10 +112,12 @@ export default class App extends Component {
lightVersion: false,
lineWrap: true,
infiniteLoopTimeout: 1000,
layoutMode: 2,
layoutMode: 1,
isJs13kModeOn: false,
autoCloseTags: true,
};
this.searchParams = new URLSearchParams(location.search);
this.isEmbed = this.searchParams.get('embed');
this.prefs = {};
if (window.zenumlDesktop) {
// hack savedItems, so we can load them on the desktop, without this object, the log in saveBtnClickHandler will not work.
Expand Down Expand Up @@ -192,8 +196,16 @@ export default class App extends Component {
(result) => {
this.toggleLayout(result.layoutMode);
this.state.prefs.layoutMode = result.layoutMode;
if (result.code) {
lastCode = result.code;
let urlCode;
try {
urlCode = JSON.parse(
decodeURIComponent(this.searchParams.get('code'))
);
} catch (err) {
console.error(err);
}
if (urlCode || result.code) {
lastCode = urlCode || result.code;
}
}
);
Expand Down Expand Up @@ -565,44 +577,46 @@ BookLibService.Borrow(id) {
});

// Editor keyboard shortucuts
window.addEventListener('keydown', async (event) => {
// TODO: refactor common listener code
// Ctrl/⌘ + S
if ((event.ctrlKey || event.metaKey) && event.keyCode === 83) {
event.preventDefault();
this.saveItem();
trackEvent('ui', 'saveItemKeyboardShortcut');
}
// Ctrl/⌘ + Shift + 5
if (
(event.ctrlKey || event.metaKey) &&
event.shiftKey &&
event.keyCode === 53
) {
event.preventDefault();
this.contentWrap.setPreviewContent(true, true);
trackEvent('ui', 'previewKeyboardShortcut');
} else if ((event.ctrlKey || event.metaKey) && event.keyCode === 79) {
// Ctrl/⌘ + O
event.preventDefault();
await this.openSavedItemsPane();
trackEvent('ui', 'openCreationKeyboardShortcut');
} else if (
(event.ctrlKey || event.metaKey) &&
event.shiftKey &&
event.keyCode === 191
) {
// Ctrl/⌘ + Shift + ?
event.preventDefault();
await this.setState({
isKeyboardShortcutsModalOpen:
!this.state.isKeyboardShortcutsModalOpen,
});
trackEvent('ui', 'showKeyboardShortcutsShortcut');
} else if (event.keyCode === 27) {
await this.closeSavedItemsPane();
}
});
if (!this.isEmbed) {
window.addEventListener('keydown', async (event) => {
// TODO: refactor common listener code
// Ctrl/⌘ + S
if ((event.ctrlKey || event.metaKey) && event.keyCode === 83) {
event.preventDefault();
this.saveItem();
trackEvent('ui', 'saveItemKeyboardShortcut');
}
// Ctrl/⌘ + Shift + 5
if (
(event.ctrlKey || event.metaKey) &&
event.shiftKey &&
event.keyCode === 53
) {
event.preventDefault();
this.contentWrap.setPreviewContent(true, true);
trackEvent('ui', 'previewKeyboardShortcut');
} else if ((event.ctrlKey || event.metaKey) && event.keyCode === 79) {
// Ctrl/⌘ + O
event.preventDefault();
await this.openSavedItemsPane();
trackEvent('ui', 'openCreationKeyboardShortcut');
} else if (
(event.ctrlKey || event.metaKey) &&
event.shiftKey &&
event.keyCode === 191
) {
// Ctrl/⌘ + Shift + ?
event.preventDefault();
await this.setState({
isKeyboardShortcutsModalOpen:
!this.state.isKeyboardShortcutsModalOpen,
});
trackEvent('ui', 'showKeyboardShortcutsShortcut');
} else if (event.keyCode === 27) {
await this.closeSavedItemsPane();
}
});
}

// Basic Focus trapping
window.addEventListener('focusin', (e) => {
Expand Down Expand Up @@ -674,10 +688,11 @@ BookLibService.Borrow(id) {
}
// Remove all layout classes
[1, 2, 3, 4, 5].forEach((layoutNumber) => {
window[`layoutBtn${layoutNumber}`].classList.remove('selected');
window[`layoutBtn${layoutNumber}`] &&
window[`layoutBtn${layoutNumber}`].classList.remove('selected');
document.body.classList.remove(`layout-${layoutNumber}`);
});
$('#layoutBtn' + mode).classList.add('selected');
$('#layoutBtn' + mode) && $('#layoutBtn' + mode).classList.add('selected');
document.body.classList.add('layout-' + mode);

await this.setState({ currentLayoutMode: mode }, () => {
Expand Down Expand Up @@ -1368,10 +1383,12 @@ BookLibService.Borrow(id) {
}

render() {
// remove field imageBase64 from currentItem and save it to a local variable as a copy
const { imageBase64, ...currentItem } = this.state.currentItem;
return (
<div>
<div class="main-container">
{window.zenumlDesktop ? null : (
<div class={clsx('main-container', this.isEmbed && 'embed-app')}>
{window.zenumlDesktop || this.isEmbed ? null : (
<MainHeader
externalLibCount={this.state.externalLibCount}
openBtnHandler={this.openBtnClickHandler.bind(this)}
Expand All @@ -1390,6 +1407,16 @@ BookLibService.Borrow(id) {
unsavedEditCount={this.state.unsavedEditCount}
/>
)}
{this.isEmbed && (
<EmbedHeader
title={this.searchParams.get('title')}
link={
`/?code=${JSON.stringify(
currentItem
)}&title=${this.searchParams.get('title')}` || ''
}
/>
)}
<ContentWrap
currentLayoutMode={this.state.currentLayoutMode}
currentItem={this.state.currentItem}
Expand All @@ -1403,39 +1430,41 @@ BookLibService.Borrow(id) {
onEditorFocus={this.editorFocusHandler.bind(this)}
onSplitUpdate={this.splitUpdateHandler.bind(this)}
/>
<Footer
prefs={this.state.prefs}
layoutBtnClickHandler={this.layoutBtnClickHandler.bind(this)}
helpBtnClickHandler={async () =>
await this.setState({ isHelpModalOpen: true })
}
settingsBtnClickHandler={async () =>
await this.setState({ isSettingsModalOpen: true })
}
notificationsBtnClickHandler={this.notificationsBtnClickHandler.bind(
this
)}
supportDeveloperBtnClickHandler={this.supportDeveloperBtnClickHandler.bind(
this
)}
detachedPreviewBtnHandler={this.detachedPreviewBtnHandler.bind(
this
)}
codepenBtnClickHandler={this.codepenBtnClickHandler.bind(this)}
saveHtmlBtnClickHandler={this.saveHtmlBtnClickHandler.bind(this)}
keyboardShortcutsBtnClickHandler={async () =>
await this.setState({ isKeyboardShortcutsModalOpen: true })
}
screenshotBtnClickHandler={this.screenshotBtnClickHandler.bind(
this
)}
onJs13KHelpBtnClick={this.js13KHelpBtnClickHandler.bind(this)}
onJs13KDownloadBtnClick={this.js13KDownloadBtnClickHandler.bind(
this
)}
hasUnseenChangelog={this.state.hasUnseenChangelog}
codeSize={this.state.codeSize}
/>
{this.isEmbed ? null : (
<Footer
prefs={this.state.prefs}
layoutBtnClickHandler={this.layoutBtnClickHandler.bind(this)}
helpBtnClickHandler={async () =>
await this.setState({ isHelpModalOpen: true })
}
settingsBtnClickHandler={async () =>
await this.setState({ isSettingsModalOpen: true })
}
notificationsBtnClickHandler={this.notificationsBtnClickHandler.bind(
this
)}
supportDeveloperBtnClickHandler={this.supportDeveloperBtnClickHandler.bind(
this
)}
detachedPreviewBtnHandler={this.detachedPreviewBtnHandler.bind(
this
)}
codepenBtnClickHandler={this.codepenBtnClickHandler.bind(this)}
saveHtmlBtnClickHandler={this.saveHtmlBtnClickHandler.bind(this)}
keyboardShortcutsBtnClickHandler={async () =>
await this.setState({ isKeyboardShortcutsModalOpen: true })
}
screenshotBtnClickHandler={this.screenshotBtnClickHandler.bind(
this
)}
onJs13KHelpBtnClick={this.js13KHelpBtnClickHandler.bind(this)}
onJs13KDownloadBtnClick={this.js13KDownloadBtnClickHandler.bind(
this
)}
hasUnseenChangelog={this.state.hasUnseenChangelog}
codeSize={this.state.codeSize}
/>
)}
</div>

<SavedItemPane
Expand Down
10 changes: 7 additions & 3 deletions src/computes.js
Original file line number Diff line number Diff line change
Expand Up @@ -178,9 +178,13 @@ export function computeJs(
const cursor = e.data && e.data.cursor;
if (code && app) {
app.render(code, { enableMultiTheme: false, onContentChange: (code) => {
window.parent.postMessage({ code })
}});
app.render(code, {
enableMultiTheme: false,
onContentChange: (code) => {
window.parent.postMessage({ code })
},
stickyOffset: Number(new URLSearchParams(window.location.search).get('stickyOffset') || 0)
});
}
if(app && (cursor !== null || cursor !== undefined)) {
Expand Down
Loading

0 comments on commit 1afdb65

Please sign in to comment.