diff --git a/CHANGELOG.md b/CHANGELOG.md index 5591a712e..469444ec8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,73 @@ +## [7.0.0](https://github.com/jwplayer/ott-web-app/compare/v5.1.1...v7.0.0) (2024-04-03) + + +### ⚠ BREAKING CHANGES + +* **project:** restructure for multiplatforms with workspaces (#435) + +### Features + +* **a11y:** many accessibility optimisations ([cc02259](https://github.com/jwplayer/ott-web-app/commit/cc02259ddb8faeed27813ddce850b5653fe1d0d3)), closes [#48](https://github.com/jwplayer/ott-web-app/issues/48) [#47](https://github.com/jwplayer/ott-web-app/issues/47) [#46](https://github.com/jwplayer/ott-web-app/issues/46) +* **a11y:** update font colors for contrast and adjust active state in header ([#76](https://github.com/jwplayer/ott-web-app/issues/76)) ([6444282](https://github.com/jwplayer/ott-web-app/commit/6444282c6c2adedb93980904ba968c8d5bf2680d)) +* accessibility improvements and bug fixes ([82b5967](https://github.com/jwplayer/ott-web-app/commit/82b5967dcf9415aba21e8f6c7bdaabd57f1589af)), closes [#127](https://github.com/jwplayer/ott-web-app/issues/127) [#109](https://github.com/jwplayer/ott-web-app/issues/109) [#115](https://github.com/jwplayer/ott-web-app/issues/115) [#117](https://github.com/jwplayer/ott-web-app/issues/117) [#116](https://github.com/jwplayer/ott-web-app/issues/116) [#121](https://github.com/jwplayer/ott-web-app/issues/121) [#125](https://github.com/jwplayer/ott-web-app/issues/125) +* **payment:** disable deprecated receipts cleeng ([#458](https://github.com/jwplayer/ott-web-app/issues/458)) ([d37905d](https://github.com/jwplayer/ott-web-app/commit/d37905df4022103e3fdf62ad936d58af6e12617c)) +* **project:** add app content search ([71433ab](https://github.com/jwplayer/ott-web-app/commit/71433abfca80431243effc246afdbe8c6901521e)) +* **project:** customizable footer through env-var ([9d8ff15](https://github.com/jwplayer/ott-web-app/commit/9d8ff150dc298880bd4cdc1323a4fc68f8d0fcba)) +* **project:** dynamic gtm snippet ([6babace](https://github.com/jwplayer/ott-web-app/commit/6babacefc3ae56191625207436fc6faaaca10445)) +* **project:** favicons in different sizes ([a1c6188](https://github.com/jwplayer/ott-web-app/commit/a1c6188ae0e6b634977d9ac0642bad437a31df3b)) +* **project:** reload site on update ([d4c851b](https://github.com/jwplayer/ott-web-app/commit/d4c851bdccc155b4953c9948ffdab86c2bfacc5e)) +* **project:** restructure for multiplatforms with workspaces ([#435](https://github.com/jwplayer/ott-web-app/issues/435)) ([3e3e2b1](https://github.com/jwplayer/ott-web-app/commit/3e3e2b14c4926e596fad46c2ea7cc99dbced05f0)), closes [#8](https://github.com/jwplayer/ott-web-app/issues/8) +* **project:** update default content-type schemas ([0a9817a](https://github.com/jwplayer/ott-web-app/commit/0a9817a9b6f5bbfaae5ce5967bbf3c16436d2f15)) +* **project:** update translations ([a34f686](https://github.com/jwplayer/ott-web-app/commit/a34f6863480b075d82c80a062833899fd26bbdc5)) +* underline for active header item and add lineair gradient ([1d2f25f](https://github.com/jwplayer/ott-web-app/commit/1d2f25f04dc06463a0a37aa4c6fddabab455cdcf)) +* **watchhistory:** change max items limit ([#418](https://github.com/jwplayer/ott-web-app/issues/418)) ([d7db57a](https://github.com/jwplayer/ott-web-app/commit/d7db57ab330630c270412ca8fa39ea94052d7675)) + + +### Bug Fixes + +* **a11y:** close search bar when pressing escape ([7a14497](https://github.com/jwplayer/ott-web-app/commit/7a14497224bc8d159bda1ac3238cc0eb566b5437)) +* **a11y:** constrast enhancement for search field ([b4c3230](https://github.com/jwplayer/ott-web-app/commit/b4c323026bc713519fcd6e1ac8efbb68dc8f8fff)) +* **a11y:** focus lost when submitting a form ([9001a21](https://github.com/jwplayer/ott-web-app/commit/9001a21c9a4b0bd35db6c182e2f46b4480983dc8)) +* **a11y:** format date call caused an error to be raised ([aef1415](https://github.com/jwplayer/ott-web-app/commit/aef1415229901704af0e15b57fd3a0d42040cbe7)) +* **a11y:** prevent duplicate global a11y selectors ([b3ccaff](https://github.com/jwplayer/ott-web-app/commit/b3ccaffe4ea1249d7ad5a80cfe6e8e20a94ef3b7)) +* **a11y:** remove outline when user is not tabbing ([5fe1665](https://github.com/jwplayer/ott-web-app/commit/5fe1665ad30e08dd7eed234c93243da7df748cce)) +* **a11y:** shelf item navigation with screen reader ([91dc66c](https://github.com/jwplayer/ott-web-app/commit/91dc66cd6b6bdbae3b48c0454fe1da335acc9f91)) +* **account:** delete account error ([a2885eb](https://github.com/jwplayer/ott-web-app/commit/a2885eb34598b413e4b81f9cdbb542bbbd849a64)) +* **auth:** capture error to prevent misleading “wrong combination” error ([588f69a](https://github.com/jwplayer/ott-web-app/commit/588f69ac9034736ddf7804bbebaddb141fe30860)) +* click not working in layout grid ([2ded57b](https://github.com/jwplayer/ott-web-app/commit/2ded57b41bbac7a08f5c1d0eeccb149fdcde3242)) +* e2e test optimisations and small fixes ([b700fbb](https://github.com/jwplayer/ott-web-app/commit/b700fbb7ea31cde67740bab99246a0b705058c55)) +* e2e tests for a11y ([c4d09c5](https://github.com/jwplayer/ott-web-app/commit/c4d09c52494b20e0d8e31fb4595f898729817255)) +* enter key not closing the account modal ([1791b4c](https://github.com/jwplayer/ott-web-app/commit/1791b4ca91e161250e354ae96e1d32f0b7bf30c9)) +* favorites and history validation error ([3deabfc](https://github.com/jwplayer/ott-web-app/commit/3deabfc766a75c12ab122a775376449e316ff232)) +* footer overlap fix ([bf79d10](https://github.com/jwplayer/ott-web-app/commit/bf79d108356418c80cfe7a9ddc2496977ae9bb17)) +* hide start watching button in avod platform ([86b461f](https://github.com/jwplayer/ott-web-app/commit/86b461fc9df4b92401055b8c56d8e9d5aec13c99)) +* **i18n:** add missing translations ([961bcd1](https://github.com/jwplayer/ott-web-app/commit/961bcd140b68c2eb8e128b898c23caa8ddcfd744)) +* language menu icon not centered ([ddcfc91](https://github.com/jwplayer/ott-web-app/commit/ddcfc91973548d6cdacc084dd6b88bb3453c6d36)) +* layout grid arrow down and end problem ([6a291a7](https://github.com/jwplayer/ott-web-app/commit/6a291a77f51626c46c082f268f454ff00cde9310)) +* layout grid home and page down problem ([a6305ef](https://github.com/jwplayer/ott-web-app/commit/a6305efbe94b0261786a2adcb76a6530aff3e4cc)) +* logo and header layout issues ([a0cca10](https://github.com/jwplayer/ott-web-app/commit/a0cca10419b9a74b4761d5701e242db2c4e8d562)) +* **menu:** ensure logo does not exceed width of the header ([ea4af42](https://github.com/jwplayer/ott-web-app/commit/ea4af42e23ddefce292a0784c8a0db9b98e4895d)) +* **payment:** incorrect couponCode success message ([c97c59b](https://github.com/jwplayer/ott-web-app/commit/c97c59b7268d540ee37cdb0bb41beb72d8946a7e)) +* **payment:** missing feedback when submitting coupon ([5097e60](https://github.com/jwplayer/ott-web-app/commit/5097e607090bcdf098335dd39a6aa6ef82250ad7)) +* **payment:** redirect after incorrect couponcode entry ([ca71f29](https://github.com/jwplayer/ott-web-app/commit/ca71f29298ea6c4af2f5c2b6c4f6379d68385df0)) +* **payment:** subscription offer panel shown for authvod+tvod ([d63b056](https://github.com/jwplayer/ott-web-app/commit/d63b0562e74c624bae0690048467442595928fe2)) +* **payment:** tvod offer not showing in AuthVOD platform ([d01d1b7](https://github.com/jwplayer/ott-web-app/commit/d01d1b71aba628feeb4510cb9b0b9d4132af3cb7)) +* personal shelves restoration ([2741eac](https://github.com/jwplayer/ott-web-app/commit/2741eac5331657ed6156a9e5fba1906c8623227b)) +* **player:** inlineplayer not supporting tvod ([bb593e9](https://github.com/jwplayer/ott-web-app/commit/bb593e97ce2635d9c33c1d027da51075509a7462)) +* **project:** ensure modals obscure underlying elements ([f52a0f3](https://github.com/jwplayer/ott-web-app/commit/f52a0f3377ed1c0d22e47f27995c597d7ec71e55)) +* **project:** fix es translations ([b80ab06](https://github.com/jwplayer/ott-web-app/commit/b80ab0682fbde1c9f85f7ddacfbf22b433a38cfb)) +* **project:** fix live stream duration check for ott plugin ([#460](https://github.com/jwplayer/ott-web-app/issues/460)) ([69eff3c](https://github.com/jwplayer/ott-web-app/commit/69eff3c1e9763d2b80e1669809323ee9c1de5f63)) +* **project:** show footer when custom footer is provided ([6503267](https://github.com/jwplayer/ott-web-app/commit/65032674e0ca75e129e5d6fca35e54fc6b690f3d)) +* **project:** undouble serieIds to prevent crash ([ca3d38e](https://github.com/jwplayer/ott-web-app/commit/ca3d38e2ad82235a84cb658da0174095c2eed10e)) +* **project:** unused dep ([72325a6](https://github.com/jwplayer/ott-web-app/commit/72325a63d43ca19f43b9ac1d76a024037889aab0)) +* related videos title layout issue ([361c58a](https://github.com/jwplayer/ott-web-app/commit/361c58a53cb6ae56b84cb6751c7b4ad3d64c702b)) +* restore personal shelves after registration ([3fdb220](https://github.com/jwplayer/ott-web-app/commit/3fdb220ef988383e6af80b72efb7c7d27e6bccb7)) +* root error screen for unexpected errors ([320fe44](https://github.com/jwplayer/ott-web-app/commit/320fe4402f7338816825471de52c21aedb95a144)) +* set wrong loading state in early return ([0837944](https://github.com/jwplayer/ott-web-app/commit/0837944dc4d022ecfe95d6e3f30959d943be9e99)) +* update order error handling ([bf3e5b5](https://github.com/jwplayer/ott-web-app/commit/bf3e5b575624580a38301968a63023748bd9a6df)) +* **user:** redirect when no integration is configured ([88ce77c](https://github.com/jwplayer/ott-web-app/commit/88ce77c587883117eb6af4dec40481ddcbfe01b2)) +* **user:** tvod subscription not reloaded after login for authvod/avod ([7de84ae](https://github.com/jwplayer/ott-web-app/commit/7de84ae37f174c04bdea26af1818721dfe9956d8)) + ## [6.0.0](https://github.com/jwplayer/ott-web-app/compare/v5.1.1...v6.0.0) (2024-03-25) diff --git a/package.json b/package.json index 6792857f4..692cef5b7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@jwp/ott", - "version": "6.0.0", + "version": "7.0.0", "private": true, "license": "Apache-2.0", "repository": "https://github.com/jwplayer/ott-web-app.git", diff --git a/packages/common/src/controllers/CheckoutController.ts b/packages/common/src/controllers/CheckoutController.ts index 63362677e..ffe195d50 100644 --- a/packages/common/src/controllers/CheckoutController.ts +++ b/packages/common/src/controllers/CheckoutController.ts @@ -91,32 +91,22 @@ export default class CheckoutController { }; updateOrder = async (order: Order, paymentMethodId?: number, couponCode?: string | null): Promise => { - let response; - try { - response = await this.checkoutService.updateOrder({ order, paymentMethodId, couponCode }); - } catch (error: unknown) { - // TODO: we currently (falsely) assume that the only error caught is because the coupon is not valid, but there - // could be a network failure as well (JWPCheckoutService) - throw new FormValidationError({ couponCode: [i18next.t('account:checkout.coupon_not_valid')] }); - } + const response = await this.checkoutService.updateOrder({ order, paymentMethodId, couponCode }); - if (response.errors.length > 0) { - // clear the order when the order doesn't exist on the server - if (response.errors[0].includes(`Order with ${order.id} not found`)) { - useCheckoutStore.getState().setOrder(null); + if (response.responseData.order) { + useCheckoutStore.getState().setOrder(response.responseData?.order); } - - // TODO: this handles the `Coupon ${couponCode} not found` message (CleengCheckoutService) - if (response.errors[0].includes(`not found`)) { - throw new FormValidationError({ couponCode: [i18next.t('account:checkout.coupon_not_valid')] }); + } catch (error: unknown) { + if (error instanceof Error) { + if (error.message === 'Order not found') { + useCheckoutStore.getState().setOrder(null); + } else if (error.message === 'Invalid coupon code') { + throw new FormValidationError({ couponCode: [i18next.t('account:checkout.coupon_not_valid')] }); + } } - throw new FormValidationError({ form: response.errors }); - } - - if (response.responseData.order) { - useCheckoutStore.getState().setOrder(response.responseData?.order); + throw new FormValidationError({ form: [i18next.t('error:unknown_error')] }); } }; diff --git a/packages/common/src/services/integrations/cleeng/CleengCheckoutService.ts b/packages/common/src/services/integrations/cleeng/CleengCheckoutService.ts index c0dcd4e9c..1dc3bce05 100644 --- a/packages/common/src/services/integrations/cleeng/CleengCheckoutService.ts +++ b/packages/common/src/services/integrations/cleeng/CleengCheckoutService.ts @@ -20,11 +20,13 @@ import type { PaymentWithPayPal, SwitchSubscription, UpdateOrder, + UpdateOrderResponse, UpdatePaymentWithPayPal, } from '../../../../types/checkout'; import CheckoutService from '../CheckoutService'; import { GET_CUSTOMER_IP } from '../../../modules/types'; import type { GetCustomerIP } from '../../../../types/get-customer-ip'; +import type { ServiceResponse } from '../../../../types/service'; import CleengService from './CleengService'; @@ -83,7 +85,21 @@ export default class CleengCheckoutService extends CheckoutService { }; updateOrder: UpdateOrder = async ({ order, ...payload }) => { - return this.cleengService.patch(`/orders/${order.id}`, JSON.stringify(payload), { authenticate: true }); + const response = await this.cleengService.patch>(`/orders/${order.id}`, JSON.stringify(payload), { + authenticate: true, + }); + + if (response.errors.length) { + if (response.errors[0].includes(`Order with ${order.id} not found`)) { + throw new Error('Order not found'); + } + + if (response.errors[0].includes(`Coupon ${payload.couponCode} not found`)) { + throw new Error('Invalid coupon code'); + } + } + + return response; }; getPaymentMethods: GetPaymentMethods = async () => { diff --git a/packages/common/src/services/integrations/cleeng/CleengService.ts b/packages/common/src/services/integrations/cleeng/CleengService.ts index 34d0ba298..7b724353d 100644 --- a/packages/common/src/services/integrations/cleeng/CleengService.ts +++ b/packages/common/src/services/integrations/cleeng/CleengService.ts @@ -193,7 +193,7 @@ export default class CleengService { return await resp.json(); } catch (error: unknown) { return { - errors: Array.of(error as string), + errors: Array.of(error instanceof Error ? error.message : String(error)), }; } }; diff --git a/packages/common/src/services/integrations/jwp/JWPCheckoutService.ts b/packages/common/src/services/integrations/jwp/JWPCheckoutService.ts index 006071ce1..678c50cd5 100644 --- a/packages/common/src/services/integrations/jwp/JWPCheckoutService.ts +++ b/packages/common/src/services/integrations/jwp/JWPCheckoutService.ts @@ -21,6 +21,7 @@ import type { } from '../../../../types/checkout'; import CheckoutService from '../CheckoutService'; import type { ServiceResponse } from '../../../../types/service'; +import { isCommonError } from '../../../utils/api'; @injectable() export default class JWPCheckoutService extends CheckoutService { @@ -71,6 +72,7 @@ export default class JWPCheckoutService extends CheckoutService { totalPrice: payload.offer.customerPriceInclTax, priceBreakdown: { offerPrice: payload.offer.customerPriceInclTax, + // @TODO is this correct? discountAmount: payload.offer.customerPriceInclTax, discountedPrice: payload.offer.customerPriceInclTax, paymentMethodFee: 0, @@ -179,26 +181,37 @@ export default class JWPCheckoutService extends CheckoutService { voucherCode: `${couponCode}`, accessFeeId: order.id, }); - order.discount = { - applied: true, - type: 'coupon', - periods: response.data.discount_duration, + + const discountAmount = order.totalPrice - response.data.amount; + const updatedOrder: Order = { + ...order, + totalPrice: response.data.amount, + priceBreakdown: { + ...order.priceBreakdown, + discountAmount, + discountedPrice: discountAmount, + }, + discount: { + applied: true, + type: 'coupon', + periods: response.data.discount_duration, + }, }; - const discountedAmount = order.totalPrice - response.data.amount; - order.totalPrice = response.data.amount; - order.priceBreakdown.discountAmount = discountedAmount; - order.priceBreakdown.discountedPrice = discountedAmount; return { errors: [], responseData: { message: 'successfully updated', - order: order, + order: updatedOrder, success: true, }, }; - } catch { - throw new Error('Invalid coupon code'); + } catch (error: unknown) { + if (isCommonError(error) && error.response.data.message === 'Voucher not found') { + throw new Error('Invalid coupon code'); + } + + throw new Error('An unknown error occurred'); } }; diff --git a/packages/common/src/stores/AccountStore.ts b/packages/common/src/stores/AccountStore.ts index 3521537a7..ad7aa3a39 100644 --- a/packages/common/src/stores/AccountStore.ts +++ b/packages/common/src/stores/AccountStore.ts @@ -19,7 +19,7 @@ type AccountStore = { }; export const useAccountStore = createStore('AccountStore', (set, get) => ({ - loading: true, + loading: false, user: null, subscription: null, transactions: null, diff --git a/packages/ui-react/src/components/Button/Button.tsx b/packages/ui-react/src/components/Button/Button.tsx index 32067f2d8..0961aacc0 100644 --- a/packages/ui-react/src/components/Button/Button.tsx +++ b/packages/ui-react/src/components/Button/Button.tsx @@ -79,7 +79,7 @@ const Button: React.FC = ({ } return ( - ); diff --git a/packages/ui-react/src/components/CheckoutForm/CheckoutForm.tsx b/packages/ui-react/src/components/CheckoutForm/CheckoutForm.tsx index a4733cf33..7213eee16 100644 --- a/packages/ui-react/src/components/CheckoutForm/CheckoutForm.tsx +++ b/packages/ui-react/src/components/CheckoutForm/CheckoutForm.tsx @@ -25,6 +25,7 @@ type Props = { onCouponInputChange: React.ChangeEventHandler; onRedeemCouponButtonClick: () => void; onCloseCouponFormClick: () => void; + error?: string; couponFormOpen: boolean; couponFormError?: string; couponFormApplied?: boolean; @@ -45,6 +46,7 @@ const CheckoutForm: React.FC = ({ offerType, onBackButtonClick, onPaymentMethodChange, + error, couponFormOpen, couponInputValue, couponFormError, @@ -89,6 +91,7 @@ const CheckoutForm: React.FC = ({ const orderTitle = offerType === 'svod' ? (offer.period === 'month' ? t('checkout.monthly') : t('checkout.yearly')) : offer.offerTitle; return (
+ {error ? {error} : null}

