Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update Read Mes #12450

Open
wants to merge 10 commits into
base: latest
Choose a base branch
from
103 changes: 102 additions & 1 deletion src/app/components/MediaLoader/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,73 @@
## Description

This component loads a media player into our webpage. It uses the BBC Universal Media Player module (BUMP) to choose the correct Embedded Media Player (EMP) for the user's device. Using BUMP removes the concerns involved in serving different devices and web-browsers as BUMP automatically provides the best fitting EMP for the client. For example, BUMP can cater for differences between mobiles, laptops and desktops, but also factors such as whether the user is using network data (3G) or a WIFI.
The MediaLoader takes data from the BFF and converts it into a BUMP settings object.

BUMP (BBC Universal Media Player) is a javascript module that embeds videos into a webpage. It's the BBC's alternative to the standard `<video>` interface in HTML5. BUMP is better because it takes into account the client's device (are they on mobile or PC?) and the client's connection (are they on 3G or WIFI?) and provides the best fitting embedded media player (EMP) for each user.

## Try it out

Below is a bare-bones example of how BUMP is used. To get a video working we provide BUMP with a valid settings object as outlined below.

- Cookbook provides us with a list of settings available: [Cook book link](https://cookbook.tools.bbc.co.uk/iplayer/customise)
- The BUMP documentation provides us with a full list of settings: [Confluence](https://confluence.dev.bbc.co.uk/display/mp/SMP+Settings+Object)

```
<html>
<head>
<title>Koala and a Butterfly</title>
<script type="text/javascript"
src="https://static.bbci.co.uk/frameworks/requirejs/0.13.0/sharedmodules/require.js"></script>
<script type="text/javascript">
bbcRequireMap = {
"bump-4": "https://emp.bbci.co.uk/emp/bump-4/bump-4"
}
require({ paths: bbcRequireMap, waitSeconds: 30 });
</script>
</head>

<body>
<div id="mediaPlayer" style="height:270px;width:480px"></div>
<script type="text/javascript">
let mediaPlayer;
require(['bump-4'], function (bump) {
// This is an example of a BUMP settings object.
var settings = {
product: 'iplayer',
responsive: true,
counterName: 'smp.demopage.player.page',
playlistObject: {
"title": "Butterfly photobombs koala film shoot at Australia zoo",
"items": [
{
"versionID": "p049sq7k",
"kind": "programme",
"duration": 37
}]
},
statsObject: { clipPID: "p049sq7f" },
autoplay: false
}
mediaPlayer = bump.player(document.getElementById('mediaPlayer'), settings);
mediaPlayer.load();
});

function playButton() {
mediaPlayer.play();
}

function stopButton() {
mediaPlayer.pause();
}

</script>

<button onclick="playButton()">PLAY |></button>
<button onclick="stopButton()">STOP |></button>

</body>

</html>
```

## Local Development

Expand All @@ -21,3 +88,37 @@ Currently, the EMP is set to only load Live video assets by default. To load tes
## Note on playback in local development

In the Next.js app we have `reactStrictMode: true`. This causes lifecycle hooks to be called twice in development mode. This can result in the media player being loaded twice, causing mulitple playbacks of the same media. This does **not** happen in production mode.

## Component Structure

├── MediaLoader
├── configs
├── aresMedia.ts
├── audio.ts
├── clipMedia.ts
├── legacyMedia.ts
├── liveMedia.ts
├── liveRadio.ts
├── tv.ts
├── index.ts
├── Placeholder
├── index.tsx

The MediaLoader component takes in a video block from the BFF and converts it into a BUMP settings object. The BFF does not provide video blocks in a uniformed way since our editors publish videos from different sources. For greater flexibility, we allow the BFF to provide video data in its native form and use respective scripts within the configs folder to process the data into a BUMP settings object. The logic for this is as follows:

1. BFF provides MediaLoader with a native response.
2. The native response is processed by `configs/index.ts` to build a basic set of settings.
3. `configs/index.ts` will then use a respective function in `configs` to further process the native response into a complete set of BUMP settings.

The following sources that our configs folder currently support are:
|Source|Description |
|--|--|
| aresMedia | |
| audio | For podcasts. |
| clipMedia | |
| legacyMedia | |
Comment on lines +116 to +119
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we try and find descriptions for these configs?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yesss, I was hoping to pair with Aaron at some point to get greater clarity on these ones.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or use co-pilot to help?

| liveMedia | For live content provided through Silver (**SI**mple **L**ive **V**ideo s**ER**vice): [More information](https://confluence.dev.bbc.co.uk/display/LiveSchedule/Silver+-+Simple+Live+Video+Service) |
| liveRadio | |
| tv | |

**Important: The media loader will not play live videos on the test environment and vice-versa.**
99 changes: 76 additions & 23 deletions ws-nextjs-app/pages/[service]/live/[id]/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,39 +2,45 @@

## Description

This is the first page to be created through our new NextJS app. It uses several NextJS features, including server side rendering and NextJS' pages router.
Live pages provide live media streams and posts updated in real time.

## BFF Response

BFF details for Live pages can be found here:
[BFF Live Response](https://github.com/bbc/fabl-modules/tree/main/modules/application/simorgh-bff#live)

## How routes are handled

Our Live Page is served through the following route:
Our Live Page is served through the following route:
`/pages/[service]/live/[id]/[[variant]]`, where the double brackets in `[[variant]]` means that the variant is optional.

This route matches the file structure of this repo:
📦ws-nextjs-app
┗ 📂pages
┃ ┣ 📂[service]
┃ ┃ ┣ 📂live
┃ ┃ ┃ ┗ 📂[id]
┃ ┃ ┃ ┃ ┗ 📜[[...variant]].page.tsx
┃ ┃ ┗ 📜[[...]].page.tsx
┃ ┣ 📜_app.page.tsx
┃ ┗ 📜_document.page.tsx

Sample routes that match this construct are:

| Service | URL |
|----------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Pidgin (no variant) | `/pidgin/live/cdvxv61l6x8t` |
| Serbian (with variant lat) | `/serbian/live/c003pmmldygt/lat` |
| Serbian | `/serbian/live/c003pmmldygt` This will ONLY work on your local host. This will NOT be served through the live NextJS app as upstream services are programmed to recognise an absence of the variant and it will instead re-route this request to alternative servers. |
This route matches the file structure of this repo:

├── ws-nextjs-app
├── pages
├── [service]
├── live
├── [id]
├── [[...variant]].page.tsx
├── [[...]].page.tsx
├── _app.page.tsx
├── _document.page.tsx

Sample routes that match this construct are:

| Service | URL |
| -------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Pidgin (no variant) | `/pidgin/live/c7p765ynk9qt` |
| Serbian (with variant lat) | `/serbian/live/c003pmmldygt/lat` |
| Serbian | `/serbian/live/c003pmmldygt` This will ONLY work on your local host. This will NOT be served through the live NextJS app as upstream services are programmed to recognise an absence of the variant and it will instead re-route this request to alternative servers. |

#### Server Side functions

Within `[[variant]].page.tsx`, the `getServerSideProps` function is called on the server side when a request to a live page is made. It's important that this function returns an object that directly correlates to the props expected by the default exported component within `[[variant]].page.tsx`.

```
export const getServerSideProps: GetServerSideProps = async context => {

context.res.statusCode = data.status;

return {
Expand All @@ -47,6 +53,53 @@ export const getServerSideProps: GetServerSideProps = async context => {
export default LivePageLayout;
```

In the code snippet above, NextJS will serve the component returned by `LivePageLayout`. Before doing so, it calls `getServerSideProps` (on the server) to retrieve the requisite props, which are then used to call `LivePageLayout`, which in turn returns a valid HTML element.
In the code snippet above, NextJS will serve the component returned by `LivePageLayout`. Before doing so, it calls `getServerSideProps` (on the server) to retrieve the requisite props, which are then used to call `LivePageLayout`, which in turn returns a valid HTML element.

**It's important that request/response data is stored within `context.res`, so that requests can be handled appropriately by our ELBs.**

## Component Structure

A typical Live page can be found here: https://www.test.bbc.com/pidgin/live/c7p765ynk9qt

Component file structure

├── ws-nextjs-app
├── pages
├── [service]
├── Live
├── [id]
├── Header
├── KeyPoints
├── Posts
├── ShareButton
├── Stream
├── LivePageLayout

The LivePageLayout propagates respective parts of BFF data to the `Header`, `KeyPoints`, `Stream` and `Pagination` components.

### Stream component

The stream component takes in the following properties:

{
streamContent: StreamResponse | null;
contributors: string | null;
}

The `Stream` component will process `streamContent` and populate its body with a series of `Posts`. `Posts` can currently support the following content types: `paragraph`, `unorderedList`, `orderedList`, `image`, `video` and `social`.

### Header component

The header component takes in the following properties:

{
showLiveLabel: boolean;
title: string;
description?: string;
imageUrl?: string;
imageUrlTemplate?: string;
imageWidth?: number;
mediaCollections?: MediaCollection[] | null;
}

**It's incredibly important that request/response data is stored within `context.res` that requests can be handled appropriately.**
`mediaCollections` contains the necessary information for live video streams.
104 changes: 104 additions & 0 deletions ws-nextjs-app/pages/[service]/send/[id]/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
# UGC Uploader Form

## Description

User Generated Content (UGC) refers to any content that is generated by the user. Our uploader form supports the following types of UGC: long text, short text, checkbox, e-mail, telephone, files and images.

## BFF Response

BFF details for UGC/Send pages can be found here:
[BFF Send Response](https://github.com/bbc/fabl-modules/tree/main/modules/application/simorgh-bff#send)

## How routes are handled

Our UGC Uploader Page is served through the following route:
`/pages/[service]/send/[id]/[[variant]]`, where the double brackets in `[[variant]]` means that the variant is optional.

This route matches the file structure of this repo:

├── ws-nextjs-app
├── pages
├── [service]
├── send
├── [id]
├── [[...variant]].page.tsx
├── [[...]].page.tsx
├── _app.page.tsx
├── _document.page.tsx

Sample routes that match this construct are:

| Service | URL |
| ------------------ | ----------------------------- |
| Mundo (no variant) | `/mundo/send/u50853489` |
| Serbian (variant) | `/serbian/send/u00000009/lat` |

#### Server Side functions

Within `[[variant]].page.tsx`, the `getServerSideProps` function is called on the server side when a request to a send page is made. It's important that this function returns an object that directly correlates to the props expected by the default exported component within `[[variant]].page.tsx`.

```
export const getServerSideProps: GetServerSideProps = async context => {

context.res.statusCode = data.status;

return {
props: {
...props expected by UGCPageLayout
},
};
};

export default UGCPageLayout;
```

In the code snippet above, NextJS will serve the component returned by `UGCPageLayout`. Before doing so, it calls `getServerSideProps` (on the server) to retrieve the requisite props, which are then used to call `UGCPageLayout`, which in turn returns a valid HTML element.

**It's important that request/response data is stored within `context.res`, so that requests can be handled appropriately by our ELBs.**

## Component Structure

A typical UGC form can be found here: https://www.bbc.com/mundo/send/u50853489

Component file structure

├── ws-nextjs-app
├── pages
├── [service]
├── send
├── [id]
├── FormContext
├── FormScreen
├── FormField
├── File
├── Checkbox
├── EmailInput
├── FieldLabel
├── Telephone
├── TextArea
├── TextInput

The FormScreen component takes in a list of fields from the BFF and populates itself with a respective body of form fields, based on the components we have available. This is a sample BFF Response:

For example, if the BFF returned the following under `data.sections.fields`, then it would render a phone field followed by a text area:

{ "id": "txt49018963",
"type": "text",
"validation": { "mandatory": false },
"htmlType": "phone",
"label": "Número de teléfono",
"description": "",
"textArea": false
},
{ "id": "txt49019016",
"type": "text",
"validation": { "mandatory": true },
"htmlType": "textarea",
"label": "Comentario (obligatorio)",
"description": "",
"textArea": true
},

### Form Context

The FormContext acts as controller to collate and send all UGC inputted into the form. The `handleSubmit` function within the FormContext effectively validates the form field values and sends it off to the UGC team.
Loading