Skip to content

Commit

Permalink
Merge branch 'develop' into epic/ssr-error-handling
Browse files Browse the repository at this point in the history
  • Loading branch information
pawelfras authored Apr 23, 2024
2 parents f280662 + 0206854 commit af10432
Show file tree
Hide file tree
Showing 23 changed files with 396 additions and 200 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@ import {
ChangeDetectorRef,
Component,
ComponentRef,
HostListener,
Input,
OnDestroy,
OnInit,
Optional,
inject,
} from '@angular/core';
import { UntypedFormControl, UntypedFormGroup } from '@angular/forms';
import {
Expand All @@ -24,8 +26,9 @@ import {
import {
CmsAddToCartComponent,
EventService,
isNotNullable,
FeatureConfigService,
Product,
isNotNullable,
} from '@spartacus/core';
import {
CmsComponentData,
Expand Down Expand Up @@ -74,6 +77,29 @@ export class AddToCartComponent implements OnInit, OnDestroy {

iconTypes = ICON_TYPE;

@Optional() featureConfigService = inject(FeatureConfigService, {
optional: true,
});

/**
* We disable the dialog launch on quantity input,
* as it causes an unexpected change of context.
* The expectation is only for the quantity to get updated in the Qty field.
*/
@HostListener('document:keydown', ['$event'])
handleKeyboardEvent(event: KeyboardEvent) {
// TODO: (CXSPA-6034) Remove Feature flag next major release
if (!this.featureConfigService?.isEnabled('a11yQuantityOrderTabbing')) {
return;
}
const eventTarget = event.target as HTMLElement;
const isQuantityInput =
eventTarget.ariaLabel === 'Quantity' && eventTarget.tagName === 'INPUT';
if (event.key === 'Enter' && isQuantityInput) {
event.preventDefault();
}
}

constructor(
protected currentProductService: CurrentProductService,
protected cd: ChangeDetectorRef,
Expand Down
4 changes: 2 additions & 2 deletions feature-libs/order/assets/translations/en/order.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@
"deliveryStatus_PICKUP_COMPLETE": "Pickup Complete",
"deliveryStatus_DELIVERY_COMPLETED": "Delivery Complete",
"deliveryStatus_PAYMENT_NOT_CAPTURED": "Payment Issue",
"deliveryStatus_IN_PROCESS": "In Process",
"deliveryStatus_READY": "In Process",
"deliveryStatus_IN_PROCESS": "Order Processing",
"deliveryStatus_READY": "Order Processing",
"deliveryStatus_DELIVERY_REJECTED": "Delivery Rejected",
"deliveryStatus_SHIPPED": "Shipped",
"deliveryStatus_TAX_NOT_COMMITTED": "Tax Issue",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,16 @@ export interface FeatureTogglesInterface {
*/
storeFrontLibCardParagraphTruncated?: boolean;

/**
* In `ConfiguratorAttributeDropDownComponent`, `ConfiguratorAttributeSingleSelectionImageComponent`
* and in 'ConfiguratorAttributeMultiSelectionImageComponent' some HTML changes were done
* to render read-only attribute with images and a long description at the value level accordingly.
*
* In `cx-configurator-price`, `cx-configurator-show-more`,`cx-configurator-attribute-drop-down`,
* `cx-configurator-attribute-selection-image`, `cx-configurator-attribute-single-selection-bundle-dropdown`,
* `cx-configurator-attribute-type` and `cx-configurator-form-group` some styling changes were done
* to render read-only attribute with images and a long description at the value level accordingly.
*/
productConfiguratorAttributeTypesV2?: boolean;

/**
Expand Down
3 changes: 3 additions & 0 deletions projects/schematics/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,6 @@ yarn-error.log*
# Mac OSX Finder files.
**/.DS_Store
.DS_Store

# FeatureToggles
src/feature-toggles.copied-from-core-lib.ts
2 changes: 2 additions & 0 deletions projects/schematics/.npmignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,5 @@ src/migrations/test/**/*
.eslintrc.json
sub-folder/
.pipeline/
copy-feature-toggles.js
src/feature-toggles.copied-from-core-lib.ts
15 changes: 15 additions & 0 deletions projects/schematics/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -211,3 +211,18 @@ Example for 6.3.2 release:
}
```
version remains unchanged

## FeatureToggles copying
The installation schematics generates a list of available feature toggles in a customer's app.
It's to help customers to see what feature toggles are available in Spartacus.

Moreover, each feature toggle is explicitly enabled in customer's app, to help customers start with the most up-to-date configuration (without a technical debt of any feature toggles disabled). Of course, they can disable any feature toggle they don't want to use.

**Technical notes:**
During running the `build` and `test` commands in the schematics project,
the file `feature-toggles.ts` is copied temporarily from the `@spartacus/core` project location
to the file `src/feature-toggles.copied-from-core-lib.ts` file in the `@spartacus/schematics` project location. The file is git-ignored.

In particular, this TS file is copied to schematics project. Then the `build` command compiles it into a JS file. Then the JS file will be shipped with all other JS files in the schematics project to customers, and it will be used in runtime of schematics to generate a list of feature toggles in customer's app.

Note: We copy the TS file to the schematics project location (instead of directly importing it from the core project) to avoid a direct dependency in `@spartacus/schematics` on the lib `@spartacus/core`.
10 changes: 10 additions & 0 deletions projects/schematics/copy-feature-toggles.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/**
* This script copies the feature-toggles.ts file from the Spartacus core project to schematics project.
*/

const fs = require('fs');
const SOURCE =
'../../projects/core/src/features-config/feature-toggles/config/feature-toggles.ts';
const DESTINATION = './src/feature-toggles.copied-from-core-lib.ts';

fs.copyFileSync(SOURCE, DESTINATION);
5 changes: 3 additions & 2 deletions projects/schematics/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@
"license": "MIT",
"main": "index.js",
"scripts": {
"build": "npm run clean && npm --prefix ../../ run generate:deps && ../../node_modules/.bin/tsc -p ./tsconfig.schematics.json",
"build": "npm run clean && npm run copy-feature-toggles && npm --prefix ../../ run generate:deps && ../../node_modules/.bin/tsc -p ./tsconfig.schematics.json",
"clean": "../../node_modules/.bin/rimraf --glob \"index.js*\" \"index.d.ts\" \"src/**/*.js\" \"src/**/*.js.map\" \"src/**/*.d.ts\"",
"test": "npm run clean && ../../node_modules/.bin/jest --config ./jest.schematics.config.js"
"test": "npm run clean && npm run copy-feature-toggles && ../../node_modules/.bin/jest --config ./jest.schematics.config.js",
"copy-feature-toggles": "node copy-feature-toggles"
},
"dependencies": {
"@angular/pwa": "^17.0.5",
Expand Down
3 changes: 3 additions & 0 deletions projects/schematics/src/add-spartacus/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ import {
import { addSpartacusConfiguration } from './configuration';
import { Schema as SpartacusOptions } from './schema';
import { setupSpartacusModule } from './spartacus';
import { addFeatureToggles } from './spartacus-feature-toggles';
import { setupSpartacusFeaturesModule } from './spartacus-features';
import { setupStoreModules } from './store';

Expand Down Expand Up @@ -577,6 +578,8 @@ export function addSpartacus(options: SpartacusOptions): Rule {

addSpartacusConfiguration(options),

addFeatureToggles(options),

updateAppModule(options),
createStylesConfig(options),
installStyles(options),
Expand Down
21 changes: 21 additions & 0 deletions projects/schematics/src/add-spartacus/index_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import {
} from '@schematics/angular/application/schema';
import { Schema as WorkspaceOptions } from '@schematics/angular/workspace/schema';
import * as path from 'path';
// eslint-disable-next-line @nx/enforce-module-boundaries
import { defaultFeatureToggles } from '../../../core/src/features-config/feature-toggles/config/feature-toggles';
import {
SPARTACUS_CONFIGURATION_MODULE,
SPARTACUS_CORE,
Expand Down Expand Up @@ -480,6 +482,25 @@ describe('add-spartacus', () => {
});
});

it('Should add provideFeatureToggles in SpartacusFeaturesModule', async () => {
const tree = await schematicRunner.runSchematic(
'add-spartacus',
defaultOptions,
appTree
);

const featureModuleContent = tree.readContent(
`/projects/schematics-test/${spartacusFeaturesModulePath}`
);

expect(featureModuleContent).toContain(`provideFeatureToggles({`);

const featureTogglesKeys = Object.keys(defaultFeatureToggles);
featureTogglesKeys.forEach((key) => {
expect(featureModuleContent).toContain(`"${key}": true`);
});
});

it('Import Spartacus styles to styles.scss', async () => {
const tree = await schematicRunner.runSchematic(
'add-spartacus',
Expand Down
113 changes: 113 additions & 0 deletions projects/schematics/src/add-spartacus/spartacus-feature-toggles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
/*
* SPDX-FileCopyrightText: 2024 SAP Spartacus team <[email protected]>
*
* SPDX-License-Identifier: Apache-2.0
*/

import {
Rule,
SchematicContext,
SchematicsException,
Tree,
} from '@angular-devkit/schematics';
import { SourceFile } from 'ts-morph';
import {
FEATURE_TOGGLES_COPIED_FROM_CORE_LIB_PATH,
PROVIDE_FEATURE_TOGGLES_FUNCTION,
SPARTACUS_CORE,
SPARTACUS_FEATURES_NG_MODULE,
addModuleProvider,
getProjectTsConfigPaths,
getSpartacusFeaturesModule,
saveAndFormat,
} from '../shared';
import { Schema as SpartacusOptions } from './schema';

export function addFeatureToggles(options: SpartacusOptions): Rule {
return (tree: Tree, context: SchematicContext): Tree => {
if (options.debug) {
context.logger.info(`⌛️ Adding Feature Toggles...`);
}

const { buildPaths } = getProjectTsConfigPaths(tree, options.project);

if (!buildPaths.length) {
throw new SchematicsException(
`Could not find any tsconfig file. Can't find ${SPARTACUS_FEATURES_NG_MODULE}.`
);
}

const basePath = process.cwd();
for (const tsconfigPath of buildPaths) {
const spartacusFeaturesModule = getSpartacusFeaturesModule(
tree,
basePath,
tsconfigPath
);
if (spartacusFeaturesModule) {
_addFeatureToggles(spartacusFeaturesModule);
break;
}
}

if (options.debug) {
context.logger.info(`✅ Feature Toggles added.`);
}
return tree;
};
}
/**
* Creates and adds a spartacus feature toggles with all of them enabled.
*/
function _addFeatureToggles(sourceFile: SourceFile): void {
const featureTogglesProvider = createFeatureTogglesProvider();
addModuleProvider(sourceFile, {
import: [
{
moduleSpecifier: SPARTACUS_CORE,
namedImports: [PROVIDE_FEATURE_TOGGLES_FUNCTION],
},
],
content: featureTogglesProvider,
});

saveAndFormat(sourceFile);
}

/**
* Returns a provider for all existing feature toggles with value `true`.
*/
function createFeatureTogglesProvider(): string {
const defaultFeatureToggles = getDefaultFeatureToggles();

//for each key in `defaultFeatureToggles` map it to a key with value true
const featureTogglesAllEnabled: Record<string, boolean> = Object.keys(
defaultFeatureToggles
).reduce((acc, key) => ({ ...acc, [key]: true }), {});
const featureTogglesString = JSON.stringify(
featureTogglesAllEnabled,
null,
2
);
return `provideFeatureToggles(${featureTogglesString})`;
}

/**
* Retrieves Spartacus core library's default feature toggles.
*
* Note: A TypeScript file is copied to the schematics project in a pre-build step,
* from the core project, to prevent a runtime dependency on `@spartacus/core`.
* This file is then compiled into JavaScript and included with the schematics
* project's distribution, used at runtime.
*
* Due to the lazy nature of the NodeJS `require()` function, the TypeScript
* file may not appear in the schematics project's source code.
*
* For more, see the script `copy-feature-toggles` in the schematics's `package.json`.
*/
function getDefaultFeatureToggles(): Record<string, boolean> {
const {
defaultFeatureToggles,
} = require(FEATURE_TOGGLES_COPIED_FROM_CORE_LIB_PATH);
return defaultFeatureToggles;
}
4 changes: 4 additions & 0 deletions projects/schematics/src/shared/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ export const EVENTS_MODULE = 'EventsModule';
export const CONFIG_MODULE_CLASS = 'ConfigModule';
export const CMS_COMPONENT_DATA_CLASS = 'CmsComponentData';
export const PROVIDE_CONFIG_FUNCTION = 'provideConfig';
export const PROVIDE_FEATURE_TOGGLES_FUNCTION = 'provideFeatureToggles';
export const SITE_CONTEXT_CONFIG = 'SiteContextConfig';
export const I18N_CONFIG = 'I18nConfig';
export const OCC_CONFIG = 'OccConfig';
Expand Down Expand Up @@ -1157,3 +1158,6 @@ export const APP_ROUTING_MODULE = 'AppRoutingModule';
export const APP_ROUTING_MODULE_LOCAL_PATH = './app-routing.module';
export const APP_ROUTING_MODULE_LOCAL_FILENAME = 'app-routing.module.ts';
export const BROWSER_MODULE = 'BrowserModule';

export const FEATURE_TOGGLES_COPIED_FROM_CORE_LIB_PATH =
'../feature-toggles.copied-from-core-lib';
Loading

0 comments on commit af10432

Please sign in to comment.