From b85f56930a71ee5331c498b1eba512cc1f357c78 Mon Sep 17 00:00:00 2001 From: Christiaan Scheermeijer Date: Thu, 25 Jan 2024 20:52:52 +0100 Subject: [PATCH] docs(project): update docs for workspaces --- README.md | 10 +- docs/configuration.md | 22 +--- docs/content-types.md | 14 +-- docs/developer-guidelines.md | 12 +-- docs/features/related-videos.md | 7 +- docs/translations.md | 65 ++++++------ docs/workspaces.md | 100 +++++------------- .../common/docs}/backend-services.md | 0 .../common/docs}/modularization.md | 8 +- platforms/web/.env | 17 ++- platforms/web/README.md | 29 +++++ .../web/docs}/build-from-source.md | 58 +++++----- platforms/web/docs/developer-guidelines.md | 50 +++++++++ {docs => platforms/web/docs}/e2e.md | 0 .../web/docs}/easy-deployments.md | 6 +- {docs => platforms/web/docs}/frameworks.md | 0 .../web/docs}/initialization-file.md | 14 +-- platforms/web/docs/web-configuration.md | 21 ++++ 18 files changed, 239 insertions(+), 194 deletions(-) rename {docs => packages/common/docs}/backend-services.md (100%) rename {docs => packages/common/docs}/modularization.md (76%) create mode 100644 platforms/web/README.md rename {docs => platforms/web/docs}/build-from-source.md (84%) create mode 100644 platforms/web/docs/developer-guidelines.md rename {docs => platforms/web/docs}/e2e.md (100%) rename {docs => platforms/web/docs}/easy-deployments.md (83%) rename {docs => platforms/web/docs}/frameworks.md (100%) rename {docs => platforms/web/docs}/initialization-file.md (78%) create mode 100644 platforms/web/docs/web-configuration.md diff --git a/README.md b/README.md index fdad7997b..4f402a895 100644 --- a/README.md +++ b/README.md @@ -34,8 +34,8 @@ The JW OTT Webapp is an open-source, dynamically generated video website built a - [Configure JW OTT Webapp](./docs/configuration.md) - [Configure Translations](./docs/translations.md) - [Contributing Guidelines](CONTRIBUTING.md) -- [Frameworks, SDKs and Libraries](./docs/frameworks.md) -- [Backend Services](./docs/backend-services.md) +- [Frameworks, SDKs and Libraries](./platforms/web/docs/frameworks.md) +- [Backend Services](./packages/common/docs/backend-services.md) - [Developer Guidelines](./docs/developer-guidelines.md) - [Workspaces](./docs/workspaces.md) @@ -60,12 +60,6 @@ The JW OTT Webapp is an open-source, dynamically generated video website built a - Self-hosted JW Players -## Getting started - -- Clone this repository -- Run `yarn` to install dependencies -- Run `yarn start` - ## Support and Bug Reporting To report bugs and feature requests, or request help using JW OTT Webapp, use this repository's [Issues](https://github.com/jwplayer/ott-web-app/issues) page. diff --git a/docs/configuration.md b/docs/configuration.md index 5f9ee4dce..0a6586576 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -1,27 +1,9 @@ # Configuration -The JW OTT Webapp is designed to consume a json configuration file served by the [JWP Delivery API](https://docs.jwplayer.com/platform/reference/get_apps-configs-config-id-json). +The JW OTT Webapp is designed to consume a JSON configuration file served by the [JWP Delivery API](https://docs.jwplayer.com/platform/reference/get_apps-configs-config-id-json). The easiest way to maintain configuration files is to use the 'Apps' section in your [JWP Dashboard account](https://dashboard.jwplayer.com/). -## Configuration File Source - -Which app config file the application uses is determined by the [ini file](initialization-file.md). - -You can specify the default that the application starts with and also which config, if any, it will allow to be set using the [`app-config=` query param](#switching-between-app-configs). -The location is usually specified by the 8-character ID (i.e. `gnnuzabk`) of the App Config from your JWP account, in which case the file will be loaded from the JW Player App Config delivery endpoint (i.e. `https://cdn.jwplayer.com/apps/configs/gnnuzabk.json`). -You may also specify a relative or absolute URL. - -### Switching between app configs - -As mentioned above, if you have 1 or more additional allowed sources (see additionalAllowedConfigSources in [`initialization-file`](initialization-file.md)), you can switch between them by adding `app-config=` as a query parameter in the web app URL in your browser (i.e. `https:///?app-config=gnnuzabk`). - -The parameter is automatically evaluated, loaded, and stored in browser session storage and should remain part of the url as the user navigates around the site. - -> _Note: Be aware that this mechanism only sets the config for the local machine, browser, and session that you are accessing the site with and it does not change the default hosted app for other users._ - -Even sharing URL's should work as long as the query parameter of the desired config is part of the URL. However, once the query parameter is removed and the stored value in the session is released, the application will revert to loading the default config source. - -> _Note: to clear the value from session storage and return to the default, you can navigate to the site with a blank query parameter value (i.e. `?app-config=`)_ +> See the [web configuration documentation](../platforms/web/docs/web-configuration.md) for configuring the OTT Web App. ## Available Configuration Parameters diff --git a/docs/content-types.md b/docs/content-types.md index 23f0cc7e0..749dff78a 100644 --- a/docs/content-types.md +++ b/docs/content-types.md @@ -4,7 +4,7 @@ In order to map data coming from the JWP delivery pipeline to the correct screen we use the concept of 'content types'. Basically, a content type is simply a custom parameter named 'contentType' on a media item with a value defining which type the media is (movie, trailer, series, etc.) -In the app, content types often map to specific screens (see [screenMapping.ts](../platforms/web/src/screenMapping.ts) and [MediaScreenRouter.tsx](src/pages/ScreenRouting/MediaScreenRouter.tsx).) +In the app, content types often map to specific screens (see [screenMapping.ts](../platforms/web/src/screenMapping.ts) and [MediaScreenRouter.tsx](../packages/ui-react/src/pages/ScreenRouting/MediaScreenRouter.tsx).) Each content type screen often expects different metadata attached to the media item's custom parameters. # Using content types in the JWP dashboard @@ -21,22 +21,22 @@ In order to quickly upload the content types, you can use the yarn script includ `yarn load-content-types --site-id=` -By default, the script will load the content types that the vanilla web app expects found in [content-types.json](scripts/content-types/content-types.json). -You can modify this file in your fork of the web app code or optionally specify another file to load by adding a `--source-file=` param to the yarn script call. +By default, the script will load the content types that the vanilla web app expects found in [content-types.json](../scripts/content-types/content-types.json). +You can modify this file in your fork of the web app code or optionally specify another file to load by adding a `--source-file=` param to the yarn script call. ### Content type upload file definition The upload file should be a json property with the schemas defined as an array on the `schemas` property on the root object. -Please refer to [content-types.json](scripts/content-types/content-types.json) and the JWP documentation for the schema format. +Please refer to [content-types.json](../scripts/content-types/content-types.json) and the JWP documentation for the schema format. To avoid unnecessary duplication the file also allows some basic abstraction. You can define reused fields and sections as key-value entries on the `fields` and `sections` properties respectively. Then you can include these reusable entities by putting their string key into schemas the same way that you would for inline fields or sections. -There are many examples in the included [content-types.json](scripts/content-types/content-types.json) +There are many examples in the included [content-types.json](../scripts/content-types/content-types.json) > Note: Although the upload file allows you to define reused fields and sections, when these are uploaded they become distinct copies for each instance in the schemas where they are used. > That means that changing fields and sections via the api after they are uploaded must be done individually for each schema. -> Alternatively, you can re-upload and overwrite the existing schemas, but use caution because you will lose any other manual changes you have made. +> Alternatively, you can re-upload and overwrite the existing schemas, but use caution because you will lose any other manual changes you have made. # Content Type Data Structure @@ -44,6 +44,6 @@ Content types do not change the underlying structure of data returned from the J ## Boolean custom params -Because custom params are always strings and any non-empty string in javascript converts to truthy, we have by convention decided on a few string values to consider strictly true or false. You can find these values in code: https://github.com/jwplayer/ott-web-app/blob/a95c3a3c9d0c5bc7c98b194928261ffc6fc4286f/src/utils/common.ts#L88-L90 +Because custom params are always strings and any non-empty string in javascript converts to truthy, we have by convention decided on a few string values to consider strictly true or false. You can find these values in code: https://github.com/jwplayer/ott-web-app/blob/a95c3a3c9d0c5bc7c98b194928261ffc6fc4286f/src/utils/common.ts#L88 Be careful to use the right version considering the fallback when the value is not matched. For example, if you want the property to only be true when matched and fallback to false, use IsTruthy. diff --git a/docs/developer-guidelines.md b/docs/developer-guidelines.md index 2c98923c5..be22aa1af 100644 --- a/docs/developer-guidelines.md +++ b/docs/developer-guidelines.md @@ -1,12 +1,12 @@ ## When working on this project, keep these in mind: -- Use yarn. -- Run the server through `yarn start` (in the platforms/web directory) -- Run the e2e tests through `yarn codecept:mobile` and `yarn codecept:desktop` (in the platforms/web directory) -- Run the tests through `yarn test` +- Use `yarn` +- Run all unit tests through `yarn test` - Format the code through `yarn format` (or automatically do it via git hooks) - Lint through `yarn lint` (eslint, prettier, stylelint and tsc checks) - Run `yarn i18next` to extract all translations keys from source-code +- Run `yarn depcheck` to validating dependency usages for all packages +- Run `npx syncpack lint` for validating dependency issues for all workspaces - The JW organization requires personal access tokens for all of their repositories. In order to create a branch or pull request you'll need to [Generate a Personal Access Token](https://github.com/settings/tokens) and then [store it in your git config](https://stackoverflow.com/questions/46645843/where-to-store-my-git-personal-access-token/67360592). (For token permissions, `repo` should be sufficient). ## Versioning and Changelog @@ -60,7 +60,7 @@ Please use one of the following: The scope must specify the location of the commit change. For example `home` or `search`. -The allowed scopes can be found in the [commitlint config file](../.commitlintrc.js). +The allowed scopes can be found in the [../.commitlintrc.js](../.commitlintrc.js) file. ### Subject @@ -87,7 +87,7 @@ The footer should contain any information about **Breaking Changes** and is also /_images - Images used in the docs and README /features - Docs coverage specific product use cases /node_modules* - Yarn generated dependencies -/packages - Re-usable code for platfroms (registered in workspace) +/packages - Re-usable code for platforms (registered in workspace) /platforms - Platform entry points (registered in workspace) /scripts - Dev helper scripts for i18n, deployment, etc. /CHANGELOG.md - Auto-generated changelog diff --git a/docs/features/related-videos.md b/docs/features/related-videos.md index abaf6dabc..323a34f0c 100644 --- a/docs/features/related-videos.md +++ b/docs/features/related-videos.md @@ -19,7 +19,7 @@ GET playlists/fuD6TWcf?related_media_id=dwEE1oBP "description":"", "kind":"FEED", "feedid":"fuD6TWcf", - "playlist":[ + "playlist": [ { "title":"Elephants Dream", "mediaid":"8pN9r7vd", @@ -33,9 +33,8 @@ GET playlists/fuD6TWcf?related_media_id=dwEE1oBP "rating":"CC-BY", "genre":"Drama", "trailerId":"EorcUZCU" - }, -    {} - ] + } + ] } ``` diff --git a/docs/translations.md b/docs/translations.md index 01896ecb1..f9a705327 100644 --- a/docs/translations.md +++ b/docs/translations.md @@ -6,7 +6,7 @@ Before changing or adding languages, read the sections below to understand the m ## Translation status -Here is a list of all supported translations included in the OTT Web App. The status indicates if the translations are +Here is a list of all supported translations included in the OTT Web App. The status indicates if the translations are generated using Google Translate/ChatGTP or validated by a person. | Language | Code | Status | Validated by | @@ -17,39 +17,42 @@ generated using Google Translate/ChatGTP or validated by a person. ## Translation files -The web app uses the [react-i18next](https://react.i18next.com/) library for displaying translated strings. Translation -files are defined in JSON format and can be found in the `./public/locales` directory. Translation files are separated -by namespace. +The web app uses the [react-i18next](https://react.i18next.com/) library for displaying translated strings. Translation +files are defined in JSON format and can be found in the `./platforms/web/public/locales` directory. Translation files +are separated by namespace. -The structure of all translation files is generated automatically using the `yarn i18next` command. This script -extracts all namespaces and translation keys from the source code. Refrain from editing the structure (e.g., adding or +> The translation files will be moved to the `./packages/i18n` package in the near future. + +The structure of all translation files is generated automatically using the `yarn i18next` command. This script +extracts all namespaces and translation keys from the source code. Refrain from editing the structure (e.g., adding or removing keys) of translation files manually because this is prone to mistakes. -To add a new language, create a new subdirectory in the `./public/locales` directory using the language code or -LCID string if the language is region specific. For example, using the `fr` language code will be available for all -French-speaking regions (e.g., Belgium, Canada, France, Luxembourg, etc.). But if you have different translations for -one or more French-speaking regions, use the LCID string (e.g., `fr-be`, `fr-ca`, `fr-lu`, or `fr-fr`) instead of the -language code. The downside of this, when having multiple French-speaking regions, a lot of translations will be +To add a new language, create a new subdirectory in the `./platforms/web/public/locales` directory using the language +code or LCID string if the language is region specific. For example, using the `fr` language code will be available for +all French-speaking regions (e.g., Belgium, Canada, France, Luxembourg, etc.). But if you have different translations +for one or more French-speaking regions, use the LCID string (e.g., `fr-be`, `fr-ca`, `fr-lu`, or `fr-fr`) instead of +the language code. The downside of this, when having multiple French-speaking regions, a lot of translations will be duplicate. -After adding the subdirectory, run the `yarn i18next` command to generate all the added -language(s) translation files. You can now translate each key for the added language(s). +After adding the subdirectory, run the `yarn i18next` command to generate all the added +language(s) translation files. You can now translate each key for the added language(s). ## Defined languages -When a language is added to the `./public/locales` folder, the OTT Web App doesn't automatically recognize this. -Instead, the language must first be added to the "defined languages" list. This is for two reasons: +When a language is added to the `./platforms/web/public/locales` folder, the OTT Web App doesn't automatically recognize +this. Instead, the language must first be added to the "defined languages" list. This is for two reasons: - As OTT Web App we want to be able to include many languages without enabling them all by default - For each language, the display name must be defined, which is shown in the language selection menu -Navigate to the [../platforms/web/src/i18n/config.ts](../platforms/web/src/i18n/config.ts) file and find the `DEFINED_LANGUAGES` constant. Each entry specifies the -language code (or LCID string) and display name. +Navigate to the `./platforms/web/src/i18n/config.ts` file and find the `DEFINED_LANGUAGES` constant. Each entry +specifies the language code (or LCID string) and display name. -> If you have added multiple languages using the LCID string identifier, each much be added to the list of defined +> If you have added multiple languages using the LCID string identifier, each much be added to the list of defined > languages and ensure to include the region in the `displayName`. For example: `Français Canadien` -The `displayName` is always translated for the language it is written for. This ensures that when the current language is +The `displayName` is always translated for the language it is written for. This ensures that when the current language +is wrong for the current user, he/her will still be able to recognize the language. ```ts @@ -65,23 +68,23 @@ export const DEFINED_LANGUAGES: LanguageDefinition[] = [ ]; ``` -> You won't have to delete entries with languages that are not supported for your OTT Web App. Instead, don't enable -> the language in the app (see the next step). +> You won't have to delete entries with languages that are not supported for your OTT Web App. Instead, don't enable +> the language in the app (see the next step). ## Enabled languages -Languages can be enabled or disabled by updating the `APP_ENABLED_LANGUAGES` environment variable. This can be changed -in the `.env` file or by adding the environment variable to the start/build commands. +Languages can be enabled or disabled by updating the `APP_ENABLED_LANGUAGES` environment variable. This can be changed +in the `/platforms/web/.env` file or by adding the environment variable to the start/build commands. -This disables the multilingual feature by only supporting the English language. The language selection icon will be +This disables the multilingual feature by only supporting the English language. The language selection icon will be hidden in the header. ```shell $ APP_ENABLED_LANGUAGES=en yarn build ``` -This builds an OTT Web App supporting the English and French languages. The language selection icon will be shown in -the header. +This builds an OTT Web App supporting the English and French languages. The language selection icon will be shown in +the header. ```shell $ APP_ENABLED_LANGUAGES=en,fr yarn build @@ -89,14 +92,14 @@ $ APP_ENABLED_LANGUAGES=en,fr yarn build ## Default language -OTT Web App will try to predict the user language by looking at the Browser language. When the language can't be -predicted, or there is no support for the Browser language, the default language will be used. By default, this is set +OTT Web App will try to predict the user language by looking at the Browser language. When the language can't be +predicted, or there is no support for the Browser language, the default language will be used. By default, this is set to `en`. -The default language can be changed in the `.env` file as well or by adding the `APP_DEFAULT_LANGUAGE` environment -variable to the start/build commands. +The default language can be changed in the `/platforms/web/.env` file as well or by adding the `APP_DEFAULT_LANGUAGE` +environment variable to the start/build commands. -Build an OTT Web App with English and French translations, but default to French when the language couldn't be +Build an OTT Web App with English and French translations, but default to French when the language couldn't be predicted. ```shell diff --git a/docs/workspaces.md b/docs/workspaces.md index 02ed7f926..8b5a28b32 100644 --- a/docs/workspaces.md +++ b/docs/workspaces.md @@ -4,42 +4,41 @@ The JW OTT Web App is an open-source repository that showcases an OTT app implementing JWP services. The OTT Web App, as the name implies, originates as a web only repository. But much of the source-code can be re-used for many different -platforms, like Capacitor, React Native, and other frameworks based on TypeScript. +platforms, such as CapacitorJS, React Native, LightningJS and other frameworks based on TypeScript. Using the previous codebase, it would be quite challenging to re-use the services because of the dependencies and browser usage. For example, the AccountController could redirect a user to a different page by using `window.location`. -This will never work in a non-browser environment and will most likely crash the app. +This will never work in a non-browser environment and will crash the app. This means that we need to: -- Make most of the shareable code platform-agnostic -- Make most of the shareable code framework-agnostic +- Make some of the shareable code platform-agnostic +- Make some of the shareable code framework-agnostic - Make importing services, controllers, stores, and utils possible in any other projects/platforms - Benefit from linting based on the environment (Node, Browser, Vite, ...) -- Easy linking of packages/dependencies ## The solution -Based on the re-usability of parts of the existing codebase, we've created separate packages using Yarn Workspaces. +Based on the re-usability of parts of the existing codebase, we've created separate modules using Yarn Workspaces. This will combine all similar code and prevent installing redundant or conflicting dependencies. -For example, all components, containers, and pages are be combined into the `packages/ui-react` package, which depends -on react and react-dom. To create a React Native app, you could add an `packages/ui-react-native` package and configure -aliases to use the correct package. +For example, all components, containers, and pages are combined into the `packages/ui-react` module, which depends on +react and react-dom. To create a React Native app, you could add a `packages/ui-react-native` module and configure +aliases to use the correct module. ## Packages & Platforms A split has been made between the platform and reusable code. All reusable code is further split into multiple packages. -This is mostly to separate the React from the non-react code. +This is mostly done to separate the React from the non-react code. -Here is a breakdown of each package: +Here is a breakdown of each module: ### Common Name: `@jwp/ott-common` -The common package contains all non-react TypeScript code reusable between multiple frameworks. These are controllers, -services, stores, utilities, and typings. There should be no platform-specific dependencies like React or React DOM. +The common module contains all non-react TypeScript code, reusable between multiple frameworks. These are controllers, +services, stores, utilities and typings. There should be no platform-specific dependencies like React or React DOM. Typings can also be reused for multiple frameworks. @@ -61,9 +60,9 @@ configureEnv({ Name: `@jwp/ott-hooks-react` Hooks are special because they are React-dependent but can be shared between the React and React Native frameworks. -That’s why they are in a separate folder for use between the two frameworks. +That’s why they are in a separate folder for usage from both the two frameworks. -### I18n (TODO) +### i18n (TODO) Name: `@jwp/ott-i18n` @@ -74,7 +73,7 @@ files between all platforms. Name: `@jwp/ott-testing` -This package contains all test fixtures and could contain some generic test utils. But it shouldn’t contain +This module can contain all test fixtures and perhaps some generic test utils. But it shouldn’t contain CodeceptJS/Playwright-specific code. ### Theme (TODO) @@ -93,7 +92,7 @@ The theme folder also contains generic assets like images, logos, and fonts. Name: `@jwp/ott-ui-react` The ui-react package contains all the existing React UI code. -The ui-react package also contains the SCSS variables and theme for use across more platforms. +The ui-react package also contains the SCSS variables and theme for usage across multiple platforms. ### Platforms/web @@ -105,25 +104,25 @@ bootstrapping the app. We can add more platforms by adding a folder to the platforms folder. -Each platform is a standalone application that may use other packages defined in the packages folder as dependency. +Each platform is a standalone application that may use other modules defined in the packages folder as dependencies. -### Configs +### Eslint, PostCSS and Stylelint -The configs directory contains packages that are used mainly for configuring common build tools. This ensures these -configurations are aligned between the different application packages in the `packages/*` and `platforms/*` folder. +Besides the mentioned packages there are also three utility packages listed in the packages folder. These utility +packages exist to align linting dependencies and configuration between the different packages. -Since most application packages depend on ESLint and use the same configuration, the recommended way of doing this in a -monorepo is by creating a local package of the eslint config. +All packages depend on Eslint and need a configuration. The recommended way of doing this in a monorepo is by creating +a local package. **eslint-config-jwp** -This is the ESLint config for React or TypeScript packages. Usage: +This is the Eslint config for React or TypeScript packages. Usage: **.eslintrc.js** ```js module.exports = { - extends: ['jwp/typescript'], // extends: ['jwp/react'], + extends: ['jwp/typescript'], // extends: ['jwp/react'], }; ``` @@ -148,54 +147,3 @@ module.exports = { extends: ['stylelint-config-jwp'], }; ``` - -## Tips when working with workspaces - -### Setup - -You can set up the OTT Web App repository by following -the [Building from source](./build-from-source.md#build-the-jw-ott-webapp) documentation. - -All packages are automatically linked and can be used from source. This prevents us from needing to compile each -package while developing. - -### Developing - -While developing the web platform, you want to cd to the `platforms/web` directory first. - -```shell -cd platforms/web -``` - -This directory contains most of the "old" scripts that were available in the package.json. - -### Dependency validation - -Because there are multiple package.json files, you can use [syncpack](https://www.npmjs.com/package/syncpack) to lint -and align the dependencies. This package is not a dependency, but can be used with the NPX from the root directory. - -Lint package.json files based on the syncpack config. - -```shell -npx syncpack lint -``` - -Organize package.json files automatically based on the syncpack config. - -```shell -npx syncpack format -``` - -### TypeScript config - -Because most of the packages use TypeScript a [tsconfig.base.json](../tsconfig.base.json) file is found in the root. -Most packages extend this tsconfig file and make the changes accordingly for the package. - -For example, the [tsconfig](../packages/common/tsconfig.json) in the common package overrides the `compilerOptions#lib` -property to disallow browser globals. - -Another example is the [tsconfig](../packages/ui-react/tsconfig.json) in the ui-react package which extends Vite typings -and ensures SCSS modules are typed as well. - - - diff --git a/docs/backend-services.md b/packages/common/docs/backend-services.md similarity index 100% rename from docs/backend-services.md rename to packages/common/docs/backend-services.md diff --git a/docs/modularization.md b/packages/common/docs/modularization.md similarity index 76% rename from docs/modularization.md rename to packages/common/docs/modularization.md index 198beaf0e..5aaf93551 100644 --- a/docs/modularization.md +++ b/packages/common/docs/modularization.md @@ -42,11 +42,11 @@ This is the price we need to pay to remove `inject` decorators from the construc ## Initialization -We use [register](../platforms/web/src/modules/register.ts) function to initialize services and controllers. Some services don't depend on any integration provider (like `ConfigService` or `EpgService`), while such services as `CleengAccountService` or `InplayerAccountService` depend on the provider and get injected into controllers conditionally based on the `INTEGRATION_TYPE` dynamic value (`JWP` or `CLEENG`). +We use [register](../src/modules/register.ts) function to initialize services and controllers. Some services don't depend on any integration provider (like `ConfigService` or `EpgService`), while such services as `CleengAccountService` or `InplayerAccountService` depend on the provider and get injected into controllers conditionally based on the `INTEGRATION_TYPE` dynamic value (`JWP` or `CLEENG`). -Initialization starts in the [index.tsx](../platforms/web/src/index.tsx) file where we register services. We do it outside of the react component to make services available in different parts of the application. +Initialization starts in the platform index.tsx file where we register services. We do it outside the React component to make services available in different parts of the application. -The app is loaded in the [useBootstrapApp](../packages/hooks-react/src/useBootstrapApp.ts) hook with the help of the `AppController` which is responsible for retrieving data from the Config and Settings services, initializing the initial state of the application and hitting init methods of the base app's controllers. +The app is loaded in the [useBootstrapApp](../src/hooks/useBootstrapApp.ts) hook with the help of the `AppController` which is responsible for retrieving data from the Config and Settings services, initializing the initial state of the application and hitting init methods of the base app's controllers. ## Controllers and Services @@ -82,6 +82,6 @@ Controllers bind different parts of the application. Controllers use services, s ### Controllers / Services retrieval -To get access to the service / controller [getModule](../packages/common/src/modules/container.ts) utility can be used. It also accepts a `required` param which can be used in case the presence of the service is optional. If `required` is provided but service itself is not bound then the error will be thrown. +To get access to the service / controller [getModule](../src/modules/container.ts) utility can be used. It also accepts a `required` param which can be used in case the presence of the service is optional. If `required` is provided but service itself is not bound then the error will be thrown. `getNamedModule` function is mostly use in controllers to retrieve integration-specific services, like AccountService or CheckoutService. diff --git a/platforms/web/.env b/platforms/web/.env index eb0bc9bd0..fb9ab08f5 100644 --- a/platforms/web/.env +++ b/platforms/web/.env @@ -1,9 +1,22 @@ APP_API_BASE_URL=https://cdn.jwplayer.com APP_PLAYER_ID=M4qoGvUk -### Web-only env vars (not sent to common/src/env configureEnv()) +# page metadata (SEO) +#APP_NAME= +#APP_SHORT_NAME= +#APP_DESCRIPTION + +# UI configuration APP_VERSION=$npm_package_version -APP_FOOTER_TEXT=\u00a9 JW Player | [jwplayer.com](https://www.jwplayer.com/) | v${APP_VERSION} +APP_FOOTER_TEXT="\u00a9 JW Player | [jwplayer.com](https://www.jwplayer.com/) | v${APP_VERSION}" + +# config for Google Services +#APP_GTM_TAG_ID +#APP_GOOGLE_SITE_VERIFICATION_ID + +# override with custom fonts. supports Google Fonts (eg. APP_BODY_FONT_FAMILY=google:Roboto,system:Verdana - use Roboto and fallback to Verdana) +#APP_BODY_FONT_FAMILY +#APP_BODY_ALT_FONT_FAMILY # the default language that the app should load when the language couldn't be detected APP_DEFAULT_LANGUAGE=en diff --git a/platforms/web/README.md b/platforms/web/README.md new file mode 100644 index 000000000..06864c9ab --- /dev/null +++ b/platforms/web/README.md @@ -0,0 +1,29 @@ +# OTT Web App + +## Getting started + +- Clone this repository +- Run `yarn` to install dependencies +- Navigate to the platform directory `cd platforms/web` +- Run unit tests through `yarn test` +- Format the code through `yarn format` (or automatically do it via git hooks) +- Lint through `yarn lint` (eslint, prettier, stylelint and tsc checks) +- Run `yarn start` + +## Create favicons / pwa icons + +First override the source icon with another image here [./public/images/icons/app-icon.png`](./public/images/icons/app-icon.png) +Use a high quality image square-sized image. We suggest a dimension 1024x1024 or higher + +- Navigate to the platform directory `cd platforms/web` +- Perform `yarn generate-pwa-assets` + +Instal `sharp` if you get the following error: Could not load the "sharp" module using the ... runtime. +And run `yarn generate-pwa-assets` afterwards + +The different icon formats are defined here [pwa-assets.config.ts](./pwa-assets.config.ts) + +## Developer guidelines + +- Read the workspace guidelines here [../../docs/developer-guidelines.md](../../docs/developer-guidelines.md). +- Read the web platform guidelines here [./docs/developer-guidelines.md](./docs/developer-guidelines.md). diff --git a/docs/build-from-source.md b/platforms/web/docs/build-from-source.md similarity index 84% rename from docs/build-from-source.md rename to platforms/web/docs/build-from-source.md index 0840fd76c..ccab5f76d 100644 --- a/docs/build-from-source.md +++ b/platforms/web/docs/build-from-source.md @@ -13,39 +13,45 @@ The following tools are needed to start building JW OTT Webapp. Follow the instr ## Build the JW OTT Webapp 1. Clone the **ott-web-app** repository on your local machine. - ```shell - $ cd ~/ - - $ git clone https://github.com/jwplayer/ott-web-app.git - $ cd ott-web-app - ``` + +```shell +$ cd ~/ + +$ git clone https://github.com/jwplayer/ott-web-app.git +$ cd ott-web-app +``` + 2. Install the required dependencies. Optional dependencies include packages that are not necessary to build the project. These optional dependencies can be safely ignored. - ```shell - $ yarn --ignore-optional - ``` - > **NOTE**: Some of the [easy deployments](easy-deployments.md) instructions require installing these optional dependencies. Use the `yarn` command to install all dependencies. The `yarn` command can be run even if `yarn --ignore-optional` has been previously run. + +```shell +$ yarn --ignore-optional +``` + +> **NOTE**: Some of the [easy deployments](easy-deployments.md) instructions require installing these optional dependencies. Use the `yarn` command to install all dependencies. The `yarn` command can be run even if `yarn --ignore-optional` has been previously run. 3. Create or update the .ini files in `/platforms/web/ini` for the modes you will be running in (probably dev and prod). You can copy the ini file from `/platforms/web/ini/templates` into `/platforms/web/ini`. The files in `/platforms/web/ini` are git-ignored, so you do not need to worry about account values in source control, but you will need to recreate the ini files each time you make a fresh checkout of the repository. + The .ini files provide startup values to the application such as which app config to load by default. See [initialization-file](initialization-file.md) for more details. + 4. Start the local development server. - ```shell - $ cd platforms/web - $ yarn start - ``` - - If you encounter any errors, make sure you have correctly set the `defaultConfigSource` in `/platforms/web/ini/.webapp.dev.ini` to point to a valid app config from your JWP account. - - > **NOTE:** Only use the development server for development purposes. The development server is not optimized for production usage. +```shell +$ cd platforms/web +$ yarn start +``` + +If you encounter any errors, make sure you have correctly set the `defaultConfigSource` in `/platforms/web/ini/.webapp.dev.ini` to point to a valid app config from your JWP account. + +> **NOTE:** Only use the development server for development purposes. The development server is not optimized for production usage. 5. Build a deployable version of the JW OTT Webapp source code.