{t('checkout.payment_method')}

diff --git a/packages/ui-react/src/components/LoginForm/LoginForm.test.tsx b/packages/ui-react/src/components/LoginForm/LoginForm.test.tsx index 8fd51f217..d6cda2224 100644 --- a/packages/ui-react/src/components/LoginForm/LoginForm.test.tsx +++ b/packages/ui-react/src/components/LoginForm/LoginForm.test.tsx @@ -116,7 +116,7 @@ describe('', () => { await waitForWithFakeTimers(); - expect(getByRole('button', { name: 'login.sign_in' })).toBeDisabled(); + expect(getByRole('button', { name: 'login.sign_in' })).toHaveAttribute('aria-disabled', 'true'); }); test('calls the onSubmit callback when the form gets submitted', async () => { diff --git a/packages/ui-react/src/containers/AccountModal/forms/Checkout.tsx b/packages/ui-react/src/containers/AccountModal/forms/Checkout.tsx index df73a5cba..825da6582 100644 --- a/packages/ui-react/src/containers/AccountModal/forms/Checkout.tsx +++ b/packages/ui-react/src/containers/AccountModal/forms/Checkout.tsx @@ -53,10 +53,10 @@ const Checkout = () => { handleSubmit, } = useForm({ initialValues: { couponCode: '', paymentMethodId: paymentMethods?.[0]?.id?.toString() || '' }, - onSubmit: async ({ couponCode, paymentMethodId }) => { + onSubmit: ({ couponCode, paymentMethodId }) => { setShowCouponCodeSuccess(false); - return await updateOrder.mutateAsync({ couponCode, paymentMethodId: parseInt(paymentMethodId) }); + return updateOrder.mutateAsync({ couponCode, paymentMethodId: parseInt(paymentMethodId) }); }, onSubmitSuccess: ({ couponCode }): void => setShowCouponCodeSuccess(!!couponCode), onSubmitError: ({ error }) => { @@ -117,6 +117,7 @@ const Checkout = () => { order={order} offer={selectedOffer} offerType={offerType} + error={errors.form} onBackButtonClick={backButtonClickHandler} paymentMethods={paymentMethods} paymentMethodId={paymentMethodId} diff --git a/platforms/web/public/locales/en/account.json b/platforms/web/public/locales/en/account.json index 7e2d7e611..e01a545ed 100644 --- a/platforms/web/public/locales/en/account.json +++ b/platforms/web/public/locales/en/account.json @@ -148,7 +148,7 @@ "password_helper_text": "Use a minimum of 8 characters (case sensitive) with at least one number", "password_strength": { "fair": "Fair", - "invalid": "Invalid", + "invalid": "", "strong": "Strong", "very_strong": "Very strong", "weak": "Weak" diff --git a/platforms/web/public/locales/es/account.json b/platforms/web/public/locales/es/account.json index 4c0c356e3..7f685fb42 100644 --- a/platforms/web/public/locales/es/account.json +++ b/platforms/web/public/locales/es/account.json @@ -18,8 +18,10 @@ "credit_card": "Tarjeta de crédito", "credit_card_name": "Nombre de la tarjeta de crédito", "days_trial_one": "Se te cobrará mañana.", + "days_trial_many": "Se te cobrará después de {{count}} días.", "days_trial_other": "Se te cobrará después de {{count}} días.", "discount_period_one": "Durante el primer {{period}}", + "discount_period_many": "Durante los primeros {{count}} {{period}}", "discount_period_other": "Durante los primeros {{count}} {{period}}", "free_trial_discount": "Prueba gratuita", "go_back_to_checkout": "Volver a la página de pago", @@ -37,6 +39,7 @@ "paypal": "PayPal", "paypal_instructions": "Al hacer clic en 'Continuar', serás redirigido al sitio de PayPal.", "periods_trial_one": "Se te cobrará después de un {{period}}.", + "periods_trial_many": "Se te cobrará después de {{count}} {{period}}.", "periods_trial_other": "Se te cobrará después de {{count}} {{period}}.", "redeem_coupon": "Canjear cupón", "save": "Guardar", @@ -57,8 +60,10 @@ "benefits": { "cancel_anytime": "Cancele en cualquier momento", "first_days_free_one": "Primer día gratis", + "first_days_free_many": "Primeros {{count}} días gratis", "first_days_free_other": "Primeros {{count}} días gratis", "first_periods_free_one": "Primer {{period}} gratis", + "first_periods_free_many": "Primeros {{count}} {{period}} gratis", "first_periods_free_other": "Primeros {{count}} {{period}} gratis", "watch_on_all_devices": "Ver en todos los dispositivos" }, @@ -71,6 +76,7 @@ "subscription": "Suscripción", "title": "Elige un plan", "tvod_access_one": "Acceso de {{count}} {{period}}", + "tvod_access_many": "Acceso de {{count}} {{period}}", "tvod_access_other": "Acceso de {{count}} {{period}}", "watch_this_on_platform": "Ver esto en {{siteName}}", "yearly": "Anual", @@ -106,14 +112,18 @@ }, "periods": { "day_one": "día", + "day_many": "días", "day_other": "días", "month": "mensual", "month_one": "mes", + "month_many": "meses", "month_other": "meses", "week_one": "semana", + "week_many": "semanas", "week_other": "semanas", "year": "anual", "year_one": "año", + "year_many": "años", "year_other": "años" }, "personal_details": { @@ -148,7 +158,7 @@ "password_helper_text": "Utiliza un mínimo de 8 caracteres (distingue entre mayúsculas y minúsculas) con al menos un número", "password_strength": { "fair": "Regular", - "invalid": "Invalida", + "invalid": "", "strong": "Fuerte", "very_strong": "Muy fuerte", "weak": "Débil" diff --git a/platforms/web/public/locales/es/search.json b/platforms/web/public/locales/es/search.json index 5d9b5d23f..897d6bbd9 100644 --- a/platforms/web/public/locales/es/search.json +++ b/platforms/web/public/locales/es/search.json @@ -15,5 +15,6 @@ "tip_two": "Hacer términos de búsqueda más generales", "tip_three": "Prueba con diferentes términos de búsqueda", "title_one": "{{count}} resultado para \"{{query}}\"", + "title_many": "{{count}} resultados para \"{{query}}\"", "title_other": "{{count}} resultados para \"{{query}}\"" } diff --git a/platforms/web/public/locales/es/user.json b/platforms/web/public/locales/es/user.json index 66d0eff36..66331fb65 100644 --- a/platforms/web/public/locales/es/user.json +++ b/platforms/web/public/locales/es/user.json @@ -104,6 +104,7 @@ "expiry_date": "Fecha de vencimiento", "granted_subscription": "Suscripción otorgada", "hidden_transactions_one": "Una transacción más", + "hidden_transactions_many": "{{count}} transacciones más", "hidden_transactions_other": "{{count}} transacciones más", "longer_than_usual": "El pago está tardando más de lo habitual. Por favor, inténtelo de nuevo más tarde.", "monthly_subscription": "Suscripción mensual", diff --git a/platforms/web/public/locales/es/video.json b/platforms/web/public/locales/es/video.json index 26dc52abc..2f555c9fc 100644 --- a/platforms/web/public/locales/es/video.json +++ b/platforms/web/public/locales/es/video.json @@ -25,6 +25,7 @@ "sign_up_to_start_watching": "¡Regístrate para comenzar a ver!", "start_watching": "Comenzar a ver", "total_episodes_one": "{{count}} episodio", + "total_episodes_many": "{{count}} episodios", "total_episodes_other": "{{count}} episodios", "trailer": "Tráiler", "watch_trailer": "Ver el tráiler" diff --git a/platforms/web/src/index.tsx b/platforms/web/src/index.tsx index cd59da4f7..b3f8c289d 100644 --- a/platforms/web/src/index.tsx +++ b/platforms/web/src/index.tsx @@ -36,4 +36,7 @@ if (rootElement) { console.info('Application - rootElement not found'); } -registerSW(); +const refresh = registerSW({ + immediate: true, + onNeedRefresh: () => refresh(true), +}); diff --git a/platforms/web/test-e2e/tests/live_channel_test.ts b/platforms/web/test-e2e/tests/live_channel_test.ts index 660839599..d83b4ef4a 100644 --- a/platforms/web/test-e2e/tests/live_channel_test.ts +++ b/platforms/web/test-e2e/tests/live_channel_test.ts @@ -148,7 +148,7 @@ Scenario('I can select an upcoming program on the same channel', async ({ I }) = I.dontSee('LIVE', locate('div').inside(videoDetailsLocator)); I.see('On Channel 1', locate('div').inside(videoDetailsLocator)); - I.seeElement(locate('button[disabled]').withText('Start watching')); + I.seeElement(locate('button[aria-disabled]').withText('Start watching')); I.seeElement(channel1LiveProgramLocator); await isLiveProgram(I, channel1LiveProgramLocator, 'channel 1'); diff --git a/platforms/web/vite.config.ts b/platforms/web/vite.config.ts index d979d8032..366269e49 100644 --- a/platforms/web/vite.config.ts +++ b/platforms/web/vite.config.ts @@ -59,6 +59,7 @@ export default ({ mode, command }: ConfigEnv): UserConfigExport => { StylelintPlugin(), svgr(), VitePWA({ + registerType: 'autoUpdate', manifestFilename: 'manifest.json', manifest: { name: app.name,