Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
1ccf777
chervon direction
mirafedas Mar 30, 2026
6920441
removed the connector lines
mirafedas Mar 30, 2026
eace76f
row selection on row click
mirafedas Mar 30, 2026
584b501
Merge branch 'main' into mwpw-190616
mirafedas Mar 31, 2026
9b25ea1
fixed offer data for variations
mirafedas Apr 1, 2026
2c14d89
Merge branch 'main' into mwpw-190616
mirafedas Apr 1, 2026
00f6e19
formatting
mirafedas Apr 3, 2026
b4101cf
Merge branch 'main' into mwpw-190616
mirafedas Apr 3, 2026
46eaf68
Merge branch 'main' into mwpw-190616
mirafedas Apr 13, 2026
1bc7de6
Merge branch 'main' into mwpw-190616
mirafedas Apr 14, 2026
5ddbc84
Merge branch 'main' into mwpw-190616
mirafedas Apr 15, 2026
72a2f5d
Merge remote-tracking branch 'origin/main' into mwpw-190616
mirafedas Apr 20, 2026
f0440ba
MWPW-190616: Add cleanup-variations IO action to remove invalid varia…
mirafedas Apr 20, 2026
9683bd1
MWPW-190616: Add unit tests for cleanup-variations action, fix 429 re…
mirafedas Apr 20, 2026
00a852b
Merge remote-tracking branch 'origin/main' into mwpw-190616
mirafedas Apr 21, 2026
644f28e
MWPW-190616: Refactor cleanup-variations — extract locales to JSON, m…
mirafedas Apr 21, 2026
86b643b
Merge branch 'main' into mwpw-190616
mirafedas Apr 24, 2026
cc70164
Merge branch 'main' into mwpw-190616
mirafedas Apr 24, 2026
a0e6058
Merge branch 'main' into mwpw-190616
mirafedas Apr 27, 2026
e4b867c
Merge branch 'main' into mwpw-190616
mirafedas Apr 28, 2026
38cfbfb
moved locales.json to www
mirafedas Apr 28, 2026
1110d77
Merge branch 'mwpw-190616' of https://github.com/adobecom/mas into mw…
mirafedas Apr 28, 2026
0e339a9
Merge branch 'main' into mwpw-190616
mirafedas Apr 29, 2026
ba83d7f
formatting
mirafedas Apr 29, 2026
efb6750
Merge branch 'main' into mwpw-190616
mirafedas Apr 30, 2026
549d2c0
Merge branch 'main' into mwpw-190616
mirafedas May 1, 2026
54c7175
Removed import, added odin-endpoint
mirafedas May 1, 2026
fff49a8
Merge branch 'main' into mwpw-190616
Axelcureno May 4, 2026
21810c6
Merge branch 'main' into mwpw-190616
mirafedas May 5, 2026
3bc96e7
Merge branch 'main' into mwpw-190616
afmicka May 7, 2026
865880c
Merge branch 'main' into mwpw-190616
mirafedas May 11, 2026
781569b
removed the cleanup variations script
mirafedas May 11, 2026
868b9fb
Merge branch 'mwpw-190616' of https://github.com/adobecom/mas into mw…
mirafedas May 11, 2026
c8023b3
removed localeFromPath and cleanup-variations from scripts
mirafedas May 11, 2026
78c2765
brought back the locales.js
mirafedas May 11, 2026
2e2d921
fixed table styles, dictionnary
mirafedas May 11, 2026
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
12 changes: 7 additions & 5 deletions studio/src/common/components/mas-select-items-table.css.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { css } from 'lit';
import {
tableHeaderBaseStyles,
tableBodyBaseStyles,
tableCellBaseStyles,
tableColumnIconStyles,
tableSelectedRowStyles,
Expand All @@ -9,6 +10,7 @@ import {

export const styles = [
tableHeaderBaseStyles,
tableBodyBaseStyles,
tableCellBaseStyles,
tableColumnIconStyles,
tableSelectedRowStyles,
Expand All @@ -28,11 +30,6 @@ export const styles = [
border-radius: 12px;
}

.fragments-table sp-table-head {
border: none;
border-radius: 0;
}

.fragments-table sp-table-head sp-table-head-cell:first-of-type,
.fragments-table sp-table-head sp-table-head-cell:last-of-type,
.fragments-table sp-table-head sp-table-checkbox-cell:first-of-type {
Expand All @@ -50,6 +47,7 @@ export const styles = [
z-index: 10;
background: var(--spectrum-gray-75);
box-shadow: 0 -2px 0 0 var(--spectrum-gray-75);
border-bottom: 1px solid var(--spectrum-gray-300);
}

sp-table-head sp-table-head-cell,
Expand All @@ -64,6 +62,10 @@ export const styles = [
sp-table-cell {
word-break: break-word;
}

sp-table-body > mas-collapsible-table-row + mas-collapsible-table-row {
border-top: 1px solid var(--spectrum-gray-300);
}
}

.fragments-table[selects='multiple'] {
Expand Down
13 changes: 6 additions & 7 deletions studio/src/common/styles/table-styles.css.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,6 @@ export const tableHeaderBaseStyles = css`
--mod-table-border-radius: 0;
}

.item-table sp-table-head {
border-top: 1px solid var(--spectrum-gray-300);
border-left: 1px solid var(--spectrum-gray-300);
border-right: 1px solid var(--spectrum-gray-300);
border-radius: 12px 12px 0 0;
}

.item-table sp-table-head-cell {
align-content: center;
}
Expand All @@ -41,6 +34,12 @@ export const tableHeaderBaseStyles = css`
}
`;

export const tableBodyBaseStyles = css`
.item-table sp-table-body {
border: none;
}
`;

export const tableColumnIconStyles = css`
.table-icon-cell {
display: flex;
Expand Down
68 changes: 68 additions & 0 deletions studio/src/common/utils/items-loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,74 @@ import {
enrichCards,
} from './item-loading.js';

/**
* Resolves parent OSI once when any variation lacks its own OSI (prefers in-memory parent), loads WCS offer
* data per variation via {@link loadOfferData} fallback (no mutation of fragment payloads), and attaches studioPath.
* @param {Object} params
* @param {{ path: string, parentFragment?: Object }} params.parent - Parent card path and optional in-memory parent fragment (e.g. from store) so OSI can be read without fetching by path first
* @param {Array<Object>} params.variations - Variation fragments with fieldTags
* @param {Object} params.repository - MasRepository with aem.getFragmentByPath
* @param {AbortSignal} params.signal - Optional abort for offer requests
* @returns {Promise<Array<Object>>} Same variations with studioPath and offerData
*/
async function enrichGroupedVariationsWithOffers({ parent, variations, repository, signal }) {
if (!variations?.length || !repository) return [];

const needsParentOsiFallback = variations.some((variation) => !new Fragment(variation).getFieldValue('osi'));

let parentWcsOsi;
if (needsParentOsiFallback) {
parentWcsOsi = parent.parentFragment ? new Fragment(parent.parentFragment).getFieldValue('osi') : undefined;
if (!parentWcsOsi) {
const parentFromAem = await repository.aem.getFragmentByPath(parent.path);
parentWcsOsi = parentFromAem ? new Fragment(parentFromAem).getFieldValue('osi') : undefined;
}
}

const offerDataResults = await processConcurrently(
variations,
(variation) =>
loadOfferData(variation, signal, 10000, {
fallbackWcsOsi: parentWcsOsi,
}),
VARIATIONS_CONCURRENCY_LIMIT,
);

return variations.map((variation, index) => ({
...variation,
studioPath: getFragmentName(new Fragment(variation)),
offerData: offerDataResults[index] ?? null,
}));
}

/**
* Resolves WCS offer data for a view-only table row: uses the fragment's own OSI, or parent card OSI when the row is a grouped variation without OSI (same idea as {@link enrichGroupedVariationsWithOffers}).
* @param {Object} card - Fragment payload (may be a parent card or a /pzn/ variation)
* @param {Object} repository - MasRepository
* @param {AbortSignal} [signal] - Abort signal
* @returns {Promise<Object|null>}
*/
async function loadOfferDataForViewOnlyCard(card, repository, signal) {
if (!repository || !card) return null;

const ownOsi = new Fragment(card).getFieldValue('osi');
if (ownOsi) {
return loadOfferData(card, signal);
}

let fallbackWcsOsi;
if (repository.resolveHydratedParentFragment && Fragment.isGroupedVariationPath(card.path)) {
try {
const parentFromAem = await repository.resolveHydratedParentFragment(card.path);
fallbackWcsOsi = new Fragment(parentFromAem).getFieldValue('osi');
} catch (err) {
console.warn(`Failed to load parent fragment for grouped variation ${card.id}:`, err.message);
}
}

return loadOfferData(card, signal, 10000, { fallbackWcsOsi });
}

/**
* Loads grouped variations for a card fragment
* @param {Object} card - Card object with path, references, fields
Expand Down
2 changes: 1 addition & 1 deletion studio/src/common/utils/render-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export function renderFragmentStatusCell(status) {
export function getItemTypeLabel(item) {
if (!item) return 'Unknown';
if (Fragment.isGroupedVariationPath(item.path)) return 'Grouped variation';
if (item.model?.path?.includes('/dictionary/')) return 'Placeholder';
if (item.model?.path?.includes('/dictionnary/')) return 'Placeholder';
if (item.model?.path === COLLECTION_MODEL_PATH) return 'Collection';
if (item.model?.path === CARD_MODEL_PATH) return 'Default';
return 'Unknown';
Expand Down
60 changes: 7 additions & 53 deletions studio/src/translation/mas-collapsible-table-row.css.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@ export const styles = [
tableSelectedRowStyles,
loadingContainerFlexStyles,
css`
:host {
display: block;
width: 100%;
box-sizing: border-box;
}

.loading-container--flex {
padding: 10px;
width: 100%;
Expand Down Expand Up @@ -97,65 +103,13 @@ export const styles = [
}

.nested-content {
--connector-offset: 30px;
position: relative;
margin-left: 60px;
}

.nested-content.has-connector::before {
content: '';
position: absolute;
left: calc(-1 * var(--connector-offset));
top: 0;
bottom: var(--nested-content-connector-bottom, 0px);
width: 1px;
background-color: var(--spectrum-gray-400);
margin-left: 30px;
}

.nested-content sp-table {
width: 100%;
}

.nested-content sp-table-body {
position: relative;
}

.nested-content sp-table-body::before {
content: '';
position: absolute;
left: calc(-1 * var(--connector-offset));
top: 0;
width: 1px;
background-color: var(--spectrum-gray-400);
}

.nested-content sp-table-body sp-table-row {
position: relative;
}

.nested-content sp-table-body sp-table-row:not(.variation-details-row)::before {
content: '';
position: absolute;
left: -30px;
top: 50%;
transform: translateY(-50%);
width: 30px;
height: 1px;
background-color: var(--spectrum-gray-400);
}

.nested-content sp-table-body sp-table-row:not(.variation-details-row)::after {
content: '';
position: absolute;
left: -3px;
top: 50%;
transform: translate(-50%, -50%);
width: 6px;
height: 6px;
border-radius: 50%;
background-color: var(--spectrum-gray-400);
}

.nested-content sp-table-body sp-table-row:first-of-type:not(.variation-details-row) {
sp-table-cell:first-of-type {
border-top-left-radius: 12px;
Expand Down
80 changes: 20 additions & 60 deletions studio/src/translation/mas-collapsible-table-row.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ export class MasCollapsibleTableRow extends LitElement {
isTopLevelExpanded: { type: Boolean },
expandedVariationsPaths: { type: Set, state: true },
isLoadingVariations: { type: Boolean, state: true },
resizeObserver: { type: Object },
repository: { type: Object, state: true },
getDisplayName: { type: Function },
renderFragmentStatusCell: { type: Function },
Expand All @@ -43,7 +42,8 @@ export class MasCollapsibleTableRow extends LitElement {
}
this.isTopLevelExpanded = false;
this.expandedVariationsPaths = new Set();
this.resizeObserver = null;
this.variationsController = new ReactiveController(this, [getItemsSelectionStore().groupedVariationsByParent]);
this.selectedCardsController = new ReactiveController(this, [getItemsSelectionStore().selectedCards]);
this.variationsController = new ReactiveController(this, [getItemsSelectionStore().groupedVariationsByParent]);
this.selectedCardsController = new ReactiveController(this, [getItemsSelectionStore().selectedCards]);
}
Expand All @@ -55,26 +55,6 @@ export class MasCollapsibleTableRow extends LitElement {
this.repository = document.querySelector('mas-repository');
}

updated(changedProperties) {
super.updated(changedProperties);
if (changedProperties.has('isTopLevelExpanded')) {
if (this.isTopLevelExpanded) {
requestAnimationFrame(() => {
this.#updateConnectorBottom();
this.#observeResize();
});
} else {
this.resizeObserver?.disconnect();
}
}
}

disconnectedCallback() {
super.disconnectedCallback();
this.resizeObserver?.disconnect();
this.resizeObserver = null;
}

get variationPaths() {
return new Fragment(this.topLevelCard).getVariations() || [];
}
Expand Down Expand Up @@ -119,6 +99,7 @@ export class MasCollapsibleTableRow extends LitElement {
value=${variationPath}
?selected=${isSelected}
aria-selected=${isSelected ? 'true' : 'false'}
@click=${(event) => this.#onRowClickForSelection(event, variationPath)}
>
<sp-table-cell class="table-icon-cell">
<sp-button
Expand All @@ -129,15 +110,15 @@ export class MasCollapsibleTableRow extends LitElement {
@click=${(e) => this.#toggleExpandVariation(e, variationPath)}
>
${isExpanded
? html`<sp-icon-chevron-up></sp-icon-chevron-up>`
: html`<sp-icon-chevron-down></sp-icon-chevron-down>`}
? html`<sp-icon-chevron-down></sp-icon-chevron-down>`
: html`<sp-icon-chevron-right></sp-icon-chevron-right>`}
</sp-button>
</sp-table-cell>
<sp-table-cell class="table-icon-cell">
<sp-checkbox
value=${variationPath}
?checked=${isSelected}
@change=${(e) => this.#toggleSelect(e, variationPath)}
@change=${(event) => this.#toggleSelect(event, variationPath)}
></sp-checkbox>
</sp-table-cell>
${repeat(this.cells, (cell) => this[`render${cell}`](variation) ?? nothing)}
Expand Down Expand Up @@ -165,8 +146,8 @@ export class MasCollapsibleTableRow extends LitElement {
@click=${this.#toggleExpandTopLevel}
>
${this.isTopLevelExpanded
? html`<sp-icon-chevron-up></sp-icon-chevron-up>`
: html`<sp-icon-chevron-down></sp-icon-chevron-down>`}
? html`<sp-icon-chevron-down></sp-icon-chevron-down>`
: html`<sp-icon-chevron-right></sp-icon-chevron-right>`}
</sp-button>
</sp-table-cell>`
: html`<sp-table-cell class="table-icon-cell table-icon-cell--chevron"></sp-table-cell>`}
Expand Down Expand Up @@ -257,37 +238,15 @@ export class MasCollapsibleTableRow extends LitElement {
}
}

#hasConnector(tab) {
return tab?.key === 'groupedVariation' && this.topLevelCardVariationsByPaths.size > 0;
}

/** Updates the bottom position of the connector between the nested content and the last row of the selected tab panel */
#updateConnectorBottom() {
const nestedContent = this.shadowRoot?.querySelector('.nested-content');
if (!nestedContent) return;

const selectedTabPanel = nestedContent.querySelector('sp-tab-panel[selected]');
const rows = selectedTabPanel?.querySelectorAll('sp-table-row:not(.variation-details-row)');
const lastRow = rows?.[rows.length - 1];
if (!lastRow) return;

let connectorBottom = lastRow.offsetHeight / 2 + 16;
if (this.expandedVariationsPaths.has(lastRow.getAttribute('value'))) {
connectorBottom += lastRow.nextElementSibling?.offsetHeight ?? 0;
}
nestedContent.style.setProperty('--nested-content-connector-bottom', `${connectorBottom}px`);
}

/** Observes the resize of the nested content when user changes the window width, and updates the bottom position of the connector */
#observeResize() {
const nestedContent = this.shadowRoot?.querySelector('.nested-content');
if (!nestedContent) return;

this.resizeObserver?.disconnect();
this.resizeObserver = new ResizeObserver(() => {
this.#updateConnectorBottom();
#onRowClickForSelection(e, path) {
const shouldIgnore = e.composedPath().some((node) => {
if (!(node instanceof Element)) return false;
if (node.tagName === 'SP-CHECKBOX') return true;
if (node.classList?.contains('expand-button')) return true;
if (node.tagName === 'SP-ACTION-BUTTON') return true;
});
this.resizeObserver.observe(nestedContent);
if (shouldIgnore) return;
this.#toggleSelect(e, path);
}

#toggleSelect(e, path) {
Expand Down Expand Up @@ -369,12 +328,13 @@ export class MasCollapsibleTableRow extends LitElement {
value=${this.topLevelCard.path}
?selected=${isSelected}
aria-selected=${isSelected ? 'true' : 'false'}
@click=${(e) => this.#onRowClickForSelection(e, this.topLevelCard.path)}
>
<sp-table-cell class="table-icon-cell">
<sp-button class="expand-button" icon-only quiet variant="secondary" @click=${this.#toggleExpandTopLevel}>
${this.isTopLevelExpanded
? html`<sp-icon-chevron-up></sp-icon-chevron-up>`
: html`<sp-icon-chevron-down></sp-icon-chevron-down>`}
? html`<sp-icon-chevron-down></sp-icon-chevron-down>`
: html`<sp-icon-chevron-right></sp-icon-chevron-right>`}
</sp-button>
</sp-table-cell>
<sp-table-cell class="table-icon-cell">
Expand All @@ -389,7 +349,7 @@ export class MasCollapsibleTableRow extends LitElement {

${this.isTopLevelExpanded
? html`<div class="nested-content-container">
<div class="nested-content ${this.#hasConnector(selectedTab) ? 'has-connector' : ''}">
<div class="nested-content">
<sp-tabs quiet .selected=${selectedTab?.key}>
${repeat(
this.tabs,
Expand Down
Loading
Loading