Skip to content

Commit

Permalink
Merge branch 'release-candidate' into release
Browse files Browse the repository at this point in the history
  • Loading branch information
AntonLantukh committed Sep 6, 2024
2 parents a5b699f + 33ce641 commit f71a0d7
Show file tree
Hide file tree
Showing 42 changed files with 302 additions and 181 deletions.
16 changes: 16 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
## [6.6.0](https://github.com/jwplayer/ott-web-app/compare/v6.5.0...v6.6.0) (2024-09-06)


### Features

* **project:** add injectable wrapper to common components ([#598](https://github.com/jwplayer/ott-web-app/issues/598)) ([a6ad0d8](https://github.com/jwplayer/ott-web-app/commit/a6ad0d88b0e7cdc36548867870c8eb3c014f1ad2))
* **project:** app metadata insertion ([3753a9c](https://github.com/jwplayer/ott-web-app/commit/3753a9c352289620af6ec597fb5f474d7b8ac6d4))
* **project:** remove free and productIds from content-types.json ([#605](https://github.com/jwplayer/ott-web-app/issues/605)) ([2268447](https://github.com/jwplayer/ott-web-app/commit/226844726061184252af24fabc8340e8539230b6))


### Bug Fixes

* **e2e:** fix tests after cleeng api update ([#606](https://github.com/jwplayer/ott-web-app/issues/606)) ([9062dba](https://github.com/jwplayer/ott-web-app/commit/9062dba9184561b5af399e25632f4fe132960223))
* **search:** override search query cache ([#594](https://github.com/jwplayer/ott-web-app/issues/594)) ([1c25ad2](https://github.com/jwplayer/ott-web-app/commit/1c25ad2cd2ecfc1d388e5f8094006f7d961c93a0))
* wrong protocol and url path ([#588](https://github.com/jwplayer/ott-web-app/issues/588)) ([de75eb7](https://github.com/jwplayer/ott-web-app/commit/de75eb7eaca51d4fef9be4a40f13d043437bf3f0))

## [6.5.0](https://github.com/jwplayer/ott-web-app/compare/v6.4.0...v6.5.0) (2024-07-25)


Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@jwp/ott",
"version": "6.5.0",
"version": "6.6.0",
"private": true,
"license": "Apache-2.0",
"repository": "https://github.com/jwplayer/ott-web-app.git",
Expand Down
3 changes: 2 additions & 1 deletion packages/common/src/controllers/CheckoutController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import { useCheckoutStore } from '../stores/CheckoutStore';
import { useAccountStore } from '../stores/AccountStore';
import { FormValidationError } from '../errors/FormValidationError';
import { determineSwitchDirection } from '../utils/subscription';
import { findDefaultCardMethodId } from '../utils/payments';

@injectable()
export default class CheckoutController {
Expand Down Expand Up @@ -70,7 +71,7 @@ export default class CheckoutController {
const { customer } = getAccountInfo();

const paymentMethods = await this.getPaymentMethods();
const paymentMethodId = paymentMethods[0]?.id;
const paymentMethodId = parseInt(findDefaultCardMethodId(paymentMethods));

const createOrderArgs: CreateOrderArgs = {
offer,
Expand Down
8 changes: 4 additions & 4 deletions packages/common/src/services/ApiService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,14 @@ export default class ApiService {
* We use playlistLabel prop to define the label used for all media items inside.
* That way we can change the behavior of the same media items being in different playlists
*/
private generateAlternateImageURL = ({ mediaId, label, playlistLabel }: { mediaId: string; label: string; playlistLabel?: string }) => {
protected generateAlternateImageURL = ({ mediaId, label, playlistLabel }: { mediaId: string; label: string; playlistLabel?: string }) => {
const pathname = `/v2/media/${mediaId}/images/${playlistLabel || label}.webp`;
const url = createURL(`${env.APP_API_BASE_URL}${pathname}`, { poster_fallback: 1, fallback: playlistLabel ? label : null });

return url;
};

private parseDate = (item: PlaylistItem, prop: string) => {
protected parseDate = (item: PlaylistItem, prop: string) => {
const date = item[prop] as string | undefined;

if (date && !isValid(new Date(date))) {
Expand All @@ -49,7 +49,7 @@ export default class ApiService {
/**
* Transform incoming content lists
*/
private transformContentList = (contentList: ContentList): Playlist => {
protected transformContentList = (contentList: ContentList): Playlist => {
const { list, ...rest } = contentList;

const playlist: Playlist = { ...rest, playlist: [] };
Expand Down Expand Up @@ -80,7 +80,7 @@ export default class ApiService {
/**
* Transform incoming playlists
*/
private transformPlaylist = (playlist: Playlist, relatedMediaId?: string) => {
protected transformPlaylist = (playlist: Playlist, relatedMediaId?: string) => {
playlist.playlist = playlist.playlist.map((item) => this.transformMediaItem(item, playlist));

// remove the related media item (when this is a recommendations playlist)
Expand Down
18 changes: 3 additions & 15 deletions packages/common/src/services/ConfigService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,16 @@ import { AppError } from '../utils/error';
import type { Config } from '../../types/config';
import env from '../env';

import ApiService from './ApiService';

/**
* Set config setup changes in both config.service.ts and config.d.ts
* */

@injectable()
export default class ConfigService {
private CONFIG_HOST = env.APP_API_BASE_URL;
protected CONFIG_HOST = env.APP_API_BASE_URL;
// Explicitly set default config here as a local variable,
// otherwise if it's a module level const, the merge below causes changes to nested properties
private DEFAULT_CONFIG: Config = {
protected DEFAULT_CONFIG: Config = {
id: '',
siteName: '',
description: '',
Expand All @@ -35,13 +33,7 @@ export default class ConfigService {
features: {},
};

private readonly apiService: ApiService;

constructor(apiService: ApiService) {
this.apiService = apiService;
}

private enrichConfig = (config: Config): Config => {
protected enrichConfig = (config: Config): Config => {
const { content, siteName } = config;
const updatedContent = content.map((content) => Object.assign({ featured: false }, content));

Expand Down Expand Up @@ -70,10 +62,6 @@ export default class ConfigService {
return source;
};

loadAdSchedule = async (adScheduleId: string | undefined | null) => {
return this.apiService.getAdSchedule(adScheduleId);
};

loadConfig = async (configLocation: string | undefined) => {
const i18n = getI18n();

Expand Down
20 changes: 12 additions & 8 deletions packages/common/src/services/FavoriteService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,31 +23,35 @@ const schema = array(
export default class FavoriteService {
private PERSIST_KEY_FAVORITES = 'favorites';

private readonly apiService;
private readonly storageService;
private readonly accountService;

constructor(@inject(INTEGRATION_TYPE) integrationType: string, apiService: ApiService, storageService: StorageService) {
protected readonly apiService;
protected readonly storageService;
protected readonly accountService;

constructor(
@inject(INTEGRATION_TYPE) integrationType: string,
@inject(ApiService) apiService: ApiService,
@inject(StorageService) storageService: StorageService,
) {
this.apiService = apiService;
this.storageService = storageService;
this.accountService = getNamedModule(AccountService, integrationType, false);
}

private validateFavorites(favorites: unknown) {
protected validateFavorites(favorites: unknown) {
if (favorites && schema.validateSync(favorites)) {
return favorites as SerializedFavorite[];
}

return [];
}

private async getFavoritesFromAccount(user: Customer) {
protected async getFavoritesFromAccount(user: Customer) {
const favorites = await this.accountService?.getFavorites({ user });

return this.validateFavorites(favorites);
}

private async getFavoritesFromStorage() {
protected async getFavoritesFromStorage() {
const favorites = await this.storageService.getItem(this.PERSIST_KEY_FAVORITES, true);

return this.validateFavorites(favorites);
Expand Down
2 changes: 1 addition & 1 deletion packages/common/src/services/GenericEntitlementService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import type { GetTokenResponse } from '../../types/entitlement';

@injectable()
export default class GenericEntitlementService {
private getToken = async <T>(url: string, body: unknown = {}, jwt?: string): Promise<T> => {
protected getToken = async <T>(url: string, body: unknown = {}, jwt?: string): Promise<T> => {
const response = await fetch(url, {
method: 'POST',
headers: {
Expand Down
4 changes: 2 additions & 2 deletions packages/common/src/services/JWPEntitlementService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import JWPAPIService from './integrations/jwp/JWPAPIService';

@injectable()
export default class JWPEntitlementService {
private readonly apiService;
protected readonly apiService;

constructor(@inject(JWPAPIService) apiService: JWPAPIService) {
this.apiService = apiService;
Expand All @@ -14,7 +14,7 @@ export default class JWPEntitlementService {
getJWPMediaToken = async (configId: string = '', mediaId: string) => {
try {
const data = await this.apiService.get<SignedMediaResponse>(
'v2/items/jw-media/token',
'/v2/items/jw-media/token',
{
withAuthentication: true,
},
Expand Down
6 changes: 3 additions & 3 deletions packages/common/src/services/SettingsService.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { injectable } from 'inversify';
import { inject, injectable } from 'inversify';
import ini from 'ini';
import { getI18n } from 'react-i18next';

Expand All @@ -12,9 +12,9 @@ import StorageService from './StorageService';

@injectable()
export default class SettingsService {
private readonly storageService;
protected readonly storageService;

constructor(storageService: StorageService) {
constructor(@inject(StorageService) storageService: StorageService) {
this.storageService = storageService;
}

Expand Down
24 changes: 14 additions & 10 deletions packages/common/src/services/WatchHistoryService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,28 +22,32 @@ const schema = array(

@injectable()
export default class WatchHistoryService {
private PERSIST_KEY_WATCH_HISTORY = 'history';
protected PERSIST_KEY_WATCH_HISTORY = 'history';

private readonly apiService;
private readonly storageService;
private readonly accountService;
protected readonly apiService;
protected readonly storageService;
protected readonly accountService;

constructor(@inject(INTEGRATION_TYPE) integrationType: string, apiService: ApiService, storageService: StorageService) {
constructor(
@inject(INTEGRATION_TYPE) integrationType: string,
@inject(ApiService) apiService: ApiService,
@inject(StorageService) storageService: StorageService,
) {
this.apiService = apiService;
this.storageService = storageService;
this.accountService = getNamedModule(AccountService, integrationType);
}

// Retrieve watch history media items info using a provided watch list
private getWatchHistoryItems = async (continueWatchingList: string, ids: string[]): Promise<Record<string, PlaylistItem>> => {
protected getWatchHistoryItems = async (continueWatchingList: string, ids: string[]): Promise<Record<string, PlaylistItem>> => {
const watchHistoryItems = await this.apiService.getMediaByWatchlist(continueWatchingList, ids);
const watchHistoryItemsDict = Object.fromEntries((watchHistoryItems || []).map((item) => [item.mediaid, item]));

return watchHistoryItemsDict;
};

// We store separate episodes in the watch history and to show series card in the Continue Watching shelf we need to get their parent media items
private getWatchHistorySeriesItems = async (continueWatchingList: string, ids: string[]): Promise<Record<string, PlaylistItem | undefined>> => {
protected getWatchHistorySeriesItems = async (continueWatchingList: string, ids: string[]): Promise<Record<string, PlaylistItem | undefined>> => {
const mediaWithSeries = await this.apiService.getSeriesByMediaIds(ids);
const seriesIds = Object.keys(mediaWithSeries || {})
.map((key) => mediaWithSeries?.[key]?.[0]?.series_id)
Expand All @@ -62,21 +66,21 @@ export default class WatchHistoryService {
return seriesItemsDict;
};

private validateWatchHistory(history: unknown) {
protected validateWatchHistory(history: unknown) {
if (history && schema.validateSync(history)) {
return history as SerializedWatchHistoryItem[];
}

return [];
}

private async getWatchHistoryFromAccount(user: Customer) {
protected async getWatchHistoryFromAccount(user: Customer) {
const history = await this.accountService.getWatchHistory({ user });

return this.validateWatchHistory(history);
}

private async getWatchHistoryFromStorage() {
protected async getWatchHistoryFromStorage() {
const history = await this.storageService.getItem(this.PERSIST_KEY_WATCH_HISTORY, true);

return this.validateWatchHistory(history);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,17 +49,17 @@ import type { Response } from './types/api';

@injectable()
export default class CleengAccountService extends AccountService {
private readonly cleengService;
private readonly getCustomerIP;
private publisherId = '';
protected readonly cleengService;
protected readonly getCustomerIP;
protected publisherId = '';

private externalData: Record<string, unknown> = {};
protected externalData: Record<string, unknown> = {};

accessModel: AccessModel = ACCESS_MODEL.AUTHVOD;
svodOfferIds: string[] = [];
sandbox = false;

constructor(cleengService: CleengService, @inject(GET_CUSTOMER_IP) getCustomerIP: GetCustomerIP) {
constructor(@inject(CleengService) cleengService: CleengService, @inject(GET_CUSTOMER_IP) getCustomerIP: GetCustomerIP) {
super({
canUpdateEmail: true,
canSupportEmptyFullName: true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,10 @@ import CleengService from './CleengService';

@injectable()
export default class CleengCheckoutService extends CheckoutService {
private readonly cleengService: CleengService;
private readonly getCustomerIP: GetCustomerIP;
protected readonly cleengService: CleengService;
protected readonly getCustomerIP: GetCustomerIP;

constructor(cleengService: CleengService, @inject(GET_CUSTOMER_IP) getCustomerIP: GetCustomerIP) {
constructor(@inject(CleengService) cleengService: CleengService, @inject(GET_CUSTOMER_IP) getCustomerIP: GetCustomerIP) {
super();
this.cleengService = cleengService;
this.getCustomerIP = getCustomerIP;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,17 +80,17 @@ const getTokenExpiration = (token: string) => {

@injectable()
export default class CleengService {
private readonly storageService;
private readonly getCustomerIP;
private readonly channel: BroadcastChannel<MessageData>;
private readonly queue = new PromiseQueue();
private isRefreshing = false;
private expiration = -1;
protected readonly storageService;
protected readonly getCustomerIP;
protected readonly channel: BroadcastChannel<MessageData>;
protected readonly queue = new PromiseQueue();
protected isRefreshing = false;
protected expiration = -1;

sandbox = false;
tokens: Tokens | null = null;

constructor(storageService: StorageService, @inject(GET_CUSTOMER_IP) getCustomerIP: GetCustomerIP) {
constructor(@inject(StorageService) storageService: StorageService, @inject(GET_CUSTOMER_IP) getCustomerIP: GetCustomerIP) {
this.storageService = storageService;
this.getCustomerIP = getCustomerIP;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { injectable } from 'inversify';
import { inject, injectable } from 'inversify';

import { createURL } from '../../../utils/urlFormatting';
import type {
Expand All @@ -17,9 +17,9 @@ import CleengService from './CleengService';

@injectable()
export default class CleengSubscriptionService extends SubscriptionService {
private readonly cleengService: CleengService;
protected readonly cleengService: CleengService;

constructor(cleengService: CleengService) {
constructor(@inject(CleengService) cleengService: CleengService) {
super();
this.cleengService = cleengService;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ type RequestOptions = {

@injectable()
export default class JWPAPIService {
private readonly storageService: StorageService;
protected readonly storageService: StorageService;

private useSandboxEnv = true;
protected useSandboxEnv = true;

constructor(@inject(StorageService) storageService: StorageService) {
this.storageService = storageService;
Expand All @@ -34,7 +34,7 @@ export default class JWPAPIService {
this.useSandboxEnv = useSandboxEnv;
};

private getBaseUrl = () => (this.useSandboxEnv ? 'https://staging-sims.jwplayer.com' : 'http://sims.jwplayer.com');
private getBaseUrl = () => (this.useSandboxEnv ? 'https://staging-sims.jwplayer.com' : 'https://sims.jwplayer.com');

setToken = (token: string, refreshToken = '', expires: number) => {
return this.storageService.setItem(INPLAYER_TOKEN_KEY, JSON.stringify({ token, refreshToken, expires }), false);
Expand Down
Loading

0 comments on commit f71a0d7

Please sign in to comment.