This command creates a new folder in the projects root folder named **build**. The `public` folder from the build directory can be uploaded to any static hosting provider to run the web app from that host. - ```shell - $ cd platforms/web - $ yarn build - ``` +```shell +$ cd platforms/web +$ yarn build +``` If you have not made any changes to the JW OTT Webapp configuration or source code, changes can now be made. Be sure to run the `yarn build` command after making any changes. @@ -72,16 +78,16 @@ Production builds optimize code and minimize debug information, while developmen ## Env Variables To allow for adjustments to be made at compile time, there are several env variables that get replaced during [vite compile](https://vitejs.dev/guide/env-and-mode.html#env-variables). -These values are then de facto constants, which means code optimizations can remove unused code such as if/else checks using them. +These values are then defacto constants, which means code optimizations can remove unused code such as if/else checks using them. For non-sensitive values, you can add them directly to the appropriate .env file for each mode. -For sensitive values, if building with GitHub actions we recommend using [GitHub secrets](https://docs.github.com/en/actions/security-guides/encrypted-secrets) and setting them in the [build action environment](https://docs.github.com/en/actions/learn-github-actions/variables). +For sensitive values, if building with github actions we recommend using [github secrets](https://docs.github.com/en/actions/security-guides/encrypted-secrets) and setting them in the [build action environment](https://docs.github.com/en/actions/learn-github-actions/variables). You can see an example of how these are used in our [Firebase Live / Preview actions.](https://github.com/jwplayer/ott-web-app/blob/develop/.github/workflows/firebase-live.yml#L14) If building manually, you can create an .env.[mode].local file and add the values there. These files are git ignored which will prevent leaking your secrets to version control. -> Note: env variables must begin with the 'APP_' prefix. or they are ignored by our vite configuration. +> Note: env variables must begin with the 'APP\_' prefix or they are ignored by our vite configuration. ### APP_DEFAULT_CONFIG_SOURCE @@ -111,7 +117,7 @@ The value to use can be found labeled 'License Key' in the 'Self-Hosted Web Play If you link directly to your JWP cloud player using the [APP_PLAYER_ID](#app_player_id) environment variable or the [playerId ini setting](initialization-file.md#playerid), you do not need to provide a value for `APP_PLAYER_LICENSE_KEY`. -It is recommended that this value be provided via a .env.local file or a GitHub secret to avoid saving it in version control. +It is recommended that this value be provided via a .env.local file or a github secret to avoid saving it in version control. If you are using pre-compiled builds instead of building the code yourself, you can also set this value with the [playerLicenseKey ini setting](initialization-file.md#playerLicenseKey). Keep in mind, if the [playerLicenseKey ini setting](initialization-file.md#playerLicenseKey) is provided, it will be used even if the `APP_PLAYER_LICENSE_KEY` environment variable is set. diff --git a/platforms/web/docs/developer-guidelines.md b/platforms/web/docs/developer-guidelines.md new file mode 100644 index 000000000..d03257ba5 --- /dev/null +++ b/platforms/web/docs/developer-guidelines.md @@ -0,0 +1,50 @@ +# Developer guidelines + +## When working on this project, keep these in mind: + +- Use `yarn` +- Run unit tests through `yarn test` +- Format the code through `yarn format` (or automatically do it via git hooks) +- Lint through `yarn lint` (eslint, prettier, stylelint and tsc checks) +- Run `yarn i18next` from the workspace root to extract all translations keys from source-code +- Run `yarn depcheck` from the workspace root to validating dependency usages for all packages +- Run `npx syncpack lint` from the workspace root for validating dependency issues for all workspaces + +## Project Structure + +``` +/build* - Directory where the code is compiled by `yarn build` +/coverage* - Location of the C8 coverage report +/docs - Documentation +/ini - Directory to group different initialization files + /templates - Template .ini files per mode +/node_modules* - Yarn generated dependencies +/public - Static files to be hosted with the application +/scripts - Dev helper scripts for deployment, etc. +/src - Source code for the application + /components - Reusable, side-effect free UI components + /containers - UI Containers + /hooks - Custom React hooks + /i18n - Internationalization tools + /modules - Container registry for IoC + /services - Services which connects external data sources to the application + /styles - Global SCSS rules, theming and variables + /utils - Utility functions + /App.tsx - The main React component which renders the app + /constants.ts - Re-usable TypeScript constants + /index.tsx - The entrypoint +/test - Data and scripts for unit and e2e testing +/test-cases - Test cases written in cucumber format +/test-e2e - End to end tests and scripts +/types - Global type definitions +/.env<.mode> - Environment variables for different Vite modes +/firebase.json - Config for firebase static hosting +/index.html - Main html file entrypoint for the application +/package.json - Yarn file for dependencies and scripts +/vite.config.ts - Vite build and test configuration file + +* = Generated directories, not in source control + +Note: Some system and util files are not shown above for brevity. +You probably won't need to mess with anything not shown here. +``` diff --git a/docs/e2e.md b/platforms/web/docs/e2e.md similarity index 100% rename from docs/e2e.md rename to platforms/web/docs/e2e.md diff --git a/docs/easy-deployments.md b/platforms/web/docs/easy-deployments.md similarity index 83% rename from docs/easy-deployments.md rename to platforms/web/docs/easy-deployments.md index faf0f630a..41044211b 100644 --- a/docs/easy-deployments.md +++ b/platforms/web/docs/easy-deployments.md @@ -5,7 +5,7 @@ The instructions in this document will help you deploy your fork of the ott-web- ## Prerequisites 1. [Fork this repo](https://docs.github.com/en/get-started/quickstart/fork-a-repo). -2. Follow the instructions in [docs/build-from-source.md](build-from-source.md). +2. Follow the instructions in [./build-from-source.md](./build-from-source.md). ## Supported Platforms @@ -19,8 +19,8 @@ Firebase has both [free and paid plans](https://firebase.google.com/pricing). Th #### Usage Instructions -First, in your fork, you will need to update the project ID in [.firebaserc](../platforms/web/.firebaserc). +First, in your fork, you will need to update the project ID in [../.firebaserc](../.firebaserc). -The easiest way to deploy is to use the [Firebase-Github integration](https://firebase.google.com/docs/hosting/github-integration). You can find the action [.yml specifications here](https://github.com/marketplace/actions/deploy-to-firebase-hosting) to deploy to a preview channel for each PR and to the live channel for each merge to your main branch. If you want to manually set up the work, you can find those instructions [here](https://github.com/FirebaseExtended/action-hosting-deploy/blob/main/docs/service-account.md). +The easiest way to deploy is to use the [Firebase-Github integration](https://firebase.google.com/docs/hosting/github-integration). You can find the action [.yml specifications here](https://github.com/marketplace/actions/deploy-to-firebase-hosting) to deploy to a preview channel for each PR and to the live channel for each merge to your main branch. If you want to manually setup the work, you can find those instructions [here](https://github.com/FirebaseExtended/action-hosting-deploy/blob/main/docs/service-account.md). You can also manually deploy using the Firebase CLI, as described [here](https://firebase.google.com/docs/hosting/quickstart). diff --git a/docs/frameworks.md b/platforms/web/docs/frameworks.md similarity index 100% rename from docs/frameworks.md rename to platforms/web/docs/frameworks.md diff --git a/docs/initialization-file.md b/platforms/web/docs/initialization-file.md similarity index 78% rename from docs/initialization-file.md rename to platforms/web/docs/initialization-file.md index 5826605d4..cea4161fe 100644 --- a/docs/initialization-file.md +++ b/platforms/web/docs/initialization-file.md @@ -2,11 +2,11 @@ The JW OTT Web App loads a small initialization (.ini) file at startup. This file provides a mechanism to set key startup parameters without modifying the source code. Template ini files are included in the repo and with the pre-compiled production release builds ([.webapp.prod.ini](/web/ini/templates/.webapp.prod.ini)). -Make sure you include a copy of the ini file edited to include your account data at `platforms/web/public/.webapp.ini` for the application to load correctly. +Make sure you include a copy of the ini file edited to include your account data at `/public/.webapp.ini` for the application to load correctly. -For all manual builds (`yarn start` or `yarn build`), the ini file is copied from `platforms/web/ini/.webapp..ini` to `platforms/web/build/public/.webapp.ini`, which the application fetches and parses at startup. For production builds, the ini file is stripped of comments and extra whitespace. -If a file doesn't exist in /ini/.webapp..ini, then the template file will first be copied from [`platforms/web/ini/templates`](../platforms/web/ini/templates). -All .ini files directly inside of `platforms/web/ini` are ignored in git, so you can create your own files locally to run the application with your account parameters without creating conflicts with committed code or leaking your details into source control. +For all manual builds (`yarn start` or `yarn build`), the ini file is copied from `/ini/.webapp..ini` to `build/public/.webapp.ini`, which the application fetches and parses at startup. For production builds, the ini file is stripped of comments and extra whitespace. +If a file doesn't exist in /ini/.webapp..ini, then the template file will first be copied from [`/ini/templates`](/web/ini/templates). +All the .ini files directly inside of `/ini` are ignored in git, so you can create your own files locally to run the application with your account parameters without creating conflicts with committed code or leaking your details into source control. ## Ini Parameters @@ -45,12 +45,12 @@ Keep in mind, if the playerLicenseKey ini setting is provided, it will be used e ### additionalAllowedConfigSources[] -An array of 8-character IDs (entered 1 per line) for app configs in your JWP account (or url paths) that can be used with the [`app-config=` query param](configuration.md#switching-between-app-configs). -This may be useful for example if you have a staging or experimental config that you want to be able to test on your site using the [`app-config` query parameter](configuration.md#switching-between-app-configs) without changing the default config that the application loads with for all of your users. +An array of 8-character IDs (entered 1 per line) for app configs in your JWP account (or url paths) that can be used with the [`app-config=` query param](web-configuration#switching-between-app-configs). +This may be useful for example if you have a staging or experimental config that you want to be able to test on your site using the [`app-config` query parameter](web-configuration#switching-between-app-configs) without changing the default config that the application loads with for all of your users. See [.webapp.test.ini](/web/ini/templates/.webapp.test.ini) for an example. ### UNSAFE_allowAnyConfigSource -Boolean flag which when true, enables **ANY** 8-character app config ID (or path) to be specified with the [`app-config=` query param](configuration.md#switching-between-app-configs). +Boolean flag which if true, enables **ANY** 8-character app config ID (or path) to be specified with the [`app-config=` query param](web-configuration#switching-between-app-configs). > _**Warning:** Generally the `UNSAFE_allowAnyConfigSource` option should only be used for dev, test, or demo deployments, because it will allow anyone to create URL's that specify any config to be displayed on your domain._ diff --git a/platforms/web/docs/web-configuration.md b/platforms/web/docs/web-configuration.md new file mode 100644 index 000000000..5db53a1ec --- /dev/null +++ b/platforms/web/docs/web-configuration.md @@ -0,0 +1,21 @@ +# Web configuration + +## Configuration File Source + +Which app config file the application uses is determined by the [ini file](../platforms/web/docs/initialization-file.md). + +You can specify the default that the application starts with and also which config, if any, it will allow to be set using the [`app-config=` query param](#switching-between-app-configs). +The location is usually specified by the 8-character ID (i.e. `gnnuzabk`) of the App Config from your JWP account, in which case the file will be loaded from the JW Player App Config delivery endpoint (i.e. `https://cdn.jwplayer.com/apps/configs/gnnuzabk.json`). +You may also specify a relative or absolute URL. + +### Switching between app configs + +As mentioned above, if you have 1 or more additional allowed sources (see additionalAllowedConfigSources in [`initialization-file`](initialization-file.md)), you can switch between them by adding `app-config=` as a query parameter in the web app URL in your browser (i.e. `https:///?app-config=gnnuzabk`). + +The parameter is automatically evaluated, loaded, and stored in browser session storage and should remain part of the url as the user navigates around the site. + +> _Note: Be aware that this mechanism only sets the config for the local machine, browser, and session that you are accessing the site with and it does not change the default hosted app for other users._ + +Even sharing URL's should work as long as the query parameter of the desired config is part of the URL. However, once the query parameter is removed and the stored value in the session is released, the application will revert to loading the default config source. + +> _Note: to clear the value from session storage and return to the default, you can navigate to the site with a blank query parameter value (i.e. `?app-config=`)_