diff --git a/.github/workflows/docker-image-rootless.yml b/.github/workflows/docker-image-rootless.yml new file mode 100644 index 0000000..1578a78 --- /dev/null +++ b/.github/workflows/docker-image-rootless.yml @@ -0,0 +1,28 @@ +name: Publish Docker rootless image + +on: + workflow_dispatch: + push: + branches: [master] + +jobs: + push_to_registry: + name: Push Docker image to Docker Hub + runs-on: ubuntu-latest + steps: + - name: Check out the repo + uses: actions/checkout@v2 + + - name: Docker Login + uses: docker/login-action@v1.12.0 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + + - name: Build and push Docker rootless image + uses: docker/build-push-action@v2.9.0 + with: + context: . + push: true + file: Dockerfile-rootless + tags: mohamnag/nginx-file-browser:latest-rootless diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml new file mode 100644 index 0000000..4e9af52 --- /dev/null +++ b/.github/workflows/docker-image.yml @@ -0,0 +1,27 @@ +name: Publish Docker image + +on: + workflow_dispatch: + push: + branches: [master] + +jobs: + push_to_registry: + name: Push Docker image to Docker Hub + runs-on: ubuntu-latest + steps: + - name: Check out the repo + uses: actions/checkout@v2 + + - name: Docker Login + uses: docker/login-action@v1.12.0 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + + - name: Build and push Docker image + uses: docker/build-push-action@v2.9.0 + with: + context: . + push: true + tags: mohamnag/nginx-file-browser:latest diff --git a/.gitignore b/.gitignore index 7a9e093..c0feb03 100644 --- a/.gitignore +++ b/.gitignore @@ -4,7 +4,7 @@ *.iml ## Directory-based project format: -#.idea/ +.idea/ # if you remove the above rule, at least ignore the following: # User-specific stuff: diff --git a/.idea/modules.xml b/.idea/modules.xml index 589ffcb..eea5117 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -3,6 +3,7 @@ + \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 9b6edd0..778ba33 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ -FROM nginx +FROM nginx:alpine -MAINTAINER Mohammad Naghavi +LABEL author="Mohammad Naghavi " ADD default.conf /etc/nginx/conf.d/default.conf ADD css/ /opt/www/file-browser/css/ diff --git a/Dockerfile-rootless b/Dockerfile-rootless new file mode 100644 index 0000000..7125a50 --- /dev/null +++ b/Dockerfile-rootless @@ -0,0 +1,12 @@ +FROM nginxinc/nginx-unprivileged:stable-alpine + +LABEL author="Mohammad Naghavi " + +ADD default-rootless.conf /etc/nginx/conf.d/default.conf +ADD css/ /opt/www/file-browser/css/ +ADD image/ /opt/www/file-browser/image/ +ADD js/ /opt/www/file-browser/js/ +ADD index.html /opt/www/file-browser/ + +VOLUME /opt/www/files/ +EXPOSE 8080 \ No newline at end of file diff --git a/README.md b/README.md index b90afd9..e72a4f7 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,8 @@ This web application is a very simple file browser which can be used effectively together with [nginx's autoindex module](http://nginx.org/en/docs/http/ngx_http_autoindex_module.html). -![nginx file browser in action](assets/Screen-Shot-1.jpg) +![nginx file browser in action - light theme](assets/screenshot-light.jpg) +![nginx file browser in action - light theme](assets/screenshot-dark.jpg) A sample nginx configuration is also included which mounts **file browser** under root (`/`) and mounts files to be listed under `/files` path. Hence is the `filesBaseUrl` under @@ -11,12 +12,17 @@ A sample nginx configuration is also included which mounts **file browser** unde Mainly for demonstration purposes a docker image is also available [here](https://hub.docker.com/r/mohamnag/nginx-file-browser/). In order to use this docker image, the volume which has to be served should -be mounted under `/opt/www/files/` and port `80` of container shall be mapped +be mounted under `/opt/www/files/` and port `80` (root) or `8080` (rootless)) of container shall be mapped to a proper port on host. A proper run would look like: +root ``` $ docker run -p 8080:80 -v /path/to/my/files/:/opt/www/files/ mohamnag/nginx-file-browser ``` +rootless: +``` +$ docker run -p 8080:8080 -v /path/to/my/files/:/opt/www/files/ mohamnag/nginx-file-browser +``` With container up and running you can point your browser to IP of docker host with given port to view the files. For example with above run command assuming docker host having IP with `192.168.0.200` we have to navigate to this URL: @@ -40,8 +46,3 @@ shall be changed to ``` And the mounting point is now `/home/myuser/files-to-serve/` instead of `/opt/www/files/`. - -## Gruvbox theme - -A gruvbox theme is present in the css. You can use it by editing line 12 of the index.html. Simply change the link from `css/main.css` to `css/main-gruvbox.css` -This theme is heavily inspired from iTerm2 color scheme that can be found here: [link](https://github.com/herrbischoff/iterm2-gruvbox) diff --git a/assets/Screen-Shot-1.jpg b/assets/Screen-Shot-1.jpg deleted file mode 100644 index 3ade45e..0000000 Binary files a/assets/Screen-Shot-1.jpg and /dev/null differ diff --git a/assets/Screen-Shot-1.png b/assets/Screen-Shot-1.png deleted file mode 100644 index 7243c8e..0000000 Binary files a/assets/Screen-Shot-1.png and /dev/null differ diff --git a/assets/file-browser.zip b/assets/icons.zip similarity index 100% rename from assets/file-browser.zip rename to assets/icons.zip diff --git a/assets/screenshot-dark.jpg b/assets/screenshot-dark.jpg new file mode 100644 index 0000000..42a14cb Binary files /dev/null and b/assets/screenshot-dark.jpg differ diff --git a/assets/screenshot-light.jpg b/assets/screenshot-light.jpg new file mode 100644 index 0000000..3fd7ee0 Binary files /dev/null and b/assets/screenshot-light.jpg differ diff --git a/css/main-gruvbox.css b/css/main-gruvbox.css deleted file mode 100644 index 4e43e42..0000000 --- a/css/main-gruvbox.css +++ /dev/null @@ -1,124 +0,0 @@ -body { - background-color: #252525; -} - -body > .container:first-child { - margin: 3rem auto 0; -} - -h1 { - color: #9dd08e; -} - -a { - text-decoration: none; - color: #549699; -} - -a.file-name { - color: #ecdbb2; -} - - -.list-sort { - background: #413e3d; - border-radius: 1rem; - padding: 1.5rem 2rem .5rem; - color: #ecdbb2; -} - -input[name="sort"] { - accent-color: #fe6142; -} - -.list-sort label { - display: inline-block; - margin: 0 1rem 0 0; -} - -.file-list { - list-style: none; -} - -.file-list li { - margin: 1rem 0; -} - -.file-list .file-name { - line-height: 4rem; - display: inline-block; - position: relative; - padding-left: 4rem; -} - -.file-list .file-name::before { - background: no-repeat center center; - background-size: contain; - width: 3rem; - content: ""; - display: block; - position: absolute; - top: 0; - bottom: 0; - left: 0; -} - -.file-list .directory .file-name::before { - background-image: url(../image/directory.png); - -} - -.file-list .file .file-name::before { - background-image: url(../image/file.png); -} - -.file-list .other .file-name::before { - background-image: url(../image/other.png); -} - -.file-list .parent .file-name::before { - background-image: url(../image/parent.png); -} - -.file-list .file-link { - -} - -.file-list .file-date { - padding: .25rem .5rem; - background: #549699; - border-radius: .5rem; - font-size: 70%; - margin: 0 .5rem; - color: #ecdbb2; -} - -.file-list .directory .file-date { -} - -.file-list .parent .file-date { - display: none; -} - -.file-list .file-size { - padding: .25rem .5rem; - background: #79aa7d; - border-radius: .5rem; - font-size: 70%; - margin: 0 .5rem; - color: #ecdbb2; -} - -.file-list .other .file-size, -.file-list .parent .file-size, -.file-list .directory .file-size { - display: none; -} - -footer { - text-align: center; -} - -footer small + small { - margin-left: 2rem; -} diff --git a/css/main.css b/css/main.css index eb8e524..606f8a6 100644 --- a/css/main.css +++ b/css/main.css @@ -7,15 +7,19 @@ a { text-decoration: none; } -.list-sort { +.controls { background: #ddd; border-radius: 1rem; padding: 1.5rem 2rem .5rem; } -.list-sort label { +.controls span:not(:first-of-type) { + padding-left: 4rem; +} + +.controls label { display: inline-block; - margin: 0 1rem 0 0; + margin: 0 0 0 .5rem; } .file-list { @@ -103,4 +107,44 @@ footer { footer small + small { margin-left: 2rem; +} + +/* + Start of alternations for dark theme +*/ + +body.dark { + background-color: #252525; + color: #ecdbb2; +} + +body.dark h1 { + color: #9dd08e; +} + +body.dark a { + color: #549699; +} + +body.dark a.file-name { + color: #ecdbb2; +} + +body.dark .controls { + background: #413e3d; + color: #ecdbb2; +} + +body.dark input[name="sort"] { + accent-color: #fe6142; +} + +body.dark .file-list .file-date { + background: #549699; + color: #ecdbb2; +} + +body.dark .file-list .file-size { + background: #79aa7d; + color: #ecdbb2; } \ No newline at end of file diff --git a/default-rootless.conf b/default-rootless.conf new file mode 100644 index 0000000..6600917 --- /dev/null +++ b/default-rootless.conf @@ -0,0 +1,26 @@ +server { + listen 8080; + server_name localhost; + + root /opt/www/; + index index.html index.htm; + + location /files/ { + alias /opt/www/files/; + index ___i; # we really need no index here, just listing files + + autoindex on; + autoindex_format json; + disable_symlinks off; + } + + location / { + root /opt/www/file-browser/; + } + + error_page 500 502 503 504 /50x.html; + location = /50x.html { + root /usr/share/nginx/html; + } + +} \ No newline at end of file diff --git a/index.html b/index.html index dcdfb29..d4178d3 100644 --- a/index.html +++ b/index.html @@ -20,8 +20,8 @@

