First make sure to configure your domain name or subdomain to point to your server's IP address.
We need to set some environment variables in order for MoodleNet to function, a list of which can be found in these files:
-`.env` - If you have a domain configured to point to your server, replace every instance of 'localhost' with 'your-domain-here.tld' and those of 'http:' with 'https:' (the 's' is critical) - **If you want to connect your instance with the MoodleNet "mothership" for indexing public content, search, and discovery**, and you agree with the [Terms for Instance Administrators](https://moodle.net/terms/admins/index.html), set CONNECT_WITH_MOTHERSHIP to true, otherwise set it to false. You should then email moodlenet-moderators@moodle.com to request an API key.
-`.env.secrets.example` (which you must copy to `.env.secrets`) - set each password and secret with something random and secure - MAIL_DOMAIN and MAIL_KEY are needed to configure transactional email, sign up at [Mailgun](https://www.mailgun.com/) and then configure the domain name and key
We need to set some environment variables in order for MoodleNet to function, a list of which can be found in these files: - `.env` - If you have a domain configured to point to your server, replace every instance of 'localhost' with 'your-domain-here.tld' and those of 'http:' with 'https:' (the 's' is critical) - **If you want to connect your instance with the MoodleNet "mothership" for indexing public content, search, and discovery**, and you agree with the [Terms for Instance Administrators](https://moodle.net/terms/admins/index.html), set CONNECT_WITH_MOTHERSHIP to true, otherwise set it to false. You should then email moodlenet-moderators@moodle.com to request an API key. - `.env.secrets.example` (which you must copy to `.env.secrets`) - set each password and secret with something random and secure - MAIL_DOMAIN and MAIL_KEY are needed to configure transactional email, sign up at [Mailgun](https://www.mailgun.com/) and then configure the domain name and key
4. Once configured, build the docker image:
```
```sh
$ docker-compose build
...
```
Or if you're building on a Raspberry Pi:
```
```sh
$ docker-compose -f docker-compose.pi.yml build
...
```
5. Try it out
...
...
@@ -71,33 +68,36 @@ c) Start the docker containers with docker-compose:
```sh
$ docker-compose up
...
```
Or if you're running on a Raspberry Pi:
```
```sh
$ docker-compose -f docker-compose.pi.yml up
...
```
6. The MoodleNet backend and frontend should now be running at [http://localhost/](http://localhost/) on your machine and at https://your-domain-name.tld/ with SSL certificates automatically configured thanks to letsencrypt.org (if your domain was correctly configured).
Once you've signed up, you may want to make yourself an instance admin, by running this in the backend console (see above): `MoodleNet.ReleaseTasks.make_instance_admin("your_username")`
6. The MoodleNet backend and frontend should now be running at [http://localhost/](http://localhost/) on your machine and at `https://your-domain-name.tld/` with SSL certificates automatically configured thanks to letsencrypt.org (if your domain was correctly configured).
Once you've signed up, you may want to make yourself an instance admin, by running this in the backend console (see above): `MoodleNet.ReleaseTasks.make_instance_admin("your_username")`
7. If that worked, start the app as a daemon next time:
@@ -138,7 +138,7 @@ Adds a locale for localisation, with [lingui library](https://lingui.js.org/ref/
### `yarn extract`
Extracts new/updated strings from the codebase into JSON files for localisation (they need to be encapsulated with [lingui library](https://lingui.js.org/ref/react.html)'s <Trans>).
Extracts new/updated strings from the codebase into JSON files for localisation (they need to be encapsulated with [lingui library](https://lingui.js.org/ref/react.html)'s `<Trans>`).
### `yarn compile`
...
...
@@ -157,17 +157,17 @@ Builds a `Storybook` static app out of the storybook's `tsx`|`mdx` modules assoc
### `yarn gqlcode`
Generates typed modules based on `src/**/*.graphql` files and `.env.development`'s `REACT_APP_GRAPHQL_ENDPOINT` Backend GraphQL schema endpoint.
Generates typed modules based on `src/**/*.graphql` files and `.env.development`'s `REACT_APP_GRAPHQL_ENDPOINT` Backend GraphQL exposed schema.
## Libraries
This section mentions notable libraries and tools used within the application and provides links to their documentation.
@@ -81,8 +81,16 @@ Some data pre-digesting may occour in FE when makes sense.
For GraphQL related APIs FE modules are paired with a `.graphql` file defining query|mutations and importing controllers `.graphql` fragment definitions to ensure exhaustiveness of selections.
### Apollo Client
### Contexts
### Routers
Currently available global contexts are:
- Algolia (src/context/global/algolia.tsx) configures and provides `InstantSearch` for algolia search features
- Localization (src/context/global/localizationCtx.tsx) configures and provides `lingui` features
- Page (src/context/global/algolia.tsx) provides simple APIs to modify page headers (currently only title but more to come)
### Routes
`src/routes/` folder contains simple tsx modules defining conventionally exporting a set of properties useful for page routing management across the app.
@@ -43,40 +43,79 @@ Examples of using the LinguiJS library are given below.
<Trans>Sign in using your social media account</Trans>
```
### Interpolated language string
It is very common to interpolate values into language strings. This can be done using the `Trans` and `Plural`
components, where the interpolated string names are denoted with curly braces (but still within the actual string)
and the component is given a key/value hash via a `values` prop, where a key of the hash is the name of a string
to be interpolated. For example, from the Login page:
```jsx
<Transid="You don't need an account to browse {site_name}."values={{site_name:'MoodleNet'}}/>
```
It is possible then to have `site_name` or any other interpolated string value produced dynamically and inserted
during runtime. If interpolated values also require localisation then you would use a language string hash,
as above in [Language strings as reference](#language-strings-as-reference), making sure to use the `i18nMark`
function to mark them for extraction by the LinguiJS CLI.
### Language strings as reference
When the string is not passed to (as props or directly as children) to the `Trans` component it will not be picked up automatically by the LinguiJS extract script.
In order to "mark" the string as a language string to be included in the compiled language files we must:
- wrap it in a call to `i18nMark` in case of static strings
- produce a `MesageDescriptor` with `t` tag-function in case of interpolated strings.
#### Simple strings
- Import the [`i18nMark` function](https://lingui.js.org/ref/react.html#i18nmark).
```js
import{i18nMark}from'@lingui/react'
```
- Define the language string however you like. It is usually the case that a file will contain more than one
language string accessed via reference, in this case organise the strings within an object with properties
that describe their purpose. For example, from the Login page:
```js
const tt = {
//...
validation: {
email: i18nMark('The email field cannot be empty'),
//...
}
}
````
- _Note:_ the `validation.email` string is wrapped in a call to `i18nMark`. As the string is not passed to (as props
or directly as children) to the `Trans` component it will not be picked up automatically by the LinguiJS extract
script. In order to "mark" the string as a language string to be included in the compiled language files we must
wrap it in a call to `i18nMark`.
- Then consume the strings. Again, for example, from the Login page:
- Define the language string however you like. For example, from the Login page:
```js
constemailRequiredMessage=i18nMark('The email field cannot be empty')
```
- _Note:_ the `emailRequiredMessage` string is wrapped in a call to `i18nMark`.
- Then consume the strings.
```jsx
validation.push({
field:ValidationField.email,
type:ValidationType.error,
message:tt.validation.email// <- notice the string reference here
}asValidationObject);
<spanclass="error">
<Trans>{emailRequiredMessage}</Trans>
</span>
```
#### Interpolated strings
- Import the [`t` tag-function](https://lingui.js.org/ref/macro.html#t).
```js
import{t}from'@lingui/macro'
```
- Define `MessageDescriptor`. For example, for an unavailable username in signup page:
```js
constuserNameUnavailable=t`Username {userName} is already taken. Choose another one`
```
- _Note:_ the `userNameUnavailable` is not a string it is a [`MessageDescriptor`](https://lingui.js.org/ref/macro.html#js-macros) constructed by the `t` tag-function
- to get an interpolated translation string it has to be consumed by the `i18n._` function exposed by the globally injected Localization `Context`: