Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 46 additions & 15 deletions blocks/edit/da-title/da-title.css
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@ da-dialog {
background: var(--s2-blue-900);
border-color: var(--s2-blue-900);
color: #FFF;

&:disabled {
background: var(--s2-gray-500);
border-color: var(--s2-gray-500);
}
}

.da-title-inner {
Expand Down Expand Up @@ -121,13 +126,16 @@ da-dialog {
z-index: 2;
}

.collab-icon.collab-popup::after {
.collab-icon.collab-popup::after,
.da-title-action::after {
display: block;
content: attr(data-popup-content);
position: absolute;
bottom: -32px;
left: 50%;
transform: translateX(-50%);
font-size: 12px;
line-height: 1.6;
text-align: center;
text-transform: capitalize;
background: #676767;
Expand All @@ -137,6 +145,21 @@ da-dialog {
border-radius: 4px;
}

.da-title-action {
position: relative;
display: none;

&::after {
display: none;
bottom: -22px;
text-transform: unset;
}

&:hover::after {
display: unset;
}
}

.collab-icon-user {
height: 24px;
border-radius: 12px;
Expand Down Expand Up @@ -172,9 +195,15 @@ da-dialog {
height: 27px;
}

.da-title-action {
.da-title-action-send {
position: relative;
display: none;
padding: 5px 0;
width: 44px;
height: 44px;
display: flex;
justify-content: center;
align-items: center;
overflow: hidden;
}

.da-title-actions {
Expand All @@ -184,7 +213,8 @@ da-dialog {
gap: 12px;
height: 44px;

&.is-open {
&.is-open,
&.has-one-action {
margin-left: 12px;

.da-title-action {
Expand All @@ -200,6 +230,18 @@ da-dialog {
}
}

&.has-one-action {
margin-left: 0;

.da-title-action-send {
display: none;
}

&::before {
background: transparent;
}
}

&.is-fixed {
position: fixed;
right: 18px;
Expand All @@ -208,17 +250,6 @@ da-dialog {
}
}

.da-title-action-send {
position: relative;
padding: 5px 0;
width: 44px;
height: 44px;
display: flex;
justify-content: center;
align-items: center;
overflow: hidden;
}

.da-title-action-send-icon {
position: relative;
display: block;
Expand Down
129 changes: 80 additions & 49 deletions blocks/edit/da-title/da-title.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,12 @@ export default class DaTitle extends LitElement {
collabUsers: { attribute: false },
previewPrefix: { attribute: false },
livePrefix: { attribute: false },
disabledText: { attribute: false },
_lazyMods: { state: true },
_configs: { state: true },
_actions: { state: true },
_status: { state: true },
_isSending: { state: true },
_dialog: { state: true },
};

Expand All @@ -68,7 +70,7 @@ export default class DaTitle extends LitElement {
update(changed) {
super.update(changed);
if (changed.has('details') && this.details) {
this.reset();
this.setup();
this.delayedSetup();
}
}
Expand All @@ -86,7 +88,49 @@ export default class DaTitle extends LitElement {
reset() {
this._scheduled = undefined;
this._configs = undefined;
this._actions = {};
}

setup() {
this.reset();
this._actions = { available: this.getAvailableActions() };
// Lazily filter the actions down
this.filterActions();
}

getAvailableActions() {
const { view, path, fullpath } = this.details;

// Config only gets save
if (view === 'config') return ['save'];

// DA app configs only get save
if (fullpath.includes('/.da/') && view === 'sheet') return ['save'];

const availableActions = [];

if (view === 'sheet') {
availableActions.push('save');
}

if (path) {
availableActions.push('preview', 'publish');
}

return availableActions;
}

async filterActions() {
const { org, site, fullpath } = this.details;
const configs = await Promise.all(fetchDaConfigs({ org, site }));
const configTab = configs.flatMap((config) => getFirstSheet(config) || []);

// Check which actions should be allowed for the document based on config
const publishConfigs = configTab.filter((c) => c.key === 'editor.hidePublish');
const hidePublish = publishConfigs.some((c) => fullpath.startsWith(c.value));
if (!hidePublish) return;

this._actions.available = this._actions.available.filter((action) => action !== 'publish');
this.requestUpdate();
}

// Run setup after a short delay.
Expand All @@ -101,11 +145,6 @@ export default class DaTitle extends LitElement {
]);

const { org, site, path, fullpath } = this.details;
const configs = await Promise.all(fetchDaConfigs({ org, site }));
this._configs = configs.flatMap((config) => getFirstSheet(config) || []);

this._actions.available = await this.getAvailableActions();
this.requestUpdate();

// Only a valid path gets AEM-bound features
if (path) {
Expand All @@ -119,40 +158,20 @@ export default class DaTitle extends LitElement {
return getExistingSchedule(org, site, path);
}

async getAvailableActions() {
const { view, path, fullpath } = this.details;

// Config only gets save
if (view === 'config') return ['save'];

const availableActions = [];

if (view === 'sheet') {
availableActions.push('save');
}

if (path) {
availableActions.push('preview');

// Check which actions should be allowed for the document based on config
const publishConfigs = this._configs.filter((c) => c.key === 'editor.hidePublish');
const hidePublish = publishConfigs.some((c) => fullpath.startsWith(c.value));

if (!hidePublish) availableActions.push('publish');
}

return availableActions;
}

toggleActions() {
this._actions.open = !this._actions.open;
this.requestUpdate();
}

handleError(json, action, icon) {
handleSuccess(action) {
const opts = { detail: { action }, composed: true, bubbles: true };
const event = new CustomEvent('success', opts);
this.dispatchEvent(event);
}

handleError(json, action) {
this._status = { ...json.error, action };
icon.classList.remove('is-sending');
icon.parentElement.classList.add('is-error');
this._isSending = false;
}

async setScheduledDialog(schedule) {
Expand Down Expand Up @@ -207,14 +226,23 @@ export default class DaTitle extends LitElement {

async handleAction(action) {
this._status = null;
this._sendButton.classList.add('is-sending');
this._isSending = true;
this._actions.open = false;
this.requestUpdate();

const { org, site, view, fullpath, path } = this.details;

const aemPath = `/${org}/${site}${path}`;

// Bail before writing if the remote drifted under us — protects against
// last-write-wins. Drift triggers the stale-content dialog via onStale.
if (view === 'sheet' || view === 'config') {
Comment thread
auniverseaway marked this conversation as resolved.
const { staleCheck } = await import('../../sheet/utils/utils.js');
if (await staleCheck.checkForDrift()) {
this._isSending = false;
return;
}
}

// Only save to DA if it is a sheet or config
if (view === 'sheet') {
const sheetPath = fullpath.replace('.json', '');
Expand All @@ -229,11 +257,16 @@ export default class DaTitle extends LitElement {
return;
}
}
if (view === 'sheet' || view === 'config') {
// Tell anything listening save was successful
this.handleSuccess('save');
}

// AEM Actions
if (action === 'preview' || action === 'publish') {
let json = await saveToAem(aemPath, 'preview');
if (json.error) {
this.handleError(json, 'preview', this._sendButton);
this.handleError(json, 'preview');
return;
}

Expand All @@ -244,7 +277,7 @@ export default class DaTitle extends LitElement {
if (this._scheduled?.scheduled) {
const shouldContinue = await this.setScheduledDialog(this._scheduled);
if (!shouldContinue) {
this._sendButton.classList.remove('is-sending');
this._isSending = false;
return;
}
}
Expand All @@ -254,7 +287,7 @@ export default class DaTitle extends LitElement {

// Handle all AEM errors
if (json.error) {
this.handleError(json, 'publish', this._sendButton);
this.handleError(json, 'publish');
return;
}

Expand Down Expand Up @@ -286,7 +319,7 @@ export default class DaTitle extends LitElement {
if (action === 'publish') saveDaVersion(fullpath, 'Published');
else if (action === 'preview') saveDaVersion(fullpath, 'Previewed');
}
this._sendButton.classList.remove('is-sending');
this._isSending = false;
}

async handleRoleRequest() {
Expand Down Expand Up @@ -317,10 +350,6 @@ export default class DaTitle extends LitElement {
this._dialog = { title, content, action: closeAction };
}

get _sendButton() {
return this.shadowRoot.querySelector('.da-title-action-send-icon');
}

get _canPrepare() {
return !!this.details.path;
}
Expand All @@ -337,7 +366,9 @@ export default class DaTitle extends LitElement {
<button
@click=${() => this.handleAction(action)}
class="con-button blue da-title-action"
aria-label="Send">
aria-label="Send"
data-popup-content=${this.disabledText ?? nothing}
?disabled=${this.disabledText}>
${action.charAt(0).toUpperCase() + action.slice(1)}
</button>
`)}`;
Expand Down Expand Up @@ -406,10 +437,10 @@ export default class DaTitle extends LitElement {
${this.collabStatus ? this.renderCollab() : nothing}
${this._canPrepare ? html`<da-prepare .details=${this.details}></da-prepare>` : nothing}
${this._status ? this.renderError() : nothing}
<div class="da-title-actions ${this._actions.open ? 'is-open' : ''} ${this._actions.fixed ? 'is-fixed' : ''}">
<div class="da-title-actions ${this._actions.available?.length === 1 && !this._isSending ? 'has-one-action' : ''} ${this._actions.open ? 'is-open' : ''} ${this._actions.fixed ? 'is-fixed' : ''}">
${this.renderActions()}
<button @click=${this.toggleActions} class="con-button blue da-title-action-send" aria-label="Send">
<svg class="da-title-action-send-icon" viewBox="0 0 20 20">
<button @click=${this.toggleActions} class="con-button blue da-title-action-send ${this._status ? 'is-error' : ''}" aria-label="Send">
<svg class="da-title-action-send-icon ${this._isSending ? 'is-sending' : ''}" viewBox="0 0 20 20">
<use href="/blocks/edit/img/S2_Icon_Publish_20_N.svg#S2_Icon_Publish"/>
</svg>
</button>
Expand Down
Loading
Loading