Skip to content

Commit b65f8db

Browse files
Merge branch '26_1' into 26_1_global_format
2 parents 56c9811 + a32e237 commit b65f8db

10 files changed

Lines changed: 95 additions & 70 deletions

File tree

packages/devextreme-scss/scss/widgets/base/_menuBase.scss

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,19 +21,14 @@
2121
list-style-type: none;
2222
display: inline-block;
2323
white-space: nowrap;
24-
cursor: pointer;
25-
}
26-
27-
.dx-state-disabled,
28-
&.dx-state-disabled .dx-menu-items-container {
29-
cursor: default;
3024
}
3125

3226
.dx-menu-item {
3327
display: inline-block;
3428
position: relative;
3529
height: 100%;
3630
width: 100%;
31+
cursor: pointer;
3732

3833
.dx-menu-item-content {
3934
white-space: nowrap;
@@ -80,6 +75,7 @@
8075

8176
.dx-submenu {
8277
box-sizing: content-box;
78+
cursor: default;
8379
}
8480
}
8581

@@ -106,3 +102,10 @@
106102
}
107103
}
108104
}
105+
106+
.dx-state-disabled {
107+
&.dx-menu-item,
108+
.dx-menu-item {
109+
cursor: default;
110+
}
111+
}

packages/devextreme/js/__internal/core/license/lcp_key_validation/lcp_key_validation.test.ts

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ describe('LCP key validation', () => {
7474
expect(version).toBe(undefined);
7575
});
7676