File Browser

-
- sort list by +
+ sort list by: + + theme: + +
    @@ -49,14 +59,12 @@ diff --git a/js/main.js b/js/main.js index 04ff12f..27e8ce1 100644 --- a/js/main.js +++ b/js/main.js @@ -6,19 +6,24 @@ * * NOTICE: * If your nginx config varies from the default config * provided in this code, you probably need to change - * value of filesBaseUrl on top of this module too. + * value of filesBaseUrl here too. * * Created by mohamnag on 11/02/16. */ - - $(document).ready(function () { - var filesBaseUrl = "/files"; + function applyTheme() { + var theme = $('input[name=theme]:checked').val() - var fileListElement = $("#file-list"); - var fileItemElementTemplate = fileListElement.find("li").detach(); + console.log(`setting theme to '${theme}'`) + + $('body') + .removeClass() + .addClass(theme) + + localStorage.setItem("theme", theme) + } function renderFileElement(directory, fileName, fileType, fileSize, fileDate) { @@ -203,14 +208,26 @@ $(document).ready(function () { } - var isNavigating = false; - function navigateToUrlLocation() { var requestedPath = window.location.hash; var startPath = requestedPath ? requestedPath.substr(1) : "/"; navigateTo(startPath); } + var filesBaseUrl = "/files"; + var isNavigating = false; + var fileListElement = $("#file-list"); + var fileItemElementTemplate = fileListElement.find("li").detach(); + + // setup theme switching + $('input[name=theme]').on("change", applyTheme); + + // apply current theme + var theme = localStorage.getItem("theme") + console.log(`theme '${theme}' loaded`) + $(`input[name=theme][value='${theme}']`).prop('checked', true) + applyTheme() + window.onpopstate = function () { if (!isNavigating) { navigateToUrlLocation();