Skip to content

Commit

Permalink
Merge branch 'next-26177/auto-imported-from-github' into 'trunk'
Browse files Browse the repository at this point in the history
NEXT-26177 - Implement language switch and smart buttons added by Extension SDK

See merge request shopware/6/product/platform!10604
  • Loading branch information
jleifeld committed Apr 26, 2023
2 parents 94f76a4 + 4995aed commit 4eca333
Show file tree
Hide file tree
Showing 15 changed files with 365 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
title: Implement language switch and smart bar buttons for main module in App
issue: NEXT-26177
author: Vu Le
author_email: [email protected]
author_github: crisalder2806
---
# Administration
* Added `smartBarButtonAdd` message handler in `app/init/main-module.init.ts` to handle adding language switch and smart buttons from `Admin Extension SDK`
* Added `sw_extension_sdk_module_smart_bar_buttons`, `sw_extension_sdk_module_language_switch` blocks in `sw-extension-sdk/page/sw-extension-sdk-module/sw-extension-sdk-module.html.twig` to render language switch and smart bar buttons added by `Admin Extension SDK`
* Changed `sw-extension-component-section/sw-extension-component-section.html.twig` to render tabs inside `card` component section
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,24 @@ Shopware.Component.register('sw-extension-component-section', {
positionId: (currentComponent) => currentComponent.positionIdentifier as string,
},

data() {
return {
activeTabName: '',
};
},

methods: {
setActiveTab(name: string) {
this.activeTabName = name;
},

getActiveTab(componentSection: ComponentSectionEntry) {
return this.activeTabName
? componentSection.props.tabs.find(tab => tab.name === this.activeTabName)
: componentSection.props.tabs[0];
},
},

props: {
positionIdentifier: {
type: String,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,35 @@
:title="componentSection.props.title"
:subtitle="componentSection.props.subtitle"
>

<template
v-if="componentSection.props?.tabs"
#tabs
>
<sw-tabs
position-identifier=""
@new-item-active="setActiveTab($event.name)"
>
<sw-tabs-item
v-for="tab in componentSection.props.tabs"
:key="tab.name"
:active-tab="getActiveTab(componentSection).name"
:name="tab.name"
>
{{ tab.label }}
</sw-tabs-item>
</sw-tabs>
</template>

<sw-iframe-renderer
v-if="componentSection.props?.tabs && getActiveTab(componentSection)"
:key="getActiveTab(componentSection).name"
:src="componentSection.src"
:location-id="getActiveTab(componentSection)?.locationId"
/>

<sw-iframe-renderer
v-if="componentSection.props?.locationId && !componentSection.props?.tabs"
:src="componentSection.src"
:location-id="componentSection.props.locationId"
/>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
/**
* @package admin
*/

import { mount } from '@vue/test-utils';
import 'src/app/component/extension-api/sw-extension-component-section';
import 'src/app/component/base/sw-card';
import 'src/app/component/base/sw-tabs';
import 'src/app/component/base/sw-tabs-item';
import Vue from 'vue';

describe('src/app/component/extension-api/sw-extension-component-section', () => {
let wrapper = null;
let stubs;

async function createWrapper() {
return mount(await Shopware.Component.build('sw-extension-component-section'), {
propsData: {
positionIdentifier: 'test-position',
},
stubs,
});
}

beforeAll(async () => {
stubs = {
'sw-card': await Shopware.Component.build('sw-card'),
'sw-tabs': await Shopware.Component.build('sw-tabs'),
'sw-tabs-item': await Shopware.Component.build('sw-tabs-item'),
'sw-ignore-class': true,
'sw-iframe-renderer': {
template: '<div></div>',
},
};
});

beforeEach(async () => {
Vue.set(Shopware.State.get('extensionComponentSections'), 'identifier', {});
});

afterEach(() => {
if (wrapper) {
wrapper.destroy();
wrapper = null;
}
});

it('should be a Vue.js component', async () => {
wrapper = await createWrapper();
expect(wrapper.vm).toBeTruthy();
});

it('should not render tabs in card section', async () => {
Shopware.State.commit('extensionComponentSections/addSection', {
component: 'card',
positionId: 'test-position',
props: {
title: 'test-card',
subtitle: 'test-card-description',
},
});

wrapper = await createWrapper();
await flushPromises();

const tabs = wrapper.find('.sw-tabs');
expect(tabs.exists()).toBe(false);
});

it('should render tabs in card section', async () => {
Shopware.State.commit('extensionComponentSections/addSection', {
component: 'card',
positionId: 'test-position',
props: {
title: 'test-card',
subtitle: 'test-card-description',
tabs: [
{
name: 'tab-1',
label: 'Tab 1',
locationId: 'tab-1',
},
{
name: 'tab-2',
label: 'Tab 2',
locationId: 'tab-2',
},
],
},
});

wrapper = await createWrapper();
await flushPromises();

const tabs = wrapper.findAll('.sw-tabs-item');
expect(tabs).toHaveLength(2);

const activeTabs = wrapper.findAll('.sw-tabs-item--active');
expect(activeTabs).toHaveLength(1);

const activeTab = activeTabs.at(0);
expect(activeTab.text()).toBe('Tab 1');
});

it('should switch tab when clicking', async () => {
Shopware.State.commit('extensionComponentSections/addSection', {
component: 'card',
positionId: 'test-position',
props: {
title: 'test-card',
subtitle: 'test-card-description',
tabs: [
{
name: 'tab-1',
label: 'Tab 1',
locationId: 'tab-1',
},
{
name: 'tab-2',
label: 'Tab 2',
locationId: 'tab-2',
},
],
},
});

wrapper = await createWrapper();
await flushPromises();

// Default active tab
const defaultIframe = wrapper.findComponent(stubs['sw-iframe-renderer']);
expect(defaultIframe.vm.$attrs['location-id']).toBe('tab-1');

// Click the 2nd tab
const tabItems = wrapper.findAll('.sw-tabs-item');
await tabItems.at(1).trigger('click');

// Check tab content
const activeIframe = wrapper.findComponent(stubs['sw-iframe-renderer']);
expect(activeIframe.vm.$attrs['location-id']).toBe('tab-2');
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,8 @@ export default function initMainModules(): void {
});
});
});

Shopware.ExtensionAPI.handle('smartBarButtonAdd', (configuration) => {
Shopware.State.commit('extensionSdkModules/addSmartBarButton', configuration);
});
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
/**
* @package admin
*/

/* Is covered by E2E tests */
/* istanbul ignore file */
import type { Module } from 'vuex';
import type { smartBarButtonAdd } from '@shopware-ag/admin-extension-sdk/es/ui/mainModule';

// eslint-disable-next-line sw-deprecation-rules/private-feature-declarations
export type ExtensionSdkModule = {
Expand All @@ -13,25 +13,33 @@ export type ExtensionSdkModule = {
baseUrl: string,
locationId: string,
displaySearchBar: boolean,
displayLanguageSwitch: boolean,
};

interface ExtensionSdkModuleState {
modules: ExtensionSdkModule[],

smartBarButtons: smartBarButtonAdd[],
}

const ExtensionSdkModuleStore: Module<ExtensionSdkModuleState, VuexRootState> = {
namespaced: true,

state: (): ExtensionSdkModuleState => ({
modules: [],
smartBarButtons: [],
}),

actions: {
addModule({ state }, { heading, locationId, displaySearchBar, baseUrl }: ExtensionSdkModule): Promise<string> {
addModule(
{ state },
{ heading, locationId, displaySearchBar, displayLanguageSwitch, baseUrl }: ExtensionSdkModule,
): Promise<string> {
const staticElements = {
heading,
locationId,
displaySearchBar,
displayLanguageSwitch,
baseUrl,
};

Expand All @@ -49,6 +57,12 @@ const ExtensionSdkModuleStore: Module<ExtensionSdkModuleState, VuexRootState> =
},
},

mutations: {
addSmartBarButton(state, button: smartBarButtonAdd) {
state.smartBarButtons.push(button);
},
},

getters: {
getRegisteredModuleInformation: (state) => (baseUrl: string): ExtensionSdkModule[] => {
return state.modules.filter((module) => module.baseUrl.startsWith(baseUrl));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ const missingTests = [
'src/app/component/data-grid/sw-data-grid-column-position/index.js',
'src/app/component/data-grid/sw-data-grid-inline-edit/index.js',
'src/app/component/data-grid/sw-data-grid-skeleton/index.js',
'src/app/component/extension-api/sw-extension-component-section/index.ts',
'src/app/component/filter/sw-sidebar-filter-panel/index.js',
'src/app/component/form/field-base/sw-base-field/index.js',
'src/app/component/form/field-base/sw-block-field/index.js',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,15 @@ Shopware.Component.register('sw-extension-sdk-module', {
showSearchBar() {
return this.module?.displaySearchBar ?? true;
},

showLanguageSwitch() {
return !!this.module?.displayLanguageSwitch;
},

smartBarButtons() {
return Shopware.State.get('extensionSdkModules').smartBarButtons
.filter(button => button.locationId === this.module?.locationId);
},
},

watch: {
Expand Down Expand Up @@ -65,4 +74,10 @@ Shopware.Component.register('sw-extension-sdk-module', {
window.clearTimeout(this.loadingTimeOut);
}
},

methods: {
onChangeLanguage(languageId) {
Shopware.State.commit('context/setApiLanguageId', languageId);
},
},
});
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,22 @@
{% endblock %}
</template>

<!-- eslint-disable-next-line sw-deprecation-rules/no-twigjs-blocks -->
{% block sw_extension_sdk_module_smart_bar_buttons %}
<template #smart-bar-actions>
<sw-button
v-for="button in smartBarButtons"
:id="button.buttonId"
:key="button.buttonId"
:disabled="button.disabled"
:variant="button.variant"
@click="button.onClickCallback"
>
{{ button.label }}
</sw-button>
</template>
{% endblock %}

<template #content>
<!-- eslint-disable-next-line sw-deprecation-rules/no-twigjs-blocks -->
{% block sw_extension_sdk_module_content %}
Expand All @@ -34,5 +50,18 @@
{% endblock %}
{% endblock %}
</template>

<!-- eslint-disable-next-line sw-deprecation-rules/no-twigjs-blocks -->
{% block sw_extension_sdk_module_language_switch %}
<template
v-if="showLanguageSwitch"
#language-switch
>
<sw-language-switch
:change-global-language="true"
@on-change="onChangeLanguage"
/>
</template>
{% endblock %}
</sw-page>
{% endblock %}
Loading

0 comments on commit 4eca333

Please sign in to comment.