Skip to content

Commit a7f67b7

Browse files
committed
feat: refine da-title block for configs and sheets
1 parent 3fb776d commit a7f67b7

10 files changed

Lines changed: 551 additions & 46 deletions

File tree

blocks/edit/da-library/helpers/helpers.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,7 @@ export async function getPreviewStatus({ org, site, pathname }) {
278278
const json = await aemAdmin(path, 'status', 'GET');
279279
return json.preview.status === 200;
280280
} catch (err) {
281+
// eslint-disable-next-line no-console
281282
console.log(`Could not get preview status for ${path}`, err);
282283
return null;
283284
}

blocks/edit/da-title/da-title.css

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ da-dialog {
3333
line-height: 16px;
3434
padding: 5px 14px;
3535
text-decoration: none;
36+
cursor: pointer;
3637
}
3738

3839
.con-button.blue {
@@ -186,12 +187,48 @@ da-dialog {
186187
background: #EFEFEF;
187188
}
188189

190+
.da-title-action {
191+
display: none;
192+
}
193+
189194
.da-title-actions.is-open .da-title-action {
190195
display: unset;
191196
}
192197

193-
.da-title-action {
194-
display: none;
198+
.da-title-actions.save-only .da-title-action {
199+
display: unset;
200+
min-height: 44px;
201+
}
202+
203+
.da-title-actions.save-only .da-title-action:not(.blue) {
204+
background: var(--s2-gray-200);
205+
border-color: var(--s2-gray-200);
206+
color: var(--s2-gray-700);
207+
cursor: default;
208+
}
209+
210+
.da-title-actions.save-only .da-title-action.is-sending {
211+
color: transparent;
212+
position: relative;
213+
overflow: hidden;
214+
}
215+
216+
.da-title-actions.save-only .da-title-action.is-sending::after {
217+
content: '';
218+
position: absolute;
219+
width: 22px;
220+
height: 22px;
221+
background: url('/blocks/edit/img/Smock_Send_18_N.svg') center/22px no-repeat;
222+
filter: brightness(0) invert(1);
223+
animation: animated-background 1s linear infinite;
224+
}
225+
226+
.da-title-save-disabled-msg {
227+
margin: 8px auto;
228+
max-width: 900px;
229+
color: var(--s2-gray-700);
230+
font-size: 12px;
231+
font-style: italic;
195232
}
196233

197234
.da-title-action-send {

blocks/edit/da-title/da-title.js

Lines changed: 129 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,16 @@ import getSheet from '../../shared/sheet.js';
1414

1515
const sheet = await getSheet('/blocks/edit/da-title/da-title.css');
1616

17+
function isSaveOnlyView(details) {
18+
if (!details) return false;
19+
if (details.view === 'config') return true;
20+
return details.view === 'sheet' && details.fullpath?.includes('/.da/');
21+
}
22+
23+
function isHiddenActionsView(details) {
24+
return details?.view === 'edit' && details?.fullpath?.includes('/.da/');
25+
}
26+
1727
const ICONS = [
1828
'/blocks/edit/img/Smock_Cloud_18_N.svg',
1929
'/blocks/edit/img/Smock_CloudDisconnected_18_N.svg',
@@ -37,6 +47,8 @@ export default class DaTitle extends LitElement {
3747
collabUsers: { attribute: false },
3848
previewPrefix: { attribute: false },
3949
livePrefix: { attribute: false },
50+
hasChanges: { attribute: false },
51+
disableMessage: { attribute: false },
4052
_actionsVis: { state: true },
4153
_status: { state: true },
4254
_fixedActions: { state: true },
@@ -46,16 +58,17 @@ export default class DaTitle extends LitElement {
4658
connectedCallback() {
4759
super.connectedCallback();
4860
this.shadowRoot.adoptedStyleSheets = [sheet];
49-
this._actionsVis = [];
5061
inlinesvg({ parent: this.shadowRoot, paths: ICONS });
51-
if (this.details.view === 'sheet') {
52-
this.collabStatus = window.navigator.onLine
53-
? 'connected'
54-
: 'offline';
62+
}
5563

56-
window.addEventListener('online', () => { this.collabStatus = 'connected'; });
57-
window.addEventListener('offline', () => { this.collabStatus = 'offline'; });
58-
}
64+
disconnectedCallback() {
65+
this.removeCollabListeners();
66+
super.disconnectedCallback();
67+
}
68+
69+
updated(changedProperties) {
70+
super.updated(changedProperties);
71+
if (changedProperties.has('details')) this.syncDetailsState();
5972
}
6073

6174
firstUpdated() {
@@ -68,6 +81,7 @@ export default class DaTitle extends LitElement {
6881
}
6982

7083
handleError(json, action, icon) {
84+
// eslint-disable-next-line no-console
7185
console.log('handleError', json, action, icon);
7286
this._status = { ...json.error, action };
7387
icon.classList.remove('is-sending');
@@ -91,26 +105,43 @@ export default class DaTitle extends LitElement {
91105
}
92106

93107
async handleAction(action) {
108+
if (!this.details) return;
94109
this.toggleActions();
95110
this._status = null;
96-
const sendBtn = this.shadowRoot.querySelector('.da-title-action-send-icon');
97-
sendBtn.classList.add('is-sending');
111+
112+
const sendBtn = this.shadowRoot.querySelector(
113+
this.actionView === 'saveOnly' ? '.da-title-action' : '.da-title-action-send-icon',
114+
);
115+
116+
if (sendBtn) {
117+
sendBtn.classList.add('is-sending');
118+
}
98119

99120
const { hash } = window.location;
100121
const pathname = hash.replace('#', '');
101122

102-
// Only save to DA if it is a sheet or config
103-
if (this.details.view === 'sheet') {
123+
if (this.details.view === 'sheet' && action === 'save') {
104124
const dasSave = await saveToDa(pathname, this.sheet);
125+
if (sendBtn) sendBtn.classList.remove('is-sending');
105126
if (!dasSave.ok) return;
127+
this.hasChanges = false;
128+
return;
106129
}
107-
if (this.details.view === 'config') {
130+
131+
if (this._isConfigView) {
108132
const daConfigResp = await saveDaConfig(pathname, this.sheet);
133+
134+
if (sendBtn) {
135+
sendBtn.classList.remove('is-sending');
136+
}
137+
109138
if (!daConfigResp.ok) {
110139
// eslint-disable-next-line no-console
111140
console.log('Saving configuration failed because:', daConfigResp.status, await daConfigResp.text());
112-
return;
141+
} else {
142+
this.dispatchEvent(new Event('config-saved'));
113143
}
144+
return;
114145
}
115146
if (action === 'preview' || action === 'publish') {
116147
const cdn = await getCdnConfig(pathname);
@@ -141,7 +172,7 @@ export default class DaTitle extends LitElement {
141172
window.open(`${toOpenInAem}?nocache=${Date.now()}`, toOpenInAem);
142173
}
143174
if (this.details.view === 'edit' && action === 'publish') saveDaVersion(pathname);
144-
sendBtn.classList.remove('is-sending');
175+
if (sendBtn) sendBtn.classList.remove('is-sending');
145176
}
146177

147178
async handleRoleRequest() {
@@ -189,15 +220,13 @@ export default class DaTitle extends LitElement {
189220
}
190221

191222
async toggleActions() {
192-
// toggle off if already on
193-
if (this._actionsVis.length > 0) {
194-
this._actionsVis = [];
223+
if (this.actionView !== 'full') {
195224
return;
196225
}
197226

198-
// toggle on for config
199-
if (this.details.view === 'config') {
200-
this._actionsVis = ['save'];
227+
// toggle off if already on
228+
if ((this._actionsVis || []).length > 0) {
229+
this._actionsVis = [];
201230
return;
202231
}
203232

@@ -217,17 +246,87 @@ export default class DaTitle extends LitElement {
217246
return !this.permissions.some((permission) => permission === 'write');
218247
}
219248

249+
get _isConfigView() {
250+
return this.details?.view === 'config';
251+
}
252+
253+
get actionView() {
254+
if (isHiddenActionsView(this.details)) return 'hidden';
255+
if (isSaveOnlyView(this.details)) return 'saveOnly';
256+
return 'full';
257+
}
258+
259+
get visibleActions() {
260+
if (this.actionView === 'saveOnly') {
261+
return ['save'];
262+
}
263+
return this._actionsVis || [];
264+
}
265+
266+
syncDetailsState() {
267+
this._actionsVis = [];
268+
this.syncCollabStatus();
269+
}
270+
271+
syncCollabStatus() {
272+
this.removeCollabListeners();
273+
if (this.details?.view !== 'sheet') {
274+
this.collabStatus = undefined;
275+
return;
276+
}
277+
278+
this.collabStatus = window.navigator.onLine
279+
? 'connected'
280+
: 'offline';
281+
282+
this._handleOnline = () => { this.collabStatus = 'connected'; };
283+
this._handleOffline = () => { this.collabStatus = 'offline'; };
284+
window.addEventListener('online', this._handleOnline);
285+
window.addEventListener('offline', this._handleOffline);
286+
}
287+
288+
removeCollabListeners() {
289+
if (this._handleOnline) {
290+
window.removeEventListener('online', this._handleOnline);
291+
this._handleOnline = null;
292+
}
293+
if (this._handleOffline) {
294+
window.removeEventListener('offline', this._handleOffline);
295+
this._handleOffline = null;
296+
}
297+
}
298+
220299
renderActions() {
221-
return html`${this._actionsVis.map((action) => html`
300+
const isDisabled = !!this.disableMessage || (this.actionView === 'saveOnly' && !this.hasChanges);
301+
return html`${this.visibleActions.map((action) => html`
222302
<button
223303
@click=${() => this.handleAction(action)}
224-
class="con-button blue da-title-action"
225-
aria-label="Send">
304+
class="con-button da-title-action ${isDisabled ? '' : 'blue'}"
305+
aria-label="${action}"
306+
?disabled=${isDisabled}>
226307
${action.charAt(0).toUpperCase() + action.slice(1)}
227308
</button>
228309
`)}`;
229310
}
230311

312+
renderActionControls() {
313+
if (this.actionView === 'hidden') return nothing;
314+
315+
return html`
316+
<div class="da-title-actions ${this._fixedActions ? 'is-fixed' : ''} ${this.actionView === 'full' && this._actionsVis?.length > 0 ? 'is-open' : ''} ${this.actionView === 'saveOnly' ? 'save-only' : ''}">
317+
${this.renderActions()}
318+
${this.actionView === 'saveOnly' ? nothing : html`
319+
<button
320+
@click=${this.toggleActions}
321+
class="con-button blue da-title-action-send"
322+
aria-label="Send">
323+
<span class="da-title-action-send-icon"></span>
324+
</button>
325+
`}
326+
</div>
327+
`;
328+
}
329+
231330
popover({ target }) {
232331
// If toggling off, simply remove;
233332
if (target.classList.contains('collab-popup')) {
@@ -279,6 +378,8 @@ export default class DaTitle extends LitElement {
279378
}
280379

281380
render() {
381+
if (!this.details) return nothing;
382+
282383
return html`
283384
<div class="da-title-inner ${this._readOnly ? 'is-read-only' : ''}">
284385
<div class="da-title-name">
@@ -290,17 +391,12 @@ export default class DaTitle extends LitElement {
290391
<div class="da-title-collab-actions-wrapper">
291392
${this.collabStatus ? this.renderCollab() : nothing}
292393
${this._status ? this.renderError() : nothing}
293-
<div class="da-title-actions ${this._fixedActions ? 'is-fixed' : ''} ${this._actionsVis.length > 0 ? 'is-open' : ''}">
294-
${this.renderActions()}
295-
<button
296-
@click=${this.toggleActions}
297-
class="con-button blue da-title-action-send"
298-
aria-label="Send">
299-
<span class="da-title-action-send-icon"></span>
300-
</button>
301-
</div>
394+
${this.renderActionControls()}
302395
</div>
303396
</div>
397+
${this.disableMessage
398+
? html`<p class="da-title-save-disabled-msg">${this.disableMessage}</p>`
399+
: nothing}
304400
${this._dialog ? this.renderDialog() : nothing}
305401
`;
306402
}

blocks/shared/da-dialog/da-dialog.css

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,13 @@ svg.icon {
6363
justify-content: space-between;
6464
align-items: center;
6565
gap: 12px;
66+
67+
.da-dialog-footer-right {
68+
display: flex;
69+
align-items: center;
70+
justify-content: flex-end;
71+
gap: 8px;
72+
}
6673

6774
.da-dialog-footer-message {
6875
font-style: italic;

blocks/shared/da-dialog/da-dialog.js

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ export default class DaDialog extends LitElement {
5656
return {
5757
label: 'OK',
5858
style: 'accent',
59-
onClick: this.close(),
59+
click: () => this.close(),
6060
};
6161
}
6262

@@ -93,11 +93,13 @@ export default class DaDialog extends LitElement {
9393
<slot name="footer-left"></slot>
9494
<p class="da-dialog-footer-message">${this.message || nothing}</p>
9595
</div>
96-
<slot name="footer-right">
97-
<sl-button class="${this._action.style}" @click=${this._action.click} ?disabled=${this._action.disabled}>
98-
${this._action.label}
99-
</sl-button>
100-
</slot>
96+
<div class="da-dialog-footer-right" part="footer-right">
97+
<slot name="footer-right">
98+
<sl-button class="${this._action.style}" @click=${this._action.click} ?disabled=${this._action.disabled}>
99+
${this._action.label}
100+
</sl-button>
101+
</slot>
102+
</div>
101103
</div>
102104
</div>
103105
</sl-dialog>

0 commit comments

Comments
 (0)