Skip to content

Commit

Permalink
style: add save text to header (ToolJet#3010)
Browse files Browse the repository at this point in the history
* style: add save text to header

* hide message if version is released:

* on version switch

* avatar border +.5px

* fix: tooltips not showing for dynamically added user

* add tooltip for undo-redo
  • Loading branch information
gondar00 authored May 9, 2022
1 parent d8f40ab commit 5cfb759
Show file tree
Hide file tree
Showing 6 changed files with 128 additions and 62 deletions.
85 changes: 47 additions & 38 deletions frontend/src/Editor/AppVersionsManager.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ export const AppVersionsManager = function AppVersionsManager({

return (
<div ref={wrapperRef} className="input-group app-version-menu">
<span className="input-group-text app-version-menu-sm">App Version</span>
<span className="input-group-text app-version-menu-sm">Version</span>
<span
className={`app-version-name form-select app-version-menu-sm ${appVersions ? '' : 'disabled'}`}
onClick={() => {
Expand All @@ -149,49 +149,58 @@ export const AppVersionsManager = function AppVersionsManager({
<div className="app-version-content">
{appVersions.map((version) =>
releasedVersionId == version.id ? (
<div className="row dropdown-item released" key={version.id} onClick={() => selectVersion(version)}>
<div className="col-md-4">{version.name}</div>
<div className="released-subtext">
<img src={'/assets/images/icons/editor/deploy-rocket.svg'} />
<span className="px-1">Currently Released</span>
<>
<div
className="row dropdown-item released"
key={version.id}
onClick={() => selectVersion(version)}
>
<div className="col-md-4">{version.name}</div>
<div className="released-subtext">
<img src={'/assets/images/icons/editor/deploy-rocket.svg'} />
<span className="px-1">Currently Released</span>
</div>
</div>
</div>
<div className="dropdown-divider m-0"></div>
</>
) : (
<div
className="dropdown-item row"
key={version.id}
onClick={() => selectVersion(version)}
onMouseEnter={() => setMouseHoveredOnVersion(version.id)}
onMouseLeave={() => setMouseHoveredOnVersion(null)}
>
<div className="col-md-4">{version.name}</div>
<>
<div
className="dropdown-item row"
key={version.id}
onClick={() => selectVersion(version)}
onMouseEnter={() => setMouseHoveredOnVersion(version.id)}
onMouseLeave={() => setMouseHoveredOnVersion(null)}
>
<div className="col-md-4">{version.name}</div>

<div className="col-md-2 offset-md-6">
<button
className="btn badge bg-azure-lt"
onClick={(e) => {
e.stopPropagation();
setDeletingVersionId(version.id);
setShowVersionDeletionConfirmation(true);
}}
disabled={isDeletingVersion}
style={{
display: mouseHoveredOnVersion === version.id ? 'flex' : 'none',
}}
>
<img
src="/assets/images/icons/query-trash-icon.svg"
width="12"
height="12"
className="mx-1"
style={{ paddingLeft: '0.6px' }}
/>
</button>
<div className="col-md-2 offset-md-6">
<button
className="btn badge bg-azure-lt"
onClick={(e) => {
e.stopPropagation();
setDeletingVersionId(version.id);
setShowVersionDeletionConfirmation(true);
}}
disabled={isDeletingVersion}
style={{
display: mouseHoveredOnVersion === version.id ? 'flex' : 'none',
}}
>
<img
src="/assets/images/icons/query-trash-icon.svg"
width="12"
height="12"
className="mx-1"
style={{ paddingLeft: '0.6px' }}
/>
</button>
</div>
</div>
</div>
<div className="dropdown-divider m-0"></div>
</>
)
)}
<div className="dropdown-divider"></div>
</div>
<div className="dropdown-item" onClick={() => setShowModal(true)}>
<span className="color-primary create-link">Create Version</span>
Expand Down
65 changes: 50 additions & 15 deletions frontend/src/Editor/Editor.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import RunjsIcon from './Icons/runjs.svg';
import EditIcon from './Icons/edit.svg';
import MobileSelectedIcon from './Icons/mobile-selected.svg';
import DesktopSelectedIcon from './Icons/desktop-selected.svg';
import Spinner from '@/_ui/Spinner';
import { AppVersionsManager } from './AppVersionsManager';
import { SearchBoxComponent } from '@/_ui/Search';
import { createWebsocketConnection } from '@/_helpers/websocketConnection';
Expand Down Expand Up @@ -127,6 +128,8 @@ class Editor extends React.Component {
showInitVersionCreateModal: false,
showCreateVersionModalPrompt: false,
isSourceSelected: false,
isSaving: false,
saveError: false,
};

this.autoSave = debounce(this.saveEditingVersion, 3000);
Expand Down Expand Up @@ -170,6 +173,12 @@ class Editor extends React.Component {
if (!isEqual(prevState.appDefinition, this.state.appDefinition)) {
computeComponentState(this, this.state.appDefinition.components);
}

if (config.ENABLE_MULTIPLAYER_EDITING) {
if (this.props.othersOnSameVersion.length !== prevProps.othersOnSameVersion.length) {
ReactTooltip.rebuild();
}
}
}

isVersionReleased = (version = this.state.editingVersion) => {
Expand All @@ -180,7 +189,7 @@ class Editor extends React.Component {
};

closeCreateVersionModalPrompt = () => {
this.setState({ showCreateVersionModalPrompt: false });
this.setState({ isSaving: false, showCreateVersionModalPrompt: false });
};

onMouseMove = (e) => {
Expand Down Expand Up @@ -390,6 +399,7 @@ class Editor extends React.Component {
});
this.setState({
editingVersion: version,
isSaving: false,
});

this.fetchDataSources();
Expand Down Expand Up @@ -526,7 +536,7 @@ class Editor extends React.Component {
},
this.handleAddPatch
);
this.setState({ appDefinition: newDefinition }, () => {
this.setState({ isSaving: true, appDefinition: newDefinition }, () => {
if (!opts.skipAutoSave) this.autoSave();
});
computeComponentState(this, newDefinition.components);
Expand Down Expand Up @@ -596,6 +606,7 @@ class Editor extends React.Component {
);
setStateAsync(_self, newDefinition).then(() => {
computeComponentState(_self, _self.state.appDefinition.components);
this.setState({ isSaving: true });
this.autoSave();
this.props.ymap?.set('appDef', {
newDefinition: newDefinition.appDefinition,
Expand All @@ -618,6 +629,7 @@ class Editor extends React.Component {
appDefinition.globalSettings[key] = value;
this.setState(
{
isSaving: true,
appDefinition,
},
() => {
Expand Down Expand Up @@ -902,21 +914,31 @@ class Editor extends React.Component {

saveEditingVersion = () => {
if (this.isVersionReleased()) {
this.setState({ showCreateVersionModalPrompt: true });
this.setState({ isSaving: false, showCreateVersionModalPrompt: true });
} else if (!isEmpty(this.state.editingVersion)) {
toast.promise(appVersionService.save(this.state.appId, this.state.editingVersion.id, this.state.appDefinition), {
loading: 'Saving...',
success: () => {
this.setState({
editingVersion: {
...this.state.editingVersion,
...{ definition: this.state.appDefinition },
appVersionService
.save(this.state.appId, this.state.editingVersion.id, this.state.appDefinition)
.then(() => {
this.setState(
{
saveError: false,
editingVersion: {
...this.state.editingVersion,
...{ definition: this.state.appDefinition },
},
},
() => {
this.setState({
isSaving: false,
});
}
);
})
.catch(() => {
this.setState({ saveError: true, isSaving: false }, () => {
toast.error('App could not save.');
});
return 'Saved!';
},
error: 'App could not save.',
});
});
}
};

Expand Down Expand Up @@ -1040,6 +1062,15 @@ class Editor extends React.Component {
</span>
</div>
)}
<span
className={cx('autosave-indicator', {
'autosave-indicator-saving': this.state.isSaving,
'text-danger': this.state.saveError,
'd-none': this.isVersionReleased(),
})}
>
{this.state.isSaving ? <Spinner size="small" /> : 'All changes are saved'}
</span>
{config.ENABLE_MULTIPLAYER_EDITING && (
<RealtimeAvatars
updatePresence={this.props.updatePresence}
Expand All @@ -1062,7 +1093,9 @@ class Editor extends React.Component {
<a
href={appVersionPreviewLink}
target="_blank"
className={`btn btn-sm font-500 color-primary ${app?.current_version_id ? '' : 'disabled'}`}
className={`btn btn-sm font-500 color-primary border-0 ${
app?.current_version_id ? '' : 'disabled'
}`}
rel="noreferrer"
>
Preview
Expand Down Expand Up @@ -1363,6 +1396,7 @@ class Editor extends React.Component {
disabled: !this.canUndo,
})}
width="44"
data-tip="undo"
height="44"
viewBox="0 0 24 24"
strokeWidth="1.5"
Expand All @@ -1380,6 +1414,7 @@ class Editor extends React.Component {
</svg>
<svg
title="redo"
data-tip="redo"
onClick={this.handleRedo}
xmlns="http://www.w3.org/2000/svg"
className={cx('cursor-pointer icon icon-tabler icon-tabler-arrow-forward-up', {
Expand Down
1 change: 0 additions & 1 deletion frontend/src/Editor/RealtimeAvatars.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
/* eslint-disable import/no-unresolved */
import React from 'react';
import config from 'config';
import Avatar from '@/_ui/Avatar';
import { useOthers } from 'y-presence';

Expand Down
25 changes: 20 additions & 5 deletions frontend/src/_styles/theme.scss
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ button {
.editor {
.header-container {
max-width: 100%;
padding: 0 15px;
padding: 0 10px;
}

.resizer-active {
Expand Down Expand Up @@ -3971,7 +3971,7 @@ input[type="text"] {
}

.app-name {
width: 325px;
width: 250px;
left: 150px;
position: absolute;
}
Expand Down Expand Up @@ -4010,7 +4010,7 @@ input[type="text"] {
}

.app-version-menu .dropdown-menu {
left: -90px;
left: -65px;
width: 283px;
}

Expand All @@ -4021,7 +4021,7 @@ input[type="text"] {
.app-version-menu .released-subtext {
font-size: 12px;
color: #36af8b;
padding: 0;
padding: 0 8px;
}

.app-version-menu .create-link {
Expand Down Expand Up @@ -5080,8 +5080,9 @@ div#driver-page-overlay {

.realtime-avatars {
position: absolute;
left: 35%;
left: 50%;
}

.widget-style-field-header{
font-family: 'Inter';
font-style: normal;
Expand Down Expand Up @@ -5114,4 +5115,18 @@ div#driver-page-overlay {
padding: 5px;
display: flex;
justify-content: end;
}

.autosave-indicator {
position: absolute;
left: 30%;
color: #868aa5;
white-space: nowrap;
font-weight: 400;
font-size: 12px;
letter-spacing: 0.5px;
}

.autosave-indicator-saving {
left: 34.5%;
}
2 changes: 1 addition & 1 deletion frontend/src/_ui/Avatar/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ const Avatar = ({ text, title = '', borderColor = '' }) => {
return (
<span
data-tip={title}
style={{ border: `1px solid ${borderColor}` }}
style={{ border: `1.5px solid ${borderColor}` }}
className="avatar avatar-sm avatar-rounded animation-fade"
>
{text}
Expand Down
12 changes: 10 additions & 2 deletions frontend/src/_ui/Spinner/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
import React from 'react';
import cx from 'classnames';

const Spinner = ({ ...props }) => (
<div {...props} className="spinner-border spinner-border-lg text-muted" role="status" />
const Spinner = ({ size = 'large', ...props }) => (
<div
{...props}
className={cx('spinner-border text-muted', {
'spinner-border-lg': size === 'large',
'spinner-border-sm': size === 'small',
})}
role="status"
/>
);

export default Spinner;

0 comments on commit 5cfb759

Please sign in to comment.