Merge pull request #412 from dannyrb/deploying-static-site-2
Guide for different static asset hosts/deployment
This commit is contained in:
commit
6bed32d229
@ -40,7 +40,7 @@
|
||||
- [Embedding the Viewer](deployment/recipes/embedded-viewer.md)
|
||||
- Stand-Alone
|
||||
- [Build for Production](deployment/recipes/build-for-production.md)
|
||||
- [Static]()
|
||||
- [Static](deployment/recipes/static-assets.md)
|
||||
- [Docker]()
|
||||
- [Nginx + Orthanc]()
|
||||
- [Nginx + dcm4chee]()
|
||||
|
||||
|
Before Width: | Height: | Size: 20 MiB After Width: | Height: | Size: 20 MiB |
BIN
docs/latest/assets/img/netlify-drop.gif
Normal file
BIN
docs/latest/assets/img/netlify-drop.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 994 KiB |
BIN
docs/latest/assets/img/surge-deploy.gif
Normal file
BIN
docs/latest/assets/img/surge-deploy.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 371 KiB |
@ -66,15 +66,24 @@ build the OHIF Viewer in our
|
||||
|
||||
##### Part 2 - Host Your App
|
||||
|
||||
There are a lot of [benefits to hosting static assets][host-static-assets]
|
||||
There are a lot of [benefits to hosting static assets][host-static-assets] over
|
||||
dynamic content. You can find instructions on how to host your build's output
|
||||
via one of these guides:
|
||||
|
||||
- AWS S3 + Cloudfront
|
||||
- GCP + Cloudflare
|
||||
- Azure
|
||||
- Netlify (can use private repo)
|
||||
- Github pages
|
||||
_Drag-n-drop_
|
||||
|
||||
Note: Include SSL instructions.
|
||||
- [Netlify: Drop](/deployment/recipes/static-assets.md#netlify-drop)
|
||||
|
||||
_Easy_
|
||||
|
||||
- [Surge.sh](/deployment/recipes/static-assets.md#surgesh)
|
||||
- [GitHub Pages](/deployment/recipes/static-assets.md#github-pages)
|
||||
|
||||
_Advanced_
|
||||
|
||||
- [AWS S3 + Cloudfront](/deployment/recipes/static-assets.md#aws-s3--cloudfront)
|
||||
- [GCP + Cloudflare](/deployment/recipes/static-assets.md#gcp--cloudflare)
|
||||
- [Azure](/deployment/recipes/static-assets.md#azure)
|
||||
|
||||
...
|
||||
|
||||
|
||||
@ -83,27 +83,63 @@ the`window.config` equal to our configuration file's value.
|
||||
|
||||
#### How do I configure my project?
|
||||
|
||||
- Modify its values directly
|
||||
- Create a new config file, and set the `REACT_APP_CONFIG` environement variable
|
||||
-
|
||||
The simplest way is to update the existing default config:
|
||||
|
||||
The build process knows which file to use based on the `REACT_APP_CONFIG`
|
||||
environment variable. You can set the value of this environment variable a few
|
||||
different ways:
|
||||
_/public/config/default.js_
|
||||
|
||||
```js
|
||||
window.config = {
|
||||
routerBasename: '/',
|
||||
relativeWebWorkerScriptsPath: '',
|
||||
servers: {
|
||||
dicomWeb: [
|
||||
{
|
||||
name: 'DCM4CHEE',
|
||||
wadoUriRoot: 'https://server.dcmjs.org/dcm4chee-arc/aets/DCM4CHEE/wado',
|
||||
qidoRoot: 'https://server.dcmjs.org/dcm4chee-arc/aets/DCM4CHEE/rs',
|
||||
wadoRoot: 'https://server.dcmjs.org/dcm4chee-arc/aets/DCM4CHEE/rs',
|
||||
qidoSupportsIncludeField: true,
|
||||
imageRendering: 'wadors',
|
||||
thumbnailRendering: 'wadors',
|
||||
requestOptions: {
|
||||
requestFromBrowser: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
You can also create a new config file and specify its path relative to the build
|
||||
output's root by setting the `REACT_APP_CONFIG` environment variable. You can
|
||||
set the value of this environment variable a few different ways:
|
||||
|
||||
- [Add a temporary environment variable in your shell](https://facebook.github.io/create-react-app/docs/adding-custom-environment-variables#adding-temporary-environment-variables-in-your-shell)
|
||||
- [Add environment specific variables in `.env` file(s)](https://facebook.github.io/create-react-app/docs/adding-custom-environment-variables#adding-development-environment-variables-in-env)
|
||||
-
|
||||
- Using the `cross-env` package in an npm script:
|
||||
- `"build": "cross-env REACT_APP_CONFIG=config/my-config.js react-scripts build"`
|
||||
|
||||
* env vars
|
||||
* `REACT_APP_*`
|
||||
* config file(s)
|
||||
After updating the configuration, `yarn run build:web` to generate updated build
|
||||
output.
|
||||
|
||||
## Next Steps
|
||||
|
||||
### Deploying our Production Build
|
||||
### Deploying Build Output
|
||||
|
||||
TODO: List of recipes
|
||||
_Drag-n-drop_
|
||||
|
||||
- [Netlify: Drop](/deployment/recipes/static-assets.md#netlify-drop)
|
||||
|
||||
_Easy_
|
||||
|
||||
- [Surge.sh](/deployment/recipes/static-assets.md#surgesh)
|
||||
- [GitHub Pages](/deployment/recipes/static-assets.md#github-pages)
|
||||
|
||||
_Advanced_
|
||||
|
||||
- [AWS S3 + Cloudfront](/deployment/recipes/static-assets.md#aws-s3--cloudfront)
|
||||
- [GCP + Cloudflare](/deployment/recipes/static-assets.md#gcp--cloudflare)
|
||||
- [Azure](/deployment/recipes/static-assets.md#azure)
|
||||
|
||||
### Testing Build Output Locally
|
||||
|
||||
|
||||
149
docs/latest/deployment/recipes/static-assets.md
Normal file
149
docs/latest/deployment/recipes/static-assets.md
Normal file
@ -0,0 +1,149 @@
|
||||
# Deploy Static Assets
|
||||
|
||||
> WARNING! All of these solutions stand-up a publicly accessible web viewer. Do
|
||||
> not hook your hosted viewer up to a sensitive source of data without
|
||||
> implementing authentication.
|
||||
|
||||
There are a lot of options for deploying static assets. Some services, like
|
||||
`netlify` and `surge.sh`, specialize in static websites. You'll notice that
|
||||
deploying with them requires much less time and effort, but comes at the cost of
|
||||
less product offerings.
|
||||
|
||||
While not required, it can simplify things to host your Web Viewer alongside
|
||||
your image archive. Services with more robust product offerings, like
|
||||
`Google Cloud`, `Microsoft's Azure`, and `Amazon Web Services (AWS)`, are able
|
||||
to accomodate this setup.
|
||||
|
||||
_Drag-n-drop_
|
||||
|
||||
- [Netlify: Drop](#netlify-drop)
|
||||
|
||||
_Easy_
|
||||
|
||||
- [Surge.sh](#surgesh)
|
||||
- [GitHub Pages](#github-pages)
|
||||
|
||||
_Advanced_
|
||||
|
||||
- [AWS S3 + Cloudfront](#aws-s3--cloudfront)
|
||||
- [GCP + Cloudflare](#gcp--cloudflare)
|
||||
- [Azure](#azure)
|
||||
|
||||
## Drag-n-drop
|
||||
|
||||
### Netlify: Drop
|
||||
|
||||
> Build, deploy, and manage modern web projects. An all-in-one workflow that
|
||||
> combines global deployment, continuous integration, and automatic HTTPS. And
|
||||
> that’s just the beginning.
|
||||
|
||||

|
||||
|
||||
_GIF demonstrating deployment with Netlify Drop_
|
||||
|
||||
1. https://app.netlify.com/drop
|
||||
2. Drag your `build/` folder on to the drop target
|
||||
3. ...
|
||||
4. _annnd you're done_
|
||||
|
||||
**Features:**
|
||||
|
||||
- Custom domains & HTTPS
|
||||
- Instant Git integration
|
||||
- Continuous deployment
|
||||
- Deploy previews
|
||||
- Access to add-ons
|
||||
|
||||
(Non-free tiers include identity, FaaS, Forms, etc.)
|
||||
|
||||
Learn more about [Netlify on their website](https://www.netlify.com/)
|
||||
|
||||
## Easy
|
||||
|
||||
### Surge.sh
|
||||
|
||||
> Static web publishing for Front-End Developers. Simple, single-command web
|
||||
> publishing. Publish HTML, CSS, and JS for free, without leaving the command
|
||||
> line.
|
||||
|
||||

|
||||
|
||||
_GIF demonstrating deployment with surge_
|
||||
|
||||
```shell
|
||||
# Add surge command
|
||||
yarn global add surge
|
||||
|
||||
# In the build directory
|
||||
surge
|
||||
```
|
||||
|
||||
**Features:**
|
||||
|
||||
- Free custom domain support
|
||||
- Free SSL for surge.sh subdomains
|
||||
- pushState support for single page apps
|
||||
- Custom 404.html pages
|
||||
- Barrier-free deployment through the CLI
|
||||
- Easy integration into your Grunt toolchain
|
||||
- Cross-origin resource support
|
||||
- And more…
|
||||
|
||||
Learn more about [surge.sh on their website](https://surge.sh/)
|
||||
|
||||
### GitHub Pages
|
||||
|
||||
> WARNING! While great for project sites and light use, it is not advised to use
|
||||
> GitHub Pages for production workloads. Please consider using a different
|
||||
> service for mission critical applications.
|
||||
|
||||
> Websites for you and your projects. Hosted directly from your GitHub
|
||||
> repository. Just edit, push, and your changes are live.
|
||||
|
||||
This deploy strategy makes more sense if you intend to maintain your project in
|
||||
a GitHub repository. It allows you to specify a `branch` or `folder` as the
|
||||
target for a GitHub Page's website. As you push code changes, the hosted content
|
||||
updates to reflect those changes.
|
||||
|
||||
1. Head over to GitHub.com and create a new repository, or go to an existing
|
||||
one. Click on the Settings tab.
|
||||
2. Scroll down to the GitHub Pages section. Choose the `branch` or `folder` you
|
||||
would like as the "root" of your website.
|
||||
3. Fire up a browser and go to `http://username.github.io/repository`
|
||||
|
||||
Configuring Your Site:
|
||||
|
||||
- [Setting up a custom domain](https://help.github.com/en/articles/using-a-custom-domain-with-github-pages)
|
||||
- [Setting up SSL](https://help.github.com/en/articles/securing-your-github-pages-site-with-https)
|
||||
|
||||
Learn more about [GitHub Pages on its website](https://pages.github.com/)
|
||||
|
||||
## Advanced
|
||||
|
||||
All of these options, while using providers with more service offerings,
|
||||
demonstrate how to host the viewer with their respective file storage and CDN
|
||||
offerings. While you can serve your static assets this way, if you're going
|
||||
through the trouble of using AWS/GCP/Azure, it's more likely you're doing so to
|
||||
avoid using a proxy or to simplify authentication.
|
||||
|
||||
If that is the case, check out some of our more advanced `docker` deployments
|
||||
that target these providers from the left-hand sidebar.
|
||||
|
||||
These guides can be a bit longer and a update more frequently. To provide
|
||||
accurate documentation, we will link to each provider's own recommended steps:
|
||||
|
||||
### AWS S3 + Cloudfront
|
||||
|
||||
- [Host a Static Website](https://docs.aws.amazon.com/AmazonS3/latest/dev/website-hosting-custom-domain-walkthrough.html)
|
||||
- [Speed Up Your Website with Cloudfront](https://docs.aws.amazon.com/AmazonS3/latest/dev/website-hosting-cloudfront-walkthrough.html)
|
||||
|
||||
### GCP + Cloudflare
|
||||
|
||||
- [Things to Know Before Getting Started](https://code.luasoftware.com/tutorials/google-cloud-storage/things-to-know-before-hosting-static-website-on-google-cloud-storage/)
|
||||
- [Hosting a Static Website on GCP](https://cloud.google.com/storage/docs/hosting-static-website)
|
||||
|
||||
### Azure
|
||||
|
||||
- [Host a Static Website](https://docs.microsoft.com/en-us/azure/storage/blobs/storage-blob-static-website)
|
||||
- [Add SSL Support](https://docs.microsoft.com/en-us/azure/storage/blobs/storage-https-custom-domain-cdn)
|
||||
- [Configure a Custom Domain](https://docs.microsoft.com/en-us/azure/storage/blobs/storage-custom-domain-name)
|
||||
@ -4,33 +4,40 @@
|
||||
|
||||
Either clone the repository using Git:
|
||||
|
||||
````bash
|
||||
```bash
|
||||
git clone git@github.com:OHIF/Viewers.git
|
||||
````
|
||||
```
|
||||
|
||||
or [Download the latest Master as a ZIP File](https://github.com/OHIF/Viewers/archive/master.zip).
|
||||
or
|
||||
[Download the latest Master as a ZIP File](https://github.com/OHIF/Viewers/archive/master.zip).
|
||||
|
||||
## Run the OHIF Viewer application against our public DICOM server
|
||||
You can either spin up locally or run with Docker.
|
||||
|
||||
You can either spin up locally or run with Docker.
|
||||
|
||||
### running locally
|
||||
|
||||
1. [Install Node.js](https://nodejs.org/en/)
|
||||
2. Open a new terminal tab, go under `ohif-viewer` directory and install all dependency packages via `yarn`
|
||||
2. Open a new terminal tab, go under `ohif-viewer` directory and install all
|
||||
dependency packages via `yarn`
|
||||
|
||||
````bash
|
||||
yarn install
|
||||
````
|
||||
```bash
|
||||
yarn install
|
||||
```
|
||||
|
||||
3. Run the application
|
||||
|
||||
````bash
|
||||
yarn start
|
||||
````
|
||||
```bash
|
||||
yarn start
|
||||
```
|
||||
|
||||
Note: This will connect to our public DICOMWeb server so you can verify your installation. Follow the next section to connect to your own local or remote DICOMWeb server.
|
||||
Note: This will connect to our public DICOMWeb server so you can verify your
|
||||
installation. Follow the next section to connect to your own local or remote
|
||||
DICOMWeb server.
|
||||
|
||||
4. Launch the OHIF Viewer Study List. By default the address is [http://localhost:3000/](http://localhost:3000/). The port may vary so check the start up output messages such as:
|
||||
4. Launch the OHIF Viewer Study List. By default the address is
|
||||
[http://localhost:3000/](http://localhost:3000/). The port may vary so check
|
||||
the start up output messages such as:
|
||||
|
||||
```bash
|
||||
Compiled successfully!
|
||||
@ -44,105 +51,132 @@ Note that the development build is not optimized.
|
||||
To create a production build, use yarn build.
|
||||
```
|
||||
|
||||
**If everything is working correctly, you should see the studies from our public archive when you visit the Study List.**
|
||||
**If everything is working correctly, you should see the studies from our public
|
||||
archive when you visit the Study List.**
|
||||
|
||||

|
||||
|
||||
5. Double-click on a Study in the Study List to launch it in the Viewer
|
||||
|
||||
**If everything is working correctly, you should see your study load into the Viewer.**
|
||||
**If everything is working correctly, you should see your study load into the
|
||||
Viewer.**
|
||||
|
||||

|
||||

|
||||
|
||||
## Set up a local DICOM server
|
||||
|
||||
1. Choose and install an Image Archive
|
||||
2. Upload some data into your archive (e.g. with DCMTK's [storescu](http://support.dcmtk.org/docs/storescu.html) or your archive's web interface)
|
||||
2. Upload some data into your archive (e.g. with DCMTK's
|
||||
[storescu](http://support.dcmtk.org/docs/storescu.html) or your archive's web
|
||||
interface)
|
||||
3. Keep the server running
|
||||
|
||||
#### Open Source DICOM Image Archive Options
|
||||
|
||||
Archive | Installation
|
||||
-------------------------------------------|
|
||||
[DCM4CHEE Archive 5.x](https://github.com/dcm4che/dcm4chee-arc-light) | [Installation with Docker](https://github.com/dcm4che/dcm4chee-arc-light/wiki/Running-on-Docker)
|
||||
[Orthanc](https://www.orthanc-server.com/) | [Installation with Docker](http://book.orthanc-server.com/users/docker.html)
|
||||
[DICOMcloud](https://github.com/DICOMcloud/DICOMcloud) (**DICOM Web only**)| [Installation](https://github.com/DICOMcloud/DICOMcloud#running-the-code)
|
||||
[OsiriX](http://www.osirix-viewer.com/) (**Mac OSX only**) |
|
||||
[Horos](https://www.horosproject.org/) (**Mac OSX only**) |
|
||||
| Archive | Installation |
|
||||
| --------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ |
|
||||
| [DCM4CHEE Archive 5.x](https://github.com/dcm4che/dcm4chee-arc-light) | [Installation with Docker](https://github.com/dcm4che/dcm4chee-arc-light/wiki/Running-on-Docker) |
|
||||
| [Orthanc](https://www.orthanc-server.com/) | [Installation with Docker](http://book.orthanc-server.com/users/docker.html) |
|
||||
| [DICOMcloud](https://github.com/DICOMcloud/DICOMcloud) (**DICOM Web only**) | [Installation](https://github.com/DICOMcloud/DICOMcloud#running-the-code) |
|
||||
| [OsiriX](http://www.osirix-viewer.com/) (**Mac OSX only**) |
|
||||
| [Horos](https://www.horosproject.org/) (**Mac OSX only**) |
|
||||
|
||||
*Feel free to make a Pull Request if you want to add to this list.*
|
||||
_Feel free to make a Pull Request if you want to add to this list._
|
||||
|
||||
#### Orthanc with Docker
|
||||
|
||||
Depending on whether or not you want uploaded studies to persist in Orthanc after Docker has been closed, there are two different methods for starting the Docker image:
|
||||
Depending on whether or not you want uploaded studies to persist in Orthanc
|
||||
after Docker has been closed, there are two different methods for starting the
|
||||
Docker image:
|
||||
|
||||
##### Temporary data storage
|
||||
This command will start an instance of the jodogne/orthanc-plugins Docker image. *All data will be removed when the instance is stopped!*
|
||||
|
||||
````
|
||||
This command will start an instance of the jodogne/orthanc-plugins Docker image.
|
||||
_All data will be removed when the instance is stopped!_
|
||||
|
||||
```
|
||||
docker run --rm -p 4242:4242 -p 8042:8042 jodogne/orthanc-plugins
|
||||
````
|
||||
```
|
||||
|
||||
##### Persistent data storage
|
||||
In order to allow your data to persist after the instance is stopped, you first need to create an image and attached data volume with Docker. The steps are as follows:
|
||||
|
||||
In order to allow your data to persist after the instance is stopped, you first
|
||||
need to create an image and attached data volume with Docker. The steps are as
|
||||
follows:
|
||||
|
||||
1. Create a persistent data volume for Orthanc to use
|
||||
|
||||
````
|
||||
docker create --name sampledata -v /sampledata jodogne/orthanc-plugins
|
||||
````
|
||||
```
|
||||
docker create --name sampledata -v /sampledata jodogne/orthanc-plugins
|
||||
```
|
||||
|
||||
**Note: On Windows, you need to use an absolute path for the data volume, like so:**
|
||||
**Note: On Windows, you need to use an absolute path for the data volume,
|
||||
like so:**
|
||||
|
||||
````
|
||||
docker create --name sampledata -v '//C/Users/erik/sampledata' jodogne/orthanc-plugins
|
||||
````
|
||||
```
|
||||
docker create --name sampledata -v '//C/Users/erik/sampledata' jodogne/orthanc-plugins
|
||||
```
|
||||
|
||||
2. Run Orthanc from Docker with the data volume attached
|
||||
|
||||
````
|
||||
docker run --volumes-from sampledata -p 4242:4242 -p 8042:8042 jodogne/orthanc-plugins
|
||||
````
|
||||
```
|
||||
docker run --volumes-from sampledata -p 4242:4242 -p 8042:8042 jodogne/orthanc-plugins
|
||||
```
|
||||
|
||||
3. Upload your data and it will be persisted
|
||||
|
||||
|
||||
### Setting up OHIF Viewer with Orthanc as an example
|
||||
|
||||
Once you have Orthanc running with docker either with temporary data storage or persistent data storage we con move forward with the next steps.
|
||||
Once you have Orthanc running with docker either with temporary data storage or
|
||||
persistent data storage we con move forward with the next steps.
|
||||
|
||||
1. Load orthanc with a dataset you might want to use. To upload data use [http://localhost:8042/app/explorer.html](http://localhost:8042/app/explorer.html).
|
||||
1. Load orthanc with a dataset you might want to use. To upload data use
|
||||
[http://localhost:8042/app/explorer.html](http://localhost:8042/app/explorer.html).
|
||||
|
||||
**orthanc is the username and password for orthanc docker**
|
||||
**orthanc is the username and password for orthanc docker**
|
||||
|
||||
2. Go under [http://localhost:8042/app/explorer.html#upload](http://localhost:8042/app/explorer.html#upload) and upload your DICOM files there
|
||||
2. Go under
|
||||
[http://localhost:8042/app/explorer.html#upload](http://localhost:8042/app/explorer.html#upload)
|
||||
and upload your DICOM files there
|
||||
|
||||
3. After you load the data, open a new terminal tab in the `ohif-viewer` directory and install all dependency packages via Yarn
|
||||
3. After you load the data, open a new terminal tab in the `ohif-viewer`
|
||||
directory and install all dependency packages via Yarn
|
||||
|
||||
````bash
|
||||
yarn install
|
||||
````
|
||||
```bash
|
||||
yarn install
|
||||
```
|
||||
|
||||
3. Run the application using one of the available configuration files.
|
||||
**the following command assumes you are under the `root` folder**
|
||||
3. Run the application using one of the available configuration files. **the
|
||||
following command assumes you are under the `root` folder**
|
||||
|
||||
````bash
|
||||
export REACT_APP_CONFIG=$(cat ./config/local_orthanc.js)
|
||||
yarn start
|
||||
````
|
||||
```bash
|
||||
export REACT_APP_CONFIG=$(cat ./config/local_orthanc.js)
|
||||
yarn start
|
||||
```
|
||||
|
||||
This uses the [Custom Environment Variables of Create-React-App](https://facebook.github.io/create-react-app/docs/adding-custom-environment-variables) to pass in your configuration. The example above will not work on Windows. Please visit the link to read about how to set environment variables on Windows.
|
||||
This uses the
|
||||
[Custom Environment Variables of Create-React-App](https://facebook.github.io/create-react-app/docs/adding-custom-environment-variables)
|
||||
to pass in your configuration. The example above will not work on Windows.
|
||||
Please visit the link to read about how to set environment variables on Windows.
|
||||
|
||||
4. Launch the OHIF Viewer Study List by visiting [http://localhost:3000/](http://localhost:3000/) in a web browser.
|
||||
4. Launch the OHIF Viewer Study List by visiting
|
||||
[http://localhost:3000/](http://localhost:3000/) in a web browser.
|
||||
|
||||
**If everything is working correctly, you should see the Study List from your archive when you visit the Study List.**
|
||||
**If everything is working correctly, you should see the Study List from your
|
||||
archive when you visit the Study List.**
|
||||
|
||||
5. Double-click on a Study in the Study List to launch it in the Viewer
|
||||
|
||||
**If everything is working correctly, you should see your study load into the Viewer.**
|
||||
**If everything is working correctly, you should see your study load into the
|
||||
Viewer.**
|
||||
|
||||
#### Troubleshooting
|
||||
* If you receive a *"No Studies Found"* message and do not see your studies, try changing the Study Date filters to a wider range.
|
||||
* If you see a 'Loading' message which never resolves, check your browser JavaScript console inside the Developer Tools to identify any errors.
|
||||
* If you receive `exit code 137`, increase the amount of memory available to your docker instances.
|
||||
* If you see any errors in your server console, check the [Troubleshooting](./troubleshooting.md) page for more in depth advice.
|
||||
|
||||
- If you receive a _"No Studies Found"_ message and do not see your studies, try
|
||||
changing the Study Date filters to a wider range.
|
||||
- If you see a 'Loading' message which never resolves, check your browser
|
||||
JavaScript console inside the Developer Tools to identify any errors.
|
||||
- If you receive `exit code 137`, increase the amount of memory available to
|
||||
your docker instances.
|
||||
- If you see any errors in your server console, check the
|
||||
[Troubleshooting](./troubleshooting.md) page for more in depth advice.
|
||||
|
||||
Loading…
Reference in New Issue
Block a user