77-
it('does not classify a valid DevExtreme product key as trial-expired when expiration metadata is in the past', () => {
77+
it('does not classify a valid DevExtreme product key as expired when expiration metadata is in the past', () => {
7878
const { parseDevExpressProductKey, TokenKind } = loadParserWithBypassedSignatureCheck();
7979
const expiredAt = msToDotNetTicks(Date.UTC(2020, 0, 1));
8080

@@ -83,17 +83,4 @@ describe('LCP key validation', () => {
8383

8484
expect(token.kind).toBe(TokenKind.verified);
8585
});
86-
87-
it('returns trial-expired for expired trial keys without DevExtreme product access', () => {
88-
const { parseDevExpressProductKey, TokenKind } = loadParserWithBypassedSignatureCheck();
89-
const expiredAt = msToDotNetTicks(Date.UTC(2020, 0, 1));
90-
91-
const payload = `meta;251,0,0,${expiredAt};`;
92-
const token = parseDevExpressProductKey(createLcpSource(payload));
93-
94-
expect(token.kind).toBe(TokenKind.corrupted);
95-
if (token.kind === TokenKind.corrupted) {
96-
expect(token.error).toBe('trial-expired');
97-
}
98-
});
9986
});

packages/devextreme/js/__internal/core/license/lcp_key_validation/lcp_key_validator.ts

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,14 @@ import {
66
PRODUCT_KIND_ERROR,
77
type Token,
88
TokenKind,
9-
TRIAL_EXPIRED_ERROR,
109
VERIFICATION_ERROR,
1110
} from '../types';
1211
import {
1312
LCP_SIGNATURE,
1413
RSA_PUBLIC_KEY_XML,
1514
SIGN_LENGTH,
1615
} from './const';
17-
import { findLatestDevExtremeVersion, getMaxExpiration } from './license_info';
16+
import { findLatestDevExtremeVersion } from './license_info';
1817
import { createProductInfo, type ProductInfo } from './product_info';
1918
import {
2019
dotNetTicksToMs,
@@ -96,13 +95,6 @@ export function parseDevExpressProductKey(productsLicenseSource: string): Token
9695

9796
const maxVersionAllowed = findLatestDevExtremeVersion({ products });
9897

99-
if (!maxVersionAllowed) {
100-
const maxExpiration = getMaxExpiration({ products });
101-
if (maxExpiration !== Infinity && maxExpiration < Date.now()) {
102-
return TRIAL_EXPIRED_ERROR;
103-
}
104-
}
105-
10698
if (!maxVersionAllowed) {
10799
return PRODUCT_KIND_ERROR;
108100
}

packages/devextreme/js/__internal/core/license/license_validation.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,9 +83,6 @@ function getLicenseCheckParams({
8383
if (license.error === 'product-kind') {
8484
return { preview, error: 'W0021', warningType: 'no-devextreme-license' };
8585
}
86-
if (license.error === 'trial-expired') {
87-
return { preview, error: 'W0020', warningType: 'trial-expired' };
88-
}
8986
return { preview, error: 'W0021', warningType: 'invalid-key' };
9087
}
9188

packages/devextreme/js/__internal/core/license/license_warnings.ts

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,6 @@ export const TEMPLATES = Object.freeze({
3939
switch (type) {
4040
case 'incompatibleVersion':
4141
return `Incompatible DevExpress license key version (v${keyVersion}). Download and register an updated DevExpress license key (v${requiredVersion}+). Clear npm/IDE/NuGet cache and rebuild your project (https://devexpress.com/DX1002).`;
42-
case 'trialExpired':
43-
return 'Your DevExpress trial period has expired. Purchase a license to continue using DevExpress product libraries.';
4442
default:
4543
return 'License key verification has failed.';
4644
}
@@ -108,12 +106,6 @@ export function logLicenseWarning(
108106
break;
109107
}
110108

111-
case 'trial-expired': {
112-
const expiredLine = `${T.warningPrefix('W0020')} ${T.keyVerificationFailed('trialExpired')}`;
113-
warnings.push([expiredLine]);
114-
break;
115-
}
116-
117109
case 'no-devextreme-license':
118110
// Only the purchase line, no additional details
119111
break;

packages/devextreme/js/__internal/core/license/types.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ export enum TokenKind {
1111

1212
export interface ErrorToken {
1313
readonly kind: TokenKind.corrupted;
14-
readonly error: 'general' | 'verification' | 'decoding' | 'deserialization' | 'payload' | 'version' | 'product-kind' | 'trial-expired';
14+
readonly error: 'general' | 'verification' | 'decoding' | 'deserialization' | 'payload' | 'version' | 'product-kind';
1515
}
1616

1717
export interface VerifiedToken {
@@ -30,15 +30,13 @@ export const DESERIALIZATION_ERROR: ErrorToken = { kind: TokenKind.corrupted, er
3030
export const PAYLOAD_ERROR: ErrorToken = { kind: TokenKind.corrupted, error: 'payload' };
3131
export const VERSION_ERROR: ErrorToken = { kind: TokenKind.corrupted, error: 'version' };
3232
export const PRODUCT_KIND_ERROR: ErrorToken = { kind: TokenKind.corrupted, error: 'product-kind' };
33-
export const TRIAL_EXPIRED_ERROR: ErrorToken = { kind: TokenKind.corrupted, error: 'trial-expired' };
3433

3534
export type LicenseWarningType = 'no-key'
3635
| 'invalid-key'
3736
| 'lcx-used'
3837
| 'old-devextreme-key'
3938
| 'version-mismatch'
40-
| 'no-devextreme-license'
41-
| 'trial-expired';
39+
| 'no-devextreme-license';
4240

4341
export interface LicenseCheckParams {
4442
preview: boolean;

packages/devextreme/license/devextreme-license.js

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -220,12 +220,7 @@ function main() {
220220
lines.push(
221221
TEMPLATES.keyVerificationFailed(warning.type, warning.keyVersion, warning.currentVersion),
222222
);
223-
224-
if(warning.type === 'trialExpired') {
225-
lines.push(prefixed(`${TEMPLATES.warningPrefix(code)} ${TEMPLATES.purchaseLicense}`));
226-
} else {
227-
lines.push(prefixed(`${TEMPLATES.warningPrefix(code)} ${TEMPLATES.installationInstructions}`));
228-
}
223+
lines.push(prefixed(`${TEMPLATES.warningPrefix(code)} ${TEMPLATES.installationInstructions}`));
229224
}
230225
}
231226

packages/devextreme/license/dx-lcx-2-lcp.js

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,6 @@ const TokenKind = Object.freeze({
141141
const GENERAL_ERROR = { kind: TokenKind.corrupted, error: 'general' };
142142
const DESERIALIZATION_ERROR = { kind: TokenKind.corrupted, error: 'deserialization' };
143143
const PRODUCT_KIND_ERROR = { kind: TokenKind.corrupted, error: 'product-kind' };
144-
const TRIAL_EXPIRED_ERROR = { kind: TokenKind.corrupted, error: 'trial-expired' };
145144

146145
function readDevExtremeVersion() {
147146
try {
@@ -219,12 +218,6 @@ function parseLCP(lcpString) {
219218
}
220219

221220
const maxVersionAllowed = findLatestDevExtremeVersion(products);
222-
if(!maxVersionAllowed) {
223-
const maxExpiration = getMaxExpiration(products);
224-
if(maxExpiration !== Infinity && maxExpiration < Date.now()) {
225-
return { ...TRIAL_EXPIRED_ERROR, licenseId };
226-
}
227-
}
228221

229222
if(!maxVersionAllowed) {
230223
return { ...PRODUCT_KIND_ERROR, licenseId };
@@ -261,9 +254,6 @@ function getLCPInfo(lcpString) {
261254
case 'product-kind':
262255
warning = { type: 'trial' };
263256
break;
264-
case 'trial-expired':
265-
warning = { type: 'trialExpired' };
266-
break;
267257
}
268258
} else {
269259
licenseId = token.payload.licenseId || null;

packages/devextreme/license/messages.js

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ const KEY_SOURCES = Object.freeze({
3434
const WARNING_CODES = Object.freeze({
3535
general: 1001,
3636
incompatibleVersion: 1002,
37-
trialExpired: 1003,
3837
});
3938

4039
const TEMPLATES = Object.freeze({
@@ -56,12 +55,6 @@ const TEMPLATES = Object.freeze({
5655
'Clear npm/IDE/NuGet cache and rebuild your project (https://devexpress.com/DX1002).',
5756
].join(' ');
5857
}
59-
if(type === 'trialExpired') {
60-
return [
61-
'Your DevExpress trial period has expired.',
62-
'Purchase a license to continue using DevExpress product libraries.',
63-
].join(' ');
64-
}
6558
return 'License key verification has failed.';
6659
},
6760

Lines changed: 81 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import $ from 'jquery';
22
import MenuBase from 'ui/context_menu/ui.menu_base';
33

4+
import 'fluent_blue_light.css!';
5+
46
QUnit.testStart(function() {
57
const markup =
68
'<div id="menu"></div>';
@@ -9,13 +11,13 @@ QUnit.testStart(function() {
911
});
1012

1113
const DX_MENU_BASE_CLASS = 'dx-menu-base';
12-
14+
const DX_MENU_ITEM_CLASS = 'dx-menu-item';
1315

1416
function createMenu(options) {
1517
const element = $('#menu');
1618
const instance = new MenuBase(element, options);
1719

18-
return { instance: instance, element: element };
20+
return { instance, element };
1921
}
2022

2123
QUnit.module('Menu markup', () => {
@@ -24,5 +26,81 @@ QUnit.module('Menu markup', () => {
2426

2527
assert.ok(menuBase.element.hasClass(DX_MENU_BASE_CLASS));
2628
});
27-
});
2829

30+
QUnit.module('Disabled item cursor style (T1327513)', () => {
31+
QUnit.test('enabled menu item should have pointer cursor', function(assert) {
32+
const menuBase = createMenu({
33+
items: [
34+
{ text: 'Item 1' },
35+
{ text: 'Item 2', disabled: true },
36+
],
37+
});
38+
39+
const $enabledItem = menuBase.element.find(`.${DX_MENU_ITEM_CLASS}`).eq(0);
40+
const cursor = $enabledItem.css('cursor');
41+
42+
assert.strictEqual(cursor, 'pointer', 'enabled item has pointer cursor');
43+
});
44+
45+
QUnit.test('disabled menu item should have default cursor', function(assert) {
46+
const menuBase = createMenu({
47+
items: [
48+
{ text: 'Item 1' },
49+
{ text: 'Item 2', disabled: true },
50+
],
51+
});
52+
53+
const $disabledItem = menuBase.element.find(`.${DX_MENU_ITEM_CLASS}`).eq(1);
54+
const cursor = $disabledItem.css('cursor');
55+
56+
assert.strictEqual(cursor, 'default', 'disabled item has default cursor');
57+
});
58+
59+
QUnit.test('item should have default cursor when disabled at runtime', function(assert) {
60+
const menuBase = createMenu({
61+
items: [
62+
{ text: 'Item 1', disabled: false },
63+
{ text: 'Item 2', disabled: false },
64+
],
65+
});
66+
67+
menuBase.instance.option('items[1].disabled', true);
68+
69+
const $disabledItem = menuBase.element.find(`.${DX_MENU_ITEM_CLASS}`).eq(1);
70+
const cursor = $disabledItem.css('cursor');
71+
72+
assert.strictEqual(cursor, 'default', 'item has default cursor after disabling at runtime');
73+
});
74+
75+
QUnit.test('items in disabled menu should have default cursor', function(assert) {
76+
const menuBase = createMenu({
77+
disabled: true,
78+
items: [
79+
{ text: 'Item 1' },
80+
{ text: 'Item 2' },
81+
],
82+
});
83+
const $item = menuBase.element.find(`.${DX_MENU_ITEM_CLASS}`).eq(0);
84+
const cursor = $item.css('cursor');
85+
assert.strictEqual(cursor, 'default', 'items in disabled menu have default cursor');
86+
});
87+
88+
QUnit.test('menu items with url should have correct cursor', function(assert) {
89+
const menuBase = createMenu({
90+
items: [
91+
{ text: 'Item 1', url: 'https://example.com' },
92+
{ text: 'Item 2', url: 'https://example.com/disabled', disabled: true },
93+
],
94+
});
95+
96+
const $enabledItem = menuBase.element.find(`.${DX_MENU_ITEM_CLASS}`).eq(0);
97+
const enabledItemCursor = $enabledItem.css('cursor');
98+
99+
const $disabledItem = menuBase.element.find(`.${DX_MENU_ITEM_CLASS}`).eq(1);
100+
const disabledItemCursor = $disabledItem.css('cursor');
101+
102+
assert.strictEqual(enabledItemCursor, 'pointer', 'enabled item with url has pointer cursor');
103+
assert.strictEqual(disabledItemCursor, 'default', 'disabled item with url has default cursor');
104+
});
105+
});
106+
});

0 commit comments

Comments
 (0)